| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- unit CnSMRPEUtils;
- interface
- {$I CnWizards.inc}
- uses
- SysUtils, Windows, Classes;
- procedure GetImportTable(ss: TStrings; const PEFile: String);
- procedure GetDelayImportTable(ss: TStrings; const PEFile: String);
- procedure GetExportTable(ss: TStrings; const PEFile: String);
- implementation
- {$RANGECHECKS OFF}
- {$IFDEF DELPHI7_UP}
- {$WARN SYMBOL_PLATFORM OFF}
- {$WARN UNIT_PLATFORM OFF}
- {$ENDIF}
- const
- IMAGE_ORDINAL_FLAG = DWORD($80000000);
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11;
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13;
- type
- PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME;
- {$EXTERNALSYM PIMAGE_IMPORT_BY_NAME}
- _IMAGE_IMPORT_BY_NAME = record
- Hint: Word;
- Name: array [0..0] of Char;
- end;
- {$EXTERNALSYM _IMAGE_IMPORT_BY_NAME}
- IMAGE_IMPORT_BY_NAME = _IMAGE_IMPORT_BY_NAME;
- {$EXTERNALSYM IMAGE_IMPORT_BY_NAME}
- TImageImportByName = IMAGE_IMPORT_BY_NAME;
- PImageImportByName = PIMAGE_IMPORT_BY_NAME;
- PIMAGE_THUNK_DATA32 = ^IMAGE_THUNK_DATA32;
- {$EXTERNALSYM PIMAGE_THUNK_DATA32}
- _IMAGE_THUNK_DATA32 = record
- case Integer of
- 0: (ForwarderString: PBYTE);
- 1: (Function_: PDWORD);
- 2: (Ordinal: DWORD);
- 3: (AddressOfData: PIMAGE_IMPORT_BY_NAME);
- end;
- {$EXTERNALSYM _IMAGE_THUNK_DATA32}
- IMAGE_THUNK_DATA32 = _IMAGE_THUNK_DATA32;
- {$EXTERNALSYM IMAGE_THUNK_DATA32}
- TImageThunkData32 = IMAGE_THUNK_DATA32;
- PImageThunkData32 = PIMAGE_THUNK_DATA32;
- TIIDUnion = record
- case Integer of
- 0: (Characteristics: DWORD);
- 1: (OriginalFirstThunk: PIMAGE_THUNK_DATA32);
- end;
- PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
- {$EXTERNALSYM PIMAGE_IMPORT_DESCRIPTOR}
- _IMAGE_IMPORT_DESCRIPTOR = record
- Union: TIIDUnion;
- TimeDateStamp: DWORD;
- ForwarderChain: DWORD;
- Name: DWORD;
- FirstThunk: PIMAGE_THUNK_DATA32;
- end;
- {$EXTERNALSYM _IMAGE_IMPORT_DESCRIPTOR}
- IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;
- {$EXTERNALSYM IMAGE_IMPORT_DESCRIPTOR}
- TImageImportDescriptor = IMAGE_IMPORT_DESCRIPTOR;
- PImageImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR;
- {$EXTERNALSYM ImgDelayDescr}
- ImgDelayDescr = packed record
- grAttrs: DWORD;
- szName: DWORD;
- phmod: PDWORD;
- pIAT: TImageThunkData32;
- pINT: TImageThunkData32;
- pBoundIAT: TImageThunkData32;
- pUnloadIAT: TImageThunkData32;
- dwTimeStamp: DWORD;
- end;
- TImgDelayDescr = ImgDelayDescr;
- PImgDelayDescr = ^ImgDelayDescr;
- PloadedImage = ^TLoadedImage;
- {$EXTERNALSYM _LOADED_IMAGE}
- _LOADED_IMAGE = record
- ModuleName: LPSTR;
- hFile: THandle;
- MappedAddress: PChar;
- FileHeader: PImageNtHeaders;
- LastRvaSection: PImageSectionHeader;
- NumberOfSections: ULONG;
- Sections: PImageSectionHeader;
- Characteristics: ULONG;
- fSystemImage: ByteBool;
- fDOSImage: ByteBool;
- Links: TListEntry;
- SizeOfImage: ULONG;
- end;
- {$EXTERNALSYM LOADED_IMAGE}
- LOADED_IMAGE = _LOADED_IMAGE;
- LoadedImage = _LOADED_IMAGE;
- TLoadedImage = _Loaded_IMAGE;
- type
- TFWOrdinalData = record
- FuncName: ShortString;
- Ordinal: DWORD;
- Addr: String[10];
- end;
- TFWOrdinalDataArray = array of TFWOrdinalData;
- var
- OrdinalData: TFWOrdinalDataArray;
- function MapAndLoad(ImageName, DllPath: LPSTR; LoadedImage: PLoadedImage;
- DotDll, ReadOnly: Bool): Bool; stdcall; external 'Imagehlp.dll';
- function UnMapAndLoad(LoadedImage: PLoadedImage): Bool; stdcall;
- external 'Imagehlp.dll';
- function FieldOffset(const Struc; const Field): Cardinal;
- begin
- Result := Cardinal(@Field) - Cardinal(@Struc);
- end;
- function IMAGE_FIRST_SECTION(NtHeader: PImageNtHeaders): PImageSectionHeader;
- begin
- Result := PImageSectionHeader(Cardinal(NtHeader) +
- FieldOffset(NtHeader^, NtHeader^.OptionalHeader) +
- NtHeader^.FileHeader.SizeOfOptionalHeader);
- end;
- function ImageRvaToSection(NtHeaders: PImageNtHeaders; Base: Pointer;
- Rva: ULONG): PImageSectionHeader;
- var
- NtSection: PImageSectionHeader;
- I: Integer;
- begin
- Result := nil;
- NtSection := IMAGE_FIRST_SECTION(NtHeaders);
- for I := 0 to NtHeaders^.FileHeader.NumberOfSections - 1 do
- if (Rva >= NtSection.VirtualAddress) and
- (Rva < NtSection.VirtualAddress + NtSection.SizeOfRawData) then
- begin
- Result := NtSection;
- Exit;
- end
- else
- Inc(NtSection);
- end;
- function ImageRvaToVa(NtHeaders: PImageNtHeaders; Base: Pointer;
- Rva: ULONG; var LastRvaSection: PImageSectionHeader): Pointer;
- var
- NtSection: PImageSectionHeader;
- begin
- Result := nil;
- NtSection := LastRvaSection;
- if (LastRvaSection = nil) or (Rva < NtSection^.VirtualAddress) or
- (Rva < NtSection^.VirtualAddress + NtSection^.SizeOfRawData) then
- NtSection := ImageRvaToSection(NtHeaders, Base, Rva);
- if NtSection = nil then Exit;
- if LastRvaSection <> nil then
- LastRvaSection := NtSection;
- Result := Pointer(DWORD(Base) + (Rva - NtSection^.VirtualAddress) +
- NtSection^.PointerToRawData);
- end;
- function ImageDirectoryEntryToData(Base: Pointer; MappedAsImage: ByteBool;
- DirectoryEntry: Word; var Size: ULONG): Pointer;
- const
- IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10B;
- IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20B;
- IMAGE_ROM_OPTIONAL_HDR_MAGIC = $107;
- var
- DOSHeader: PImageDosHeader;
- NTHeader: PImageNtHeaders;
- FileHeader: TImageFileHeader;
- NtSection: PImageSectionHeader;
- OptionalHeader: TImageOptionalHeader;
- DirectoryAddress: DWORD;
- I: Integer;
- begin
- Result := nil;
- if (DWORD(Base) and 1) = 1 then
- Base := Pointer((DWORD(Base) and not 1));
- DOSHeader := PImageDosHeader(Base);
- if IsBadReadPtr(Pointer(Base), SizeOf(TImageNtHeaders)) then Exit;
- if (DOSHeader^.e_magic <> IMAGE_DOS_SIGNATURE) then Exit;
- NTHeader := PImageNtHeaders(DWORD(DOSHeader) + DWORD(DOSHeader^._lfanew));
- if NTHeader^.Signature <> IMAGE_NT_SIGNATURE then Exit;
- FileHeader := NTHeader^.FileHeader;
- if FileHeader.Machine <> IMAGE_FILE_MACHINE_I386 then Exit;
- OptionalHeader := NTHeader^.OptionalHeader;
- if OptionalHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC then Exit;
- if DirectoryEntry >= OptionalHeader.NumberOfRvaAndSizes then
- begin
- Size := 0;
- Exit;
- end;
- DirectoryAddress :=
- OptionalHeader.DataDirectory[DirectoryEntry].VirtualAddress;
- if DirectoryAddress = 0 then
- begin
- Size := 0;
- Exit;
- end;
- Size := OptionalHeader.DataDirectory[DirectoryEntry].Size;
- if MappedAsImage and (DirectoryAddress < OptionalHeader.SizeOfHeaders) then
- begin
- Result := Pointer(DWORD(Base) + DirectoryAddress);
- Exit;
- end;
- NtSection := ImageRvaToSection(NTHeader, Base, DirectoryAddress);
- if NtSection = nil then
- begin
- Size := 0;
- Exit;
- end;
- for I := 0 to FileHeader.NumberOfSections - 1 do
- if (DirectoryAddress >= NtSection^.VirtualAddress) and
- (DirectoryAddress < NtSection^.VirtualAddress + NtSection^.SizeOfRawData) then
- begin
- Result := Pointer(DWORD(Base) +
- (DirectoryAddress - NtSection^.VirtualAddress) + NtSection^.PointerToRawData);
- Break;
- end
- else
- Inc(NtSection);
- end;
- procedure MapAndLoadModuleForReadOrdinalFuncName(const ModuleName: String);
- type
- PDWORDArray = ^TDWORDArray;
- TDWORDArray = array [0..MaxInt div SizeOf(DWORD) - 1] of DWORD;
- var
- liImageInfo: LoadedImage;
- pExportDirectory: PImageExportDirectory;
- nDirSize: Cardinal;
- pDummy: PImageSectionHeader;
- I: Cardinal;
- pNameRVAs: PDWORDArray;
- FuncName, FuncAddr: String;
- Ordinal: PWORD;
- begin
- SetLength(OrdinalData, 0);
- if MapAndLoad(PAnsiChar(AnsiString(ModuleName)), nil, @liImageInfo, True, True) then
- begin
- try
- pExportDirectory := ImageDirectoryEntryToData(liImageInfo.MappedAddress,
- False, IMAGE_DIRECTORY_ENTRY_EXPORT, nDirSize);
- if (pExportDirectory <> nil) then
- begin
- pDummy := nil;
- pNameRVAs := ImageRvaToVa(liImageInfo.FileHeader,
- liImageInfo.MappedAddress,
- DWORD(pExportDirectory^.AddressOfNames), pDummy);
- pDummy := nil;
- Ordinal := ImageRvaToVa(liImageInfo.FileHeader,
- liImageInfo.MappedAddress,
- DWORD(pExportDirectory^.AddressOfNameOrdinals), pDummy);
-
- for I := 0 to pExportDirectory^.NumberOfNames - 1 do
- begin
- SetLength(OrdinalData, Length(OrdinalData) + 1);
-
- pDummy := nil;
- FuncName := PChar(ImageRvaToVa(liImageInfo.FileHeader,
- liImageInfo.MappedAddress, pNameRVAs^[i], pDummy));
- FuncAddr := PChar('0x' + IntToHex(Integer(pNameRVAs^[I]), 8));
-
- OrdinalData[Length(OrdinalData) - 1].FuncName := FuncName;
- OrdinalData[Length(OrdinalData) - 1].Addr := FuncAddr;
- OrdinalData[Length(OrdinalData) - 1].Ordinal := Ordinal^ + pExportDirectory^.Base;
- Inc(Ordinal);
- end;
- end;
- finally
- UnMapAndLoad(@liImageInfo);
- end;
- end;
- end;
- function ReadOrdinalFuncName(const Ordinal: DWORD): String;
- var
- I: Integer;
- begin
- Result := '';
- for I := 0 to Length(OrdinalData) - 1 do
- if OrdinalData[I].Ordinal = Ordinal then
- begin
- Result := OrdinalData[I].FuncName;
- Break;
- end;
- end;
- function ReadOrdinalFuncAddr(const Ordinal: DWORD): String;
- var
- I: Integer;
- begin
- Result := '';
- for I := 0 to Length(OrdinalData) - 1 do
- if OrdinalData[I].Ordinal = Ordinal then
- begin
- Result := OrdinalData[I].Addr;
- Break;
- end;
- end;
- procedure GetImportTable(ss: TStrings; const PEFile: String);
- var
- ImageInfo: LOADED_IMAGE;
- DirSize: Cardinal;
- pDummy: PImageSectionHeader;
- Image: PIMAGE_IMPORT_DESCRIPTOR;
- ModuleName: PAnsiChar;
- Thunk: PImageThunkData32;
- begin
- ss.BeginUpdate;
- try
- if MapAndLoad(PAnsiChar(AnsiString(PEFile)), nil, @ImageInfo, True, True) then
- begin
- try
- Image := ImageDirectoryEntryToData(ImageInfo.MappedAddress,
- False, IMAGE_DIRECTORY_ENTRY_IMPORT, DirSize);
- if (Image <> nil) then
- begin
- while Image^.Name <> 0 do
- begin
- pDummy := nil;
- ModuleName := ImageRvaToVa(ImageInfo.FileHeader,
- ImageInfo.MappedAddress, Image^.Name, pDummy);
- ss.Add(ModuleName);
- if Image^.Union.OriginalFirstThunk <> nil then
- Thunk := PImageThunkData32(ImageRvaToVa(ImageInfo.FileHeader,
- ImageInfo.MappedAddress, Image^.Union.Characteristics, pDummy))
- else
- Thunk := PImageThunkData32(ImageRvaToVa(ImageInfo.FileHeader,
- ImageInfo.MappedAddress, DWORD(Image^.FirstThunk), pDummy));
- if Thunk <> nil then
- try
- while Thunk^.Function_ <> nil do
- begin
- if (DWORD(Thunk^.Function_) and IMAGE_ORDINAL_FLAG) = IMAGE_ORDINAL_FLAG then
- begin
- if Length(OrdinalData) = 0 then
- MapAndLoadModuleForReadOrdinalFuncName(ModuleName);
- end;
- ss.Add(ModuleName);
- Inc(Thunk);
- end;
- Inc(Image);
- finally
- SetLength(OrdinalData, 0);
- end;
- end;
- end;
- finally
- UnMapAndLoad(@ImageInfo);
- end;
- end;
- finally
- ss.EndUpdate;
- end;
- end;
- procedure GetDelayImportTable(ss: TStrings; const PEFile: String);
- var
- ImageInfo: LOADED_IMAGE;
- DirSize: Cardinal;
- Image: PImgDelayDescr;
- ModuleName: PAnsiChar;
- Thunk: PImageThunkData32;
- function RvaToVaWithAmendment(Value: DWORD): Pointer;
- var
- pDummy: PImageSectionHeader;
- begin
- if (Value > ImageInfo.SizeOfImage) and
- (Value > ImageInfo.FileHeader^.OptionalHeader.ImageBase) then
- Dec(Value, ImageInfo.FileHeader^.OptionalHeader.ImageBase);
- pDummy := nil;
- Result := ImageRvaToVa(ImageInfo.FileHeader, ImageInfo.MappedAddress,
- Value, pDummy);
- end;
- begin
- ss.BeginUpdate;
- try
- if MapAndLoad(PAnsiChar(AnsiString(PEFile)), nil, @ImageInfo, True, True) then
- begin
- try
- Image := ImageDirectoryEntryToData(ImageInfo.MappedAddress,
- False, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, DirSize);
- if (Image <> nil) then
- begin
- while Image^.szName <> 0 do
- begin
- ModuleName := RvaToVaWithAmendment(DWORD(Image^.szName));
- ss.Add(ModuleName);
- Thunk := PImageThunkData32(RvaToVaWithAmendment(DWORD(Image^.pINT.AddressOfData)));
- if Thunk <> nil then
- try
- while Thunk^.Function_ <> nil do
- begin
- if (DWORD(Thunk^.Function_) and IMAGE_ORDINAL_FLAG) = IMAGE_ORDINAL_FLAG then
- begin
- if Length(OrdinalData) = 0 then
- MapAndLoadModuleForReadOrdinalFuncName(ModuleName);
- end;
- ss.Add(ModuleName);
- Inc(Thunk);
- end;
- Inc(Image);
- finally
- SetLength(OrdinalData, 0);
- end;
- end;
- end;
- finally
- UnMapAndLoad(@ImageInfo);
- end;
- end;
- finally
- ss.EndUpdate;
- end;
- end;
- procedure GetExportTable(ss: TStrings; const PEFile: String);
- type
- PDWORDArray = ^TDWORDArray;
- TDWORDArray = array [0..MaxInt div SizeOf(DWORD) - 1] of DWORD;
- var
- liImageInfo: LoadedImage;
- pExportDirectory: PImageExportDirectory;
- nDirSize: Cardinal;
- pDummy: PImageSectionHeader;
- I: Integer;
- pNameRVAs: PDWORDArray;
- FuncName, FuncAddr: String;
- begin
- ss.BeginUpdate;
- try
- if MapAndLoad(PAnsiChar(AnsiString(PEFile)), nil, @liImageInfo, True, True) then
- begin
- try
- pExportDirectory := ImageDirectoryEntryToData(liImageInfo.MappedAddress,
- False, IMAGE_DIRECTORY_ENTRY_EXPORT, nDirSize);
- if (pExportDirectory <> nil) then
- begin
- pDummy := nil;
- pNameRVAs := ImageRvaToVa(liImageInfo.FileHeader,
- liImageInfo.MappedAddress,
- DWORD(pExportDirectory^.AddressOfNames), pDummy);
-
- for I := 0 to pExportDirectory^.NumberOfNames - 1 do
- begin
- pDummy := nil;
- FuncName := PChar(ImageRvaToVa(liImageInfo.FileHeader,
- liImageInfo.MappedAddress, pNameRVAs^[i], pDummy));
- FuncAddr := PChar('0x' + IntToHex(Integer(pNameRVAs^[I]), 8));
- ss.Add(FuncName);
- end;
- end;
- finally
- UnMapAndLoad(@liImageInfo);
- end;
- end;
- finally
- ss.EndUpdate;
- end;
- end;
- end.
|