Jump to content
Tuts 4 You

[Delphi] Add Imports problem


steve10120

Recommended Posts

Posted (edited)

Hi. Got a problem with some code I've written to add imports to a file. Its working fine on something like a Delphi Hello World, but on notepad.exe its crashing for some reason, can't work out why.

{ Add Imports Example  Author: steve10120
Description: Add imports to a PE file.
Website: http://hackhound.org
History: First try
Added multiple import support. }unit uAddImport;interfaceuses Windows;type
TFuncArray = array of string;
TImports = packed record
szLibName: string;
Funcs: TFuncArray;
end;procedure AddImport(szFilePath:string; Imports:TImports);type
PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: DWORD;
TimeDateStamp: DWORD;
ForwarderChain: DWORD;
Name: DWORD;
FirstThunk: DWORD;
end;type
PImportByName = ^TImportByName;
TImportByName = packed record
Name1: DWORD;
end;type
TByteArray = array of Byte;implementationfunction FileToBytes(sPath:string; var bFile:TByteArray):Boolean;
var
hFile: THandle;
dSize: DWORD;
dRead: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(sPath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile <> 0 then
begin
dSize := GetFileSize(hFile, nil);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
SetLength(bFile, dSize);
if ReadFile(hFile, bFile[0], dSize, dRead, nil) then
Result := TRUE;
CloseHandle(hFile);
end;
end;procedure BytesToFile(bData:TByteArray; sPath:string);
var
hFile: THandle;
dWritten: DWORD;
begin
hFile := CreateFile(PChar(sPath), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> 0 then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
WriteFile(hFile, bData[0],Length(bData), dWritten, nil);
CloseHandle(hFile);
end;
end;function OffsetToRVA(dwOffset:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwOffset - dwRaw + dwVA;
end;function RVAToOffset(dwRVA:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwRVA - dwVA + dwRaw;
end;function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
if dwAlign <> 0 then
begin
if dwValue mod dwAlign <> 0 then
begin
Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
Exit;
end;
end;
Result := dwValue;
end;procedure AddImport(szFilePath:string; Imports:TImports);
var
bFile: TByteArray;
IDH: PImageDosHeader;
INH: PImageNtHeaders;
ISH: PImageSectionHeader;
IID: PImageImportDescriptor;
IBN: array of TImportByName;
i: DWORD;
dwIATPos: DWORD;
dwPos: DWORD;
bBuff: TByteArray;
dwSize: DWORD;
begin
if FileToBytes(szFilePath, bFile) then
begin
IDH := @bFile[0];
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
INH := @bFile[IDH._lfanew];
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
for i := 0 to INH.FileHeader.NumberOfSections - 1 do
begin
ISH := @bFile[IDH._lfanew + 248 + i * 40];
if (INH.OptionalHeader.DataDirectory[1].VirtualAddress >= ISH.VirtualAddress) and (INH.OptionalHeader.DataDirectory[1].VirtualAddress <= (ISH.VirtualAddress + ISH.Misc.VirtualSize)) then
begin
dwIATPos := RVAToOffset(INH.OptionalHeader.DataDirectory[1].VirtualAddress, ISH.VirtualAddress, ISH.PointerToRawData);
Break;
end;
end;
IID := @bFile[dwIATPos];
SetLength(bBuff, 20);
dwPos := 0;
repeat
CopyMemory(@bBuff[dwPos], IID, 20);
Inc(IID);
Inc(dwPos, 20);
SetLength(bBuff, dwPos + 20);
until IID.Name = 0;
dwPos := Length(bFile);
dwSize := Align(Length(bBuff) + 20, INH.OptionalHeader.FileAlignment);
SetLength(bFile, Length(bFile) + dwSize);
ISH := @bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40];
Imports.szLibName := Imports.szLibName + #0;
CopyMemory(@bFile[dwPos], @Imports.szLibName[1], Length(Imports.szLibName));
IID.Name := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
Inc(dwPos, Length(Imports.szLibName));
SetLength(IBN, Length(Imports.Funcs));
for i := 0 to Length(Imports.Funcs) - 1 do
begin
Imports.Funcs[i] := #0#0 + Imports.Funcs[i] + #0;
CopyMemory(@bFile[dwPos], @Imports.Funcs[i][1], Length(Imports.Funcs[i]));
IBN[i].Name1 := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
Inc(dwPos, Length(Imports.Funcs[i]));
end;
IID.FirstThunk := OffsetToRVA(dwPos + Length(bBuff) + 20, ISH.VirtualAddress, ISH.PointerToRawData);
CopyMemory(@bBuff[Length(bBuff) - 20], IID, 20);
SetLength(bBuff, Length(bBuff) + 20);
CopyMemory(@bFile[dwPos], @bBuff[0], Length(bBuff));
INH.OptionalHeader.DataDirectory[1].VirtualAddress := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
INH.OptionalHeader.DataDirectory[1].Size := Length(bBuff);
Inc(dwPos, Length(bBuff));
for i := 0 to Length(IBN) - 1 do
begin
CopyMemory(@bFile[dwPos], @IBN[i], 4);
Inc(dwPos, 4);
end;
Inc(ISH.SizeOfRawData, dwSize);
Inc(ISH.Misc.VirtualSize, dwSize);
CopyMemory(@bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40], ISH, 40);
INH.OptionalHeader.SizeOfImage := ISH.VirtualAddress + ISH.Misc.VirtualSize;
CopyMemory(@bFile[IDH._lfanew], INH, 248);
BytesToFile(bFile, szFilePath);
end;
end;
end;
end;end.

The error is on:

IID.Name := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);

Looks fine to me so probably a pointer problem like before but I can't find it.

error.jpg

Thanks. :)

