Solved

Import Name Table

Posted on 2004-03-20
6
426 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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

744 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now