Statistics

Members: 1927
News: 293
Web Links: 1
Visitors: 3932637

Who's Online

Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Introduction to the IAT by coding an Imports Viewer
User Rating: / 1
PoorBest 
Written by Rheingold   
Side Story
Adding Imports by Hand

This is a tutorial about the imports i wrote "by the way" while solving a harder problem. It focus on 2 particular problems: Building up all the imports information and adding imports (both by hand). It does NOT touch the problem of reconstructing a dumped imports section but, hopefully, I will release tutorials on the later as i tackle more well-known packers. While elaborating this tutorial i worked on Win98 and WinXP, but everything should be a trivial translation for other OSes (excluding section 5, but this deal with the differences between Win2k and the rest of Oses).

 


Read More >>



And one more article that deals with the Win32 PE format. Yes, I really work much with it ;) Anyway, this article is only a by-product of a project I am currently working on and that might provide a very interesting topic for another article. Although the Import Address Table, to reveal what IAT means for the reader that did not yet dig too much inside the PE format, and generally Imports of Win32 PE files, are very easy to learn with some good references I thought it might by a good idea to present a small description and some source code that uses the IAT in some way. Obviously, there is not much to do with the an Import Table and as an introduction a simple sourcecode for a viewer that shows which DLLs and which functions from those DLLs an EXE uses should be enough. As usual, I coded my small PE related tools in Win32 assembly (MASM) but this time - after I saw many ppl claiming that using high level syntax makes the source to C-like - I tried to avoid the high level MASM syntax and use just plain x86 commands (at least for most parts). The resulting sourcecode was better structured but lost readability because the API calls can't be read as easily as when I had used a C like calling syntax. I will switch back to my old style at the next program ;) Alright, let's start with a small introduction about the IAT, it's location, it's use and it's method of working.
 

Location: 0x80 bytes after the PE header started is a DWORD pointer (RVA) to the beginning of the IAT. The next DWORD (PE+0x84) is the length of the IAT. As a reference I use my version of calc.exe (German/V5.001764.1/Win98). In the following hex dump, the beginning of the PE file is marked red and the beginning of the IAT and it's length is green.
Use: When a program needs functions from resources (mostly DLL files) it can't rely on the hope that the current system has the same version of that DLL and all offsets for the functions it needs are the same. Relocated DLLs and other Image Bases on different operating systems (Win9X group vs. WinNT group) are other problems why it is not possible to resolve the offsets of the functions while compiling a program. Another way must be found.
Method of Work: When the EXE file is loaded into memory, the Windows EXE loader parses the IAT, loads needed DLL files into the memory and resolves the offsets of the functions inside these DLLs. These offsets are written to the IAT and all function calls to - statically loaded - DLL files are redirected through this function address table.

000000C0 0000 0000 0000 0000 5045 0000 4C01 0300 ........PE..L...
000000D0 B4AF FD34 0000 0000 0000 0000 E000 0F03 ...4............
000000E0 0B01 050C 001C 0100 0032 0000 0000 0000 .........2......
000000F0 E019 0100 0010 0000 0030 0100 0000 0001 .........0......
00000100 0010 0000 0010 0000 0500 0000 0500 0000 ................
00000110 0400 0000 0000 0000 0070 0100 0006 0000 .........p......
00000120 1F0E 0200 0200 0000 0000 0400 0010 0000 ................
00000130 0000 1000 0010 0000 0000 0000 1000 0000 ................
00000140 0000 0000 0000 0000 2020 0100 8C00 0000 ........  ...... 
Here you can see that the beginning of the IAT is at relative virtual offset 12020 and the length is 8C. To convert the relative virtual offset to a raw offset, please see article 4 of the Programming Journal #1. For calc.exe that does not matter because here the virtual offset is the same as the raw offset. When you look at this offset in a hexeditor you see

00012020 9C21 0100 F248 2737 FFFF FFFF A222 0100 .!...H'7....."..

00012030
F010 0000 4021 0100 1520 2F37 FFFF FFFF ....@!... /7....

