既不让我回帖,也不让我贴附件。晕晕ing
那个时候,作的英雄王座的unpacker。他的解码主要是第一个节的解码和IAT的重建。
代码中也有点错误,不过还没遇到过错误。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,Math;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
// TBSItem = packed record
//
// end;
//
// TBSUnpackerINEXE = packed record
// unknown_000:DWORD;
// unknown_004:DWORD;
// unknown_008:DWORD;
// unknown_00C:DWORD;//<===
// unknown_010:DWORD;//<===
// unknown_014:DWORD;//<===
// unknown_018:DWORD;//<===
// unknown_01C:DWORD;
// unknown_020:DWORD;
// unknown_024:DWORD;
// unknown_028:DWORD;
// end;
// TBSFile = packed record
// classbase:DWORD;//+000;
// bsFileBuf:PChar;//+004;//
// bsFileSize:DWORD;//+008;//ReadSize
// bsFileName:array[0..$100-1] of char;//+0014//FileName
// LastErrorCode : DWORD;//+214;//LastErrorCode;
// hbsFile:THandle;//+218;hFile;
// end;
// TBSPacker = packed record
// unknown_000:DWORD;//+000
// unknown_004:DWORD;//+004
// unknown_008:DWORD;//+008:000
// unknown_00C:DWORD;//+00C:004=??????=1
// unknown_010:DWORD;//+010:008=ErrorCode
// ImageBase:DWORD;//+014:00C=ImageBase=0x00400000<====
// unknown_018:DWORD;//+018:010=
// pDosHeader:PImageDosHeader;//+01C:014=pEXE
// pPEHeader:PImageNtHeaders;//+020:018=pPE
// pSectionHeader:PImageSectionHeader;//+024:01C=pSection
// VA_OAT:DWORD;//+028:020=pPE^.78 + ImageBase=OAT
// VA_IAT:DWORD;//+02C:024=pPE^.80 + ImageBase=IAT<===
// OriginalImageBase:DWORD;//+030:028=pPE^.34 = OriImageBase
// Offset_BS:DWORD;//+034:02C=offsetbs
// unknown_038:DWORD;//+038
// KEY2 : array[0..$100-1] of char;//+058:
// KEY2Len : DWORD;//+158
// //+174 = Size
// //+170 = buf
// //+178 = Now
// end;
TBSFile = packed record
bsFileBuf:PChar;//+004;//
bsFileSize:DWORD;//+008;//ReadSize
end;
TBSPacker = packed record
ImageBase:DWORD;
pDosHeader:PImageDosHeader;
pPEHeader:PImageNtHeaders;
pSectionHeader:PImageSectionHeader;
NewSectionHeader:PImageSectionHeader;
exeFileBuf:PChar;
exeFileSize:DWORD;
end;
TBSUnpacker = packed record
newFileName : String;
Packer:TBSPacker;
bsFile:TBSFile;
end;
procedure Init(var Unpacker:TBSUnpacker);
var
p:PChar;
begin
P := Unpacker.Packer.exeFileBuf;
Unpacker.Packer.pDosHeader := PImageDosHeader(P);
Unpacker.Packer.pPEHeader := PImageNTHeaders(DWORD(P) + DWORD(Unpacker.Packer.pDosHeader^._lfanew));
Unpacker.Packer.pSectionHeader := PImageSectionHeader(DWORD(Unpacker.Packer.pPEHeader) + SizeOf(TImageNTHeaders));
Unpacker.Packer.ImageBase := Unpacker.Packer.pPEHeader^.OptionalHeader.ImageBase;
end;
function RVA_TO_Offset(RVA:DWORD;PE:PImageNTHeaders):DWORD;
var
P:PImageSectionHeader;
Count:DWORD;
Size,Align:DWORD;
begin
P := PImageSectionHeader(DWORD(PE) + SizeOf(TImageNTHeaders));
Count := PE^.FileHeader.NumberOfSections;
Align := PE^.OptionalHeader.SectionAlignment;
result := 0;
while Count > 0 do
begin
Size := P^.Misc.VirtualSize;
Size := ((Size + Align - 1 ) div Align) * Align;
if (Count = 1 ) or ((P^.VirtualAddress + Size) >= RVA) then
begin
result := (RVA - P^.VirtualAddress) + P^.PointerToRawData;
break;
end;
inc(P);
dec(Count);
end;
end;
function Offset_To_RVA(Offset:DWORD;PE:PImageNTHeaders):DWORD;
var
P:PImageSectionHeader;
Count:DWORD;
Size,Align:DWORD;
begin
P := PImageSectionHeader(DWORD(PE) + SizeOf(TImageNTHeaders));
Count := PE^.FileHeader.NumberOfSections;
Align := PE^.OptionalHeader.FileAlignment;
result := 0;
while Count > 0 do
begin
Size := P^.SizeOfRawData;
Size := ((Size + Align - 1 ) div Align) * Align;
if (Count = 1) or ((P^.PointerToRawData + Size) >= Offset) then
begin
result := (Offset - P^.PointerToRawData) + P^.VirtualAddress;
break;
end;
inc(P);
dec(Count);
end;
end;
function Offset_To_VA(Offset:DWORD;PE:PImageNTHeaders):DWORD;
begin
result := Offset_To_RVA(Offset,PE) + PE^.OptionalHeader.ImageBase;
end;
const
mENCODE = 0;
mDECODE = 1;
type
TBlock = array[0..3] of DWORD;
PBlock = ^TBlock;
TSubkeyBlock = array[0..4-1] of DWORD;
PSubkeyBlock = ^TSubkeyBlock;
TSubKeyIndex = array[0..16-1] of PSubkeyBlock;
TKeyArray = array[0..16-1] of TSubkeyBlock;
procedure InitKey(KEY:PBlock;var UArray:TKeyArray;var KEYBlock:TSubKeyIndex);
var
Index:Integer;
K0,K1,K2,K3:DWORD;
begin
K0 := KEY[0];K1 := KEY[1];K2 := KEY[2];K3 := KEY[3];
for Index := 0 to 15 do
begin
KEYBlock[Index] := @UArray[Index];
K0 := (K0 + K1) * (K2 + K3);//EAX
K1 := (K0 + K2) * (K1 + K3);//ECX
K2 := (K2 + K1) * (K0 + K3);//EDX
K3 := K3 + ((K0 + K1) + K2);//ESI
UArray[Index,1]:= K1;
UArray[Index,0]:= K0;
UArray[Index,2]:= K2;
UArray[Index,3]:= K3;
end;
end;
procedure Coding(var InBlock:TBlock;SubKey:PSubkeyBlock;var OutBlock:TBlock;iMode:DWORD);
var
K0,K1,K2,K3,I0,I1,I2,I3,U1,U2:DWORD;
begin
I0 := InBlock[0];I1 := InBlock[1];I2 := InBlock[2];I3 := InBlock[3];
K0 := SubKey[0];K1 := SubKey[1];K2 := SubKey[2];K3 := SubKey[3];
U2 := (K0 + K1) * (I2 + I3) * (K2 + K3);//EAX
U1 := (I2 * I3) + ((K1 + K3) * (K2 + K0));//ECX
OutBlock[0] := I2;
OutBlock[1] := I3;
OutBlock[2] := I0 xor U2;
OutBlock[3] := I1 xor U1;
end;
procedure Coder(InBlock,KEY,OutBlock:PChar;iMode:DWORD);
var
KeyArray:TKeyArray;
SubKeyIndex:TSubKeyIndex;
TmpInBlock,TmpOutBlock:TBlock;
Index : Integer;
begin
ZeroMemory(@KeyArray[0],SizeOf(KeyArray));
Move(InBlock^,TmpInBlock,4*4);
InitKey(PBlock(KEY),KeyArray,SubKeyIndex);
if iMode = mDECODE then
begin//解密
for Index := 0 to 15 do
begin
Coding(TmpInBlock,SubKeyIndex[Index],TmpOutBlock,mENCODE);
TmpInBlock := TmpOutBlock;
end;
end else
begin//加密
for Index := 15 downto 0 do
begin
Coding(TmpInBlock,SubKeyIndex[Index],TmpOutBlock,mDECODE);
TmpInBlock := TmpOutBlock;
end;
end;
//高8位和低8交换
TmpOutBlock[0] := TmpInBlock[2];
TmpOutBlock[1] := TmpInBlock[3];
TmpOutBlock[2] := TmpInBlock[0];
TmpOutBlock[3] := TmpInBlock[1];
Move(TmpOutBlock[0],OutBlock^,4*4);
end;
//根据
//只计算整数部分
procedure _Decode(BUF:PChar;BUFSize:DWORD;KEY:PChar;KEYLen:DWORD);
var
Count:Integer;
InBlock,OutBlock:PChar;
begin
InBlock := BUF;
Count := BUFSize shr 4;//(BUFSize + 15) shr 4;//只计算整数部分
while (Count > 0) do
begin
OutBlock := InBlock;
Coder(InBlock,KEY,OutBlock,mDECODE);
Inc(InBlock,16);
Dec(Count);
end;
end;
procedure DecodeFirstSection(var Unpacker:TBSUnpacker);
var
P:PChar;
Size,Res:DWORD;
T:array[0..15] of char;
begin
//UnpackerData.
P := PChar(Unpacker.Packer.exeFileBuf + Unpacker.Packer.pSectionHeader^.PointerToRawData);
Size := Unpacker.Packer.pSectionHeader^.SizeOfRawData;
_Decode(P,Size,'1234567890987654',16);
Res := Size and $0F;
if res <> 0 then
begin
FillChar(T,16,0);
Move(PChar(DWORD(P) + Size - Res)^,T,Res);
_Decode(@T,16,'1234567890987654',16);
Move(T,PChar(DWORD(P) + Size - Res)^,Res);
end;
end;
function GetDWORD(BUF:PCHAR):DWORD;
begin
GetDWORD := PDWORD(BUF)^;
end;
//function GetSize(BUF:PCHAR):DWORD;
//var
// Count:DWORD;
// p:PDWORD;
//begin
// Result := 0;
// Count := PDWORD(BUF)^;
// p := PDWORD(DWORD(BUF) + 8);
// while Count>0 do
// begin
// if p^ > Result then
// Result := p^;
// dec(Count);
// p := PDWORD(DWORD(p)+ p^ + 4);
// end;
//end;
//Updater.bs UPDATER.EXE
//BSSerJ.bs BSSerialJ.exe
//BSLic.bs BSLicense.exe
//BSBookJ.bs BSBookJ.exe
//packet.bs Travia.exe
function Loadbs(var bsFile:TBSFile;const FileName:String):Boolean;
var
hbsFile : THandle;
begin
Result := False;
hbsFile := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
if hbsFile <> $FFFFFFFF then
begin
bsFile.bsFileSize := GetFileSize(hbsFile,nil);
GetMem(bsFile.bsFileBuf,bsFile.bsFileSize);
FileRead(hbsFile,bsFile.bsFileBuf^,bsFile.bsFileSize);
CloseHandle(hbsFile);
result := True;
end;
end;
function GetIATBlockByIndex(BUF:PChar;Index:DWORD):PChar;
var
P : PDWORD;
begin
P := PDWORD(DWORD(BUF) + 8);
while Index > 0 do
begin
dec(Index);
p := PDWORD(DWORD(p)+ p^ + 4);
end;
GetIATBlockByIndex := Pointer(DWORD(P)+4);
end;
function GetIATBlockSizeByIndex(BUF:PChar;Index:DWORD):DWORD;
var
P : PDWORD;
begin
P := PDWORD(DWORD(BUF) + 8);
while Index > 0 do
begin
dec(Index);
p := PDWORD(DWORD(p)+ p^ + 4);
end;
GetIATBlockSizeByIndex := P^;
end;
type
TImport = packed record
ImportFlag:DWORD;
TimeStamp:DWORD;
MajorVersion,MinorVersion:WORD;
RVA_DLLNAME:DWORD;
RVA_ImportLookupTable:DWORD;
// RVA_ImportAddress:DWORD;
end;
PImport = ^TImport;
//10001F9C
function MakeIAT(FileBase:DWORD;PE:PImageNTHeaders;BUF:PChar;P3:PImport;var P1:PDWORD;var P2:PCHAR):Boolean;
var
nCountOfIATBlock : DWORD;
Index : DWORD;
P,PAPI,PAPI2,PFIX:PChar;
// Size:DWORD;
Index2,Count2:DWORD;
Index3,Count3:DWORD;
prefix : PDWORD;
fixrva : PDWORD;
PD : PDWORD;
begin
Result := True;
nCountOfIATBlock := GetDWORD(BUF);//项目个数,0=DLL,1..API//=Count
P := GetIATBlockByIndex(BUF,0);//P=DLLNAME//10002006
P2 := PCHAR(DWORD(P1) + nCountOfIATBlock * 4);
P3^.RVA_ImportLookupTable := Offset_To_RVA(DWORD(P1) - FileBase,PE);
P3^.RVA_DLLNAME := Offset_To_RVA(DWORD(P2) - FileBase,PE);
// P3^.RVA_ImportAddress :=
Move(P^,P2^,strlen(P));//DLLName
Inc(P2,strlen(P));
P2^ := #0;
Inc(P2);
P2^ := #0;
if (DWORD(P2) and 1) <> 0 then Inc(P2);
for Index := 1 to nCountOfIATBlock - 1 do//API个数
begin
PAPI := GetIATBlockByIndex(BUF,Index);//100020A5=??Mem1
Count2 := GetDWORD(PAPI);
PAPI2 := GetIATBlockByIndex(PAPI,0);//100020E9=API=Memx
if PAPI2^ <> #0 then
begin//By Name,+5
Inc(PAPI2,5);
P1^ := Offset_To_RVA(DWORD(P2) - FileBase,PE);
P2^ := #0;Inc(P2);P2^ := #0;Inc(P2);
Move(PAPI2^,P2^,strlen(PAPI2));
Inc(P2,strlen(PAPI2));
P2^ := #0;
Inc(P2);
P2^ := #0;
if (DWORD(P2) and 1) <> 0 then Inc(P2);
end else
begin//By Order,+5
Inc(PAPI2,5);
PD := PDWORD(PAPI2);
P1^ := PD^ or $80000000;
end;
//Fix//=3
for Index2 := 1 to Count2 - 1 do//几种模式
begin
PFIX := GetIATBlockByIndex(PAPI,Index2);
Count3 := GetIATBlockSizeByIndex(PAPI,Index2);
Count3 := (Count3 - 8) shr 2;//
fixrva := PDWORD(DWORD(PFIX) + 8);
prefix := PDWORD(PFIX);
for Index3 := 1 to Count3 do//几个地方
begin
PD := PDWORD(RVA_to_Offset(fixrva^,PE) + FileBase);
if PD = nil then
MessageBeep(0);
PD^ := prefix^;
if PD^ > $FF then
asm
push eax
push edx
mov edx,PD
mov eax,[edx]
bswap eax
shr eax,16
mov [edx],eax
pop edx
pop eax
end;
if prefix^ = $A1 then
begin//+1
PD := PDWORD(DWORD(PD) + 1);
end else
begin//+2
PD := PDWORD(DWORD(PD) + 2);
end;
PD^ := DWORD(Offset_To_VA(DWORD(P1) - FileBase,PE));//?
inc(fixrva);
end;
end;
//Size := GetIATBlockSizeByIndex(PAPI,0);
inc(P1);
end;
P1^ := 0;
Inc(P1);
end;
function Decodebs(var Unpacker:TBSUnpacker;KEY:PChar;KEYLen:DWORD):Boolean;
var
nCountOfIATBlock : DWORD;
Index : DWORD;
P:PChar;
Size:DWORD;
P1:PDWORD;
P2:PCHAR;
P3:PImport;
IATSize : DWORD;
FileBase:DWORD;
hf,NewFileSize : DWORD;
Align:DWORD;
begin
Result := True;
nCountOfIATBlock := GetDWORD(Unpacker.bsFile.bsFileBuf);
//留一个空
P3 := PImport(DWORD(Unpacker.Packer.exeFileBuf) + Unpacker.Packer.NewSectionHeader^.PointerToRawData);
Unpacker.Packer.pPEHeader^.OptionalHeader.DataDirectory[1].VirtualAddress := Unpacker.Packer.NewSectionHeader^.VirtualAddress;
IATSize := (nCountOfIATBlock + 1) * SizeOf(TImport);
FillChar(P3^,IATSize,0);
Unpacker.Packer.pPEHeader^.OptionalHeader.DataDirectory[1].Size := IATSize;
P1 := PDWORD(DWORD(P3) + IATSize);
//修改IAT指针
FileBase := DWORD(Unpacker.Packer.exeFileBuf);
for Index := 0 to nCountOfIATBlock - 1 do
begin
P := GetIATBlockByIndex(Unpacker.bsFile.bsFileBuf,Index);
Size := GetIATBlockSizeByIndex(Unpacker.bsFile.bsFileBuf,Index);
Inc(P,4);
Dec(Size,4);
_Decode(P,Size,KEY,KEYLen);//直接整数部分//余数部分不用处理
//P1=起始地址
MakeIAT(FileBase,Unpacker.Packer.pPEHeader,P,P3,P1,P2);
P1 := PDWORD(P2);
inc(P3);
end;
NewFileSize := (DWORD(P1) - FileBase);
Align := Unpacker.Packer.pPEHeader^.OptionalHeader.FileAlignment;
Size := NewFileSize - Unpacker.Packer.NewSectionHeader^.PointerToRawData;
Size := ((Size + Align - 1) div Align) * Align;
Unpacker.Packer.NewSectionHeader^.SizeOfRawData := Size;
Align := Unpacker.Packer.pPEHeader^.OptionalHeader.SectionAlignment;
Size := NewFileSize - Unpacker.Packer.NewSectionHeader^.PointerToRawData;
Size := ((Size + Align - 1) div Align) * Align;
Unpacker.Packer.NewSectionHeader^.Misc.VirtualSize := Size;
//Unpacker.Packer.pPEHeader^.OptionalHeader.DataDirectory[1].Size := Size;
Unpacker.Packer.pPEHeader^.OptionalHeader.SizeOfImage :=Unpacker.Packer.NewSectionHeader^.VirtualAddress + Size;
NewFileSize := Unpacker.Packer.NewSectionHeader^.PointerToRawData + Unpacker.Packer.NewSectionHeader^.SizeOfRawData;
hf := FileCreate(Unpacker.newFileName);
FileWrite(hf,Unpacker.Packer.exeFileBuf^,NewFileSize);
FileClose(hf);
end;
function LoadExe(var Unpacker:TBSUnpacker;const FileName:String):Boolean;
var
hexeFile : THandle;
begin
Result := False;
hexeFile := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
if hexeFile <> $FFFFFFFF then
begin
Unpacker.Packer.exeFileSize := GetFileSize(hexeFile,nil);
GetMem(Unpacker.Packer.exeFileBuf,Unpacker.Packer.exeFileSize + Unpacker.bsFile.bsFileSize);
FileRead(hexeFile,Unpacker.Packer.exeFileBuf^,Unpacker.Packer.exeFileSize);
CloseHandle(hexeFile);
Unpacker.Packer.exeFileSize := Unpacker.Packer.exeFileSize + Unpacker.bsFile.bsFileSize;
result := True;
end;
end;
// ('UPDATER.EXE', 'Updater.bs'),
// ('BSSerialJ.exe', 'BSSerJ.bs'),
// ('BSLicense.exe', 'BSLic.bs'),
// ('BSBookJ.exe', 'BSBookJ.bs'),
// ('Travia.exe', 'packet.bs'));
procedure UnpackIt(exeFileName,bsFileName,toFileName:String);
var
Unpacker :TBSUnpacker;
Offset,Align:DWORD;
begin
Unpacker.newFileName := toFileName;
if LoadBs(Unpacker.bsFile,bsFileName) then//Load bs file;
begin
if LoadExe(Unpacker,exeFileName) then
begin
Init(Unpacker);
//解开第一个节
DecodeFirstSection(Unpacker);
//处理其他,新节的数据
Inc(Unpacker.Packer.pSectionHeader,Unpacker.Packer.pPEHeader.FileHeader.NumberOfSections);
Inc(Unpacker.Packer.pPEHeader.FileHeader.NumberOfSections);
Unpacker.Packer.NewSectionHeader := Unpacker.Packer.pSectionHeader;
Dec(Unpacker.Packer.pSectionHeader);
FillChar(Unpacker.Packer.NewSectionHeader^,SizeOf(TImageSectionHeader),0);
Move('.idata',Unpacker.Packer.NewSectionHeader^.Name,6);
Offset := Unpacker.Packer.pSectionHeader^.Misc.VirtualSize;
Align := Unpacker.Packer.pPEHeader^.OptionalHeader.SectionAlignment;
Offset := ((Offset + Align - 1) div Align) * Align;
Unpacker.Packer.NewSectionHeader^.VirtualAddress := Unpacker.Packer.pSectionHeader^.VirtualAddress + Offset;
Offset := Unpacker.Packer.pSectionHeader^.SizeOfRawData;
Align := Unpacker.Packer.pPEHeader^.OptionalHeader.FileAlignment;
Offset := ((Offset + Align - 1) div Align) * Align;
Unpacker.Packer.NewSectionHeader^.PointerToRawData := Unpacker.Packer.pSectionHeader^.PointerToRawData + Offset;
Unpacker.Packer.NewSectionHeader^.Characteristics := $E0000020;
//解开重建IAT
Decodebs(Unpacker,'1234567890987654',16);
//Unpacker.Packer.NewSectionHeader^.SizeOfRawData := 0;
//Unpacker.Packer.NewSectionHeader^.Misc.VirtualSize := 0;
//
FreeMem(Unpacker.Packer.exeFileBuf,Unpacker.Packer.exeFileSize);
end;
FreeMem(Unpacker.bsFile.bsFileBuf,Unpacker.bsFile.bsFileSize);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
UnpackIt('Travia.exe','packet.bs','Travia~.exe');
UnpackIt('Updater.exe','Updater.bs','Updater~.exe');
ShowMessage('Finished.');
end;
end.