Differences between revisions 9 and 10
Revision 9 as of 2006-12-17 12:45:42
Size: 3413
Comment:
Revision 10 as of 2006-12-17 12:55:16
Size: 4283
Comment:
Deletions are marked like this. Additions are marked like this.
Line 41: Line 41:
Well, now you have the imported the function and can call it. Oh wait, can you? Unfortunately, you can't (unless you want to taste a sweet crash ;-)). Well, now you have the imported the function and can call it. Oh wait, can you? Unfortunately, you can't (unless you want to taste a sweet crash ;-)). The problem is this is a member method of an class so it expects the class instance to exist. Since we don't have any headers on static import library, there is no way to recover how the class is stored in the memory. The good news is we don't have to. As long as we stick to using member methods (do not try to access member variables directly), the class structure is completely hidden and unimportant. The only thing we have to do is allocate a block of memory to store the instance. Since we don't know what does the class signature looks like, we have to guess the size. It doesn't really matter if the allocated chunk is bigger, it just must not be smaller. A size of one megabyte could be considered safe but keep in mind that if you're going to make lots of "instances" the memory will be eaten quite fast (one kilobyte should be fine most classes but not all).

Importing classes from Windows DLLs

/!\ This is a work in progress...

GoogleAd()

What do we want to achieve

During the work on my school's final work I had to "steal" some functionality from binary-only Windows DLLs which were unfortunately written in C++ (object-oriented). There was no static import library available so the only option was to load the DLL at runtime. Since there is no real standard in how methods/classes should be exported I've found myself in quite hopeless situation. It's quite easy to use plain C functions imported from DLLs since you just find the correct function address and then call it (you have to know the return type and arguments it expects). In case of C++, class methods are exported as plain C functions and their names are mangled (so that you can have both Class1::DoSomething() and Class2::DoSomething()). Also, you don't really have to know the return type and arguments since their description is a part of the mangled name. The main problem here is how to use these functions as instance specific (ie. how to wrap the whole thing to make it look like you're using classes and their methods).

GoogleAd()

How to achieve that

Words of caution

The described method is an ugly hack and it's likely it crash your computer, steal all your money and rape your dog. You've been warned... :-)

This will work only on Windows (maybe only on Visual C++ compiler) on x86 architecture. Similar ugly hack is possible on other platforms as well but there are slight differences.

Method name de-mangling

There is no standard in how C++ method names should be mangled so the final function names are compiler-specific. Microsoft Visual C++ compiler mangles the names so they get exported as ??0SLNEPasswd@@QAE@ABV0@@Z or ?GetNEData@NACommDB@@QAE?AW4NAResult@1@VCString@@AAVNANEData@@@Z. Quite a mess, isn't it? Fortunately for us, the mangled named name contains all the information we need to successfully use the function in a object-oriented way. There are lots of tools laying around on the net which can be used to de-mangle the names to full method signatures. I've used IDA Pro (quite handy disassembler). Other tools should do fine, too. Here's some sample output:

; private: class CLBinary __thiscall SLNEPasswd::GetMD5Encryption(class CLBinary const &)
                public ?GetMD5Encryption@SLNEPasswd@@AAE?AVCLBinary@@ABV2@@Z
?GetMD5Encryption@SLNEPasswd@@AAE?AVCLBinary@@ABV2@@Z proc near

So now you know what the function expects as arguments and what it's going to return. Let's move on to how to actually call the function...

Windows C++ call convention

So far, we've been only studying the DLL. Now, let's get our hands dirty with all the ugliness I've mentioned before.

First, import the library using the LoadLibrary() WinAPI function. Then find the function address with GetProcAddress() call (use the mangled name). You get a generic function pointer so need to cast it a proper typed function pointer. Use what the disassembler told you to create a signature.

/!\ TODO: code sample?

Well, now you have the imported the function and can call it. Oh wait, can you? Unfortunately, you can't (unless you want to taste a sweet crash ;-)). The problem is this is a member method of an class so it expects the class instance to exist. Since we don't have any headers on static import library, there is no way to recover how the class is stored in the memory. The good news is we don't have to. As long as we stick to using member methods (do not try to access member variables directly), the class structure is completely hidden and unimportant. The only thing we have to do is allocate a block of memory to store the instance. Since we don't know what does the class signature looks like, we have to guess the size. It doesn't really matter if the allocated chunk is bigger, it just must not be smaller. A size of one megabyte could be considered safe but keep in mind that if you're going to make lots of "instances" the memory will be eaten quite fast (one kilobyte should be fine most classes but not all).

Bloody recursive imports

This is where the real fun starts.