Edit: I'm calling like,

var
Imports: TImports;begin
SetLength(Imports.Funcs, 1);
Imports.szLibName := 'kernel32.dll';
CopyFile('notepad.exe', 'Output.exe', FALSE);
Imports.Funcs[0] := 'GetTempFileNameA';
AddImport('Output.exe', Imports);
end.
Edited by steve10120
Posted

Hello steve10120:

Check the CreateFileA sentences.

You'd check against the hfile <> -1 value, instead of 0. It is not being opening an existing file, since Copy sentence has not found out the notepad.exe file, and consequently has not created a new file called output.exe.

You'd rather use absolute paths for files, better than just file names.

Best regards

Nacho_dj

Posted

Thanks for the reply.

Do you mean the FileToBytes/BytesToFile functions? Pretty sure there ok I use them like this all the time.

Posted

Yes, those functions. I never check against zero value but -1 value for the handle returned.

I have been debugging your code, that's the way I have got my conclusions.

Copy procedure only creates a new file if the origin exists. Giving as parameter just a name of file implies you need to have in your tool's folder that file, otherwise none copied file will be created.

You may use the Delphi debugger to test all of this.

Cheers

Nacho_dj

Posted

Sorry yes, I wrote those functions ages ago it should be INVALID_HANDLE_VALUE.

Copy procedure only creates a new file if the origin exists. Giving as parameter just a name of file implies you need to have in your tool's folder that file, otherwise none copied file will be created.

Not sure what you mean there. The reading/writing functions are working fine when the files are in the right place(eg same folder as main app), the whole thing is working fine on some files, but not all.

Using the Delphi debugger I found the problem line to be the one I posted above.

Posted

Using the Delphi debugger I found the problem line to be the one I posted above.

Well, you found the line where it crashes but the problem is much deeper. It's caused by pointers and memory reallocation. Something like this:


Line 117: if FileToBytes(szFilePath, bFile) then // allocates a memory for TByteArray
Line 134: IID := @bFile[dwIATPos]; // IID is a pointer into current TByteArray
Line 145: SetLength(bFile, Length(bFile) + dwSize); // resizes TByteArray, memory is not reallocated yet
Line 148: CopyMemory(@bFile[dwPos], @Imports.szLibName[1], Length(Imports.szLibName)); // first write into resized array, Delphi memory manager reallocates memory. IID is a pointer into garbage now.
Line 149: IID.Name := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData); // crash!