00012040
BA23 0100 9410 0000 AC20 0100 E046 2737 .#....... ...F'7

00012050
FFFF FFFF 2E24 0100 0010 0000 C820 0100 .....$....... ..

00012060
B3C2 1F37 FFFF FFFF FA25 0100 1C10 0000 ...7.....%......

00012070
BC20 0100 72C2 3E35 FFFF FFFF 2626 0100 . ..r.>5....&&..

00012080
1010 0000 A421 0100 E046 2737 FFFF FFFF .....!...F'7....

00012090
022A 0100 F810 0000 0000 0000 0000 0000 .*..............

000120A0
0000 0000 0000 0000 0000 0000 ............
This is the "complete" IAT header, starting at offset 12020h and ending 8Ch bytes later. Obviously this is not everything you need for resolving the DLL functions. An IAT has to specify which DLLs to load, which function offsets to resolve and where to write the result. This is done in the part presented above and which is specified in the PE header. The pointers to the DLL and function names and the buffers to write the result to are specified in this part which is build like this:
typedef struct tagImportDirectory
{
DWORD    dwRVAFunctionNameList;
DWORD    dwUseless1;
DWORD    dwUseless2;
DWORD    dwRVAModuleName;
DWORD    dwRVAFunctionAddressList;
}IMAGE_IMPORT_MODULE_DIRECTORY,
* PIMAGE_IMPORT_MODULE_DIRECTORY;

(Taken from "The Portable Executable File Format from Top to Bottom" by Randy Kath)

This struct defines a pointer to the names of the functions that need to be resolved (dwRVAFunctionNameList), a pointer to the name of the DLL where those functions are (dwRVAModuleName) and a pointer to a table where the Virtual Offsets of the resolved functions are stored (dwRVAFunctionAddressList). The struct is 20 bytes long and "repeats one after another for each imported module in the file" (taken from Randy Kath again, because of lacking English ;). When all DLL files are added 20 00-bytes are added to the end of the struct-array to indicate the end.
In our example we have 6 imported DLL files and the 6 IMAGE_IMPORT_MODULE_DIRECTORIES start at 12020, 12034, 12048, 1205C, 12070 and 12084. This is actually enough information to write a simple viewer of the DLLs an EXE file loads and resolves the functions "by name". Another way to resolve functions is "by ordinal". This is the ID number of a function in a DLL. You can identify a function which should be imported "by ordinal" by looking at the highest bit of the of the pointer to the name of the dwRVAFunctionNameList table. When the highest bit is set, this value is no pointer to the function name but the ordinal ID of the function (without the highest bit; 80000045 would be ID 00000045). This behaviour is similar to the one in the resource section and loading resources by name or by ID as presented in Programming Journal 1.
The rest of calc.exe's import section:

