Uninformed: Informative Information for the Uninformed

Vol 4» 2006.Jun

The Signature

For demonstration purposes the signature used is simple. All objects are allocated in NonPagedPool so only non-paged memory is enumerated for the search. The signature is detected as follows:

  1. Enumeration is performed by assuming the start of a pool block.
  2. The signature offset is added to this pointer.
  3. The assumed signature is compared with the OBJECT_HEADER->Type for the object type being searched for.
  4. The assumed POOL_HEADER->PoolType is compared to the objects known pool type.
  5. The assumed POOL_HEADER is validated using the function from section [*], ValidatePoolBlock.

The following is the function which sets up the parameters in order to perform the pool enumeration and validation of a block by a single PVOID signature. On a match, a callback is made using the pointer to the start of the matching block. As an alternative to the PVOID signature, the poolgrep.c code can easily be modified to accept either a structure to several signatures and offsets or a validation function pointer in order to perform a more complex signature validation.

NTSTATUS ScanPoolForExecutiveObjectByType (
    IN  PVOID           Object,
    IN  FOUND_BLOCK_CB  Callback,
    IN  PVOID           CallbackContext
) {
    NTSTATUS        ntStatus = STATUS_SUCCESS;
    PPOOL_HEADER    pPoolHdr;
    ULONG_PTR       blockSigOffset;
    ULONG_PTR       blockSignature;

    pObjHdr         = OBJECT_TO_OBJECT_HEADER( Object );
    pPoolHdr        = OBJHDR_TO_POOL_HEADER( pObjHdr );
    blockSigOffset  = (ULONG_PTR)&pObjHdr->Type - (ULONG_PTR)pObjHdr
                       + OBJHDR_TO_POOL_BLOCK_OFFSET(pObjHdr);
    blockSignature  = (ULONG_PTR)pObjHdr->Type;

    (VOID)ScanPoolForBlockBySignature(  pPoolHdr->PoolType - 1,
                                        0, // pPoolHdr->PoolTag OPTIONAL,
                                        CallbackContext );
    return ntStatus;