Jump to content
Tuts 4 You

Fixing irregular IATs


p0c

Recommended Posts

First of all:

Thank you for that awsome project and making it open source! :)

Second:

In case anone has the same problem while trying to compile Scally Imports Reconstruction here are some hints:

For x86 VisualStudio10:

Follow instructions in Scylla\README-WTL

additionally:

set Platformtoolset to v100 instead of v90 for all 3 projects

Download distorm.package3.1 and unpack it in the diStorm directory. Open diStorm\include\distorm.h and comment line 40 (#define SUPPORT_64BIT_OFFSET) to disable it (else i got linker errors)

in "Linker --> Input -->additional Dependencies" add: psapi.lib and Imagehlp.lib

Now to main part of my post:

Imagine you have a IAT that looks like this:


004101D4 7C80236B kernel32.CreateProcessA
004101D8 7C801E1A kernel32.TerminateProcess
004101DC 7C83610D kernel32.SetCurrentDirectoryA
004101E0 7C94232E ntdll.RtlCreateUserThread
004101E4 7C9740CB ntdll.RtlExitUserThread
004101E8 7C91D92E ntdll.ZwQuerySystemInformation
004101EC 7C91CFEE ntdll.ZwClose
004101F0 77DB51B6 ADVAPI32.RegEnumKeyExA
004101F4 77DC9BBF ADVAPI32.RegEnumValueA
004101F8 77DAE9F4 ADVAPI32.RegCreateKeyExA

You see that the single blocks for the libraries are not splitted by zeros, but are next to each other.

First i tried Import REConstructor (ImpRec), but it failed and told me the imports were invalid. (you will soon see why)

Then i tried Scylla, but it has also problem. Then i was like

31025604.jpg

Scylla has problems fixing this since a special way of building the imports is chosen.

Basics:

If you look at the structure IMAGE_IMPORT_DESCRIPTOR, you can see three important fields: OriginalFirstThunk, Name, and FirstThunk.

"Name" is obviously a RVA to the name of the dll. Basically it says "take the imports from this dll"

"OriginalFirstThunk" is a RVA to where the imported address shall be placed - "Put the imports there!"

"FirstThunk" is a RVA to a list of RVAs (or ordinals). This list is terminated by an entry (a double word) that is set to zero (make a mental note here: "the list is terminated by zeros"). The elements of this list are either ordinals or pointer to function-strings (like "MessageBoxA") - The "FirstThunk" pointer says: "Walk this list and import all the functions until you find a zero".

One image import descriptors is only for one dll. If you import from several dlls, you just add further of this structures.

What Scylla does:

Scylla omitts the "OriginalFirstThunk", which makes the windows loader to go into fall back mode and use "FirstThunk" as "OriginalFirstThunk"... Yep, "FirstThunk" is used for two lists:

One list is the "imports this functions" list, and the other is the "put the imports here" list. So by creating one list, the other one is written over.

So far no problem - it can even save space to merge both lists into one.

Scylla obviously has to take the IAT as this list, since the imports should be filled into the IAT. Makes sense, right?

But what about the funny IAT i posted above? The imports for each dll are not separated by zeros (now recall the mental note from above)...

What happens:

When windows tries to parse the first IMAGE_IMPORT_DESCRIPTOR it creates a pointer the dll given in "Name" , and it takes the "FirstThunk" pointer and starts to import the first function and write the imported address over the address that was previously read. When the imports of this dll are made, it should stop and go to the next IMAGE_IMPORT_DESCRIPTOR. But the terminator are the zero bytes at the end of the "FirstThunk" list. Because of the malformed IAT there is no zero, which makes windows to parse further. Thereby it tries to import the following functions from the very same dll - which will of course not work and the binary can not be started.

How i fixed it:

The fix is quite simple: Do what Windows expects. Meaning you should use the "OriginalFirstThunk" pointer.

But where to place the list of "FirstThunk" if i should not use the IAT? Put it simply in the import section that is appended. Then set the "OriginalFirstThunk" to the IAT.

So we tell windows: "take all import stuff from the appended import section and write the imports to the IAT, but do not use the IAT for reading".

To implement the fix only one file has to be altered. My fix can be seen in http://pastebin.com/FBVXwkiD.

So if you like, you can add this fix to the next version of Scylla. I think a checkbox to make this optional would be cool, because my fix increases the size of the file.

Thanks again for the tool!

Cheers,

p0c

  • Like 2
Link to comment

Yeah you're right, OriginalFirstThunk and FirstThunk were made with a goal, so omitting one of them is risking a lot for such situations like yours.

In the case you want to correct that kind of IAT if there won't be FirstThunk in the new import table after rebuilding, you'll have to move those arrays to add at least one zero field between them, and fix every reference in the code section to the new addresses where IAT will be, and because of more bytes required to fit it, this could overlap any other field of the target... so, do it with care, or move this IAT to elsewhere such a new appended section.

Btw, this configuration of IAT without zeroes is not a new trick, I have found this sometimes, or even scattered handles inside the IAT, as Armadillo does... and target runs, though... :)

Nice post anyway! Best regards

Nacho_dj

Link to comment

Thank you very much! It's always nice to see that somebody is using the source code to improve something. This is sadly pretty uncommon. Most people are not able to use the source for something good.

I am compiling the x86 version with platformtoolset v90. I guess your problem is that you haven't installed VS 2008. And probably you haven't got VS2010 Pro or Pre or Ulti. The Express edition doesnt have x64 support.

I will add your source code asap and provide some binaries.

Your code doesn't provide x64 support as I can see, so I have to modify it a little bit.

Link to comment

Yeah you're right, OriginalFirstThunk and FirstThunk were made with a goal, so omitting one of them is risking a lot for such situations like yours.

In the case you want to correct that kind of IAT if there won't be FirstThunk in the new import table after rebuilding, you'll have to move those arrays to add at least one zero field between them, and fix every reference in the code section to the new addresses where IAT will be, and because of more bytes required to fit it, this could overlap any other field of the target... so, do it with care, or move this IAT to elsewhere such a new appended section.

Btw, this configuration of IAT without zeroes is not a new trick, I have found this sometimes, or even scattered handles inside the IAT, as Armadillo does... and target runs, though... :)

Nice post anyway! Best regards

Nacho_dj

I thought about relocating the IAT to another address, but i was not sure that i would be able to locate all references, so i didn't risk it. (Think of "polymorph" malware that unpacks additional code during runtime)

Also i knew that it would not be a big problem to add the use of OriginalFirstThunk pointer, so it just looked at the source code and fixed it. :)

Thank you very much! It's always nice to see that somebody is using the source code to improve something. This is sadly pretty uncommon. Most people are not able to use the source for something good.

I am compiling the x86 version with platformtoolset v90. I guess your problem is that you haven't installed VS 2008. And probably you haven't got VS2010 Pro or Pre or Ulti. The Express edition doesnt have x64 support.

I will add your source code asap and provide some binaries.

Your code doesn't provide x64 support as I can see, so I have to modify it a little bit.

I used VS2010 Pro, but it does not have a VS2008 compiler included. And since i don't have VS2008 installed on the same machine i had to switch to v100.

I also tried to open the project with VS2008(on another machine), but VS was bitching that the given project was not a VS2008 project, so i switched to VS2010.

Actually the discription of how i compiled it was just a tip of how to compile Scylla, since it costed me some time to figure it out myself and i wanted to create a little "manual". ;)

You're right that my additions do not support x64, i forgot to mention that. :)

Thanks again for making your tool open source and adding improvements!

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...