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 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;
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);
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=起始地址
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);