Your code is quite a mess, so it's hard to give a suggestion how to fix it properly. I'd try avoid using pointers into bFile at all costs.

Cheers,

kao.

Posted

Thanks! Fixed it, now working on all files, still a bit of a mess but it will do for now. :thumbsup:

Posted

Sorry for the double post.

Appears I spoke to soon on this, after a couple of recodes its still giving me problems. Its now wiping my thunk array on a CopyMemory call, even tho the array isn't one of the parameters.

I'm obviously lacking some Delphi memory management skills, does any body have a reference/link that could help me on this?

Cheers.

Posted

I don't know if this will help, but dynamic arrays always have the first component in the 0 index and the last one in the Length(array) - 1 index. Forgetting this lots of times produce errors in execution time.

If you need especifically more help in your updated code, don't doubt to post it again...

Cheers

Nacho_dj

Posted (edited)

Thanks, but yeah think the arrays are ok. In the debugger I can literally see, array is full >> call CopyMemory >> array is empty.

This is my updated code, well...one of them. *I know, its messy*

{ Add Imports Example  Author: steve10120
Description: Add imports to a PE file.
Website: http://hackhound.org
History: First try
Added multiple import support. }unit uAddImport;interfaceuses Windows, SysUtils;type
TFuncArray = array of string;
TImports = packed record
szLibName: string;
Funcs: TFuncArray;
end;procedure AddImport(szFilePath:string; Imports:TImports; var dwThunk:DWORD);type
PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: DWORD;
TimeDateStamp: DWORD;
ForwarderChain: DWORD;
Name: DWORD;
FirstThunk: DWORD;
end;type
PImportByName = ^TImportByName;
TImportByName = packed record
Name1: DWORD;
end;implementationfunction FileToMem(szFilePath:string; var pFile:Pointer; var dwSize:DWORD):Boolean;
var
hFile: DWORD;
dwNull: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(szFilePath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
dwSize := GetFileSize(hFile, nil);
if dwSize > 0 then
begin
GetMem(pFile, dwSize);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
ReadFile(hFile, pFile^, dwSize, dwNull, nil);
CloseHandle(hFile);
Result := TRUE;
end;
end;
end;function GetPointerSize(lpBuffer: Pointer): Cardinal; // Function by ErazerZ
begin
if lpBuffer = nil then
Result := Cardinal(-1)
else
Result := Cardinal(Pointer(Cardinal(lpBuffer) -4)^) and $7FFFFFFC -4;
end;
procedure MemToFile(pData:Pointer; sPath:string);
var
hFile: THandle;
dWritten: DWORD;
dSize: DWORD;
begin
hFile := CreateFile(PChar(sPath), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
if hFile <> 0 then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
dSize := GetPointerSize(pData);
WriteFile(hFile, pData^, dSize, dWritten, nil);
FreeMem(pData, dSize);
CloseHandle(hFile);
end;
end;function OffsetToRVA(dwOffset:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwOffset - dwRaw + dwVA;
end;function RVAToOffset(dwRVA:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwRVA - dwVA + dwRaw;
end;function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
if dwAlign <> 0 then
begin
if dwValue mod dwAlign <> 0 then
begin
Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
Exit;
end;
end;
Result := dwValue;
end;procedure AddImport(szFilePath:string; Imports:TImports; var dwThunk:DWORD);
var
pFile: Pointer;
dwSizeOfFile: DWORD;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
ISH: TImageSectionHeader;
IID: TImageImportDescriptor;
IBN: array of TImportByName;
i: DWORD;
dwIATPos: DWORD;
dwPos: DWORD;
pBuff: Pointer;
dwBuffLen: DWORD;
dwSize: DWORD;
begin
if FileToMem(szFilePath, pFile, dwSizeOfFile) then
begin
CopyMemory(@IDH, pFile, 64);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
CopyMemory(@INH, Pointer(DWORD(pFile) + IDH._lfanew), 248);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
for i := 0 to INH.FileHeader.NumberOfSections - 1 do
begin
CopyMemory(@ISH, Pointer(DWORD(pFile) + IDH._lfanew + 248 + i * 40), 40);
if (INH.OptionalHeader.DataDirectory[1].VirtualAddress >= ISH.VirtualAddress) and (INH.OptionalHeader.DataDirectory[1].VirtualAddress <= (ISH.VirtualAddress + ISH.Misc.VirtualSize)) then
begin
dwIATPos := RVAToOffset(INH.OptionalHeader.DataDirectory[1].VirtualAddress, ISH.VirtualAddress, ISH.PointerToRawData);
Break;
end;
end;
GetMem(pBuff, 20);
dwPos := 0;
repeat
CopyMemory(@IID, Pointer(DWORD(pFile) + dwIATPos + dwPos), 20);
if IID.Name <> 0 then
begin
ReallocMem(pBuff, dwPos + 20);
CopyMemory(Pointer(DWORD(pBuff) + dwPos), @IID, 20);
end;
Inc(dwPos, 20);
until IID.Name = 0;
ReallocMem(pBuff, dwPos + 20);
dwSize := Align(dwPos + 20, INH.OptionalHeader.FileAlignment);
dwBuffLen := dwPos;
dwPos := dwSizeOfFile;
ReallocMem(pFile, dwSizeOfFile + dwSize);
CopyMemory(@ISH, Pointer(DWORD(pFile) + IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40), 40);
Imports.szLibName := Imports.szLibName + #0;
CopyMemory(Pointer(DWORD(pFile) + dwPos), @Imports.szLibName[1], Length(Imports.szLibName));
IID.Name := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
Inc(dwPos, Length(Imports.szLibName));
SetLength(IBN, Length(Imports.Funcs));
for i := 0 to Length(Imports.Funcs) - 1 do
begin
Imports.Funcs[i] := #0#0 + Imports.Funcs[i] + #0;
CopyMemory(Pointer(DWORD(pFile) + dwPos), @Imports.Funcs[i][1], Length(Imports.Funcs[i]));
IBN[i].Name1 := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
Inc(dwPos, Length(Imports.Funcs[i]));
end;
IID.FirstThunk := OffsetToRVA(dwPos + dwBuffLen, ISH.VirtualAddress, ISH.PointerToRawData);
dwThunk := IID.FirstThunk;
CopyMemory(Pointer(DWORD(pBuff) + dwBuffLen - 20), @IID, 20);
CopyMemory(Pointer(DWORD(pFile) + dwPos), pBuff, dwBuffLen);
INH.OptionalHeader.DataDirectory[1].VirtualAddress := OffsetToRVA(dwPos, ISH.VirtualAddress, ISH.PointerToRawData);
INH.OptionalHeader.DataDirectory[1].Size := dwBuffLen;
Inc(dwPos, dwBuffLen);
for i := 0 to Length(IBN) - 1 do
begin
CopyMemory(Pointer(DWORD(pFile) + dwPos), @IBN[i], 4);
Inc(dwPos, 4);
end;
Inc(ISH.SizeOfRawData, dwSize);
Inc(ISH.Misc.VirtualSize, dwSize);
ISH.Characteristics := ISH.Characteristics or IMAGE_SCN_MEM_WRITE;
INH.OptionalHeader.SizeOfImage := ISH.VirtualAddress + ISH.Misc.VirtualSize;
CopyMemory(Pointer(DWORD(pFile) + IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40), @ISH, 40);
CopyMemory(@ISH, Pointer(DWORD(pFile) + IDH._lfanew + 248), 40);
ISH.Characteristics := ISH.Characteristics or IMAGE_SCN_MEM_WRITE;
CopyMemory(Pointer(DWORD(pFile) + IDH._lfanew + 248), @ISH, 40);
CopyMemory(Pointer(DWORD(pFile) + IDH._lfanew), @INH, 248);
MemToFile(pFile, szFilePath);
end;
end;
end;
end;end.

Any advice would be appreciated here, driving me crazy.

Edit: This is the line, nothing todo with the array.

CopyMemory(Pointer(DWORD(pFile) + dwPos), pBuff, dwBuffLen);
Edited by steve10120
Posted (edited)

Hi steve10120:

The code seems to work fine. Anyway, you'd need to change something in the code to give a slight different output.

At the end of import table you need to have 5 dwords equal to zero, then you can set the FirstThunk pointer.

So, after changes, you'll have something like this (a piece of output.exe file edited in hexadecimal):

offset
--------
0000C9D0 00000000 00000000 00000000 10F70000
0000C9E0 F8F70000 00000000 00000000 00000000
0000C9F0 00000000 00000000 1DF70000 00000000

Although it runs, I would modify the size of Import Table in Data Directories from 0xB4 to 0xC8, since this is the current size of it.

By the way, you can re-use the string 'kernel.dll' of the original import table, without having to write it again in the new import table... ;)

Good work in any case!

Nacho_dj

Edited by Nacho_dj
Posted

Thanks for the reply. Forgot to post that I've fixed it. Instead of enlarging the last section just went for adding a new section, only problem with that is that I'm using a fixed size for the section(1024), will have to come up with a GetITSize function.

By the way, you can re-use the string 'kernel.dll' of the original import table, without having to write it again in the new import table...

That would be a good way to optimize it yeah, search all Names if match then use that RVA. And yeah made sure theres 20 bytes at the end of the IID's. :)

Anyway this is the working code.

unit uAddImport;interfaceuses Windows, SysUtils, uAddSection;type
TFuncArray = array of string;
TImports = packed record
szLibName: string;
Funcs: TFuncArray;
end;procedure AddImport(szFilePath:string; Imports:TImports; var dwThunk:DWORD);type
PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: DWORD;
TimeDateStamp: DWORD;
ForwarderChain: DWORD;
Name: DWORD;
FirstThunk: DWORD;
end;type
PImportByName = ^TImportByName;
TImportByName = packed record
Name1: DWORD;
end;implementationfunction FileToMem(szFilePath:string; var pFile:Pointer; var dwSize:DWORD):Boolean;
var
hFile: DWORD;
dwNull: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(szFilePath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
dwSize := GetFileSize(hFile, nil);
if dwSize > 0 then
begin
GetMem(pFile, dwSize);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
ReadFile(hFile, pFile^, dwSize, dwNull, nil);
CloseHandle(hFile);
Result := TRUE;
end;
end;
end;function GetPointerSize(lpBuffer: Pointer): Cardinal; // Function by ErazerZ
begin
if lpBuffer = nil then
Result := Cardinal(-1)
else
Result := Cardinal(Pointer(Cardinal(lpBuffer) -4)^) and $7FFFFFFC -4;
end;
procedure MemToFile(pData:Pointer; sPath:string);
var
hFile: THandle;
dWritten: DWORD;
dSize: DWORD;
begin
hFile := CreateFile(PChar(sPath), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
if hFile <> 0 then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
dSize := GetPointerSize(pData);
WriteFile(hFile, pData^, dSize, dWritten, nil);
CloseHandle(hFile);
end;
end;function OffsetToRVA(dwOffset:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwOffset - dwRaw + dwVA;
end;function RVAToOffset(dwRVA:DWORD; dwVA:DWORD; dwRaw:DWORD):DWORD;
begin
Result := dwRVA - dwVA + dwRaw;
end;function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
if dwAlign <> 0 then
begin
if dwValue mod dwAlign <> 0 then
begin
Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
Exit;
end;
end;
Result := dwValue;
end;procedure AddImport(szFilePath:string; Imports:TImports; var dwThunk:DWORD);
var
pFile: Pointer;
dwSizeOfFile: DWORD;
dwSectionSize: DWORD;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
ISH: TImageSectionHeader;
IID: TImageImportDescriptor;
IBN: array of TImportByName;
i: WORD;
dwSectionRVA: DWORD;
dwSectionPos: DWORD;
dwIATPos: DWORD;
pSectionBuff: Pointer;
dwBuffPos: DWORD;
dwStrLen: DWORD;
dwNewThunkPos: DWORD;
begin
dwSectionSize := 1024;
if AddSection(szFilePath, '.idata2', dwSectionSize, IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE, dwSectionRVA, dwSectionPos) then
begin
if FileToMem(szFilePath, pFile, dwSizeOfFile) then
begin
CopyMemory(@IDH, pFile, 64);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
CopyMemory(@INH, Pointer(DWORD(pFile) + IDH._lfanew), 248);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
for i := 0 to INH.FileHeader.NumberOfSections - 1 do
begin
CopyMemory(@ISH, Pointer(DWORD(pFile) + IDH._lfanew + 248 + i * 40), 40);
if (INH.OptionalHeader.DataDirectory[1].VirtualAddress >= ISH.VirtualAddress) and (INH.OptionalHeader.DataDirectory[1].VirtualAddress <= (ISH.VirtualAddress + ISH.Misc.VirtualSize)) then
begin
dwIATPos := RVAToOffset(INH.OptionalHeader.DataDirectory[1].VirtualAddress, ISH.VirtualAddress, ISH.PointerToRawData);
Break;
end;
end;
// needs to be done for some files..for some reason..
ISH.Characteristics := ISH.Characteristics or IMAGE_SCN_MEM_WRITE;
CopyMemory(Pointer(DWORD(pFile) + IDH._lfanew + 248 + i * 40), @ISH, 40); GetMem(pSectionBuff, dwSectionSize);
CopyMemory(pSectionBuff, Pointer(DWORD(pFile) + dwSectionPos), dwSectionSize); Imports.szLibName := Imports.szLibName + #0;
dwStrLen := Length(Imports.szLibName);
CopyMemory(pSectionBuff, @Imports.szLibName[1], dwStrLen); dwBuffPos := dwStrLen;
repeat
CopyMemory(@IID, Pointer(DWORD(pFile) + dwIATPos), 20);
CopyMemory(Pointer(DWORD(pSectionBuff) + dwBuffPos), @IID, 20);
Inc(dwBuffPos, 20);
Inc(dwIATPos, 20);
until IID.Name = 0;
IID.Name := dwSectionRVA;
dwNewThunkPos := dwBuffPos - 20;
Inc(dwBuffPos, 40); SetLength(IBN, Length(Imports.Funcs));
for i := 0 to Length(Imports.Funcs) - 1 do
begin
Imports.Funcs[i] := #0#0 + Imports.Funcs[i] + #0;
dwStrLen := Length(Imports.Funcs[i]);
CopyMemory(Pointer(DWORD(pSectionBuff) + dwBuffPos), @Imports.Funcs[i][1], dwStrLen);
IBN[i].Name1 := dwSectionRVA + dwBuffPos;
Inc(dwBuffPos, dwStrLen);
end; IID.FirstThunk := dwSectionRVA + dwBuffPos;
dwThunk := IID.FirstThunk;
CopyMemory(Pointer(DWORD(pSectionBuff) + dwNewThunkPos), @IID, 20); for i := 0 to Length(IBN) - 1 do
begin
CopyMemory(Pointer(DWORD(pSectionBuff) + dwBuffPos), @IBN[i], 4);
Inc(dwBuffPos, 4);
end; INH.OptionalHeader.SizeOfImage := dwSectionRVA + dwSectionSize;
INH.OptionalHeader.DataDirectory[1].VirtualAddress := dwSectionRVA + Length(Imports.szLibName);
INH.OptionalHeader.DataDirectory[1].Size := dwBuffPos; CopyMemory(Pointer(DWORD(pFile) + dwSectionPos), pSectionBuff, dwSectionSize);
CopyMemory(Pointer(DWORD(pFile) + IDH._lfanew), @INH, 248); MemToFile(pFile, szFilePath);
end;
end;
end;
end;
end;end.

Thanks all. :)

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...