Drawbacks of Hard-Encoding

Nothing can be simpler that calling API functions by absolute addresses. Having chosen a function (let it be the GetCurrentThreadId function exported by kernel32.dll), process it with the dumpbin utility supplied as part of practically any compiler. Having recognized the Relative Virtual Address (RVA) of the required function, it is necessary to add it to the base load address reported by dumpbin . As a result, the absolute address of the function will be obtained.

The complete session of working with the dumpbin utility appears as shown in Listing 11.3. Here, the absolute address of the GetCurrentThreadId function is determined by adding its RVA ( 76A1h ) to the base load address of the module ( 77E80000h ).

Listing 11.3: Determining absolute address of the GetCurrentThreadld function
image from book
 >dumpbin.exe /EXPORTS KERNEL32.DLL > KERNEL32.TXT >type KERNEL32.TXT  MORE ordinal hint RVA      name     270      10D 00007DD2 GetCurrentProcessId 271      10E 000076AB GetCurrentThread 272      10F  000076A1  GetCurrentThreadld 273      110 00017CE2 GetDateFormatA 274      111 00019E18 GetDateFormatW     >dumpbin.exe /HEADERS KERNEL32.DLL > KERNEL32.TXT >type KERNEL32.TXT  MORE     OPTIONAL HEADER VALUES              10B Magic #             5.12 Linker version            5D800 Size of code            56400 Size of initialized data                0 Size of uninitialized data             871D RVA of entry point             1000 Base of code            5A000 Base of data  77E80000  Image base             1000 Section alignment              200 File alignment ... 
image from book
 

On my machine, the absolute address of the GetCurrentThreadId function is equal to 77E876A1h ; however, in different versions of Windows NT it certainly will be different. Regardless, the call to this function easily fits within two lines of code (or 1 bytes), as shown in Listing 11.4.

Listing 11.4: Direct call to the API function by its absolute address
image from book
 00000000: B8A1867E07        MOV   EAX, 0077E86A1  00000005: FFDO              CALL  EAX 
image from book
 

Now try to call the connect function exported by ws2_32.dll. Process ws2_32.dll with dumpbin and Wait! Who promised that this DLL would be loaded into the memory? Furthermore, even if it happens to be loaded, no one can guarantee that the base address written in its header matches the actual base load address. After all, DLLs are numerous , and if this address is already occupied by another module, the operating system will load this library into another memory region.

Only two DLLs are guaranteed to be present in the address space of any process, and they always are loaded at the same addresses (the base load address of these DLLs is constant for a given operating system version). These are kernel32.dll and ntdlLdH. Functions exported by other libraries must be called as shown in Listing 11.5.

Listing 11.5: Pseudocode demonstrating the procedure of calling arbitrary functions
image from book
 h = LoadLibraryA("ws2_32.DLL") ; if (h != 0) __error__; zzz = GetProcAddress(h, "connect"); 
image from book
 

Thus, the task of calling an arbitrary function is reduced to searching addresses of the LoadLibraryA and GetProcAddress functions.



Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net