For CodedK and 8080Diver, but Delphi experts can comment too

Continuetion of the discussion, since I've Awarded and close a previous link.

The last comment of 8080Diver:
8080_Diver:

systan,

Your last request closely resembles the following question (which I defy you to answer Yes or No):

Are you still molesting children?

Are you saying that you are writing the Wininit.dll and you are puttinng a string in the code at the point of the InternetOpenA function?

Or, are you saying that "there exists a WinInit.dll that exports the InternetOpenA function"?

Also, is the 00015912h a relative address or an absolute address?

Finally, are you analyzing this DLL as it resides in memory or as a binary data file that you read and analyze without loading in the usual fashion?

On the other hand, if you know that 00015912h is the address of the InternetOpen entry point, why do you need to search for it ?

Finally, your "code structure" is psuode-Delphi code but could not be written that way.  You would need to find the position of '00015912' within the block of binary data that you have read from the WinInit.dll file but you would need to read blocks with an overlap of  least 8 characters (so that you don't read in 00015 in one block and 912 in the next one.

Given that you are reading WinInit.dll as a data file and that you have the 00015912 as a text string within the file and that you are handling the block reads in an appropriate manner, then yes, that would be one technique for finding the entry point.  Although, that technique cannot be generalized because you cannot guarantee that all DLL's will provide such convenient markers. ;-)
LVL 14
systanAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CodedKSenior Software EngineerCommented:
Hi Systan.

What i know until now and correct me if i am wrong is that you want to get the list of the
procedures & functions that an application is using.

I believe that this started from the fact that someone can get the list of exported functions from a dynamic link library.
Sources from that can be found
(several authors :Dmitry Streblechenko, Peter Below, Steve Turner, Andrey ANM and others).

But an executable application does not work like that. It doesn't share the same structure.
PE Format for windows is different. A PE file consists of a number of headers and sections that tell the dynamic linker how to map the file into memory. An executable image consists of several different regions, each of which require different memory protection, so the start of each section must be aligned to a page boundary.

For instance, typically the .text section (which holds program code) is mapped as execute/readonly, and the .data section (holding global variables) is mapped as no-execute/readwrite. Part of the job of the dynamic linker is to map each section to memory individually and assign the correct permissions to the resulting regions, according to the instructions found in the headers.

Starting from Delphi, when you write code for an application Delphi translates it to machine code.
That coded is stored in the .text section.
Now when Delphi has compiled the application and an ".exe" is produced, without having the
source the only human readable code you can get in your hands is Assembly code.

For this, a Disassembler takes control to deliver an output for you.
A combination of disassembler & decompiler takes this output and "tries" with heuristic analysis to level up this output producing a high level language like structure.
There are Decompilers for Delphi. Search for DeDe aka Delphi Decompiler. And others too.

For executables that was written in C, C#, .Net, Java there are also decompilers in the internet and there are free.

Now if you download one you will immediately understand that its not a small project to :
Disassembly & Decompile and do heuristics to get the procedures for one language.
Imagine for every language.

One thing that you can do that will be by far the best solution is :
Download this : http://home.roadrunner.com/~rllibby/downloads/disasm32.zip
This is Delphi Disassembler Conversion of libdisasm 2.0. It was written by Russell.
Write you own disassembler. And see where that goes.

Another thing you can do is hook every api known and launch an application and check the apis that this application uses and the parameters that the application passes.
But this will only catch API calls.

Another thing would be combine my first solution with a Delphi map file. But this is useless if you are trying to do this without having the source. And if you have the source there is no reason to do that from the beginning.

Hope this helps.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
systanAuthor Commented:
Since I have close and awarded points, and again ask a question after that, this is the last question I ask when was closed.
//---------------------
Ok, a followup question, one last answer please, just YES or NO, no following sentence

if its hard to get the function name inside the application(.exe), what if I assigned or PUT the entry_point or the address of the function that I am searching for:
like this:

Wininet.DLL exports TAble:
...
00015912h            264     InternetOpenA
00013491h            229     InternetConnectA
...

note:
00015912  (the address/entrypoint of InternetOpen in Wininet.DLL) I will put it in my code as string

code structure:
if "00015912" is found at "InternetEXE.exe" then
begin
showmessage('Internet open is found')
end;

iS this a possible technique?
//---------------------

Answered by: 8080Diver on the question body I posted.

Continuetion:

@8080Diver, hi
>Are you still molesting children?
NO, I'm not trying to do anything harm, honestly.

>>and you are puttinng a string in the code at the point of the InternetOpenA function?
YES, not only "InternetOpen"

>Or, are you saying that "there exists a WinInit.dll that exports the InternetOpenA function"?
NO, I'm not looking for a .DLL, I am looking for the Executable Application that has not been launch that contains a function "InternetOpen" or any other functions the application is using.

>Also, is the 00015912h a relative address or an absolute address?
YES, its the relative address
I don't know about absolute address, but if is usable to get the functions used, YES

>Finally, are you analyzing this DLL as it resides in memory or as a binary data file that you read and analyze without loading in the usual fashion?
NO, I'm not analyzing the DLL,
YES, as a binary data file that to be read and analyze without loading in the usual fashion

>On the other hand, if you know that 00015912h is the address of the InternetOpen entry point, why do you need to search for it ?
I'm not really after the "InternetOpen" , I'm only searching it because it is the only function that I was remind to use to search, later on if I know the code, I will search for other functions.
And I just want to let you know that I am not making any BAD application, why do i? instead of BAD, why not making it for a good use later on.
I'm not making a <virus>. why should i, it doesn't point me to the right direction.
As I know many other e-e user's manage to ask question that is very clear that there using it for making a <virus>. I have observed that, and I know you have too.
To be frank again, I'm not using it to build a <virus>.

>Finally, your "code structure" is psuode-Delphi code but could not be written that way.  You would need to find the position of '00015912' within the block of binary data that you have read from the WinInit.dll file but you would need to read blocks with an overlap of  least 8 characters (so that you don't read in 00015 in one block and 912 in the next one.
OK

>Given that you are reading WinInit.dll as a data file and that you have the 00015912 as a text string within the file and that you are handling the block reads in an appropriate manner, then yes, that would be one technique for finding the entry point.  Although, that technique cannot be generalized because you cannot guarantee that all DLL's will provide such convenient markers. ;-)
NO, I'm not reading the DLL as a data file, I'm reading the Executable,  But if is needed to read the DLL because the Executable(.exe) points the function to the DLL, then i will.

Thanks 8080Diver

@CodedK,
I'll post an answer to your questions and ideas, Later, lol, I have to read all the comments, enable for us to communicate well.
Ok, let me finish my dinner. lol
Thank you very much.
0
systanAuthor Commented:
OK, iM back,
@codedK
>is that you want to get the list of the
procedures & functions that an application is using.
NO,
you mean like this:
procedure somepro;
begin
writeln('hello');
end;
function anum:byte;
begin
result:=1;
end;
//So, I read the .exe and determined somepro? anum? NO, not that

But this one:
procedure opennet;
var
  hSession: HINTERNET;
begin
hSession := InternetOpen('MyApp', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
end; //sample only
//////// So, I will determine if Executable is using <"InternetOpen">
That is want I want.

Another sample:
procedure findafile;
var
  searchResult : TSearchRec;   ///////////////// if possible that knowing the Executable is using <"TSearchRec"> also. (if possible also)
begin
  if FindFirst('Unit1.d*', faAnyFile, searchResult) = 0 then
  begin
    repeat
    //sample only
    until FindNext(searchResult) <> 0;
    FindClose(searchResult);
  end;
end;
//////// So, I will determined if Executable is using the function <"FindFrist"> and then the Executable is using also <"FindClose">


OK, I have read your comments
>Another thing you can do is hook every api known and launch an application and check the apis that this application uses and the parameters that the application passes.
But this will only catch API calls.

OK, whats that mean? "will only catch API calls"
If this could make a solution so why not.

>Another thing would be combine my first solution with a Delphi map file.
OK, if is possible, then I should try.

>And if you have the source there is no reason to do that from the beginning.
Oh, I don't know why you said that.

Now, I'm thinking...

Thank you
0
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

8080_DiverCommented:
Systan,
Actually, I never thought you were doing a naughty thing here.  I just thought you might be analyzing a DLL.
In order to be able to search for the text (e.g. "InternetOpen"), you would have to have a something like the following in your code:
procedure opennet;
var
  hSession: HINTERNET;
  DummyString : string;

begin
  DummyString := 'About to call InternetOpen';

 hSession := InternetOpen('MyApp', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
end;

Just putting a comment in the code won't work because comments aren't compiled.  You have to actually have to have the text as part of some line that gets compiled.  You also may lose that line if you compile with the optimization turned on because, uless that variable and the value is used, the optimizer may consider it to be "dead code" and ignore it.
By the way, your answer to my question is below:
>Are you still molesting children?
NO, I'm not trying to do anything harm, honestly.

The implication of  your answer is that you were, at one time, engaging in that activity.  While I seriously doubt that is the case, it illustrates the fact that some questions simply cannot be answered with a "Yes." or "No." . . . they have to have more explanation that either of those two words (or at least the "No." answer) provides.
Similarly, whether or not you can find the calls you are looking for cannot be answered with "Yes." or "No." . . . it has to be a qualified "Maybe." at best.  
>Another thing you can do is hook every api known and launch an application and check the apis that this application uses and the parameters that the application passes.
But this will only catch API calls.

OK, whats that mean? "will only catch API calls"
That means that, because you have hooked/sniffed the API calls, you will be able to catch the calls to the APIs; however, not all calls to DLL functions/procedures are API calls, so you won't ctch those calls.

If this could make a solution so why not.
For the reason stated above.  Unless you have a way to "sniff" or intercept the calls, which can be done with API calls, they won't be apparent to you.  If the DLL is compiled into the application (static rather than dynamic loading of it), then the function/procedure calls are, for all intents and purposes, pretty much like the calls to other functions and procedures in the main part of the application.
>Another thing would be combine my first solution with a Delphi map file.
OK, if is possible, then I should try.


>And if you have the source there is no reason to do that from the beginning.
Oh, I don't know why you said that.


 As he said, unless you have the source code, you won't know what the map refers to; however, if you have the source code (so that you know what the map refers to), why not just look at the source code?
0
8080_DiverCommented:
Continued . . .
>Also, is the 00015912h a relative address or an absolute address?
YES, its the relative address
I don't know about absolute address, but if is usable to get the functions used, YES

 The Absolute address is the address at which that point in the code is actually loaded.  When an application is loaded into memory, it isn't loaded starting at Byte number 0 but, rather at some off-set position.  For the sake of argument, lets say that your application is loaded such that the DLL starts loading at 000F5198h.  That will result in your DLL code's relative address of 00015912h being at an absolute address (for this one loading) of 0010AAAAh.
As if that isn't enough of a complication, your DLL most probably will be loaded somewhere other than at the very beginning of your application but it is also not extremely likely that it will be loaded at the very end of your app.  So, it will wind up being loaded somewhere between relative address 0 of you application and the very end of your app.  So, you have to figure out a) where it loads in your app (i.e. where it got compiled into your app) and b) where the new relative address gets loaded into memory.
Given that you are writing the DLL and given that you manage to get your bit of text compiled into the DLL and given that you know the relative offset of the function call from the text. then if you are reading the code you could look for the text and, based on the relative offset (say, 10 bytes) from the last of the 'About to call InternetOpen' (i.e. the underlined n in that text), you could identify the call position.  
0
systanAuthor Commented:
OK, I understand

Ok, I will ask once more, since this is connected to my questions

I have already the code to List all the functions and RVA by a DLL not running.

Can you give me a Delphi Code Web Link, that shows <To Get All DLL's Used By The Application>?
I've seen it, using Lister(Pluggin) of TotalCommander

Or if you have already the code, I hope you can share it.

And I also found out that the Lister(TCPluggin) could know the functions used by the application, even is compressed by upx.

   wininet.dll
      Import Lookup Table RVA:        00000000h       (Unbound IAT)
      TimeDateStamp:       00000000h  
      ForwarderChain:       00000000h
      DLL Name RVA:       00057FE6h
      Import Address Table RVA:       00056704h
      First thunk RVA:       00056704h
      Ordn        Name
      -----      -----
         0       InternetReadFile
         0       InternetOpenUrlA
         0       InternetOpenA
         0       InternetCloseHandle
         0       HttpQueryInfoA

Thank you
0
systanAuthor Commented:
Ok, please skip my last question about:
<To Get All DLL's Used By The Application>

Now, please help me with this: I have now the code to know what functions the Application is using.
The problem with this, it is not stable, sometimes can get "InternetOpenA" and sometimes not, whats wrong with the code?  
It only gets "InternetOpenA" in the first time of reading the exefile.

here is the code: (please make it stable)
unit Unit1;

interface

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

const
  IMAGE_DOS_SIGNATURE    = $5A4D;       { MZ }
  IMAGE_OS2_SIGNATURE    = $454E;       { NE }
  IMAGE_OS2_SIGNATURE_LE = $454C;       { LE }
  IMAGE_VXD_SIGNATURE    = $454C;       { LE }
  IMAGE_NT_SIGNATURE     = $00004550;   { PE00 }

  IMAGE_SIZEOF_SHORT_NAME            = 8;
  IMAGE_SIZEOF_SECTION_HEADER        = 40;
  IMAGE_NUMBEROF_DIRECTORY_ENTRIES   = 16;
  IMAGE_RESOURCE_NAME_IS_STRING      = $80000000;
  IMAGE_RESOURCE_DATA_IS_DIRECTORY   = $80000000;
  IMAGE_OFFSET_STRIP_HIGH            = $7FFFFFFF;
  DIRECTORY_ENTRY_EXPORT             = 0;   // Export Directory
  IMAGE_DIRECTORY_ENTRY_IMPORT       = 1;   // Import Directory
  IMAGE_DIRECTORY_ENTRY_RESOURCE     = 2;   // Resource Directory
  IMAGE_DIRECTORY_ENTRY_EXCEPTION    = 3;   // Exception Directory
  IMAGE_DIRECTORY_ENTRY_SECURITY     = 4;   // Security Directory
  IMAGE_DIRECTORY_ENTRY_BASERELOC    = 5;   // Base Relocation Table
  IMAGE_DIRECTORY_ENTRY_DEBUG        = 6;   // Debug Directory
  IMAGE_DIRECTORY_ENTRY_COPYRIGHT    = 7;   // Description String
  IMAGE_DIRECTORY_ENTRY_GLOBALPTR    = 8;   // Machine Value (MIPS GP)
  IMAGE_DIRECTORY_ENTRY_TLS          = 9;   // TLS Directory
  IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG  = 10;   // Load Configuration Directory
  IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11;   // Bound Import Directory in headers
  IMAGE_DIRECTORY_ENTRY_IAT          = 12;

type
plist_entry = ^LIST_ENTRY;
LIST_ENTRY = record
  Flink:pLIST_ENTRY;
  Blink:pLIST_ENTRY;
end;

type 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;

type FPO_DATA =packed record
ulOffStart: DWORD;             // offset 1st byte of function code
cbProcSize:DWORD ;             // # bytes in function
cdwLocals:DWORD;              // # bytes in locals/4
cdwParams:WORD ;              // # bytes in params/4
cbProlog:WORD;           // # bytes in prolog
cbRegs:WORD;           // # regs saved
fHasSEH:WORD;           // TRUE if SEH in func
fUseBP:WORD;           // TRUE if EBP has been allocated
reserved:WORD;           // reserved for future use
cbFrame:WORD;           // frame type
end;
PFPO_DATA=^FPO_DATA;

type
IMAGE_FUNCTION_ENTRY=packed record
  StartingAddress:dword;
  EndingAddress:dword;
  EndOfPrologue:dword;
end;
PIMAGE_FUNCTION_ENTRY=^IMAGE_FUNCTION_ENTRY;

type
  PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
  IMAGE_DOS_HEADER = packed record      { DOS .EXE header }
    e_magic         : WORD;             { Magic number }
    e_cblp          : WORD;             { Bytes on last page of file }
    e_cp            : WORD;             { Pages in file }
    e_crlc          : WORD;             { Relocations }
    e_cparhdr       : WORD;             { Size of header in paragraphs }
    e_minalloc      : WORD;             { Minimum extra paragraphs needed }
    e_maxalloc      : WORD;             { Maximum extra paragraphs needed }
    e_ss            : WORD;             { Initial (relative) SS value }
    e_sp            : WORD;             { Initial SP value }
    e_csum          : WORD;             { Checksum }
    e_ip            : WORD;             { Initial IP value }
    e_cs            : WORD;             { Initial (relative) CS value }
    e_lfarlc        : WORD;             { File address of relocation table }
    e_ovno          : WORD;             { Overlay number }
    e_res           : packed array [0..3] of WORD; { Reserved words }
    e_oemid         : WORD;             { OEM identifier (for e_oeminfo) }
    e_oeminfo       : WORD;             { OEM information; e_oemid specific }
    e_res2          : packed array [0..9] of WORD; { Reserved words }
    e_lfanew        : Longint;          { File address of new exe header }
  end;

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

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

  PIMAGE_OPTIONAL_HEADER = ^IMAGE_OPTIONAL_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_SECTION_HEADER = ^IMAGE_SECTION_HEADER;
  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_NT_HEADERS = ^IMAGE_NT_HEADERS;
  IMAGE_NT_HEADERS = packed record
    Signature       : DWORD;
    FileHeader      : IMAGE_FILE_HEADER;
    OptionalHeader  : IMAGE_OPTIONAL_HEADER;
  end;

  PIMAGE_RESOURCE_DIRECTORY = ^IMAGE_RESOURCE_DIRECTORY;
  IMAGE_RESOURCE_DIRECTORY = packed record
    Characteristics : DWORD;
    TimeDateStamp   : DWORD;
    MajorVersion    : WORD;
    MinorVersion    : WORD;
    NumberOfNamedEntries : WORD;
    NumberOfIdEntries : WORD;
  end;

  PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^IMAGE_RESOURCE_DIRECTORY_ENTRY;
  IMAGE_RESOURCE_DIRECTORY_ENTRY = packed record
    Name: DWORD;        // Or ID: Word (Union)
    OffsetToData: DWORD;
  end;

  PIMAGE_RESOURCE_DATA_ENTRY = ^IMAGE_RESOURCE_DATA_ENTRY;
  IMAGE_RESOURCE_DATA_ENTRY = packed record
    OffsetToData    : DWORD;
    Size            : DWORD;
    CodePage        : DWORD;
    Reserved        : DWORD;
  end;

  PIMAGE_RESOURCE_DIR_STRING_U = ^IMAGE_RESOURCE_DIR_STRING_U;
  IMAGE_RESOURCE_DIR_STRING_U = packed record
    Length          : WORD;
    NameString      : array [0..0] of WCHAR;
  end;

type LOADED_IMAGE = record
  ModuleName:pchar;
  hFile:thandle;
  MappedAddress:pchar;
  FileHeader:PIMAGE_NT_HEADERS;
  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;

type IMAGE_LOAD_CONFIG_DIRECTORY = packed record
    Characteristics:DWORD;
    TimeDateStamp:DWORD;
    MajorVersion:WORD;
    MinorVersion:WORD;
    GlobalFlagsClear:DWORD;
    GlobalFlagsSet:DWORD;
    CriticalSectionDefaultTimeout:DWORD;
    DeCommitFreeBlockThreshold:DWORD;
    DeCommitTotalFreeThreshold:DWORD;
    LockPrefixTable:Pointer;
    MaximumAllocationSize:DWORD;
    VirtualMemoryThreshold:DWORD;
    ProcessHeapFlags:DWORD;
    ProcessAffinityMask:DWORD;
    Reserved: array[0..2] of DWORD;
  end;
PIMAGE_LOAD_CONFIG_DIRECTORY=^IMAGE_LOAD_CONFIG_DIRECTORY;

type IMAGE_IMPORT_BY_NAME = packed record
  Hint:WORD;
  Name:DWORD;
end;
PIMAGE_IMPORT_BY_NAME=^IMAGE_IMPORT_BY_NAME;

type IMAGE_THUNK_DATA =packed record
  ForwarderString:PBYTE;
  Func:PDWORD;
  Ordinal:DWORD;
  AddressOfData:PIMAGE_IMPORT_BY_NAME;
end;
PIMAGE_THUNK_DATA=^IMAGE_THUNK_DATA;

type IMAGE_IMPORT_DESCRIPTOR= packed record
  Characteristics:DWORD;
  TimeDateStamp:DWORD;
  ForwarderChain:DWORD;
  Name:DWORD;
  FirstThunk:DWORD;
end;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    procedure ProcessFile;
  end;

var
  Form1: TForm1;
  h1,hmap:integer;
  bptr:pointer;
  gptr:pbyte;
  ntsign:plongword;
  doshd:PIMAGE_DOS_HEADER;
  pehd:PIMAGE_FILE_HEADER;
  peoptn:PIMAGE_OPTIONAL_HEADER;
  sectionheads:array of PIMAGE_SECTION_HEADER;
  offsetmem:longword;
  idataphysicaladress:pbyte;
  idata:PIMAGE_IMPORT_DESCRIPTOR;
  modulename,functionname:pchar;
  dptr:plongword;
  ord:word;
  pexpdir:PIMAGE_EXPORT_DIRECTORY;
  pexpnames:pdword;
  expfname:pchar;
implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Clear;
processfile;
end;

procedure TForm1.ProcessFile;
var
i,j:integer;
begin
if opendialog1.Execute=false  then
  exit
else
  h1:=fileopen(opendialog1.FileName,fmShareDenyNone or fmOpenRead);
hmap:=CreateFileMapping(h1,nil,PAGE_READONLY,0,0,nil);
doshd:=PIMAGE_DOS_HEADER(mapviewoffile(hmap,FILE_MAP_READ,0,0,0));
bptr:=doshd;
memo1.Lines.Clear;
memo1.lines.add('DOS Header');
memo1.Lines.Add(' -e_magic='+inttostr(doshd.e_magic));
memo1.Lines.Add(' -e_cblp='+inttostr(doshd.e_cblp));
memo1.Lines.Add(' -e_cp='+inttostr(doshd.e_cp));
memo1.Lines.Add(' -e_crlc='+inttostr(doshd.e_crlc));
memo1.Lines.Add(' -e_cparhdr='+inttostr(doshd.e_cparhdr));
memo1.Lines.Add(' -e_minalloc='+inttostr(doshd.e_minalloc));
memo1.Lines.Add(' -e_maxalloc='+inttostr(doshd.e_maxalloc));
memo1.Lines.Add(' -e_ss='+inttostr(doshd.e_ss));
memo1.Lines.Add(' -e_sp='+inttostr(doshd.e_sp));
memo1.Lines.Add(' -e_csum='+inttostr(doshd.e_csum));
memo1.Lines.Add(' -e_ip='+inttostr(doshd.e_ip));
memo1.Lines.Add(' -e_cs='+inttostr(doshd.e_cs));
memo1.Lines.Add(' -e_lfarlc='+inttostr(doshd.e_lfarlc));
memo1.Lines.Add(' -e_ovno='+inttostr(doshd.e_ovno));
memo1.Lines.Add(' -e_oemid='+inttostr(doshd.e_oemid));
memo1.Lines.Add(' -e_oeminfo='+inttostr(doshd.e_oeminfo));
memo1.Lines.Add(' -e_lfanew='+inttostr(doshd.e_lfanew));
gptr:=bptr;
inc(gptr,doshd.e_lfanew);
ntsign:=plongword(gptr);
if (ntsign^=IMAGE_NT_SIGNATURE) then
  begin
   memo1.Lines.Add('NT Signature<'+inttostr(IMAGE_NT_SIGNATURE)+'>='+inttostr(ntsign^));
   memo1.Lines.Add('Windows Executable');
   memo1.lines.add('------------------------------------------');
   gptr:=bptr;
   inc(gptr,doshd.e_lfanew+4);
   pehd:=PIMAGE_FILE_HEADER(gptr);
   memo1.lines.add('PE Header');
   memo1.Lines.Add(' -Machine='+inttostr(pehd.Machine));
   memo1.Lines.Add(' -Number of Sections='+inttostr(pehd.NumberOfSections));
   memo1.Lines.Add(' -TimeDateStamp='+IntToStr(pehd.TimeDateStamp));
   memo1.Lines.Add(' -PointerToSymbolTable='+IntToStr(pehd.PointerToSymbolTable));
   memo1.Lines.Add(' -Number of Symbols='+IntToStr(pehd.NumberOfSymbols));
   memo1.Lines.Add(' -SizeOfOptionalHeader='+IntToStr(pehd.SizeOfOptionalHeader));
   memo1.Lines.Add(' -Characteristics='+IntToStr(pehd.Characteristics));
   memo1.lines.add('------------------------------------------');
   gptr:=pbyte(pehd);
   inc(gptr,sizeof(IMAGE_FILE_HEADER));
   peoptn:=PIMAGE_OPTIONAL_HEADER(gptr);
   memo1.lines.add('PE Optional Header');
   memo1.Lines.Add(' -Magic='+inttostr(peoptn.Magic));
   memo1.Lines.Add(' -MajorLinkerVersion='+inttostr(peoptn.MajorLinkerVersion));
   memo1.Lines.Add(' -MinorLinkerVersion='+inttostr(peoptn.MinorLinkerVersion));
   memo1.Lines.Add(' -SizeOfCode='+inttostr(peoptn.SizeOfCode));
   memo1.Lines.Add(' -SizeOfInitializedData='+inttostr(peoptn.SizeOfInitializedData));
   memo1.Lines.Add(' -SizeOfUninitializedData='+inttostr(peoptn.SizeOfUninitializedData));
   memo1.Lines.Add(' -AddressOfEntryPoint='+inttostr(peoptn.AddressOfEntryPoint));
   memo1.Lines.Add(' -BaseOfCode='+inttostr(peoptn.BaseOfCode));
   memo1.Lines.Add(' -BaseOfData='+inttostr(peoptn.BaseOfData));
   memo1.Lines.Add(' -ImageBase='+inttostr(peoptn.ImageBase));
   memo1.Lines.Add(' -SectionAlignment='+inttostr(peoptn.SectionAlignment));
   memo1.Lines.Add(' -FileAlignment='+inttostr(peoptn.FileAlignment));
   memo1.Lines.Add(' -MajorOperatingSystemVersion='+inttostr(peoptn.MajorOperatingSystemVersion));
   memo1.Lines.Add(' -MinorOperatingSystemVersion='+inttostr(peoptn.MinorOperatingSystemVersion));
   memo1.Lines.Add(' -MajorImageVersion='+inttostr(peoptn.MajorImageVersion));
   memo1.Lines.Add(' -MinorImageVersion='+inttostr(peoptn.MinorImageVersion));
   memo1.Lines.Add(' -MajorSubsystemVersion='+inttostr(peoptn.MajorSubsystemVersion));
   memo1.Lines.Add(' -MinorSubsystemVersion ='+inttostr(peoptn.MinorSubsystemVersion ));
   memo1.Lines.Add(' -Reserved1 ='+inttostr(peoptn.Reserved1));
   memo1.Lines.Add(' -SizeOfImage ='+inttostr(peoptn.SizeOfImage));
   memo1.Lines.Add(' -SizeOfHeaders ='+inttostr(peoptn.SizeOfHeaders));
   memo1.Lines.Add(' -CheckSum ='+inttostr(peoptn.CheckSum));
   memo1.Lines.Add(' -SubSystem ='+inttostr(peoptn.Subsystem));
   memo1.Lines.Add(' -DllCharacteristics ='+inttostr(peoptn.DllCharacteristics));
   memo1.Lines.Add(' -SizeOfStackReserve ='+inttostr(peoptn.SizeOfStackReserve));
   memo1.Lines.Add(' -SizeOfStackCommit ='+inttostr(peoptn.SizeOfStackCommit));
   memo1.Lines.Add(' -SizeOfHeapReserve ='+inttostr(peoptn.SizeOfHeapReserve));
   memo1.Lines.Add(' -SizeOfHeapCommit ='+inttostr(peoptn.SizeOfHeapCommit));
   memo1.Lines.Add(' -LoaderFlags ='+inttostr(peoptn.LoaderFlags));
   memo1.Lines.Add(' -NumberOfRvaAndSizes ='+inttostr(peoptn.NumberOfRvaAndSizes));
   memo1.lines.add('------------------------------------------');
   setlength(sectionheads,pehd.NumberOfSections);
   for i:=0 to pehd.NumberOfSections -1 do
    begin
     gptr:=pbyte(peoptn);
     inc(gptr,sizeof(IMAGE_OPTIONAL_HEADER)+i*sizeof(IMAGE_SECTION_HEADER));
     sectionheads[i]:=PIMAGE_SECTION_HEADER(gptr);
    end;
   if peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size=0 then
    begin
     memo1.lines.add('No Export Table Present');
     memo1.lines.add('------------------------------------------');
    end
   else
    begin
     memo1.lines.add('Export Table Present');
     for i:=pehd.NumberOfSections-1 downto 0 do
      begin
       if peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress>=sectionheads[i].VirtualAddress then
        begin
         offsetmem:=sectionheads[i].PointerToRawData-sectionheads[i].VirtualAddress;
         break;
        end;
      end;
     gptr:=bptr;
     inc(gptr,offsetmem+peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
     pexpdir:=PIMAGE_EXPORT_DIRECTORY(gptr);
     pexpnames:=pdword(longint(bptr)+integer(PIMAGE_EXPORT_DIRECTORY(gptr).pAddressOfNames));
     for i:=0 to pexpdir.NumberOfNames-1 do
      begin
       expfname:=pchar(integer(bptr)+integer(pexpnames^));
       memo1.lines.add(' -'+expfname);
       inc(pexpnames);
      end;
     memo1.lines.add('------------------------------------------');
    end;
   if peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size=0 then
    memo1.lines.add('No Import Table Present')
   else
    begin
     memo1.lines.add('Import Table Present');
     for i:=pehd.NumberOfSections-1 downto 0 do
      begin
       if peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress>=sectionheads[i].VirtualAddress then
        begin
         offsetmem:=sectionheads[i].PointerToRawData-sectionheads[i].VirtualAddress;
         break;
        end;
      end;
     gptr:=bptr;
     inc(gptr,offsetmem+peoptn.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
     idataphysicaladress:=gptr;
     i:=0;
     j:=0;
     while true do
      begin
       gptr:=idataphysicaladress;
       inc(gptr,i*sizeof(IMAGE_IMPORT_DESCRIPTOR));
       idata :=PIMAGE_IMPORT_DESCRIPTOR(gptr);
       if idata.Name = 0 then
        break;
       gptr:=bptr;
       inc(gptr,offsetmem+idata.Name);
       modulename:=pchar(gptr);
       memo1.Lines.Add('Module Name:_____________'+ modulename);
       while true do
        begin
         if (idata.FirstThunk + j*4)= 0 then
          break;
         gptr:=bptr;
         inc(gptr,offsetmem+idata.FirstThunk +j*4);
         dptr:=plongword(gptr);
         gptr:=bptr;
         inc(gptr,offsetmem+dptr^);
         if isbadcodeptr(gptr) then
          break;
         ord:=pword(gptr)^;
         inc(gptr,2);
         functionname:=pchar(gptr);
         if isbadcodeptr(functionname) then
          break;
         if functionname=nil then
          break;
         memo1.Lines.Add('  -Ord:'+inttohex(ord,3)+' Function Name:===='+ functionname);
         inc(j);
        end;
       inc(i);
      end;
    end;
  end;
UnmapViewOfFile(bptr);
closehandle(hmap);
fileclose(h1);
end;

end.


And below is my attach that i test with:
testfiles.zip
0
systanAuthor Commented:
I was supposed to award points directly, I'll try again to accept multiple points.
0
systanAuthor Commented:
Thank you
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.