shows the data structures that are typically followed in order to find the base address for kernel32.dll (only relevant fields and offsets within each structure are shown).
AddressOfFunctions
is an array of RVAs that points to the actual export functions. It is indexed by an export ordinal (an alternative way of finding an exported symbol).The shellcode needs to map the export name to the ordinal in order to use this array, and it does so using the AddressOfNames
and AddressOfNameOrdinals
arrays. These two arrays exist in parallel. They have the same number of entries, and equivalent indices into these arrays are directly related. AddressOfNames
is an array of 32-bit RVAs that point to the strings of symbol names. AddressOfNameOrdinals
is an array of 16-bit ordinals. For a given index idx
into these arrays, the symbol at AddressOfNames[idx]
has the export ordinal value at AddressOfNameOrdinals[idx]
. The AddressOfNames
array is sorted alphabetically so that a binary search can quickly find a specific string, though most shellcode simply performs a linear search starting at the beginning of the array.
To find the export address of a symbol, follow these steps:
Iterate over the AddressOfNames
array looking at each char*
entry, and perform a string comparison against the desired symbol until a match is found. Call this index into AddressOfNames
iName
.
Index into the AddressOfNameOrdinals
array using iName
. The value retrieved is the value iOrdinal
.
Use iOrdinal
to index into the AddressOfFunctions
array. The value retrieved is the RVA of the exported symbol. Return this value to the requester.
A sample implementation of this algorithm is shown later in the chapter as part of a full Hello World example.