Wednesday, April 4, 2012

EXE dependencies - Read from PEB

I was trying to understand where executables load all their dependencies from. So for example: When I load up minesweeper (winmine.exe) there are a host of additional DLLs that are loaded up as well. That's fine as there are functions inside each of those DLLs that winmine uses. What was interesting to find out though, was how the list of those DLLs was built in the first place. Where did the OS loader look...into the process..to find out 'what else to load'?

So I loaded up winmine.exe in Olly, Dep Walker and a few other tools to get an understanding of 'what all' was loaded. Once that was done I read up a little about the PE header to understand where dependencies are accessed from. In PE terminology, these are called imports. It turned out there was a Data Directory for the Import Table. So i thought; lets read the import table; that should give me a list.

So I wrote a little bit of Python code [after learning Python from Google's Python class ;)] to read the IMPORT TABLE from the PE header. This did give me quite a few DLLs but it still did not tally with what Olly was displaying.

The next thing I did was to modify my code to be recursive. So...

--- Load EXE. Get dependent DLLs from import table.
--- Load 1st DLL from previous list. Get its dependent DLLs. Add to list.
--- Load 2nd DLL from previous list. Get its dependent DLLs. Add to list.

And so on... until all dependencies were resolved.This was doubtlessly an improvement as I was closer to what was displayed in Olly [Alt+E]. It still wasn't complete though.

Then I read some more, read how Dependency Walker works, asked on Woodmann and re-read a few sections from Xeno Kovah's Life Of Binaries class. Turns out there are somethings called Delayed Imports. These aren't loaded statically at load time; like the Import table but only when a particular function needs to be called..later on...at runtime.

So I modified the code a little to recursively get all the DELAYED IMPORTS too. This would have been enough but it gave me a huge huge list which contained much much more than what Olly ever showed me :). So obviously this wasn't efficient either and it was something else.

So as usual when I'm stuck I bug the nice guys on Woodmann and I'm rarely disappointed. This time was no exception and I was pointed in the direction of something called a PEB.

The PEB or the Process Environment Block is apparently the only "part" (very loosely used) of a process that is in User Mode. Everything else is in Kernel mode. So if you want to find out every DLL that an EXE depends upon; its best to query the PEB instead of doing all that stuff I did earlier :)

I want to quickly touch upon the structure of the PEB before I finish this post. To look at the entire structure of the PEB you can visit this link. You need to query the PEB_LDR_DATA structure to get the list of Loaded DLLs. Here is an article that I found quite useful while I was learning stuff about all this.

And lastly..here is the complete thread of my discussion on Woodmann, if at all you are interested :).

1 comment:

Neo85 said...

I also use winmine for testing :-)