View Full Version : Export Table Tester

August 7th, 2016, 15:17
Export Table Tester - Version 1.1 - 2016, August the 7th

This is a tool to test & practice to better understand how an export table works.

First, select a file, or drag & drop it over the tool. If it is a valid PE32 or PE64 file and it contains an export table, all fields will be filled with the proper data.

Moving the cursor over any field will display the offset in the file where you can find the item pointed.

Now, select at any listbox the value required and more data will appear, also here you can use cursor to find file offsets.

As a sidenote, forwarded functions are those that won't be executed by the current module, since the address of function points to a string instead of an assembler instruction. That stringis composed by two substrings separated by a dot: the first substring indicates the name of the module owner of the function name of the second substring.

For instance: 'NTDLL.RtlDeleteCriticalSection' is found inside the export table of kernel32.dll, and this string is pointed by the address of the function 'DeleteCriticalSection'.

So, in the case the function 'DeleteCriticalSection' of kernel32.dll is invoked, it will inform the system to load the NTDLL.DLL module and use its function named 'RtlDeleteCriticalSection'.

Thanks to LCF-AT for his always valuable help and the idea of building this little tool.

Version 1.1 - Added support to edit export table.

Coded in Delphi by Nacho_dj/ARTeam - 2012, December the 31th
Any suggestion or bugs reported are very welcome always!

Best regards


EDITED: Version 1.1.1 - 2016, August the 11th
+ Fixed some bugs and algos, thanks to Kayaker for his suggestions

August 8th, 2016, 19:36
Originally Posted by Kayaker
As far as I know there are no automagic tools to add exports.

Heheh, I stand corrected. Nice one Nacho_dj, very nice. Now there's a tool for everything

I thought I might outline how I added an export as an intro to using your potentially very useful tool. I did have a couple of issues with it that I'll mention at the end.

I started with Iczelion's Tutorial #17 dll/exe example

The usedll.exe calls the export TestHello in DLLSkeleton.dll. I recompiled the exe with Masm32 to add another call to an export called NewExport. One could instead hex edit the single original export name to something else (with the same number of letters) for simple testing purposes.

In the dll I wanted to duplicate the existing MessageBox example, but with a new caption and text. I needed to add new code and data to the file before adding a new export entry so I could point to the proper RVA for the function. I added 2 new sections with CFF Explorer and decided to fill them with created opcode data (Add Section - File Data), rather than creating blank sections and filling them later.

For the new data section I used a hex editor to create a file with two very uninspired text strings separated by 00's:

00000000 4E 65 77 20 43 61 70 74 69 6F 6E 20 4E 65 77 00 New Caption New.
00000010 54 65 78 74 00 Text.

For the new code section I took the existing opcodes from the original function:

10001070 TestHello proc near
10001070 6A 00 push 0 ; uType
10001072 68 00 30 00 10 push offset aDllSkeleton ; "DLL Skeleton"
10001077 68 0D 30 00 10 push offset aHelloYouReCallingAFunctionInThisDl ; "Hello, you're calling a function in thi"...
1000107C 6A 00 push 0 ; hWnd
1000107E E8 01 00 00 00 call MessageBoxA
10001083 C3 retn
10001083 TestHello endp

and zeroed out the offset/relative displacement information given in the operands (in red), since they would need to be recalculated once the new code and data sections were in place

00000000 6A 00 68 00 00 00 00 68 00 00 00 00 6A 00 E8 00 j.h....h....j...
00000010 00 00 00 C3 ....

Now that the two files had been created they could be added to the dll with CFF Explorer as new sections, making sure to use the proper Code Characteristics for code and data.

Now we have a temporary dll with which to calculate displacement values for the push and call instructions. In IDA, View/Subviews/Segments shows us our two new sections:

.newdata:10005000 4E 65 77 20 43 61+aNewCaption db 'New Caption',0
.newdata:1000500C 4E 65 77 20 54 65+aNewText db 'New Text',0
.newdata:10005015 00 00 00 00 00 00+ align 1000h

.newcode:10006000 6A 00 push 0
.newcode:10006002 68 00 00 00 00 push 0
.newcode:10006007 68 00 00 00 00 push 0
.newcode:1000600C 6A 00 push 0
.newcode:1000600E E8 00 00 00 00 call $+5
.newcode:10006013 C3 retn

The offsets for the push instructions can be taken directly from the disassembly. To correctly reference the MessageBox call we need to calculate the relative displacement to the function call:

E8 - CALL rel32 Call near, relative, displacement relative to next instruction

10001084 ; int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
10001084 MessageBoxA proc near
10001084 FF 25 00 20 00 10 jmp ds:__imp_MessageBoxA
10001084 MessageBoxA endp

So, (10001084 - 10006013) = -0x4F8F as a signed 32-bit value, or in proper notation, 0xFFFFB071.

A new sequence of opcodes can now be created and used with CFF explorer to give a correct disassembly.

The final step is to use Nacho_dj's tool to add an export entry for the new function, taking note of its RVA, 0x6000. This part is too easy and only takes a sentence to describe

Drag and drop the temporary dll to the tool, Edit Exports, add the new function name, adjust the address of the function to 00006000, click Add, select the Add New Section (.edata) checkbox and save. One small addendum to this - the exports seemingly should be in alphabetical order, so use the arrow buttons to reorder them appropriately.

