Finding VMAs
Upon obtaining the function ordinal, our next objective is to convert it into its corresponding Virtual Memory Address, as this is essential for invoking Win32 APIs.
Last updated
Upon obtaining the function ordinal, our next objective is to convert it into its corresponding Virtual Memory Address, as this is essential for invoking Win32 APIs.
Last updated
In the last section we were able to find functions in a module by name, this is only the first step in resolving the Virtual Memory Address (VMA) of a function. In order to call a function we need to know its VMA.
A VMA is a concept used in computer systems, particularly in the context of virtual memory management. It refers to a unique address or location in the virtual memory space of a process.
Virtual memory allows programs to operate on a larger address space than the physical memory (RAM) available in the system.
The Export Address Table (EAT) contains three lists:
When we looped over the AddressOfNames
table we found a match for our function name that we wanted to resolve. We can now find that index in the AddressOfNameOrdinals
which will point to the AddressOfFunctions
table which contains pointers to the VMA of that function.
We can continue from where we left off in the previous section (the addresses may have changed but the offsets are the same). We can see in the output below that third entry in the EAT is ActivateActCtx
at offset 0x9e3e5
in the AddressOfNames
table:
Next we can take a look at the AddressOfNameOrdinals
table. We can see that the third entry is the same index that the ActivateActCtx
is located at, so this is easy to resolve:
Finally we can look at the AddressOfFunctions
table at offset 0x1c
. We can then look at the third entry to get the offset address of 0x1be90
. If we uncompile this we find that we now have the VMA of KERNEL32!ActivateActCtxWorker
:
Now that we have resolved a VMA manually we can write some shellcode to do this automatically and on demand.
The shellcode to resolve the VMA of a function is shown below:
The shellcode corresponds to what we carried out manually using Windbg, it:
Locates the AddressOfNamesOrdinals
on lines 5
through 7
.
Uses the table to find the number of the function on line 9
. Notice that the table entries are 2 bytes in size.
Lines 11
through 13
are used to locate the AddressOfFunctions
table.
Uses the table to locate the offset of the function on line 16
.
Adds this offset to the base address of kernel32.dll
on line 17
.
Finally the address is stored in rdi
and the function returns.
In the next section we will put everything we have learned together to create shellcode that displays a message box.