Sunday, April 6, 2014

Retrieving an exported function address within a loaded module

Hi,
Today I came with a shellcode friendly blogpost , I didn't have time to write the code in ASM but I'll do it as soon as I have some time.
The goal of this small blogpost is retrieving a pointer to an exported function of choice within a loaded module and certainly without the use of any API calls. 
This method can be really effective against ASLR, the only condition that needs to be met is that the function must be exported by the loaded module.
The process of applying this technique consists of retrieving the base address of the loaded module by walking through a doubly linked list. The linked list head pointer can be found using : &(PEB->Ldr.InMemoryOrderModuleList)
To walk the linked list we'll be just interested in the Flink pointer. Besides being a pointer to another list entry it's also a pointer to a _LDR_DATA_TABLE_ENTRY structure which contains ,among other elements, the Module name and the Module Base.
After running the search : if the Base Address was successfully found , we must get the address of the Export directory within the loaded module . In order to do that we perform some basic PE parsing to find the DataDirectory Array.
The first element of this array "DataDirectory[0]" contains the RVA to the export directory within the module , so all we have to do is add the RVA to the base to get the address.
The key elements of the Export directory that we'll need are the following :

AddressOfNames : This is an array of  RVAs to ASCII strings which we'll use to search for the target function's RVA to name.

AddressOfNameOrdinals : This is an array of exported functions ordinals used as indexes to the AddressOfFunctions array.We will use the index found from AddressOfNames to retrieve the ordinal.

AddressOfFunctions : This is an array of function's RVAs , we will access this array using the ordinal that we retrieved previously in order to get the RVA to the exported function.
Finally All we have to do is Add the base address to the RVA and we'll get a valid pointer to the exported function.

Here's an example of getting a pointer to LoadLibraryA :

See you soon ;
Souhail.


3 comments:

  1. I think this will fail if the module you're looking for is the first in the linked list (if it's ModListHead) but this might be guaranteed to not be the case.

    ReplyDelete
    Replies
    1. Hi,
      I'm afraid that's not the case because ModListHead is initialized to point to the list's head (type : PLIST_ENTRY), and ModListHead->Flink gives us the first entry. Frequently on Windows the list heads are elements of different structures than the one they point to, so a head's next element is the first entry.

      Delete