IDA recognizes the new export and it's ready to go!

.newcode:10006000 public NewExport
.newcode:10006000 NewExport proc near
.newcode:10006000 6A 00 push 0 ; uType
.newcode:10006002 68 00 50 00 10 push offset aNewCaption ; "New Caption"
.newcode:10006007 68 0C 50 00 10 push offset aNewText ; "New Text"
.newcode:1000600C 6A 00 push 0 ; hWnd
.newcode:1000600E E8 71 B0 FF FF call MessageBoxA
.newcode:10006013 C3 retn
.newcode:10006013 NewExport endp


Here are the two items of note. When I added the second export with your tool I first did them in this order:
TestHello (original export)

GetProcAddress in the exe failed to find the second export. I had read that the AddressOfNames array is sorted alphabetically so that a binary search can quickly find a specific string, but I wasn't aware that it was (apparently) an absolute necessity. When I reordered the exports alphabetically GetProcAddress had no problems. Similarly, if I renamed the new export something like ZewExport and kept it in the second position, all was OK.

One small suggestion then if this is truly the case, might be to either reorder the exports alphabetically automatically before saving, or mention it in the help file. If doing that automatically might mess up functions exported by ordinal only, perhaps it's best to leave it up to the discretion of the user.


I also got an error message when saving modifications (like the reordering) to an existing .edata section that the tool previously created. By unchecking the Add New Section box, the RVA of the current .edata section is entered, which is nice, but gave an error after entering the name for the file.

Access violation at address 00403126 in module 'ExportTableTester.exe'. Read of address 00007000.

In my case the RVA of the .edata section was 0x7000. The error occurred in one of those compiler specific functions that redirects calls from a call table:

403126 8B08 MOV ECX, [EAX] ; eax was 0x7000
403128 FF51FC CALL NEAR [ECX-4]

which was reached from this point in your code:

00479EEE E8DD59FFFF CALL 0046F8D0 ; access violation in here
00479EF3 84C0 TEST AL,AL
00479EF5 751D JNZ 00479F14
00479EF7 6A30 PUSH 30
00479EF9 6864A44700 PUSH 0047A464 ; "Export Table Tester - Nacho_dj / ARTeam
00479EFE 685CA84700 PUSH 0047A85C ; "Error when saving export table to new f
00479F03 6A00 PUSH 00
00479F05 E822CDF8FF CALL USER32!MessageBoxA

Perhaps I didn't take something into account and did the procedure wrong, but I'd thought I'd mention the error.


August 11th, 2016, 10:03
Hey mate, first many thanks for such a detailed explanation. It seems there is no feature in the tool not tested by you...
That's the way to find always where a tool is weaker...

Anyway, I agree with you, when saving file by using a custom address for export table, it was crashing because I had moved a line of code after my tests (oh my God!), causing a crash every time you were saving the file in that way. Sorry for that. Now it should run fine.

The possibility of a binary search for names was not implemented in the tool. But PECoff document is clear about that point, so the tool has been improved to save export tables with all names sorted alphabetically. In fact this is viewed in this way when you first load any dll in the tool and check the listbox of function names. For instance, you could try to load msvcrt.dll and you will find that curious sorting done. Now it is expected GetProcAddress will work better...

Many thanks for taking your time to find all of these important bugs... in fact this is the first and only one report of bugs for the tool among the different forums where it has been released...

Other things such export table no fitting into a section has been include to be checked previously to saving the file. I hope this time the tool will do its work as expected.

Please get the new compiled tool in the same post as release was done:



August 25th, 2016, 08:50
Thanks for This tool , it is truly awesome.
One thing i wish to inform , when i am adding more than one function entry it is causing problem , whole kernel32.dll is breaking.
This is already 98% full blown export tool still few new features will be extremely helpful.
*Automated Function calculator
*Option for editing extra code of a export not only entry
*Ability to find extra code.
Thanks for this awesome tool , You had made me your big fan.

Best of Luck
Best wishes from your Japanese friend XPFOREVER and all RCE Forum member

September 6th, 2016, 19:42
Your Tool is breaking shell32,kernel32.
can you please fix it?

September 7th, 2016, 18:43
[Originally Posted by XPFOREVER;97424]Your Tool is breaking shell32,kernel32.
can you please fix it?

Really? That's all you're going to give him as an explanation to try to fix a problem that only you know about?
You said that if you add more than 1 function to kernel32.dll it "breaks". If I add more than 1 function to the test dll I described above, I do not have a problem, whether I add them to separate .edata sections or combine them into an existing .edata section. So I don't think your problem is due to the tool itself, but perhaps to how you're using it.

You must be getting some error message, at the very least mention that. If there is some problem with the tool under certain conditions, you're going to have to help trying to figure out what it is.

Nacho_dj, thanks for the update. I hope you continue to develop it if you have any interest in doing that. The only thing I could see to make it "all encompassing" for the purpose of adding new exports might be to add that small functionality of CFF, the ability to add new sections as existing file data or blank "code caves". It hardly matters really, it's easy enough to switch tools, but if you do play with it further it's just an idea. Cheers.