I am introducing a new dependency walker, with a new look, but my target is not to introduce a dependency walker in front of you, but rather to make you familiar with PE (Portable Executable) format. I hope all of you have heard about PE, it is nothing but our Windows Executable (EXE, DLL, OCX, etc.) which is actually inherited from COFF (Common Object File Format), which was used for object file and executable in UNIX.
With this article, I make you familiar with coding making your own dependency walker, so that you can customize and make your own dependency walker. More than that, you can learn about PE, and how to parse a PE file with simplicity. To explain more, I am attaching an application and source code named
The term "Portable Executable" was chosen because the intent was to have a common file format for all versions of Windows, on all supported CPUs. To a large extent, this goal has been achieved with the same format used on Windows NT and descendants, Windows 95 and descendants, and Windows CE.
To get familiar with PE format, firstly get familiar with some of the data structures, which are used to manage the data inside an executable in Windows.
- PE Headers
- PE Sections
Using the Code
Before compling the code, make sure that you have Microsoft Platform SDK installed properly. Current project is made for Visual Studio 6.0, but can be converted to later versions.
All the structures mentioned below are defined in WINNT.h file. Since PE file is basically starts withMS DOS header MZ header, to get further knowledge like import and export headers, you need to parse further based on the offset so that you can even get DEBUG information.
Let me introduce the data structures commonly used for coding with PE file format:
I am only explaining some of the data structures, if you need more information, you can refer to MSDN.
IMAGE_DOS_HEADER: Data structure holds the header of DOS, or simply the starting address from which we can take reference to get the content of a PE file.
IMAGE_OPTIONAL_HEADER: The data structure holds the import and export address, it holds the starting address for import and export based on the offset.
_IMAGE_EXPORT_DIRECTORY: This data structure holds the export address, based on this address we can get the exported functions of PE file.
IMAGE_IMPORT_DESCRIPTOR: This data structure holds the import address, based on this address we can get the imported functions of PE file.
Examples are illustrated below:
hMod = LoadLibrary( lpctszModName_i )
IMAGE_DOS_HEADER* IDH = (IMAGE_DOS_HEADER*)hMod;
IMAGE_OPTIONAL_HEADER* IOH =
(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + IDH->e_lfanew + 24);
IMAGE_IMPORT_DESCRIPTOR* IID =
_IMAGE_EXPORT_DIRECTORY* pExportDescriptor =
Points of Interest
I am giving you a small example with an implementation that will surely help you understand how our dependency walker may have been coded, but never compare with it, just a overview. I cannot compare my code with the Mark E. Russinovich. Leave those things, this is my first article, and I will surely write a lot of articles only if it is helpful to you. If it is not worthy or if you have any suggestions, then please inform me. I am planning for more topics, if my lord allows me to write it.
ExeInside Beta is an application written just to understand how a dependency walker works, and still I am trying to improve it more effectively, I will never say it's fully bug free, yet it tested up to some extent and it has some additional functionality like, you can specify a PE file (EXE, DLL, OCX) and specify a directory, it will search which PE files have dependency with the specified PE file.
Well I am expecting your cooperation to make it more better than ever.
For more information, go and understand the below link for study purpose http://www.skynet.ie/~caolan/pub/winresdump/winresdump/doc/pefile.html
- 2nd June, 2009: Initial post
- 29th May, 2012: Minor corrections.