Hi dudes!

Here is the next part about my "accessing to DLLs functions in no
conventional way" texts.

http://arnold.mcdonald.free.fr/php/Index.php?p=1007

Feedback and english corrections are welcome.

--
AMcD?

http://arnold.mcdonald.free.fr/
Posted on 2004-04-30 11:25:21 by amcd
*) you must (end up) import(ing from) kernel32 if you want your executables to load on all win32 versions.

*) bound imports, forwarded exports...?

*) use binary search when scanning for import.
Posted on 2004-04-30 11:51:59 by f0dder
What a cryptic post...

Why don't you write using verbs, words and adjectives :-)?

Please be more explicit, I'll can see then.

CU
Posted on 2004-04-30 12:32:55 by amcd
Sorry, I was in a hurry :)

You must make sure kernel32 is mapped in your process, otherwise your process won't load on all win32 versions (win2k, for instance). You don't have to do this directly, you can import from, say, GDI32 since it ends up importing from kernel32 (it's safest importing kernel32!exitprocess though). And yes, it is a kernel32 requirement, trying to load a process that has a dummy.dll import won't work (hm - I haven't tried importing from only ntdll.dll though).

Bound import can make loading of DLLs faster, by not having to do the function search if TimeDateStamp matches. I think bound imports might cause problems with simple importers, since the FirstThunk array doesn't contain RVAs to names, but rather the VAs of the loaded DLLs - so I guess this could cause you trouble if you blindly parse the FirstThunk chain. And because of stupid bugged Borland linkers, you can't just blindly follow the OriginalFirstThunk chain blindly.

Exports are (have to be!) sorted alphabetically in DLLs. This means you can use a binary search (aka "divide and conquer") to scan for the names. This search method gives very good performance. I believe the performance is O(log2N), which is "pretty good". Much much better than a linear search ;)
Posted on 2004-04-30 13:05:38 by f0dder
>Sorry, I was in a hurry

No problem.

>You must make sure kernel32 is mapped in your process, otherwise your process won't load on all win32 versions (win2k, for instance).

Well, actually, all I write is about WinXP HE/Pro. Just write an application using only a ret instruction and use a debugger, you'll see that Kernel32.dll is always loaded. I don't remenber how it is with old versions of Windows.

> You don't have to do this directly, you can import from, say, GDI32 since it ends up importing from kernel32 (it's safest importing kernel32!exitprocess though). And yes, it is a kernel32 requirement, trying to load a process that has a dummy.dll import won't work (hm - I haven't tried importing from only ntdll.dll though).

But of course in case you are not sure, just import ExitProcess() et voil?! Kernel32.dll will be mapped. But the game was to write a sample program showing no import at all when disassembled, a case study :o).

> Bound import can make loading of DLLs faster, by not having to do the function search if TimeDateStamp matches. I think bound imports might cause problems with simple importers, since the FirstThunk array doesn't contain RVAs to names, but rather the VAs of the loaded DLLs - so I guess this could cause you trouble if you blindly parse the FirstThunk chain. And because of stupid bugged Borland linkers, you can't just blindly follow the OriginalFirstThunk chain blindly.

Er, I don't clearly understand your dilemna :o). But with opne point you are right, I should have speak about bound imports. we'll see that in a future text.

> Exports are (have to be!) sorted alphabetically in DLLs. This means you can use a binary search (aka "divide and conquer") to scan for the names. This search method gives very good performance. I believe the performance is O(log2N), which is "pretty good". Much much better than a linear search

This will be discussed in a next article too :o).

CU

AMcD
Posted on 2004-04-30 20:39:29 by amcd

Well, actually, all I write is about WinXP HE/Pro. Just write an application using only a ret instruction and use a debugger, you'll see that Kernel32.dll is always loaded. I don't remenber how it is with old versions of Windows.

I know, but other versions require kernel32... otherwise the PE will fail loading, and it will do so silently - no error message from the shell.


But of course in case you are not sure, just import ExitProcess() et voil?! Kernel32.dll will be mapped. But the game was to write a sample program showing no import at all when disassembled, a case study

You should update the text saying that this method will not work on all windows versions :) - if you want to use this method for anything practical, you should indeed include kernel32!exitprocess. (Or, if you're doing 4k intros, you might want to import something from gdi32 by ordinal, that's probably the shortest way to get kernel32 mapped.)


Er, I don't clearly understand your dilemna ). But with opne point you are right, I should have speak about bound imports. we'll see that in a future text.

If an image is bound, the FirstThunk array no longer contains RVAs to <hint,name> pairs - it contains the bound address of the DLL function. Thus, if you blindly follow FirstThunk and don't check for bound imports, your loader will crash. And unfortunately, you cannot choose to just process OriginalFirstThunk, since broken borland linkers don't output this array.


This will be discussed in a next article too

Good :) - you might want to check the hint, too, before embarking on a full binary search of the export table.
Posted on 2004-05-01 07:35:00 by f0dder
PS: forwarded exports. Try using your loader to resolve Kernel32.HeapAlloc on some NT version. You will realize that you need to check if export RVA from the DLL lies within the export table, you will need to handle forwarded export - ie, split the "NTDLL.HeapAlloc" string into DLL name and function name, and do LoadLibrary/GetModuleHandle + GetProcAddress.
Posted on 2004-05-01 07:40:51 by f0dder