unit UnitUFS; interface uses D2XXUnit, HexUtils, FBoots, Windows, Masks, Forms, sysutils, classes, boots, dialogs; procedure readUID(); // внешняя функция для использования function readUIDstep1(): Boolean; // Общая функция чтения function SendRawID(Asic: integer; Loader: string): integer; // Сама функция чтения данных function Select2ndDie(idr: string): Boolean; // подбираем лоадеры implementation uses UnitE1, UnitPavel, unit1, FlashBoots, USBmain, unitmisc, Graphics, UnitUFS; function Select2ndDie(idr: string): Boolean; var s: string; begin result := true; idr := copy(idr, 1, 5); FbusFloader := ''; FbusSloader := ''; case Str2Byte(idr[1] + idr[2]) of $BA: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAP3Gv3_BAF3A9C3DBFA8454937DB77F2B8852B1.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_BAF3A9C3DBFA8454937DB77F2B8852B1.bin'; bof := StartDir + 'Flash\UFS\Special\RAP3Gv3_BO.bin'; end; $9D: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAP3Gv3_9DDBFCFE6E73CED7D8C6268C8EB85723.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_9DDBFCFE6E73CED7D8C6268C8EB85723.bin'; bof := StartDir + 'Flash\UFS\Special\RAP3Gv3_BO.bin'; end; $E9: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAP3Gv2_E9EFF4BFAA5393217CA6B17755FC3E14.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_E9EFF4BFAA5393217CA6B17755FC3E14.bin'; bof := StartDir + 'Flash\UFS\Special\RAP3Gv2_BO.bin'; end; $38: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAP3Gv3_38F312750F686F9FC9B1B3778774A195.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_38F312750F686F9FC9B1B3778774A195.bin'; bof := StartDir + 'Flash\UFS\Special\RAP3Gv3_BO.bin'; end; $A5: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAP3Gv3_A5404AE83A594ECADEE532F0C236BFA6.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_A5404AE83A594ECADEE532F0C236BFA6.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; $9A: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAPIDOv11_9A28E119033B91D14D22838C86D0D53C.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_9A28E119033B91D14D22838C86D0D53C.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; $CA: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAPIDOv11_CAEEBB65D3C48E6DC73B49DC5063A2EE.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_CAEEBB65D3C48E6DC73B49DC5063A2EE.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; $F2: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAPIDOv11_F2D76DFAFD66C7F195F278417DF05888.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_F2D76DFAFD66C7F195F278417DF05888.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; $F6: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAPIDOv11_F682624FFB08F6D955DBE7D9C0485084.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_F682624FFB08F6D955DBE7D9C0485084.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; $FC: begin FbusFloader := StartDir + 'Flash\UFS\Special\RAPIDOv11_FCB5C510AF7F09F313D9BDE85A707CC0.bin'; FbusSloader := StartDir + 'Flash\UFS\Special\BootCustom_FCB5C510AF7F09F313D9BDE85A707CC0.bin'; bof := StartDir + 'Flash\UFS\Special\RAPIDO_BO.bin'; end; else result := False; end; end; function readUIDstep1(): Boolean; begin result := false; form1._msg('Setting FlashMode'); if not SwitchBoxMode('FlashBus') then begin form1._msg('UFSx : FlashMode init fail! Reconnect box'); form1._msg(''); form1.SetReady; exit; end; Form1.statusbar.Panels[0].Text := 'UFS : Booting phone...'; ufs_cmd(3500, @CMTread[0], 2, @cmd_buf, 200); //Form1._msg('BootData : '+BufToHexStr(@cmd_buf[0], $FF)); Application.ProcessMessages; if (FT_IN_BUFFER[1] > 20) and (FT_IN_BUFFER[2] <> $72) and (FT_IN_BUFFER[2] <> $20) then FetchBootData else begin form1._msg('No answer from phone... :('); form1._msg('1. Check cable/connection, try again'); form1._msg('2. Maybe HW fault or bad cable'); form1._msg(''); form1.SetReady; Exit; end; if not Select2ndDie(ROOTKEY) then begin // выбор лоадера по необходимый руткейхэшь Form1._msg('Error finding required loader... :('); form1._msg(''); form1.SetReady; Exit; end; if SendRawId(0, FbusFloader) <> 0 then exit; result := True; end; function SendRawID(Asic: integer; Loader: string): integer; var rawloader, rawblock: TMemoryStream; b: Boolean; chk: word; tmp: array of Byte; i: integer; flblk: integer; lb: Byte; filename: string; mmc: System.Text; id: string; begin result := 9; algo := ''; Form1.statusbar.Panels[0].Text := 'UFS : CMT 2ND boot...'; // шлем бут Form1._msg('CMT : Sending 2nd loader...'); Application.ProcessMessages; RAWloader := TMemoryStream.Create; rawloader.LoadFromFile(loader); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); if rawloader.size = 0 then exit; result := 8; // RAwloader prepare error if (FLbyte = $F1) or (FLbyte = $F5) or (FLbyte = $F3) then begin ufs_cmd(50, @prerawcheck[0], 3, @cmd_buf, 1); Form1._msg('Set Data [' + Byte2Str(ft_in_buffer[0]) + ']'); //form1._msg('Set Data ['+Byte2Str(replyverify3)+']'); end; rawloader.ReadBuffer(tmp[0], rawloader.Size); RawLen[6] := rawloader.Size mod $100; RawLen[5] := rawloader.Size div $100; result := 7; // PrebootCheck error - raw len no accepted ufs_cmd(50, @Rawlen[0], 7, @cmd_buf, 2); Form1._msg('Set data [' + byte2str(FT_In_Buffer[0]) + ']'); devbyte := FT_In_Buffer[0]; if FT_In_Buffer[1] <> $72 then Exit; Application.ProcessMessages; FT_Out_Buffer[0] := $69; FT_Out_Buffer[1] := $02; FT_Out_Buffer[2] := $0A; FT_Out_Buffer[3] := $00; FT_Out_Buffer[5] := rawloader.Size mod $100; FT_Out_Buffer[4] := rawloader.Size div $100; FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; Application.ProcessMessages; for i := 0 to rawloader.size + 7 do FT_Out_Buffer[i + 8] := TMP[i]; ufs_cmd(500, @FT_out_buffer, (rawloader.Size + 8), @cmd_buf, 7); result := 6; // rawloader not accepted by phone if ft_in_buffer[0] <> $00 then begin form1._msg('ERR: ' + buftohexstr(@FT_in_buffer[0], 7)); exit; end; //if ft_in_buffer[5]<>$F1 then exit; if ft_in_buffer[6] <> $72 then begin form1._msg('ERR: ' + buftohexstr(@FT_in_buffer[0], 7)); exit; end; Application.ProcessMessages; Form1._msg('CMT Loader sent, Boot Ok'); Form1.statusbar.Panels[0].Text := 'UFS : 2ND Boot Ok, wait...'; // выполняем переполнение бута rawloader.Free; RAWloader := TMemoryStream.Create; rawloader.LoadFromFile(bof); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); rawloader.ReadBuffer(tmp[0], rawloader.Size); Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $20; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $02; FT_Out_Buffer[4] := $E4; for i := 0 to rawloader.size + 4 do FT_Out_Buffer[i + 5] := TMP[i]; ufs_cmd(500, @FT_out_buffer, (rawloader.Size + 5), @cmd_buf, 2); rawloader.Free; if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufs_cmd(500, @flow, Length(flow), @cmd_buf, 2); Form1.statusbar.Panels[0].Text := 'UFS : Exploit Ok, wait...'; // Переполнение прошло, шлем кастом-лоадер Application.ProcessMessages; Form1._msg('OWF : ' + byte2str(ft_in_buffer[0])); if ft_in_buffer[1] <> $72 then exit; RAWloader := TMemoryStream.Create; rawloader.LoadFromFile(FbusSloader); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); rawloader.ReadBuffer(tmp[0], rawloader.Size); Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $20; FT_Out_Buffer[2] := $00; FT_Out_Buffer[4] := rawloader.Size mod $100; FT_Out_Buffer[3] := rawloader.Size div $100; for i := 0 to rawloader.size + 4 do FT_Out_Buffer[i + 5] := TMP[i]; dwordswap(@FT_out_buffer[5]); ufs_cmd(500, @FT_out_buffer, (rawloader.Size + 5), @cmd_buf, 2); rawloader.free; if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufs_cmd(500, @flow, Length(flow), @cmd_buf, 2); Application.ProcessMessages; Form1._msg('OWF2 : ' + byte2str(ft_in_buffer[0])); // Кастом-лоадер запущен, начинаем подготовливать стеки if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufs_cmd(500, @overready, 9, @cmd_buf, 11); Form1._msg('OWF3 : ' + byte2str(ft_in_buffer[9])); //if ft_in_buffer[8]<>$72 then exit; Application.ProcessMessages; ufs_cmd(500, @readdieid, 6, @cmd_buf, $40); // читаем наши данные - 20 байт RAP_PUBLIC_ID+20 байт UNIQUEID Form1.statusbar.Panels[0].Text := 'UFS : Fetching data, wait...'; id := buftohexstr(@ft_in_buffer[0], $40); try FileName := getcurrentdir + '\' + 'Special' + '\' + buftohexstr(@RAPInfo.PUBLIC_ID, Length(RAPInfo.PUBLIC_ID)) + '_fetch.best'; // сохраняем по значению рапайди except FileName := getcurrentdir + '\Err_read_info_fetch.best'; end; if fileexists(filename) then filename := getcurrentdir + '\' + 'Special' + '\' + 'rand' + '__fetch.best'; System.Assign(MMC, FileName); System.Rewrite(MMC); System.WriteLn(MMC, '[fetched]'); System.Writeln(MMC, 'RAPID=' + buftohexstr(@RAPInfo.PUBLIC_ID, Length(RAPInfo.PUBLIC_ID))); System.Writeln(MMC, 'HASH=' + buftohexstr(@RAPInfo.ROOT_KEY_HASH, Length(RAPInfo.ROOT_KEY_HASH))); System.Writeln(MMC, 'ROMID=' + buftohexstr(@RAPInfo.ROM_ID, Length(RAPInfo.ROM_ID))); System.Writeln(MMC, 'id=' + id); System.Close(mmc); Form1._msg('Saved to : ' + filename); Form1.statusbar.Panels[0].Text := ''; result := 0; end; procedure readUID(); begin if not readUIDstep1 then form1._msg('Error fetching data... :(') else form1._msg('ID read done ;)'); end;