Solved

Import Name Table

Posted on 2004-03-20
6
440 Views
Last Modified: 2010-04-05
Ive been trying different ways of getting the import table with memory mapped files and mapandload() with imagervatova()

I just want some code that gets the import name table and all its function names WHILE the process is running.

Make sure you actually test it before posting.
0
Comment
Question by:Blacksoulman
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10641678
GETTING FUNCTIONS OF DLL
How to get the list of functions exported by a Dll module.
Answer:


To get the list of functions exported by a Dll module you need to use the following functions.

MapAndLoad function in 'imagehlp.pas'.
ImageRvaToVa function in 'imagehlp.pas'.

You also need to define the following structures.
To find details about what the members of these structures mean visit the web page 'http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/msdn_peeringpe.html'

const
IMAGE_SIZEOF_SHORT_NAME            = 8;
IMAGE_NUMBEROF_DIRECTORY_ENTRIES   = 16;

  IMAGE_DATA_DIRECTORY = packed record
    VirtualAddress  : DWORD;
    Size            : DWORD;
  PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;

IMAGE_SECTION_HEADER = packed record
    Name     : packed array [0..IMAGE_SIZEOF_SHORT_NAME-1] of Char;
    PhysicalAddress : DWORD; // or VirtualSize (union);
    VirtualAddress  : DWORD;
    SizeOfRawData   : DWORD;
    PointerToRawData : DWORD;
    PointerToRelocations : DWORD;
    PointerToLinenumbers : DWORD;
    NumberOfRelocations : WORD;
    NumberOfLinenumbers : WORD;
    Characteristics : DWORD;
  end;
  PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;

  IMAGE_OPTIONAL_HEADER = packed record
   { Standard fields. }
    Magic           : WORD;
    MajorLinkerVersion : Byte;
    MinorLinkerVersion : Byte;
    SizeOfCode      : DWORD;
    SizeOfInitializedData : DWORD;
    SizeOfUninitializedData : DWORD;
    AddressOfEntryPoint : DWORD;
    BaseOfCode      : DWORD;
    BaseOfData      : DWORD;
   { NT additional fields. }
    ImageBase       : DWORD;
    SectionAlignment : DWORD;
    FileAlignment   : DWORD;
    MajorOperatingSystemVersion : WORD;
    MinorOperatingSystemVersion : WORD;
    MajorImageVersion : WORD;
    MinorImageVersion : WORD;
    MajorSubsystemVersion : WORD;
    MinorSubsystemVersion : WORD;
    Reserved1       : DWORD;
    SizeOfImage     : DWORD;
    SizeOfHeaders   : DWORD;
    CheckSum        : DWORD;
    Subsystem       : WORD;
    DllCharacteristics : WORD;
    SizeOfStackReserve : DWORD;
    SizeOfStackCommit : DWORD;
    SizeOfHeapReserve : DWORD;
    SizeOfHeapCommit : DWORD;
    LoaderFlags     : DWORD;
    NumberOfRvaAndSizes : DWORD;
    DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1]                                            of IMAGE_DATA_DIRECTORY;
  end;
  PIMAGE_OPTIONAL_HEADER = ^IMAGE_OPTIONAL_HEADER;

IMAGE_FILE_HEADER = packed record
    Machine              : WORD;
    NumberOfSections     : WORD;
    TimeDateStamp        : DWORD;
    PointerToSymbolTable : DWORD;
    NumberOfSymbols      : DWORD;
    SizeOfOptionalHeader : WORD;
    Characteristics      : WORD;
  end;
  PIMAGE_FILE_HEADER = ^IMAGE_FILE_HEADER;

IMAGE_NT_HEADERS = packed record
  Signature       : DWORD;
  FileHeader      : IMAGE_FILE_HEADER;
  OptionalHeader  : IMAGE_OPTIONAL_HEADER;
end;
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;

