Solved

Import Name Table

Posted on 2004-03-20
6
432 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
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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
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

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

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

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
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…

772 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