因为经常要使用ghost制作安装包,有时候gho文件设置了密码,忘记就麻烦了,所以闲来无事,研究了一下,并捣鼓出一个gho文件密码读取的程序出来。其实很简单,我已经把它封装一个函数,现在把部分源代码贴出来,供大家研究研究。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
unit GetGhopass; (**************************************************************) (* 读取GHO文件密码单元文件 *) (* 理论上支持(ghost8.0、ghost11.0、Ghost11.5生成的gho文件 *) (* *) (* *) (* Copyright (c) 2018 hnhv.com QQ: 58715222 *) (* *) (* *) (**************************************************************) interface uses System.SysUtils,System.Classes; const gs: string = 'BinaryResearch'; gKey: array[0..255] of Integer = ( ); function GetGHOPwd(f: string): string; implementation function GetGHOPwd(f: string): string; var fs: TFileStream; rBytes: array[1..25] of Byte; //获取GHO的密文 r2Bytes: array[1..15] of Byte; //用于储存结果 i,r: Integer; s: string; function DecOK: Boolean; //判断结果是否与字符相等 var i: Integer; begin Result := True; for i := 1 to Length(gs) do begin if r2Bytes[i] <> Ord(gs[i]) then begin Result := False; Break; end; end; end; procedure DecryptStr(p,n,r: Integer); //解密运算 //用于计算rBytes序号1..15 16..25 var i,j: Integer; ak,r1,rs: Integer; begin rs := r; j := 1; for i := p to n do begin r2Bytes[j] := rBytes[i] xor Byte(rs); r1 := rs shr 8; ak := r1 xor rBytes[i]; //XOR EDX,EBX 密文与结果运算得到密钥位置 r1 := Byte(rs) shl 8; //MOV BH,CL rs := r1 xor gKey[ak]; //XOR BX,WORD PTR DS:[EDX * 2 + 402040] Inc(j); end; end; begin Result := ''; if FileExists(f) then begin fs := TFileStream.Create(f,fmOpenRead); fs.Seek(0,soFromBeginning); for i := 1 to 2 do //读取文件头用于判断是否为GHO文件 FE EF 01 01 (ghost8.0)(02)ghost11.0,(03)Ghost11.5 begin fs.Read(rBytes[i],1); s := Format('%s%.2x',[s,rBytes[i]]); end; if s = 'FEEF' then //是GHO文件 begin fs.Seek(11,soFromBeginning); fs.Read(rBytes[1],1); //是否有密码 if Boolean(rBytes[1]) then //有密码 rBytes[1]=1表示有密码 begin for i := 1 to 25 do //提取密文 begin fs.Read(rBytes[i],1); end; r := 1; while (not DecOK) and (r < $10000) do begin DecryptStr(1,15,r); Inc(r); end; s := ''; if r < $10000 then //开始提取密码 begin FillChar(r2Bytes,15,0); //清零 DecryptStr(16,25,r-1); for i := 1 to 15 do begin s := s + Char(r2Bytes[i]); end; end; Result := s; end; end; fs.Free; end; end; end. |