type LOADED_IMAGE = record
  ModuleName:pchar;//name of module
  hFile:thandle;//handle of file
  MappedAddress:pchar;// the base address of mapped file
  FileHeader:PIMAGE_NT_HEADERS;//The Header of the file.
  LastRvaSection:PIMAGE_SECTION_HEADER;
  NumberOfSections:integer;
  Sections:PIMAGE_SECTION_HEADER ;
  Characteristics:integer;
  fSystemImage:boolean;
  fDOSImage:boolean;
  Links:LIST_ENTRY;
  SizeOfImage:integer;
end;
PLOADED_IMAGE= ^LOADED_IMAGE;

here is the code

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Menus,structures,imagehlp;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Open1: TMenuItem;
    OpenDialog1: TOpenDialog;
    ListBox2: TListBox;
    procedure Open1Click(Sender: TObject);
  private
  public
   procedure DLLFuncstoList(fname:string;alistbox:tlistbox);
  end;

var
  Form1: TForm1;
implementation

{$R *.DFM}


procedure TForm1.DLLFuncstoList(fname:string;alistbox:tlistbox);
var
  fih:LOADED_IMAGE;
  pexpdir:PIMAGE_EXPORT_DIRECTORY;
  pexpnames:pdword;//pointer to list of exported fucntions
  pt1:PImageSectionHeader;
  i:integer;
  exportedfuncname:pchar;//exported function name
