RtlDeleteElementGenericTablehas three primary steps. First of all it
uses the famous RtlLocateNodeGenericTable (ntdll.7C92147B) for
locating the element to be removed. It then calls the (exported) RtlDeleteto
actually remove the element. I will not go into the actual algorithm that
RtlDeleteimplements in order to remove elements from the tree, but one
thing that’s important about it is that after performing the actual removal it
also calls RtlSplayin order to restructure the table.
The last function call made by RtlDeleteElementGenericTable is
actually quite interesting. It appears to be a callback into user code, where the
callback function pointer is accessed from offset +20 in the TABLEstructure. It
is pretty easy to guess that this is the element-free callback that frees the mem-
ory allocated in the TABLE_ALLOCATE_ELEMENTcallback earlier. Here is a
prototype for TABLE_FREE_ELEMENT:
typedef void ( _stdcall * TABLE_FREE_ELEMENT) (
TABLE *pTable,
PVOID Element
);
There are two things to note here. First of all, TABLE_FREE_ELEMENTclearly
doesn’t have a return value, and if it does RtlDeleteElementGenericTable
certainly ignores it (see how right after the callback returns ALis set to 1). Sec-
ond, keep in mind that the Elementpointer is going to be a pointer to the begin-
ning of the NODEdata structure, and not to the beginning of the element’s data,
as you’ve been seeing all along. That’s because the caller allocated this entire
memory block, including the header, so it’s now up to the caller to free this entire
memory block.
RtlDeleteElementGenericTablereturns a Boolean that is set to TRUE
if an element is found by RtlLocateNodeGenericTable, and FALSEif
RtlLocateNodeGenericTablereturns NULL.
Putting the Pieces Together
Whenever a reversing session of this magnitude is completed, it is advisable to
prepare a little document that describes your findings. It is an elegant way to
summarize the information obtained while reversing, not to mention that
most of us tend to forget this stuff as soon as we get up to get a cup of coffee or
a glass of chocolate milk (my personal favorite).
The following listings can be seen as a formal definition of the generic table
API, which is based on the conclusions from our reversing sessions. Listing
5.11 presents the internal data structures, Listing 5.12 presents the callbacks
prototypes, and Listing 5.13 presents the function prototypes for the APIs.
194 Chapter 5