000120A0 0000 0000 0000 0000 0000 0000 1E24 0100 .............$..
000120B0 0A24 0100 FC23 0100 0000 0000 0826 0100 .$...#.......&..
000120C0 1626 0100 0000 0000 6624 0100 7624 0100 .&......f$..v$..
000120D0 8424 0100 5424 0100 E825 0100 D425 0100 .$..T$...%...%..
000120E0 C425 0100 B225 0100 A225 0100 9225 0100 .%...%...%...%..
000120F0 8425 0100 7625 0100 6A25 0100 6225 0100 .%..v%..j%..b%..
00012100 4C25 0100 3E25 0100 3025 0100 2025 0100 L%..>%..0%.. %..
00012110 1225 0100 0225 0100 F224 0100 E424 0100 .%...%...$...$..
00012120 D824 0100 C224 0100 3C24 0100 4824 0100 .$...$..<$..H$..
00012130 AA24 0100 B624 0100 9624 0100 0000 0000 .$...$...$......
00012140 0E23 0100 FA22 0100 AE22 0100 C422 0100 .#..."..."..."..
00012150 D822 0100 EE23 0100 D623 0100 C623 0100 ."...#...#...#..
00012160 A623 0100 9423 0100 8623 0100 7623 0100 .#...#...#..v#..
00012170 6623 0100 5223 0100 4623 0100 3623 0100 f#..R#..F#..6#..
00012180 2C23 0100 2423 0100 1623 0100 E622 0100 ,#..$#...#..."..
00012190 0423 0100 F022 0100 0000 0000 9422 0100 .#..."......."..
000121A0 0000 0000 3026 0100 3E26 0100 5226 0100 ....0&..>&..R&..
000121B0 6626 0100 7E26 0100 8826 0100 9C26 0100 f&..~&...&...&..
000121C0 AA26 0100 BE26 0100 D026 0100 DE26 0100 .&...&...&...&..
000121D0 EA26 0100 FE26 0100 1227 0100 2027 0100 .&...&...'.. '..
000121E0 2C27 0100 3E27 0100 4E27 0100 5C27 0100 ,'..>'..N'..\'..
000121F0 6E27 0100 8427 0100 9227 0100 9C27 0100 n'...'...'...'..
00012200 AC27 0100 BA27 0100 CC27 0100 DC27 0100 .'...'...'...'..
00012210 EC27 0100 FA27 0100 1028 0100 2028 0100 .'...'...(.. (..
00012220 3028 0100 3C28 0100 5028 0100 5C28 0100 0(..<(..P(..\(..
00012230 6A28 0100 7A28 0100 8628 0100 9828 0100 j(..z(...(...(..
00012240 AA28 0100 BC28 0100 D028 0100 E028 0100 .(...(...(...(..
00012250 EE28 0100 0229 0100 0E29 0100 2029 0100 .(...)...).. )..
00012260 3829 0100 4A29 0100 5C29 0100 6829 0100 8)..J)..\)..h)..
00012270 7A29 0100 9829 0100 A829 0100 B429 0100 z)...)...)...)..
00012280 C029 0100 CE29 0100 E029 0100 F029 0100 .)...)...)...)..
00012290 0000 0000 6E00 5368 656C 6C41 626F 7574 ....n.ShellAbout
000122A0 4100 5348 454C 4C33 322E 646C 6C00 4100 A.SHELL32.dll.A.
000122B0 5F43 7878 5468 726F 7745 7863 6570 7469 _CxxThrowExcepti
000122C0 6F6E 0000 4900 5F5F 4378 7846 7261 6D65 on..I.__CxxFrame
000122D0 4861 6E64 6C65 7200 4200 5F45 485F 7072 Handler.B._EH_pr
000122E0 6F6C 6F67 0000 D102 746F 7570 7065 7200 olog....toupper.
000122F0 B402 7374 7263 6872 0000 C501 5F73 7472 ..strchr...._str
00012300 7265 7600 9502 6D65 6D6D 6F76 6500 D000 rev...memmove...
00012310 5F65 7869 7400 4800 5F58 6370 7446 696C _exit.H._XcptFil
00012320 7465 7200 4602 6578 6974 0000 8D00 5F61 ter.F.exit...._a
00012330 636D 646C 6E00 5800 5F5F 6765 746D 6169 cmdln.X.__getmai
00012340 6E61 7267 7300 0C01 5F69 6E69 7474 6572 nargs..._initter
00012350 6D00 8200 5F5F 7365 7475 7365 726D 6174 m...__setusermat
00012360 6865 7272 0000 9B00 5F61 646A 7573 745F herr...._adjust_
00012370 6664 6976 0000 6900 5F5F 705F 5F63 6F6D fdiv..i.__p__com
00012380 6D6F 6465 0000 6E00 5F5F 705F 5F66 6D6F mode..n.__p__fmo
00012390 6465 0000 8000 5F5F 7365 745F 6170 705F de....__set_app_
000123A0 7479 7065 0000 C700 5F65 7863 6570 745F type...._except_
000123B0 6861 6E64 6C65 7233 0000 4D53 5643 5254 handler3..MSVCRT
000123C0 2E64 6C6C 0000 1000 3F3F 3340 5941 5850 .dll....??3@YAXP
000123D0 4158 405A 0000 0E00 3F3F 3174 7970 655F 
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
 ??1type_