begin
   alistbox.items.clear;
   pt1:=nil;
   MapAndLoad(pchar(fname),pchar('#0'),@fih,true,true);//load the  
                                                 file into memory.
   pExpDir:=PIMAGE_EXPORT_DIRECTORY(fih.FileHeader.OptionalHeader.
                                    DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
   pExpDir:=PIMAGE_EXPORT_DIRECTORY(ImageRvaToVa
         (fih.FileHeader,fih.MappedAddress,DWORD(pExpDir),pt1));
   pExpNames:= pExpDir.pAddressOfNames;
   pExpNames:=PDWORD(ImageRvaToVa
       (fih.FileHeader,fih.MappedAddress,dword(pExpNames),pt1));
   pt1:=nil;
   for i:=0 to pexpdir.NumberOfNames-1 do
    begin
     exportedfuncname:=pchar(ImageRvaToVa  
       (fih.FileHeader,fih.MappedAddress,dword(pExpNames^),pt1));
     alistbox.items.add(exportedfuncname);
     inc(pexpnames);
    end;
   UnMapAndLoad(@fih);//Un load the mapped file  from memory.
end;

procedure TForm1.Open1Click(Sender: TObject);
var
begin
if opendialog1.execute = true then
  begin
   DLLFuncstoList(opendialog1.filename,listbox1);
  end;
end;


end.
 


Comments to this article
Write a new comment
 
Avoid General protection faults
    Florin Oltean (Sep 13 2000 8:53AM)

You shold better do something like :
if not MapAndLoad(pchar(fname),pchar('#0'),@fih,true,true) then Exit;

because if the call fails you will get a pretty nice GPF.
Respond

 
missing structure
    Florin Oltean (Sep 13 2000 8:32AM)

Your code is not running because you forgot to publish this structure :

IMAGE_EXPORT_DIRECTORY = packed record
  Characteristics : DWORD;
  TimeDateStamp   : DWORD;
  MajorVersion    : WORD;
  MinorVersion    : WORD;
  Name : DWORD;            
  Base : DWORD;
  NumberOfFunctions     : DWORD;
  NumberOfNames         : DWORD;
  pAddressOfFunctions   : PDWORD;
  pAddressOfNames       : PDWORD;
  pAddressOfNameOrdinals: PWORD;
end;
PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
Respond

 
suggestions
    Andreas Schmidt (Aug 24 2000 3:20AM)

please separate the opendialog from the main procedure.

Put the core of Open1Click in a own procedure:

procedure DLLFuncsToListbox(filename:TFilename; lb:TListBox);
begin
...
end;


procedure TForm1.Open1Click(Sender: TObject);
begin
  if opendialog1.execute = true then
  begin
     listbox1.items.clear;
     DLLFuncsToListbox(opendialog1.filename, listbox1);
  end;
end;
0
 

Author Comment

by:Blacksoulman
ID: 10641864
ok look at the title... "Import Name Table"  The INT is different from the exports

I can get examples of the ent anywhere on google.  And once again, for those who are going to try and answer this question, make sure you actually test the code you are going to submit.
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10641910
Hey Blacksoulman,

You might get a few people too help you out if you don't come across so beligerent.

Im listening to see how many people jump on this one.....

SHane
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 11

Expert Comment

by:robert_marquardt
ID: 10642924
The question is if you can read another EXE at all while it is running.
If so you may use the PEViewer example of the Jedi Code Library.
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 500 total points
ID: 10671453

If your asking (just want to make sure) how to get the IAT, including library and function names for the current process, then I have some code that will do this. It could be modified very easily to walk another process if needed.

Russell

ps: Im still looking at the other question, and this code is related to the answer for it.

----

usage:

var  bRepeat: Boolean;
     Entry:   TIATEntry;
begin

  Memo1.Lines.Clear;
  bRepeat:=FindFirstIAT(Entry);
  while bRepeat do
  begin
     Memo1.Lines.Add(Format('%s.%s(%p)', [Entry.lpszLib, Entry.lpszFunc, Entry.lpFuncAddr]));
     bRepeat:=FindNextIAT(Entry);
  end;

end;

----- unit source -----

unit IAT;

interface

uses
  Windows, SysUtils;

type
  PImageImportDesc        =  ^TImageImportDesc;
  TImageImportDesc        =  packed record
     FuncNameList:        DWORD;
     TimeDateStamp:       DWORD;
     ForwarderChain:      DWORD;
     Name:                DWORD;
     FirstThunk:          DWORD;
  end;

type
  PIATEntry            =  ^TIATEntry;
  TIATEntry            =  packed record
     dwValid:          Integer;
     ImageImportDesc:  PImageImportDesc;
     dwEndDesc:        DWORD;
     ImportCode:       ^Pointer;
     lpszLib:          PChar;
     lpszFunc:         PChar;
     lpFuncAddr:       Pointer;
  end;

function   FindFirstIAT(var IATEntry: TIATEntry): Boolean;
function   FindNextIAT(var IATEntry: TIATEntry): Boolean;

implementation

function CalculateEntryHash(IATEntry: TIATEntry): Integer;
begin

  result:=Integer(IATEntry.ImageImportDesc)+Integer(IATEntry.lpszLib)+
          Integer(IATEntry.lpszFunc)+Integer(IATEntry.lpFuncAddr);

end;

function NextFunctionName(lpName: PChar): PChar;
begin

  result:=StrEnd(lpName);
  while (result^ = #0) do Inc(result);

end;

function FindFirstIAT(var IATEntry: TIATEntry): Boolean;
var  ImageNTHeaders:   PImageNtHeaders;
     ImageDosHeader:   PImageDosHeader;
begin

  // Clear the IATEntry first
  ZeroMemory(@IATEntry, SizeOf(IATEntry));

  // Get start of PE32 header and NT header
  ImageDosHeader:=Pointer(GetModuleHandle(nil));
  ImageNTHeaders:=Pointer(Integer(ImageDosHeader)+ImageDosHeader^._lfanew);

  // Set default result
  result:=False;

  // Validation
  if Assigned(ImageNTHeaders) then
  begin
     // Get import entry and ending point for imports
     with ImageNTHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] do
     begin
        IATEntry.ImageImportDesc:=Pointer(DWORD(ImageDosHeader)+VirtualAddress);
        IATEntry.dwEndDesc:=VirtualAddress+Size;
     end;
     // Check import entry
     if Assigned(IATEntry.ImageImportDesc) then
     begin
        // Last item in the entry will be null
        if (IATEntry.ImageImportDesc^.Name > 0) then
        begin
           // Check offsets
           if (IATEntry.ImageImportDesc^.FirstThunk <= IATEntry.dwEndDesc) then
           begin
              // Check the first thunk address
              if (IATEntry.ImageImportDesc^.FirstThunk > 0) then
              begin
                 // Get the library name and the IAT
                 IATEntry.lpszLib:=PChar(DWORD(ImageDosHeader)+IATEntry.ImageImportDesc^.Name);
                 IATEntry.ImportCode:=Pointer(DWORD(ImageDosHeader)+IATEntry.ImageImportDesc^.FirstThunk);
                 if Assigned(IATEntry.ImportCode^) then
                 begin
                    // Get the first function
                    IATEntry.lpszFunc:=NextFunctionName(IATEntry.lpszLib);
                    IATEntry.lpFuncAddr:=IATEntry.ImportCode^;
                    // Increment next
                    Inc(IATEntry.ImportCode);
                    // Validate the header
                    IATEntry.dwValid:=CalculateEntryHash(IATEntry);
                    // Success
                    result:=True;
                 end;
              end;
           end;
        end;
     end;
  end;

end;

function FindNextIAT(var IATEntry: TIATEntry): Boolean;
begin

  // Set default result
  result:=False;

  // Validate settings
  if (IATEntry.dwValid <> 0) and (IATEntry.dwValid = CalculateEntryHash(IATEntry)) then
  begin
     // Check to see if we can enumerate the next function entry
     if Assigned(IATEntry.ImportCode^) then
     begin
        // Get the next function
        IATEntry.lpszFunc:=NextFunctionName(IATEntry.lpszFunc);
        IATEntry.lpFuncAddr:=IATEntry.ImportCode^;
        // Increment next
        Inc(IATEntry.ImportCode);
        // Validate the header
        IATEntry.dwValid:=CalculateEntryHash(IATEntry);
        // Success
        result:=True;
     end
     else
     begin
        // Need to check the next library entry (if there is one)
        Inc(IATEntry.ImageImportDesc);
        // Last item in the entry will be null
        if (IATEntry.ImageImportDesc^.Name > 0) then
        begin
           // Check offsets
           if (IATEntry.ImageImportDesc^.FirstThunk <= IATEntry.dwEndDesc) then
           begin
              // Check the first thunk address
              if (IATEntry.ImageImportDesc^.FirstThunk > 0) then
              begin
                 // Get the library name and the IAT
                 IATEntry.lpszLib:=PChar(GetModuleHandle(nil)+IATEntry.ImageImportDesc^.Name);
                 IATEntry.ImportCode:=Pointer(GetModuleHandle(nil)+IATEntry.ImageImportDesc^.FirstThunk);
                 if Assigned(IATEntry.ImportCode^) then
                 begin
                    // Get the first function
                    IATEntry.lpszFunc:=NextFunctionName(IATEntry.lpszLib);
                    IATEntry.lpFuncAddr:=IATEntry.ImportCode^;
                    // Increment next
                    Inc(IATEntry.ImportCode);
                    // Validate the header
                    IATEntry.dwValid:=CalculateEntryHash(IATEntry);
                    // Success
                    result:=True;
                 end;
              end;
           end;
        end;
     end;
  end;

end;

end.
0
 

Author Comment

by:Blacksoulman
ID: 10673325
i was actually asking to just get the import function names.  I heard the PE loader patches the Import Name Table with Virtual addresses(IAT) and that you had to convert them.
Eh anyway all i needed was this nifty function:

function NextFunctionName(lpName: PChar): PChar;
begin

  result:=StrEnd(lpName);
  while (result^ = #0) do Inc(result);

end;

Once again, thanks.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question