steve10120 Posted September 10, 2009 Posted September 10, 2009 (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;varhFile: 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);varhFile: 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. 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 September 10, 2009 by steve10120
Nacho_dj Posted September 10, 2009 Posted September 10, 2009 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 regardsNacho_dj
steve10120 Posted September 10, 2009 Author Posted September 10, 2009 Thanks for the reply.Do you mean the FileToBytes/BytesToFile functions? Pretty sure there ok I use them like this all the time.
Nacho_dj Posted September 10, 2009 Posted September 10, 2009 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.CheersNacho_dj
steve10120 Posted September 10, 2009 Author Posted September 10, 2009 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.
kao Posted September 11, 2009 Posted September 11, 2009 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 TByteArrayLine 134: IID := @bFile[dwIATPos]; // IID is a pointer into current TByteArrayLine 145: SetLength(bFile, Length(bFile) + dwSize); // resizes TByteArray, memory is not reallocated yetLine 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.
steve10120 Posted September 11, 2009 Author Posted September 11, 2009 Thanks! Fixed it, now working on all files, still a bit of a mess but it will do for now.
steve10120 Posted September 12, 2009 Author Posted September 12, 2009 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.
Nacho_dj Posted September 12, 2009 Posted September 12, 2009 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...CheersNacho_dj
steve10120 Posted September 12, 2009 Author Posted September 12, 2009 (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 ErazerZbegin if lpBuffer = nil then Result := Cardinal(-1) else Result := Cardinal(Pointer(Cardinal(lpBuffer) -4)^) and $7FFFFFFC -4;end;procedure MemToFile(pData:Pointer; sPath:string);varhFile: 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 September 12, 2009 by steve10120
Nacho_dj Posted September 14, 2009 Posted September 14, 2009 (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 10F700000000C9E0 F8F70000 00000000 00000000 000000000000C9F0 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 September 14, 2009 by Nacho_dj
steve10120 Posted September 14, 2009 Author Posted September 14, 2009 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 ErazerZbegin if lpBuffer = nil then Result := Cardinal(-1) else Result := Cardinal(Pointer(Cardinal(lpBuffer) -4)^) and $7FFFFFFC -4;end;procedure MemToFile(pData:Pointer; sPath:string);varhFile: 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.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now