000123E0 696E 666F 4040 5541 4540 585A 0000 B400 info@@
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
 
000123F0 5F63 6F6E 7472 6F6C 6670 0000 5B01 5265 _controlfp..[.Re
00012400 6743 6C6F 7365 4B65 7900 7B01 5265 6751 gCloseKey.{.RegQ
00012410 7565 7279 5661 6C75 6545 7841 0000 7201 ueryValueExA..r.
00012420 5265 674F 7065 6E4B 6579 4578 4100 4144 RegOpenKeyExA.AD
00012430 5641 5049 3332 2E64 6C6C 0000 0203 6C73 VAPI32.dll....ls
00012440 7472 6370 7941 0000 CC01 4C6F 6361 6C46 trcpyA....LocalF
00012450 7265 6500 4701 4765 7450 726F 6669 6C65 ree.G.GetProfile
00012460 496E 7441 0000 CF01 4C6F 6361 6C52 6541 IntA....LocalReA
00012470 6C6C 6F63 0000 C801 4C6F 6361 6C41 6C6C lloc....LocalAll
00012480 6F63 0000 CA00 4765 7443 6F6D 6D61 6E64 oc....GetCommand
00012490 4C69 6E65 4100 4B01 4765 7450 726F 6669 LineA.K.GetProfi
000124A0 6C65 5374 7269 6E67 4100 0803 6C73 7472 leStringA...lstr
000124B0 6C65 6E41 0000 F902 6C73 7472 6361 7441 lenA....lstrcatA
000124C0 0000 CE02 5761 6974 466F 7253 696E 676C ....WaitForSingl
000124D0 654F 626A 6563 7400 6502 5365 7445 7665 eObject.e.SetEve
000124E0 6E74 0000 2B02 5265 7365 7445 7665 6E74 nt..+.ResetEvent
000124F0 0000 4A00 4372 6561 7465 5468 7265 6164 ..J.CreateThread
00012500 0000 3100 4372 6561 7465 4576 656E 7441 ..1.CreateEventA
00012510 0000 1B00 436C 6F73 6548 616E 646C 6500 ....CloseHandle.
00012520 9301 476C 6F62 616C 556E 6C6F 636B 0000 ..GlobalUnlock..
00012530 9001 476C 6F62 616C 5369 7A65 0000 8C01 ..GlobalSize....
00012540 476C 6F62 616C 4C6F 636B 0000 ED02 5772 GlobalLock....Wr
00012550 6974 6550 726F 6669 6C65 5374 7269 6E67 iteProfileString
00012560 4100 9602 536C 6565 7000 FC02 6C73 7472 A...Sleep...lstr
00012570 636D 7041 0000 8801 476C 6F62 616C 4672 cmpA....GlobalFr
00012580 6565 0000 8101 476C 6F62 616C 416C 6C6F ee....GlobalAllo
00012590 6300 8F01 476C 6F62 616C 5265 416C 6C6F c...GlobalReAllo
000125A0 6300 8201 476C 6F62 616C 436F 6D70 6163 c...GlobalCompac
000125B0 7400 3E01 4765 7450 726F 6341 6464 7265 t.>.GetProcAddre
000125C0 7373 0000 C201 4C6F 6164 4C69 6272 6172 ss....LoadLibrar
000125D0 7941 0000 2601 4765 744D 6F64 756C 6548 yA..&.GetModuleH
000125E0 616E 646C 6541 0000 5001 4765 7453 7461 andleA..P.GetSta
000125F0 7274 7570 496E 666F 4100 4B45 524E 454C rtupInfoA.KERNEL
00012600 3332 2E64 6C6C 0000 CD01 5365 7442 6B43 32.dll....SetBkC
00012610 6F6C 6F72 0000 F301 5365 7454 6578 7443 olor....SetTextC
00012620 6F6C 6F72 0000 4744 4933 322E 646C 6C00 olor..GDI32.dll.
00012630 BE01 4D65 7373 6167 6542 6F78 4100 9500 ..MessageBoxA...
00012640 4469 7370 6174 6368 4D65 7373 6167 6541 DispatchMessageA
00012650 0000 8202 5472 616E 736C 6174 654D 6573 ....TranslateMes
00012660 7361 6765 0000 7F02 5472 616E 736C 6174 sage....Translat
00012670 6541 6363 656C 6572 6174 6F72 4100 8501 eAcceleratorA...
00012680 4973 4368 696C 6400 8801 4973 4469 616C IsChild...IsDial
00012690 6F67 4D65 7373 6167 6541 0000 2A01 4765 ogMessageA..*.Ge
000126A0 744D 6573 7361 6765 4100 9601 4C6F 6164 tMessageA...Load
000126B0 4163 6365 6C65 7261 746F 7273 4100 5900 AcceleratorsA.Y.
000126C0 4372 6561 7465 5769 6E64 6F77 4578 4100 CreateWindowExA.
000126D0 AB01 4C6F 6164 5374 7269 6E67 4100 2500 ..LoadStringA.%.
000126E0 4368 6172 4E65 7874 4100 F301 5265 6769 CharNextA...Regi
000126F0 7374 6572 436C 6173 7345 7841 0000 4401 sterClassExA..D.
00012700 4765 7453 7973 436F 6C6F 7242 7275 7368 GetSysColorBrush
00012710 0000 9A01 4C6F 6164 4375 7273 6F72 4100 ....LoadCursorA.
00012720 9E01 4C6F 6164 4963 6F6E 4100 7A01 496E ..LoadIconA.z.In
00012730 7661 6C69 6461 7465 5265 6374 0000 9102 validateRect....
00012740 5570 6461 7465 5769 6E64 6F77 0000 6A02 UpdateWindow..j.
00012750 5368 6F77 5769 6E64 6F77 0000 2C02 5365 ShowWindow..,.Se
00012760 7444 6C67 4974 656D 5465 7874 4100 3500 tDlgItemTextA.5.
00012770 4368 6563 6B4D 656E 7552 6164 696F 4974 CheckMenuRadioIt
00012780 656D 0000 4201 4765 7453 7562 4D65 6E75 em..B.GetSubMenu
00012790 0000 1C01 4765 744D 656E 7500 5B02 5365 ....GetMenu.[.Se
000127A0 7457 696E 646F 7750 6F73 0000 D201 4F66 tWindowPos....Of
000127B0 6673 6574 5265 6374 0000 B901 4D61 7057 fsetRect....MapW
000127C0 696E 646F 7750 6F69 6E74 7300 F000 4765 indowPoints...Ge
000127D0 7443 6C69 656E 7452 6563 7400 B700 456E tClientRect...En
000127E0 6162 6C65 5769 6E64 6F77 0000 0201 4765 ableWindow....Ge
000127F0 7444 6C67 4974 656D 0000 4F00 4372 6561 tDlgItem..O.Crea
00012800 7465 4469 616C 6F67 5061 7261 6D41 0000 teDialogParamA..
00012810 8E00 4465 7374 726F 7957 696E 646F 7700 ..DestroyWindow.
00012820 5C01 4765 7457 696E 646F 7752 6563 7400 \.GetWindowRect.
00012830 2602 5365 7443 7572 736F 7200 3600 4368 &.SetCursor.6.Ch
00012840 6563 6B52 6164 696F 4275 7474 6F6E 0000 eckRadioButton..
00012850 2F02 5365 7446 6F63 7573 0000 BD01 4D65 /.SetFocus....Me
00012860 7373 6167 6542 6565 7000 1402 5365 6E64 ssageBeep...Send
00012870 4D65 7373 6167 6541 0000 B900 456E 6444 MessageA....EndD
00012880 6961 6C6F 6700 9300 4469 616C 6F67 426F ialog...DialogBo
00012890 7850 6172 616D 4100 5E02 5365 7457 696E xParamA.^.SetWin
000128A0 646F 7754 6578 7441 0000 3C00 436C 6F73 dowTextA..<.Clos
000128B0 6543 6C69 7062 6F61 7264 0000 F200 4765 eClipboard....Ge
000128C0 7443 6C69 7062 6F61 7264 4461 7461 0000 tClipboardData..
000128D0 D301 4F70 656E 436C 6970 626F 6172 6400 ..OpenClipboard.
000128E0 8D00 4465 7374 726F 794D 656E 7500 7D02 ..DestroyMenu.}.
000128F0 5472 6163 6B50 6F70 7570 4D65 6E75 4578 TrackPopupMenuEx
00012900 0000 A601 4C6F 6164 4D65 6E75 4100 8400 ....LoadMenuA...
00012910 4465 6657 696E 646F 7750 726F 6341 0000 DefWindowProcA..
00012920 3700 4368 696C 6457 696E 646F 7746 726F 7.ChildWindowFro
00012930 6D50 6F69 6E74 0000 0A02 5363 7265 656E mPoint....Screen
00012940 546F 436C 6965 6E74 0000 E001 506F 7374 ToClient....Post
00012950 5175 6974 4D65 7373 6167 6500 A602 5769 QuitMessage...Wi
00012960 6E48 656C 7041 0000 B500 456E 6162 6C65 nHelpA....Enable
00012970 4D65 6E75 4974 656D 0000 8601 4973 436C MenuItem....IsCl
00012980 6970 626F 6172 6446 6F72 6D61 7441 7661 ipboardFormatAva
00012990 696C 6162 6C65 0000 0101 4765 7444 6C67 ilable....GetDlg
000129A0 4374 726C 4944 0000 AF00 4472 6177 5465 CtrlID....DrawTe
000129B0 7874 4100 A500 4472 6177 4564 6765 0000 xtA...DrawEdge..
000129C0 4301 4765 7453 7973 436F 6C6F 7200 3300 C.GetSysColor.3.
000129D0 4368 6563 6B44 6C67 4275 7474 6F6E 0000 CheckDlgButton..
000129E0 2B02 5365 7444 6C67 4974 656D 496E 7400 +.SetDlgItemInt.
000129F0 5E01 4765 7457 696E 646F 7754 6578 7441 ^.GetWindowTextA
00012A00 0000 5553 4552 3332 2E64 6C6C 0000 0000 ..USER32.dll.... 
I will use the API function CheckDlgButton as an example how to parse the import table and after that I present the source of my small IAT viewer. CheckDlgButton is located in USER32.DLL (offset 12A002). Now we have to find a dwRVAModuleName value which points to this offset. It's obvious that an import viewer does not use the way I use here to get the values of CheckDlgButton, but parses the IAT from 1st function/1st DLL1 to last function/last DLL. For finding the pointer to the pointer to USER32.DLL you start at the beginning of the IAT+12 (because dwRVAModuleName is the 4th DWORD which in the struct) and if the DWORD value there does not match 12A002 you look 20 bytes (sizeof(tagImportDirectory)) ahead and so on. The offset we need is marked red in the first IAT dump (offset 12090). Eight bytes earlier you can find the value of dwRVAFunctionNameList:121A4 (marked green). At this offset starts a table of DWORD values which point to the different functions which were imported from USER32.DLL. Now you have to check for a DWORD value which points to 129CE because the definition of the functionname does not start at the first char of the functionname but 2 bytes before. Those two bytes are the so called "hint". When the loader tries to resolve the imported functions it uses the hint - an index into the DLL's export table - to resolve the correct offset and when this fails it uses the binary string. At offset 12284 you can find the pointer to the hint of CheckDlgItem.
When the exe loader has looked the functions up, it writes the resolved address to a offset which is defined in the dwRVAFunctionAddressList. For USER32.DLL it uses the RVA 10F8. This offset is not part of the code section, but of the section which contains the code of calc.exe.

000010F0 6616 CE7F 0000 0000 2E41 F5BF 3347 F5BF f........A..3G..
00001100
6957 F5BF A257 F5BF A820 F5BF FC57 F5BF iW...W... ...W..
00001110
3D57 F5BF 1D13 F5BF 715C F5BF 8C55 F5BF =W......q\...U..
00001120
3E49 F5BF 1D2F F5BF 734C F5BF 0F5A F5BF >I.../..sL...Z..

Here you can see that the offsets calc.exe expects the imported functions to be are already written to the dwRVAFunctionAddressList. This is called "bound imports" because a small utility (normally bind.exe) does at once what the loader would do when the EXE file gets loaded. It resolves the API functions' offsets and writes them to the dwRVAFunctionAddressList. This works fine until the user has a different version of the DLL file. In that case the EXE loader has to to the work again (with the help of the dwRVAFunctionNameList). That's the reason why in most cases another way - the standard way - of import binding is used. In this way the dwRVAFunctionAddressList is nothing more but a copy of the dwRVAFunctionAddressList table.
So, that is enough for a simple IAT viewer. I present the MASM source for a very simple one which only parses the DLL names and the corresponding function names. With the information above you can easily extend it to display the dwRVAFunctionAddressList, the hint or the way of imports binding. I will only copy the important code here, the rest can be downloaded.

;; --- User clicked the button - Show the OpenFile dialog ---
      mov      ofn.lStructSize, sizeof ofn
push     hInstance
pop      ofn.hInstance
mov      ofn.lpstrFilter, OFFSET FilterString
mov      ofn.lpstrFile, OFFSET buffer
mov      byte ptr [buffer], 0
mov      ofn.nMaxFile, 256
mov      ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
push     OFFSET ofn
call     GetOpenFileName
;; ---  If not file was selected, return ---
test     eax, eax
jz       @RETURN
push     hFile
call     CloseHandle
;; --- Open the selected file with read access  ---
      push     NULL
push     FILE_ATTRIBUTE_NORMAL
push     OPEN_EXISTING
push     NULL
push     FILE_SHARE_READ
push     GENERIC_READ
push     OFFSET buffer
call     CreateFileA
test     eax, eax
jnz      @FILEOPENED
;; --- Show message that something did not work  ---
      push     MB_OK
push     OFFSET caption
push     OFFSET cantopen
push     hWin
call     MessageBoxA
ret
@FILEOPENED:
;; --- If file was opened correctly, go on with checking if it's a valid PE file  ---
      mov      hFile, eax
push     hFile
call     CheckForPEFileAndGetBeginningOfImportSection ;; Return Beginning of import section in eax
push     hFile
push     eax
call     ConvertRVAToFileOffset
mov      beginiat, eax
mov      lengthiat, ebx
test     eax, eax
jnz      @VALIDPE
;; ---  Show message that it is no valid PE file ---
      push     MB_OK
push     OFFSET caption
push     OFFSET nopeorimp
push     hWin
call     MessageBoxA
ret
@VALIDPE:
;; --- Check if the file is big enough to hold an IAT  ---
      push     0
push     hFile
call     GetFileSize
add      ebx, beginiat
cmp      ebx, eax
jbe      @CORRECTFILESIZE
;; ---  If the filesize can't be of a correct PE file, show a message ---
      push     MB_OK
push     OFFSET caption
push     OFFSET nope
push     hWin
call     MessageBoxA
ret
@CORRECTFILESIZE:
;; ---  Allocate memory for reading the file ---
      mov      ebx, eax
push     MEM_RELEASE
push     0
push     allocbuff
call     VirtualFree
push     PAGE_READWRITE
push     MEM_COMMIT
push     ebx
push     0
call     VirtualAlloc
mov      allocbuff, eax
;; --- Set the file pointer and read the complete file  ---
      push     FILE_BEGIN
push     0
push     0
push     hFile
call     SetFilePointer
push     0
push     OFFSET buffer2
push     ebx
push     allocbuff
push     hFile
call     ReadFile
mov      esi, allocbuff
;; --- ESI points to the beginning of the IAT of the loaded file  ---
      add      esi, beginiat
mov      edi, OFFSET RVA1buffer
xor      eax, eax
jmp      @PARSELOOP
;; --- The following loop extracts the dwRVAFunctionNameList to RVAbuffer1, the dwRVAModuleName to RVA2buffer and
;; --- the dwRVAFunctionAddressList to RVA3buffer
      @BEGINOFPARSELOOP:
mov      edi, OFFSET RVA1buffer
add      edi, eax
movsd
add      esi, 8
mov      edi, OFFSET RVA2buffer
add      edi, eax
movsd
mov      edi, OFFSET RVA3buffer
add      edi, eax
movsd
shr      eax, 2
inc      eax
shl      eax, 2
@PARSELOOP:
cmp      dword ptr [esi+16], 0
jnz      @BEGINOFPARSELOOP
;; --- Terminate all RVAxbuffers with a 0 DWORD  ---
      mov      edi, OFFSET RVA1buffer
add      edi, eax
mov      dword ptr [edi], 0
mov      edi, OFFSET RVA2buffer
add      edi, eax
mov      dword ptr [edi], 0
mov      edi, OFFSET RVA3buffer
add      edi, eax
mov      dword ptr [edi], 0
;; --- Empty the listbox  ---
      mov      esi, OFFSET RVA2buffer
push     0
push     0
push     LB_RESETCONTENT
push     hwndList
call     SendMessage
jmp      @FILLLOOP
;; ---  This loop writes the ModuleNames in the 1st listbox ---
      @BEGINOFFILLLOOP:
mov      eax, dword ptr [esi]
push     hFile
push     eax
call     ConvertRVAToFileOffset
add      eax, allocbuff
push     eax
push     0
push     LB_ADDSTRING
push     hwndList
call     SendMessage
add      esi, 4
@FILLLOOP:
cmp      dword ptr [esi], 0
jnz @BEGINOFFILLLOOP
mov      esi, dword ptr [RVA1buffer]
push     0
push     0
push     LB_SETCURSEL
push     hwndList
call     SendMessage
ret
@ID_LIST:
cmp      ax, ID_LIST1
jnz      @RETURN
shr      eax, 16
cmp      ax, LBN_SELCHANGE
jnz      @RETURN
;; --- User selects another DLL file ---
      mov      esi, OFFSET RVA1buffer
push     0
push     0
push     LB_GETCURSEL
push     hwndList
call     SendMessage
shl      eax, 2
add      esi, eax
mov      esi, [esi] ;; ESI = dwRVAFunctionNameList
push     hFile
push     esi
call     ConvertRVAToFileOffset
mov      esi, eax
add      esi, allocbuff
push     0
push     0
push     LB_RESETCONTENT
push     hwndList2
call     SendMessage
jmp      @DISP2LOOP
@BEGINOFDISP2LOOP: ;; Write Functionnames to 2nd DLL
mov      eax, dword ptr [esi]
push     hFile
push     eax
call     ConvertRVAToFileOffset
test eax, eax
jnz      @ImpByName ;; Jump if eax is not 0 (offset exists in file) - if not, ImpByOrd
mov      eax, [esi]
and      eax, 7FFFFFFFh
push     eax
push     OFFSET conv
push     OFFSET buffer
call     wsprintfA
push     OFFSET buffer
push     0
push     LB_ADDSTRING
push     hwndList2
call     SendMessage ;; Give out "ImpByOrd(x)"
add      esi, 4
jmp      @DISP2LOOP
@ImpByName:
add      eax, allocbuff
add      eax, 2
push     eax
push     0
push     LB_ADDSTRING
push     hwndList2
call     SendMessage ;; Give out function name
add      esi, 4
@DISP2LOOP:
cmp      dword ptr [esi], 0
jnz      @BEGINOFDISP2LOOP
@RETURN:
xor eax, eax
ret
MainWndProc endp

This e-mail address is being protected from spam bots, you need JavaScript enabled to view it