We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Mar 16, 2010 3:52:13 PM
{
Unit: uAddImport
Author: steve10120
Description: Add imports to a PE file.
Website: ic0de.org
History: First try
Added multiple import support.
}
unit uAddImport;//steve10120interfaceuses 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.Usage:
var Imports: TImports;begin SetLength(Imports.Funcs, 2); Imports.szLibName := 'urlmon.dll'; Imports.Funcs[0] := 'URLDownloadToFileA'; Imports.Funcs[1] := 'URLDownloadToFileW'; AddImport('Hello.exe', Imports);end.