We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Jun 29, 2010 2:48:30 AM
When the PE loader runs a program, it loads the associated DLLs into the process address space. It then extracts information about the import functions from the main program. It uses the information to search the DLLs for the addresses of the functions to be patched into the main program. The place in the DLLs where the PE loader looks for the addresses of the functions is the export table.
http://win32assembly.online.fr/pe-tut7.html
This unit, written by steve10120 of ic0de.org, enables you to add exports to a PE.
unit uAddExports;interfaceuses Windows;type TRVAArray = array of DWORD; TStringArray = array of string; TExportRec = packed record szDLLName: string; Entries: TStringArray; end;function AddPEExports(szFilePath:string; szDestFile:string; ExportsData:TExportRec; FunctionAddrs:TRVAArray):Boolean;implementationfunction 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;function GetStringSizes(Strings:TStringArray):DWORD;var i: DWORD;begin Result := 0; for i := 0 to Length(Strings) - 1 do Inc(Result, Length(Strings[i]));end;function AddPEExports(szFilePath:string; szDestFile:string; ExportsData:TExportRec; FunctionAddrs:TRVAArray):Boolean;var IDH: TImageDosHeader; INH: TImageNtHeaders; ISH: TImageSectionHeader; IED: TImageExportDirectory; dwBase: DWORD; pTemp: Pointer; dwTemp: DWORD; dwPos: DWORD; RVAs: TRVAArray; i: WORD; dwNumberOfEntries: DWORD; dwSizeOfStrings: DWORD; dwSizeOfData: DWORD; dwActualSize: DWORD; wTemp: WORD; pNamesBuff: Pointer; pNumbsBuff: Pointer; pAddrsBuff: Pointer; hFile: DWORD; dwNull: DWORD;begin Result := FALSE; CopyFile(PChar(szFilePath), PChar(szDestFile), FALSE); hFile := CreateFile(PChar(szDestFile), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hFile <> INVALID_HANDLE_VALUE then begin SetFilePointer(hFile, 0, nil, FILE_BEGIN); ReadFile(hFile, IDH, 64, dwNull, nil); if IDH.e_magic = IMAGE_DOS_SIGNATURE then begin SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN); ReadFile(hFile, INH, 248, dwNull, nil); if INH.Signature = IMAGE_NT_SIGNATURE then begin SetFilePointer(hFile, IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40, nil, FILE_BEGIN); ReadFile(hFile, ISH, 40, dwNull, nil); dwBase := Align(ISH.VirtualAddress + ISH.Misc.VirtualSize, INH.OptionalHeader.FileAlignment); dwNumberOfEntries := Length(ExportsData.Entries); dwSizeOfStrings := GetStringSizes(ExportsData.Entries); dwActualSize := SizeOf(IED) + dwSizeOfStrings + (dwNumberOfEntries * 4) + (dwNumberOfEntries * 2) + (dwNumberOfEntries * 4) + Length(ExportsData.szDLLName); dwSizeOfData := Align(dwActualSize, INH.OptionalHeader.FileAlignment); ZeroMemory(@IED, SizeOf(IED)); dwPos := 0; IED.Base := 1; IED.MinorVersion := 1; IED.MajorVersion := 0; GetMem(pTemp, dwSizeOfData); ZeroMemory(pTemp, dwSizeOfData); dwTemp := Length(ExportsData.szDLLName); CopyMemory(pTemp, @ExportsData.szDLLName[1], dwTemp); IED.Name := dwBase; Inc(dwBase, dwTemp); Inc(dwPos, dwTemp); SetLength(RVAs, dwNumberOfEntries); for i := 0 to Length(ExportsData.Entries) - 1 do begin dwTemp := Length(ExportsData.Entries[i]); CopyMemory(Pointer(DWORD(pTemp) + dwPos), @ExportsData.Entries[i][1], dwTemp); RVAs[i] := dwBase; Inc(dwBase, dwTemp); Inc(dwPos, dwTemp); end; IED.NumberOfNames := dwNumberOfEntries; IED.NumberOfFunctions := dwNumberOfEntries; IED.AddressOfNames := Pointer(dwBase); GetMem(pNamesBuff, 4 * dwNumberOfEntries); dwTemp := 0; for i := 0 to Length(ExportsData.Entries) - 1 do begin CopyMemory(Pointer(DWORD(pNamesBuff) + dwTemp), @RVAs[i], 4); Inc(dwTemp, 4); end; GetMem(pNumbsBuff, 2 * dwNumberOfEntries); dwTemp := 0; for i := 0 to Length(ExportsData.Entries) - 1 do begin wTemp := i; CopyMemory(Pointer(DWORD(pNumbsBuff) + dwTemp), @wTemp, 2); Inc(dwTemp, 2); end; GetMem(pAddrsBuff, 4 * dwNumberOfEntries); dwTemp := 0; for i := 0 to Length(ExportsData.Entries) - 1 do begin CopyMemory(Pointer(DWORD(pAddrsBuff) + dwTemp), @FunctionAddrs[i], 4); Inc(dwTemp, 4); end; CopyMemory(Pointer(DWORD(pTemp) + dwPos), pNamesBuff, 4 * dwNumberOfEntries); Inc(dwBase, 4 * dwNumberOfEntries); Inc(dwPos, 4 * dwNumberOfEntries); IED.AddressOfNameOrdinals := Pointer(dwBase); CopyMemory(Pointer(DWORD(pTemp) + dwPos), pNumbsBuff, 2 * dwNumberOfEntries); Inc(dwBase, 2 * dwNumberOfEntries); Inc(dwPos, 2 * dwNumberOfEntries); IED.AddressOfFunctions := Pointer(dwBase); CopyMemory(Pointer(DWORD(pTemp) + dwPos), pAddrsBuff, 4 * dwNumberOfEntries); Inc(dwBase, 4 * dwNumberOfEntries); Inc(dwPos, 4 * dwNumberOfEntries); CopyMemory(Pointer(DWORD(pTemp) + dwPos), @IED, SizeOf(IED)); INH.OptionalHeader.DataDirectory[0].VirtualAddress := dwBase; INH.OptionalHeader.DataDirectory[0].Size := dwActualSize; SetFilePointer(hFile, 0, nil, FILE_END); WriteFile(hFile, pTemp^, dwSizeOfData, dwNull, nil); ISH.SizeOfRawData := Align(ISH.SizeOfRawData + dwSizeOfData, INH.OptionalHeader.FileAlignment); ISH.Misc.VirtualSize := Align(ISH.Misc.VirtualSize + dwSizeOfData, INH.OptionalHeader.SectionAlignment); INH.OptionalHeader.SizeOfImage := Align(ISH.VirtualAddress + ISH.Misc.VirtualSize, INH.OptionalHeader.SectionAlignment); SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN); WriteFile(hFile, INH, 248, dwNull, nil); SetFilePointer(hFile, IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40, nil, FILE_BEGIN); WriteFile(hFile, ISH, 40, dwNull, nil); FreeMem(pTemp); FreeMem(pNamesBuff); FreeMem(pNumbsBuff); FreeMem(pAddrsBuff); Result := TRUE; end; end; CloseHandle(hFile); end;end;end.