Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2858 lines
82 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
regext.c
Abstract:
Kernel debugger extensions useful for the registry
Author:
John Vert (jvert) 7-Sep-1993
Environment:
Loaded as a kernel debugger extension
Revision History:
John Vert (jvert) 7-Sep-1993
created
Dragos C. Sambotin (dragoss) 05-May-2000
updated to support new registry layout
enhanced with new commands
--*/
#include "precomp.h"
#pragma hdrstop
ULONG TotalPages;
ULONG TotalPresentPages;
PCHAR pc;
BOOLEAN SavePages;
BOOLEAN RestorePages;
HANDLE TempFile;
ULONG64 gHiveListAddr;
static ULONG DirectoryOffset, TableOffset, BlockAddrOffset, PtrSize, ULongSize, HMapSize, GotOnce = FALSE;
void
poolDumpHive(
IN ULONG64 Hive
);
VOID
poolDumpMap(
IN ULONG Length,
IN ULONG64 Map
);
void
dumpHiveFromFile(
HANDLE hFile
);
void
regdumppool(
LPSTR args
)
/*++
Routine Description:
Goes through all the paged pool allocated to registry space and
determines which pages are present and which are not.
Called as:
!regpool [s|r]
s Save list of registry pages to temporary file
r Restore list of registry pages from temp. file
Arguments:
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the pattern and expression for this
command.
Return Value:
None.
--*/
{
ULONG64 pCmpHiveListHead;
ULONG64 pNextHiveList;
ULONG64 pHiveListEntry;
ULONG BytesRead;
ULONG64 CmHive;
BYTE HiveList[1024];
CHAR Dummy1[ 256 ],Dummy2[64];
if (sscanf(args,"%s %I64lX",Dummy1,Dummy2)) {
Dummy2[0] = 0;
}
if (toupper(Dummy2[0])=='S') {
SavePages = TRUE;
} else {
SavePages = FALSE;
}
if (toupper(Dummy2[0])=='R') {
RestorePages = TRUE;
} else {
RestorePages = FALSE;
}
//
// Go get the hivelist.
//
// memset(HiveList,0,sizeof(HiveList));
pHiveListEntry = GetExpression("nt!CmpMachineHiveList");
gHiveListAddr = pHiveListEntry;
if (pHiveListEntry != 0) {
// Kd caches hive list
ReadMemory(pHiveListEntry,
HiveList,
8 * GetTypeSize("_HIVE_LIST_ENTRY"),
&BytesRead);
}
//
// First go and get the hivelisthead
//
pCmpHiveListHead = GetExpression("nt!CmpHiveListHead");
if (pCmpHiveListHead==0) {
dprintf("CmpHiveListHead couldn't be read\n");
return;
}
if (!ReadPointer(pCmpHiveListHead, &pNextHiveList)) {
dprintf("Couldn't read first Flink (%p) of CmpHiveList\n",
pCmpHiveListHead);
return;
}
TotalPages = TotalPresentPages = 0;
if (SavePages || RestorePages) {
TempFile = CreateFile( "regext.dat",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
0,
NULL
);
if (TempFile == INVALID_HANDLE_VALUE) {
dprintf("Couldn't open regext.dat\n");
return;
}
}
if (RestorePages) {
dumpHiveFromFile(TempFile);
} else {
ULONG HiveListOffset;
FIELD_INFO offField = {"HiveList", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
// Get The offset
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
return;
}
HiveListOffset = (ULONG) offField.address;
while (pNextHiveList != pCmpHiveListHead) {
CmHive = pNextHiveList - HiveListOffset;
poolDumpHive(CmHive);
if (GetFieldValue(pNextHiveList, "_LIST_ENTRY", "Flink", pNextHiveList)) {
dprintf("Couldn't read Flink (%p) of %p\n",
pCmpHiveListHead,pNextHiveList);
break;
}
if (CheckControlC()) {
return;
}
}
}
dprintf("Total pages present = %d / %d\n",
TotalPresentPages,
TotalPages);
if (SavePages || RestorePages) {
CloseHandle( TempFile );
}
}
BOOLEAN
GetHiveMaps(
ULONG64 pHive,
ULONG64 *pStableMap,
ULONG *pStableLength,
ULONG64 *pVolatileMap,
ULONG *pVolatileLength
)
{
ULONG BytesRead;
ULONG Stable_Length=0, Volatile_Length=0;
ULONG64 Stable_Map=0, Volatile_Map=0;
ULONG StorageOffset, DUAL_Size;
FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
// Get the offset of Hive.Storage in _CMHIVE
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
dprintf("Cannot find _CMHIVE type.\n");
return FALSE;
}
StorageOffset = (ULONG) offField.address;
DUAL_Size = GetTypeSize("_DUAL");
GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Length", Stable_Length);
GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Length", Volatile_Length);
GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Map", Stable_Map);
GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Map", Volatile_Map);
(*pStableMap) = Stable_Map;
(*pStableLength) = Stable_Length;
(*pVolatileMap) = Volatile_Map;
(*pVolatileLength) = Volatile_Length;
return TRUE;
}
BOOLEAN
USE_OLD_CELL(
ULONG64 pHive
)
{
ULONG Version;
if(!GetFieldValue(pHive, "_CMHIVE", "Hive.Version", Version)) {
return (Version==1);
}
return FALSE;
}
ULONG64
MyHvpGetCellPaged(
ULONG64 pHive,
ULONG Cell
)
/*++
Routine Description:
Returns the memory address for the specified Cell. Will never
return failure, but may assert. Use HvIsCellAllocated to check
validity of Cell.
This routine should never be called directly, always call it
via the HvGetCell() macro.
This routine provides GetCell support for hives with full maps.
It is the normal version of the routine.
Arguments:
Hive - supplies a pointer to the hive control structure for the
hive of interest
Cell - supplies HCELL_INDEX of cell to return address for
Return Value:
Address of Cell in memory. Assert or BugCheck if error.
--*/
{
ULONG Type;
ULONG Table;
ULONG Block;
ULONG Offset;
ULONG Stable_Length=0, Volatile_Length=0;
ULONG64 Stable_Map=0, Volatile_Map=0;
ULONG64 MapTable;
ULONG64 Map;
ULONG64 MapEntryAddress, BlockAddress=0;
ULONG64 lRez;
ULONG64 pcell;
if(!GetHiveMaps(pHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
return 0;
}
Type = ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT));
Table = (Cell & HCELL_TABLE_MASK) >> HCELL_TABLE_SHIFT;
Block = (Cell & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
Offset = (Cell & HCELL_OFFSET_MASK);
if( Type == 0 ) {
Map = Stable_Map;
} else {
Map = Volatile_Map;
}
dprintf("Map = %p Type = %lx Table = %lx Block = %lx Offset = %lx\n",Map,Type,Table,Block,Offset);
if (!ReadPointer(Map + DirectoryOffset + Table*PtrSize,
&MapTable))
return 0;
dprintf("MapTable = %p \n",MapTable);
MapEntryAddress = MapTable + Block * HMapSize + BlockAddrOffset;
if (!ReadPointer(MapEntryAddress, &BlockAddress)) {
dprintf(" can't read HMAP_ENTRY at %p\n",
MapEntryAddress);
return 0;
}
dprintf("BlockAddress = %p \n\n",BlockAddress);
pcell = ((ULONG64)(BlockAddress) + Offset);
lRez = (ULONG64)pcell;
if (USE_OLD_CELL(pHive)) {
return lRez + ULongSize + ULongSize;
//return (struct _CELL_DATA *)&(hcell.u.OldCell.u.UserData);
} else {
return lRez + ULongSize;
//return (struct _CELL_DATA *)&(hcell.u.NewCell.u.UserData);
}
return 0;
}
ULONG64
MyHvpGetCellFlat(
ULONG64 pHive,
ULONG Cell
)
/*++
Routine Description:
Returns the memory address for the specified Cell. Will never
return failure, but may assert. Use HvIsCellAllocated to check
validity of Cell.
This routine should never be called directly, always call it
via the HvGetCell() macro.
This routine provides GetCell support for read only hives with
single allocation flat images. Such hives do not have cell
maps ("page tables"), instead, we compute addresses by
arithmetic against the base image address.
Such hives cannot have volatile cells.
Arguments:
Hive - supplies a pointer to the hive control structure for the
hive of interest
Cell - supplies HCELL_INDEX of cell to return address for
Return Value:
Address of Cell in memory. Assert or BugCheck if error.
--*/
{
ULONG64 BaseBlock;
ULONG64 lRez;
if (GetFieldValue(pHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
dprintf("\tCan't CMHIVE Read from %p\n",pHive);
return 0;
}
//
// Address is base of Hive image + Cell
//
lRez = (ULONG64)BaseBlock + HBLOCK_SIZE + Cell;
if (USE_OLD_CELL(pHive)) {
return lRez + ULongSize + ULongSize;
//return (struct _CELL_DATA *)&(pcell->u.OldCell.u.UserData);
} else {
return lRez + ULongSize;
//return (struct _CELL_DATA *)&(pcell->u.NewCell.u.UserData);
}
return 0;
}
void
poolDumpHive(
IN ULONG64 pHive
)
{
ULONG BytesRead;
WCHAR FileName[HBASE_NAME_ALLOC/2 + 1];
CHAR buf[512];
ULONG cb;
ULONG Stable_Length=0, Volatile_Length=0;
ULONG64 Stable_Map=0, Volatile_Map=0;
ULONG64 BaseBlock;
ULONG StorageOffset, DUAL_Size;
FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
// Get the offset of Hive.Storage in _CMHIVE
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
dprintf("Cannot find _CMHIVE type.\n");
return ;
}
StorageOffset = (ULONG) offField.address;
dprintf("\ndumping hive at %p ",pHive);
if (GetFieldValue(pHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
dprintf("\tCan't CMHIVE Read from %p\n",pHive);
return;
}
if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
wcscpy(FileName, L"UNKNOWN");
} else {
if (FileName[0]==L'\0') {
wcscpy(FileName, L"NONAME");
} else {
FileName[HBASE_NAME_ALLOC/2]=L'\0';
}
}
dprintf("(%ws)\n",FileName);
DUAL_Size = GetTypeSize("_DUAL");
GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Length", Stable_Length);
GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Length", Volatile_Length);
GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Map", Stable_Map);
GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Map", Volatile_Map);
dprintf(" Stable Length = %lx\n",Stable_Length);
if (SavePages) {
sprintf(buf,
"%ws %d %d\n",
FileName,
Stable_Length,
Volatile_Length);
WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
}
poolDumpMap(Stable_Length, Stable_Map);
dprintf(" Volatile Length = %lx\n",Volatile_Length);
poolDumpMap(Volatile_Length, Volatile_Map);
}
VOID
poolDumpMap(
IN ULONG Length,
IN ULONG64 Map
)
{
ULONG Tables;
ULONG MapSlots;
ULONG i;
ULONG BytesRead;
ULONG64 MapTable;
ULONG Garbage;
ULONG Present=0;
CHAR buf[512];
ULONG cb;
// Get the offsets
if (!GotOnce) {
if (GetFieldOffset("_HMAP_DIRECTORY", "Directory", &DirectoryOffset)){
return;
}
if (GetFieldOffset("_HMAP_ENTRY", "BlockAddress", &BlockAddrOffset)) {
return;
}
if (GetFieldOffset("_HMAP_TABLE", "Table", &TableOffset)) {
return;
}
PtrSize = DBG_PTR_SIZE;
ULongSize = sizeof(ULONG); // This doesn't change with target GetTypeSize("ULONG");
HMapSize = GetTypeSize("_HMAP_ENTRY");
GotOnce = TRUE;
}
if (Length==0) {
return;
}
MapSlots = Length / HBLOCK_SIZE;
Tables = 1+ ((MapSlots-1) / HTABLE_SLOTS);
//
// read in map directory
//
// ReadMemory((DWORD)Map,
// &MapDirectory,
// Tables * sizeof(PHMAP_TABLE),
// &BytesRead);
/* if (BytesRead < (Tables * sizeof(PHMAP_TABLE))) {
dprintf("Only read %lx/%lx bytes from %lx\n",
BytesRead,
Tables * sizeof(PHMAP_TABLE),
Map);
return;
}*/
//
// check out each map entry
//
for (i=0; i<MapSlots; i++) {
ULONG64 MapEntryAddress, BlockAddress=0;
if (!ReadPointer(Map + DirectoryOffset + (i/HTABLE_SLOTS)*PtrSize,
&MapTable))
return;
MapEntryAddress = MapTable + TableOffset + (i%HTABLE_SLOTS) * PtrSize;
if (!ReadPointer(MapEntryAddress, &BlockAddress)) {
dprintf(" can't read HMAP_ENTRY at %p\n",
MapEntryAddress);
}
if (SavePages) {
sprintf(buf, "%p\n",BlockAddress);
WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
}
//
// probe the HBLOCK
//
ReadMemory( BlockAddress,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
if (CheckControlC()) {
return;
}
}
dprintf(" %d/%d pages present\n",
Present,
MapSlots);
TotalPages += MapSlots;
TotalPresentPages += Present;
}
void
dumpHiveFromFile(
HANDLE hFile
)
/*++
Routine Description:
Takes a list of the registry hives and pages from a file and
checks to see how many of the pages are in memory.
The format of the file is as follows
hivename stablelength volatilelength
stable page address
stable page address
.
.
.
volatile page address
volatile page address
.
.
.
hivename stablelength volatilelength
.
.
.
Arguments:
File - Supplies a file.
Return Value:
None.
--*/
{
#if 0
CHAR Hivename[33];
ULONG StableLength;
ULONG VolatileLength;
ULONG64 Page;
ULONG NumFields;
ULONG Garbage;
ULONG Present;
ULONG Total;
ULONG BytesRead;
BYTE buf[512];
while (!feof(File)) {
NumFields = fscanf(File,"%s %d %d\n",
Hivename,
&StableLength,
&VolatileLength);
if (NumFields != 3) {
dprintf("fscanf returned %d\n",NumFields);
return;
}
dprintf("\ndumping hive %s\n",Hivename);
dprintf(" Stable Length = %lx\n",StableLength);
Present = 0;
Total = 0;
while (StableLength > 0) {
fscanf(File, "%I64lx\n",&Page);
ReadMemory((DWORD)Page,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
++Total;
StableLength -= HBLOCK_SIZE;
}
if (Total > 0) {
dprintf(" %d/%d stable pages present\n",
Present,Total);
}
TotalPages += Total;
TotalPresentPages += Present;
dprintf(" Volatile Length = %lx\n",VolatileLength);
Present = 0;
Total = 0;
while (VolatileLength > 0) {
fscanf(File, "%lx\n",&Page);
ReadMemory(Page,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
++Total;
VolatileLength -= HBLOCK_SIZE;
}
if (Total > 0) {
dprintf(" %d/%d volatile pages present\n",
Present,Total);
}
TotalPages += Total;
TotalPresentPages += Present;
}
#endif //0
}
USHORT
GetKcbName(
ULONG64 KcbAddr,
PWCHAR NameBuffer,
ULONG BufferSize
)
/*++
Routine Description:
Takes a kcb and dump its complete name.
Arguments:
KcbAddr - Address of key control block.
NameBuffer - The Name buffer to fill in the name.
BufferSize - Size of Buffer.
Return Value:
Size of Name String.
--*/
{
WCHAR Name[ 256 ];
ULONG64 TmpKcbAddr;
ULONG64 NameBlockAddr;
DWORD BytesRead;
ULONG Length;
ULONG TotalLength;
ULONG size;
ULONG i;
ULONG BeginPosition;
ULONG NameOffset;
WCHAR *w1, *w2;
WCHAR *BufferEnd;
UCHAR *u2;
//
// Calculate the total string length.
//
TotalLength = 0;
TmpKcbAddr = KcbAddr;
// dprintf("Kcb %p ", KcbAddr);
while (TmpKcbAddr) {
ULONG Compressed=0, NameLength=0;
if (GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "NameBlock", NameBlockAddr)) {
dprintf("Cannot find CM_KEY_CONTROL_BLOCK type.\n");
return 0;
}
if (GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "Compressed", Compressed) ||
GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "NameLength", NameLength)) {
dprintf("Cannot find type _CM_NAME_CONTROL_BLOCK.\n");
return 0;
}
if (Compressed) {
Length = NameLength * sizeof(WCHAR);
} else {
Length = NameLength;
}
TotalLength += Length;
//
// Add the sapce for OBJ_NAME_PATH_SEPARATOR;
//
TotalLength += sizeof(WCHAR);
GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", TmpKcbAddr);
if (CheckControlC()) {
return 0;
}
}
BufferEnd = &(NameBuffer[BufferSize/sizeof(WCHAR) - 1]);
if (TotalLength < BufferSize) {
NameBuffer[TotalLength/sizeof(WCHAR)] = UNICODE_NULL;
} else {
*BufferEnd = UNICODE_NULL;
}
//
// Now fill the name into the buffer.
//
TmpKcbAddr = KcbAddr;
BeginPosition = TotalLength;
GetFieldOffset("CM_NAME_CONTROL_BLOCK", "Name", &NameOffset);
while (TmpKcbAddr) {
ULONG NameLength=0, Compressed=0;
//
// Read the information.
//
if (GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "NameBlock", NameBlockAddr)) {
dprintf("Cannot find CM_KEY_CONTROL_BLOCK type.\n");
return 0;
}
if (GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "Compressed", Compressed) ||
GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "NameLength", NameLength)) {
dprintf("Cannot find type _CM_NAME_CONTROL_BLOCK.\n");
return 0;
}
if (NameLength > sizeof(Name)) {
NameLength = sizeof(Name);
}
ReadMemory(NameBlockAddr + NameOffset,// FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name),
Name,
NameLength,
&BytesRead);
if (BytesRead < NameLength) {
dprintf("Could not read Name BUFFER: 5\n");
return (0);
}
//
// Calculate the begin position of each subkey. Then fill in the char.
//
if (Compressed) {
BeginPosition -= (NameLength + 1) * sizeof(WCHAR);
w1 = &(NameBuffer[BeginPosition/sizeof(WCHAR)]);
if (w1 < BufferEnd) {
*w1 = OBJ_NAME_PATH_SEPARATOR;
}
w1++;
u2 = (UCHAR *) &(Name[0]);
for (i=0; i<NameLength; i++) {
if (w1 < BufferEnd) {
*w1 = (WCHAR)(*u2);
} else {
break;
}
w1++;
u2++;
}
} else {
BeginPosition -= (NameLength + sizeof(WCHAR));
w1 = &(NameBuffer[BeginPosition/sizeof(WCHAR)]);
if (w1 < BufferEnd) {
*w1 = OBJ_NAME_PATH_SEPARATOR;
}
w1++;
w2 = Name;
for (i=0; i<NameLength; i=i+sizeof(WCHAR)) {
if (w1 < BufferEnd) {
*w1 = *w2;
} else {
break;
}
w1++;
w2++;
}
}
GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", TmpKcbAddr);
}
// dprintf("\n%5d, %ws\n", TotalLength, NameBuffer);
return ((USHORT) TotalLength);
}
#define CMP_CELL_CACHED_MASK 1
#define CMP_IS_CELL_CACHED(Cell) ((ULONG64) (Cell) & CMP_CELL_CACHED_MASK)
#define CMP_GET_CACHED_ADDRESS(Cell) (((ULONG64) (Cell)) & ~CMP_CELL_CACHED_MASK)
void
regkcb(
LPSTR args
)
/*++
Routine Description:
Dumps the name when given a KCB address
Called as:
!regkcb KCB_Address
Arguments:
args - Supplies the address of the KCB.
Return Value:
.
--*/
{
WCHAR KeyName[ 256 ];
ULONG64 KcbAddr, ParentKcbAddr, KeyHiveAddr, IndexHintAddr,RealKcb;
DWORD BytesRead;
ULONG ExtFlags, Delete, Flags, KeyCell, KcbMaxNameLen, KcbMaxValueNameLen,KcbMaxValueDataLen,SubKeyCount,ValueCount;
ULONG ValueCacheOffset,i,CellIndex;
ULONG64 ValueList,ValueAddr,CellData;
USHORT RefCount, TotalLevels;
SHORT DelayedCloseIndex;
LARGE_INTEGER KcbLastWriteTime;
CHAR Dummy[ 256 ];
ULONG KeyBodyListHeadOffset;
if (sscanf(args,"%s %lX",Dummy,&KcbAddr)) {
KcbAddr = GetExpression(args + strlen(Dummy));
}
if (GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "ExtFlags", ExtFlags) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "Flags", Flags) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "Delete", Delete) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "RefCount", RefCount) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", ParentKcbAddr) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KeyHive", KeyHiveAddr) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KeyCell", KeyCell) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "TotalLevels", TotalLevels) ||
GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "DelayedCloseIndex", DelayedCloseIndex)
) {
dprintf("Could not read Kcb\n");
return;
}
if(GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
dprintf("Key : %ws\n", KeyName);
} else {
dprintf("Could not read key name\n");
return;
}
dprintf("RefCount : %lx\n", RefCount);
dprintf("Flags :");
if (Delete) {
dprintf(" Deleted,");
}
if (Flags & KEY_COMP_NAME) {
dprintf(" CompressedName,");
}
if (Flags & KEY_PREDEF_HANDLE) {
dprintf(" PredefinedHandle,");
}
if (Flags & KEY_SYM_LINK) {
dprintf(" SymbolicLink,");
}
if (Flags & KEY_NO_DELETE) {
dprintf(" NoDelete,");
}
if (Flags & KEY_HIVE_EXIT) {
dprintf(" HiveExit,");
}
if (Flags & KEY_HIVE_ENTRY) {
dprintf(" HiveEntry,");
}
if (Flags & KEY_VOLATILE) {
dprintf(" Volatile");
} else {
dprintf(" Stable");
}
dprintf("\n");
dprintf("ExtFlags :");
if (ExtFlags & CM_KCB_KEY_NON_EXIST) {
dprintf(" Fake,");
}
if (ExtFlags & CM_KCB_SYM_LINK_FOUND) {
dprintf(" SymbolicLinkFound,");
}
if (ExtFlags & CM_KCB_NO_DELAY_CLOSE) {
dprintf(" NoDelayClose,");
}
if (ExtFlags & CM_KCB_INVALID_CACHED_INFO) {
dprintf(" InvalidCachedInfo,");
}
if (ExtFlags & CM_KCB_NO_SUBKEY) {
dprintf(" NoSubKey,");
}
if (ExtFlags & CM_KCB_SUBKEY_ONE) {
dprintf(" SubKeyOne,");
}
if (ExtFlags & CM_KCB_SUBKEY_HINT) {
dprintf(" SubKeyHint");
}
dprintf("\n");
dprintf("Parent : 0x%p\n", ParentKcbAddr);
dprintf("KeyHive : 0x%p\n", KeyHiveAddr);
dprintf("KeyCell : 0x%lx [cell index]\n", KeyCell);
dprintf("TotalLevels : %u\n", TotalLevels);
dprintf("DelayedCloseIndex: %d\n", DelayedCloseIndex);
if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxNameLen", KcbMaxNameLen)) {
dprintf("MaxNameLen : 0x%lx\n", KcbMaxNameLen);
}
if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxValueNameLen", KcbMaxValueNameLen)) {
dprintf("MaxValueNameLen : 0x%lx\n", KcbMaxValueNameLen);
}
if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxValueDataLen", KcbMaxValueDataLen)) {
dprintf("MaxValueDataLen : 0x%lx\n", KcbMaxValueDataLen);
}
if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbLastWriteTime", KcbLastWriteTime)) {
dprintf("LastWriteTime : 0x%8lx:0x%8lx\n", KcbLastWriteTime.HighPart,KcbLastWriteTime.LowPart);
}
if( !GetFieldOffset("CM_KEY_CONTROL_BLOCK", "KeyBodyListHead", &KeyBodyListHeadOffset) ) {
ParentKcbAddr = KcbAddr + KeyBodyListHeadOffset;
dprintf("KeyBodyListHead : ");
if (!GetFieldValue(ParentKcbAddr, "_LIST_ENTRY", "Flink", KeyHiveAddr)) {
dprintf("0x%p ", KeyHiveAddr);
}
if (!GetFieldValue(ParentKcbAddr, "_LIST_ENTRY", "Blink", KeyHiveAddr)) {
dprintf("0x%p", KeyHiveAddr);
}
dprintf("\n");
}
if(!(Flags&KEY_HIVE_ENTRY)) {
dprintf("SubKeyCount : ");
if( !(ExtFlags & CM_KCB_INVALID_CACHED_INFO) ) {
if (ExtFlags & CM_KCB_NO_SUBKEY ) {
dprintf("0");
} else if (ExtFlags & CM_KCB_SUBKEY_ONE ) {
dprintf("1");
} else if (ExtFlags & CM_KCB_SUBKEY_HINT ) {
if( !GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "IndexHint", IndexHintAddr) ) {
if( !GetFieldValue(IndexHintAddr, "CM_INDEX_HINT_BLOCK", "Count", SubKeyCount) ) {
dprintf("%lu",SubKeyCount);
}
}
} else {
if( !GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "SubKeyCount", SubKeyCount) ) {
dprintf("%lu",SubKeyCount);
}
}
} else {
dprintf("hint not valid");
}
dprintf("\n");
}
GetFieldOffset("CM_KEY_CONTROL_BLOCK", "ValueCache", &ValueCacheOffset);
if( ExtFlags & CM_KCB_SYM_LINK_FOUND ) {
if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "RealKcb", RealKcb)) {
dprintf("RealKcb : 0x%p\n", RealKcb);
}
} else {
if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "Count", ValueCount)) {
dprintf("ValueCache.Count : %lu\n", ValueCount);
if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "ValueList", ValueList)) {
if (CMP_IS_CELL_CACHED(ValueList)) {
ValueList = CMP_GET_CACHED_ADDRESS(ValueList);
if(!GetFieldValue(ValueList, "_CM_CACHED_VALUE_INDEX", "CellIndex", CellIndex) ) {
dprintf("ValueList : 0x%lx\n", CellIndex);
GetFieldOffset("_CM_CACHED_VALUE_INDEX", "Data.CellData", &ValueCacheOffset);
ValueList += ValueCacheOffset;
for (i = 0; i < ValueCount; i++) {
dprintf(" ValueList[%2lu] = ",i);
ReadMemory(ValueList + i*PtrSize, &ValueAddr, PtrSize, &BytesRead);
if (BytesRead < PtrSize) {
dprintf("Couldn't read memory\n");
} else {
dprintf(" 0x%p\n",ValueAddr);
}
}
}
} else {
dprintf("ValueCache.List : 0x%p\n", ValueList);
}
}
}
}
}
//
// Miscelaneous Hash routines
//
ULONG CmpHashTableSize = 0;
#define RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */
#define RNDM_PRIME 1000000007 /* prime number, also used for scrambling */
#define HASH_KEY(_convkey_) ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)
#define GET_HASH_INDEX(Key) HASH_KEY(Key) % CmpHashTableSize
#define GET_HASH_ENTRY(Table, Key) Table[GET_HASH_INDEX(Key)]
void
regopenkeys(
LPSTR args,
LPSTR subkey
)
/*++
Routine Description:
Dumps the registry hash table
Called as:
!openkeys <HiveAddr|0>
Arguments:
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the pattern and expression for this
command.
Return Value:
None.
--*/
{
DWORD64 TableSizeAddr;
DWORD64 HashTableAddr;
ULONG64 HashTable;
DWORD i;
ULONG64 KcbAddr;
WCHAR KeyName[ 256 ];
ULONG64 HashEntryAddr;
DWORD BytesRead;
ULONG KeyHashOffset;
BOOLEAN First;
ULONG64 TargetHive = 0;
CHAR Dummy[ 256 ];
ULONG ConvKey = 0;
ULONG j,Count;
ULONG SearchedIndex;
WCHAR FullKeyName[ 512 ];
TableSizeAddr = GetExpression("nt!CmpHashTableSize");
if (TableSizeAddr == 0) {
dprintf("Couldn't find address of CmpHashTableSize\n");
return;
}
HashTableAddr = GetExpression("nt!CmpCacheTable");
if (HashTableAddr == 0) {
dprintf("Couldn't find address of CmpCacheTable\n");
return;
}
ReadMemory(TableSizeAddr, &CmpHashTableSize, sizeof(CmpHashTableSize), &BytesRead);
if (BytesRead < sizeof(CmpHashTableSize)) {
dprintf("Couldn't get CmpHashTableSize from %08p\n",TableSizeAddr);
return;
}
if (!ReadPointer(HashTableAddr, &HashTable)) {
dprintf("Couldn't get CmpCacheTable from %08p\n",HashTableAddr);
return;
}
if( subkey == NULL ) {
if (sscanf(args,"%s %lX",Dummy,&TargetHive)) {
TargetHive = GetExpression(args + strlen(Dummy));
}
i=0;
SearchedIndex = CmpHashTableSize - 1;
} else {
for( Count=0;subkey[Count];Count++) {
FullKeyName[Count] = (WCHAR)subkey[Count];
if( FullKeyName[Count] != OBJ_NAME_PATH_SEPARATOR ) {
ConvKey = 37 * ConvKey + (ULONG) RtlUpcaseUnicodeChar(FullKeyName[Count]);
}
}
FullKeyName[Count] = UNICODE_NULL;
SearchedIndex = GET_HASH_INDEX(ConvKey);
i=SearchedIndex;
}
GetFieldOffset("CM_KEY_CONTROL_BLOCK", "KeyHash", &KeyHashOffset);
for (; i<=SearchedIndex; i++) {
if (CheckControlC()) {
return;
}
if (!ReadPointer(HashTable + i*PtrSize,&HashEntryAddr)) {
dprintf("Couldn't get HashEntryAddr from %08p\n", HashTable + i*PtrSize);
continue;
}
if (HashEntryAddr != 0) {
First = TRUE;
while (HashEntryAddr != 0) {
#define KcbFld(F) GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", #F, F)
ULONG64 KeyHive, NextHash;
ULONG ConvKey, KeyCell, Flags, ExtFlags;
KcbAddr = HashEntryAddr - KeyHashOffset;
if (KcbFld(ConvKey)) {
dprintf("Couldn't get HashEntry from %08lx\n", HashEntryAddr);
break;
}
KcbFld(KeyHive); KcbFld(KeyCell);
KcbFld(Flags); KcbFld(ExtFlags); KcbFld(NextHash);
if( subkey == NULL ) {
if( (TargetHive == 0) || ((ULONG64)TargetHive == (ULONG64)KeyHive) ) {
if( !First ) {
dprintf("\t");
} else {
dprintf("Index %x: ",i);
}
dprintf("\t %08lx kcb=%p cell=%08lx f=%04lx%04lx ",
ConvKey,
KcbAddr,
KeyCell,
Flags,
ExtFlags);
First = FALSE;
if (GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
dprintf("%ws\n", KeyName);
}
}
} else {
//
// findkcb case
//
if (GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
for(j=0;KeyName[j] != UNICODE_NULL;j++);
if( (j == Count) && (_wcsnicmp(FullKeyName,KeyName,Count) == 0) ) {
dprintf("\nFound KCB = %p :: %ws\n\n",KcbAddr,KeyName);
return;
}
}
}
HashEntryAddr = NextHash;
if (CheckControlC()) {
return;
}
#undef KcbFld
}
}
}
if( subkey != NULL ) {
dprintf("\nSorry <%ws> is not cached \n\n",FullKeyName);
}
}
void
regcellindex(
LPSTR args
)
/*++
Routine Description:
Dumps the name when given a KCB address
Called as:
!cellindex HiveAddr HCELL_INDEX
Arguments:
args - Supplies the address of the HCELL_INDEX.
Return Value:
.
--*/
{
ULONG64 HiveAddr;
ULONG IdxAddr;
ULONG64 pcell;
BOOLEAN Flat;
CHAR Dummy[ 256 ];
if (sscanf(args,"%s %lX %lx",Dummy,&HiveAddr,&IdxAddr)) {
if (GetExpressionEx(args + strlen(Dummy), &HiveAddr, &args)) {
IdxAddr = (ULONG) GetExpression(args);
}
}
if(!GetFieldValue(HiveAddr, "HHIVE", "Flat", Flat) ){
if(Flat) {
pcell = MyHvpGetCellFlat(HiveAddr,IdxAddr);
} else {
pcell = MyHvpGetCellPaged(HiveAddr,IdxAddr);
}
dprintf("pcell: %p\n",pcell);
} else {
dprintf("could not read hive\n");
}
}
void
reghashindex (
LPSTR args
)
/*++
Routine Description:
display the index for the convkey
Called as:
!hashindex conv_key
Arguments:
args - convkey.
Return Value:
.
--*/
{
ULONG ConvKey;
CHAR Dummy[ 256 ];
DWORD64 TableSizeAddr;
DWORD64 HashTableAddr;
ULONG64 HashTable;
DWORD BytesRead;
ULONG Index;
if (!sscanf(args,"%s %lx",Dummy,&ConvKey)) {
ConvKey = 0;
}
TableSizeAddr = GetExpression("nt!CmpHashTableSize");
if (TableSizeAddr == 0) {
dprintf("Couldn't find address of CmpHashTableSize\n");
return;
}
ReadMemory(TableSizeAddr, &CmpHashTableSize, sizeof(CmpHashTableSize), &BytesRead);
if (BytesRead < sizeof(CmpHashTableSize)) {
dprintf("Couldn't get CmpHashTableSize from %08p\n",TableSizeAddr);
return;
}
HashTableAddr = GetExpression("nt!CmpCacheTable");
if (HashTableAddr == 0) {
dprintf("Couldn't find address of CmpCacheTable\n");
return ;
}
if (!ReadPointer(HashTableAddr, &HashTable)) {
dprintf("Couldn't get CmpCacheTable from %08p\n",HashTableAddr);
return;
} else {
dprintf("CmpCacheTable = %p\n\n",HashTable);
}
Index = GET_HASH_INDEX(ConvKey);
HashTable += Index*PtrSize;
dprintf("Hash Index[%8lx] : %lx\n",ConvKey,Index);
dprintf("Hash Entry[%8lx] : %p\n",ConvKey,HashTable);
}
void
regknode(
LPSTR args
)
/*++
Routine Description:
Dumps the name when given a KCB address
Called as:
!knode KNode_Address
Arguments:
args - Supplies the address of the CM_KEY_NODE.
Return Value:
.
--*/
{
char KeyName[ 256 ];
ULONG64 KnodeAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
USHORT Signature,Flags,NameLength;
LARGE_INTEGER LastWriteTime;
ULONG Parent,MaxNameLen,MaxClassLen,MaxValueNameLen,MaxValueDataLen,Security,Class;
ULONG KeyNameOffset,Count,ValueList;
ULONG SubKeys[4];
if (sscanf(args,"%s %lX",Dummy,&KnodeAddr)) {
KnodeAddr = GetExpression(args + strlen(Dummy));
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Signature", Signature) ) {
if( Signature == CM_KEY_NODE_SIGNATURE) {
dprintf("Signature: CM_KEY_NODE_SIGNATURE (kn)\n");
} else if(Signature == CM_LINK_NODE_SIGNATURE) {
dprintf("Signature: CM_LINK_NODE_SIGNATURE (kl)\n");
} else {
dprintf("Invalid Signature %u\n",Signature);
}
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "NameLength", NameLength) ) {
GetFieldOffset("CM_KEY_NODE", "Name", &KeyNameOffset);
if( !ReadMemory(KnodeAddr + KeyNameOffset,
KeyName,
NameLength,
&BytesRead) ) {
dprintf("Could not read KeyName\n");
} else {
KeyName[NameLength] = '\0';
dprintf("Name : %s\n", KeyName);
}
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Parent", Parent) ) {
dprintf("ParentCell : 0x%lx\n", Parent);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Security", Security) ) {
dprintf("Security : 0x%lx [cell index]\n", Security);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Class", Class) ) {
dprintf("Class : 0x%lx [cell index]\n", Class);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Flags", Flags) ) {
dprintf("Flags : 0x%lx\n", Flags);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxNameLen", MaxNameLen) ) {
dprintf("MaxNameLen : 0x%lx\n", MaxNameLen);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxClassLen", MaxClassLen) ) {
dprintf("MaxClassLen : 0x%lx\n", MaxClassLen);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxValueNameLen", MaxValueNameLen) ) {
dprintf("MaxValueNameLen : 0x%lx\n", MaxValueNameLen);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxValueDataLen", MaxValueDataLen) ) {
dprintf("MaxValueDataLen : 0x%lx\n", MaxValueDataLen);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "LastWriteTime", LastWriteTime) ) {
dprintf("LastWriteTime : 0x%8lx:0x%8lx\n", LastWriteTime.HighPart,LastWriteTime.LowPart);
}
if(!(Flags&KEY_HIVE_ENTRY)) {
GetFieldOffset("CM_KEY_NODE", "SubKeyCounts", &KeyNameOffset);
if( !ReadMemory(KnodeAddr + KeyNameOffset,
SubKeys,
4*ULongSize,
&BytesRead) ) {
dprintf("Could not read SubKey Info\n");
} else {
dprintf("SubKeyCount[Stable ]: 0x%lx\n", SubKeys[0]);
dprintf("SubKeyLists[Stable ]: 0x%lx\n", SubKeys[2]);
dprintf("SubKeyCount[Volatile]: 0x%lx\n", SubKeys[1]);
dprintf("SubKeyLists[Volatile]: 0x%lx\n", SubKeys[3]);
}
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "ValueList.Count", Count)) {
dprintf("ValueList.Count : 0x%lx\n", Count);
if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "ValueList.List", ValueList)) {
dprintf("ValueList.List : 0x%lx\n", ValueList);
}
}
}
}
void
regkbody(
LPSTR args
)
/*++
Routine Description:
displays a CM_KEY_BODY
Called as:
!kbody KBody_Address
Arguments:
args - Supplies the address of the CM_KEY_BODY.
Return Value:
.
--*/
{
ULONG64 KbodyAddr,KeyControlBlock,NotifyBlock,Process,KeyBodyList,CallerAddress;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG Type,Offset,Callers,i;
if (sscanf(args,"%s %lX",Dummy,&KbodyAddr)) {
KbodyAddr = GetExpression(args+ strlen(Dummy));
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Type", Type) ) {
if( Type == KEY_BODY_TYPE) {
dprintf("Type : KEY_BODY_TYPE\n");
} else {
dprintf("Invalid Type %lx\n",Type);
return;
}
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "KeyControlBlock", KeyControlBlock) ) {
dprintf("KCB : %p\n", KeyControlBlock);
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "NotifyBlock", NotifyBlock) ) {
dprintf("NotifyBlock : %p\n", NotifyBlock);
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Process", Process) ) {
dprintf("Process : %p\n", Process);
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "KeyBodyList", KeyBodyList) ) {
GetFieldOffset("CM_KEY_BODY", "KeyBodyList", &Offset);
dprintf("KeyBodyList : ");
if (!GetFieldValue(KbodyAddr + Offset, "_LIST_ENTRY", "Flink", KeyBodyList)) {
dprintf("0x%p ", KeyBodyList);
}
if (!GetFieldValue(KbodyAddr + Offset, "_LIST_ENTRY", "Blink", KeyBodyList)) {
dprintf("0x%p", KeyBodyList);
}
dprintf("\n");
}
if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Callers", Callers) ) {
GetFieldOffset("CM_KEY_BODY", "CallerAddress", &Offset);
if( Callers ) {
dprintf("Callers Stack: ");
}
for(i = 0;i< Callers;i++) {
dprintf("[%lu] ",i);
if( !ReadMemory(KbodyAddr + Offset + i*PtrSize,
&CallerAddress,
sizeof(CallerAddress),
&BytesRead) ) {
dprintf("Could not memory\n");
} else {
dprintf(" %p\n", CallerAddress);
}
}
}
}
void
regkvalue(
LPSTR args
)
/*++
Routine Description:
Dumps the name when given a KCB address
Called as:
!kvalue KValue_Address
Arguments:
args - Supplies the address of the CM_KEY_NODE.
Return Value:
.
--*/
{
char ValName[ 256 ];
ULONG64 KvalAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG Offset,DataLength,Data,Type;
USHORT Signature,Flags,NameLength;
if (sscanf(args,"%s %lX",Dummy,&KvalAddr)) {
KvalAddr = GetExpression(args+ strlen(Dummy));
}
if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Signature", Signature) ) {
if( Signature == CM_KEY_VALUE_SIGNATURE) {
dprintf("Signature: CM_KEY_VALUE_SIGNATURE (kv)\n");
} else {
dprintf("Invalid Signature %lx\n",Signature);
}
}
if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Flags", Flags) ) {
if( (Flags & VALUE_COMP_NAME) &&
!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "NameLength", NameLength)
) {
GetFieldOffset("CM_KEY_VALUE", "Name", &Offset);
ReadMemory(KvalAddr + Offset,
ValName,
NameLength,
&BytesRead);
ValName[NameLength] = '\0';
dprintf("Name : %s {compressed}\n", ValName);
}
}
if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "DataLength", DataLength) ) {
dprintf("DataLength: %lx\n", DataLength);
}
if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Data", Data) ) {
dprintf("Data : %lx [cell index]\n", Data);
}
if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Type", Type) ) {
dprintf("Type : %lx\n", Type);
}
}
void
regbaseblock(
LPSTR args
)
/*++
Routine Description:
displays the base block structure
Called as:
!baseblock HiveAddress
Arguments:
args - convkey.
Return Value:
.
--*/
{
WCHAR FileName[HBASE_NAME_ALLOC/sizeof(WCHAR) + 1];
ULONG64 BaseBlock,HiveAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG Work;
LARGE_INTEGER TimeStamp;
if (sscanf(args,"%s %lX",Dummy,&HiveAddr)) {
HiveAddr = GetExpression(args+ strlen(Dummy));
}
if (GetFieldValue(HiveAddr, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
dprintf("\tCan't CMHIVE Read from %p\n",HiveAddr);
return;
}
if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
wcscpy(FileName, L"UNKNOWN");
} else {
if (FileName[0]==L'\0') {
wcscpy(FileName, L"NONAME");
} else {
FileName[HBASE_NAME_ALLOC/sizeof(WCHAR)]=L'\0';
}
}
dprintf("FileName : %ws\n",FileName);
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Signature", Work )) {
if( Work == HBASE_BLOCK_SIGNATURE ) {
dprintf("Signature: HBASE_BLOCK_SIGNATURE\n");
} else {
dprintf("Signature: %lx\n",Work);
}
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Sequence1", Work )) {
dprintf("Sequence1: %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Sequence2", Work )) {
dprintf("Sequence2: %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "TimeStamp", TimeStamp )) {
dprintf("TimeStamp: %lx %lx\n",TimeStamp.HighPart,TimeStamp.LowPart);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Major", Work )) {
dprintf("Major : %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Minor", Work )) {
dprintf("Minor : %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Type", Work )) {
switch(Work) {
case HFILE_TYPE_PRIMARY:
dprintf("Type : HFILE_TYPE_PRIMARY\n");
break;
case HFILE_TYPE_LOG:
dprintf("Type : HFILE_TYPE_LOG\n");
break;
case HFILE_TYPE_EXTERNAL:
dprintf("Type : HFILE_TYPE_EXTERNAL\n");
break;
default:
dprintf("Type : %lx\n",Work);
break;
}
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Format", Work )) {
if( Work == HBASE_FORMAT_MEMORY ) {
dprintf("Format : HBASE_FORMAT_MEMORY\n");
} else {
dprintf("Format : %lx\n",Work);
}
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "RootCell", Work )) {
dprintf("RootCell : %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Length", Work )) {
dprintf("Length : %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Cluster", Work )) {
dprintf("Cluster : %lx\n",Work);
}
if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "CheckSum", Work )) {
dprintf("CheckSum : %lx\n",Work);
}
}
void
reghivelist(
)
/*++
Routine Description:
dumps all the hives in the system
Called as:
!hivelist
Arguments:
Return Value:
.
--*/
{
ULONG64 pCmpHiveListHead;
ULONG64 pNextHiveList;
ULONG BytesRead, WorkVar;
ULONG64 CmHive;
USHORT Count;
ULONG HiveListOffset;
FIELD_INFO offField = {"HiveList", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
ULONG Stable_Length=0, Volatile_Length=0;
ULONG64 Stable_Map=0, Volatile_Map=0;
WCHAR FileName[HBASE_NAME_ALLOC/sizeof(WCHAR) + 1];
ULONG64 BaseBlock;
//
// First go and get the hivelisthead
//
pCmpHiveListHead = GetExpression("nt!CmpHiveListHead");
if (pCmpHiveListHead==0) {
dprintf("CmpHiveListHead couldn't be read\n");
return;
}
if (!ReadPointer(pCmpHiveListHead, &pNextHiveList)) {
dprintf("Couldn't read first Flink (%p) of CmpHiveList\n",
pCmpHiveListHead);
return;
}
TotalPages = TotalPresentPages = 0;
// Get The offset
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
return;
}
HiveListOffset = (ULONG) offField.address;
dprintf("-------------------------------------------------------------------------------------------------------------\n");
dprintf("| HiveAddr |Stable Length|Stable Map|Volatile Length|Volatile Map|MappedViews|PinnedViews|U(Cnt)| BaseBlock | FileName \n");
dprintf("-------------------------------------------------------------------------------------------------------------\n");
while (pNextHiveList != pCmpHiveListHead) {
if (CheckControlC()) {
break;
}
CmHive = pNextHiveList - HiveListOffset;
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
break;
}
}
dprintf("| %p ",CmHive);
if(!GetHiveMaps(CmHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
break;
}
dprintf("| %8lx ",Stable_Length);
dprintf("| %p ",Stable_Map);
dprintf("| %8lx ",Volatile_Length);
dprintf("| %p ",Volatile_Map);
if (!GetFieldValue(CmHive, "CMHIVE", "MappedViews", Count)) {
dprintf("| %8u ",Count);
}
if (!GetFieldValue(CmHive, "CMHIVE", "PinnedViews", Count)) {
dprintf("| %8u ",Count);
}
if (!GetFieldValue(CmHive, "CMHIVE", "UseCount", WorkVar)) {
dprintf("| %5u",WorkVar);
}
if (GetFieldValue(CmHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
dprintf("\tCan't CMHIVE Read from %p\n",CmHive);
continue;
}
dprintf("| %p |",BaseBlock);
if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
wcscpy(FileName, L"<UNKNOWN>");
} else {
if (FileName[0]==L'\0') {
wcscpy(FileName, L"<NONAME>");
} else {
FileName[HBASE_NAME_ALLOC/sizeof(WCHAR)]=L'\0';
}
}
dprintf(" %ws\n",FileName);
if (GetFieldValue(pNextHiveList, "_LIST_ENTRY", "Flink", pNextHiveList)) {
dprintf("Couldn't read Flink (%p) of %p\n",
pCmpHiveListHead,pNextHiveList);
break;
}
}
dprintf("-------------------------------------------------------------------------------------------------------------\n");
dprintf("\n");
}
void
regviewlist(
LPSTR args
)
/*++
Routine Description:
dumps all the views mapped/pinned for the specified hive
Called as:
!viewlist <HiveAddr>
Arguments:
args - hive.
Return Value:
.
--*/
{
ULONG64 CmHive,PinViewListHead,LRUViewListHead,Flink,Blink,ViewAddr,Address;
ULONG64 List1,List2;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar,OffsetPinned,OffsetMapped,OffsetPinnedHead,OffsetMappedHead;
USHORT MappedViews,PinnedViews;
if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
CmHive = GetExpression(args+ strlen(Dummy));
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
return;
}
} else {
dprintf("Could not read hive at %p\n",CmHive);
return;
}
if (GetFieldValue(CmHive, "CMHIVE", "MappedViews", MappedViews) ||
GetFieldValue(CmHive, "CMHIVE", "PinnedViews", PinnedViews) ||
GetFieldOffset("_CMHIVE", "PinViewListHead", &OffsetPinnedHead) ||
GetFieldOffset("_CMHIVE", "LRUViewListHead", &OffsetMappedHead) ||
GetFieldOffset("_CM_VIEW_OF_FILE", "PinViewList", &OffsetPinned) ||
GetFieldOffset("_CM_VIEW_OF_FILE", "LRUViewList", &OffsetMapped)
) {
dprintf("Could not read hive at %p\n",CmHive);
return;
}
PinViewListHead = CmHive + OffsetPinnedHead;
LRUViewListHead = CmHive + OffsetMappedHead;
if ( !GetFieldValue(PinViewListHead, "_LIST_ENTRY", "Flink", Flink) &&
!GetFieldValue(PinViewListHead, "_LIST_ENTRY", "Blink", Blink)
) {
dprintf("%4u Pinned Views ; PinViewListHead = %p %p\n",PinnedViews,Flink,Blink);
if( PinnedViews ) {
dprintf("--------------------------------------------------------------------------------------------------------------\n");
dprintf("| ViewAddr |FileOffset| Size |ViewAddress| Bcb | LRUViewList | PinViewList | UseCount |\n");
dprintf("--------------------------------------------------------------------------------------------------------------\n");
for(;PinnedViews;PinnedViews--) {
if (CheckControlC()) {
break;
}
ViewAddr = Flink;
ViewAddr -= OffsetPinned;
dprintf("| %p ",ViewAddr);
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "FileOffset", WorkVar) ) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Size", WorkVar) ) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "ViewAddress", Address) ) {
dprintf("| %p ",Address);
}
if( Address == 0 ) {
dprintf("could not read memory - paged out\n");
break;
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Bcb", Address) ) {
dprintf("| %p ",Address);
}
if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Flink", List1) ) {
dprintf("| %p",List1);
}
if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Blink", List2) ) {
dprintf(" %p ",List2);
}
if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Flink", Flink) ) {
dprintf("| %p",Flink);
}
if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Blink", Blink) ) {
dprintf(" %p |",Blink);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "UseCount", WorkVar) ) {
dprintf(" %8lx |\n",WorkVar);
}
}
dprintf("--------------------------------------------------------------------------------------------------------------\n");
}
}
dprintf("\n");
if ( !GetFieldValue(LRUViewListHead, "_LIST_ENTRY", "Flink", Flink) &&
!GetFieldValue(LRUViewListHead, "_LIST_ENTRY", "Blink", Blink)
) {
dprintf("%4u Mapped Views ; LRUViewListHead = %p %p\n",MappedViews,Flink,Blink);
if( MappedViews ) {
dprintf("--------------------------------------------------------------------------------------------------------------\n");
dprintf("| ViewAddr |FileOffset| Size |ViewAddress| Bcb | LRUViewList | PinViewList | UseCount |\n");
dprintf("--------------------------------------------------------------------------------------------------------------\n");
for(;MappedViews;MappedViews--) {
if (CheckControlC()) {
break;
}
ViewAddr = Flink;
ViewAddr -= OffsetMapped;
dprintf("| %p ",ViewAddr);
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "FileOffset", WorkVar) ) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Size", WorkVar) ) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "ViewAddress", Address) ) {
dprintf("| %p ",Address);
}
if( Address == 0 ) {
dprintf("could not read memory - paged out\n");
break;
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Bcb", Address) ) {
dprintf("| %p ",Address);
}
if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Flink", Flink) ) {
dprintf("| %p",Flink);
}
if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Blink", Blink) ) {
dprintf(" %p ",Blink);
}
if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Flink", List1) ) {
dprintf("| %p",List1);
}
if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Blink", List2) ) {
dprintf(" %p |",List2);
}
if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "UseCount", WorkVar) ) {
dprintf(" %8lx |\n",WorkVar);
}
}
dprintf("--------------------------------------------------------------------------------------------------------------\n");
}
}
dprintf("\n");
}
void
regfreebins(
LPSTR args
)
/*++
Routine Description:
dumps all the free bins for the specified hive
Called as:
!freebins <HiveAddr>
Arguments:
args - hive.
Return Value:
.
--*/
{
ULONG64 CmHive,AnchorAddr,BinAddr,Flink,Blink;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar,OffsetFreeBins,Offset;
ULONG DUAL_Size,StorageOffset;
FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
USHORT Nr = 0;
if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
CmHive = GetExpression(args+ strlen(Dummy));
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
return;
}
} else {
dprintf("Could not read hive at %p\n",CmHive);
return;
}
// Get the offset of Hive.Storage in _CMHIVE
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
dprintf("Cannot find _CMHIVE type.\n");
return;
}
StorageOffset = (ULONG) offField.address;
DUAL_Size = GetTypeSize("_DUAL");
GetFieldOffset("_FREE_HBIN", "ListEntry", &Offset);
GetFieldOffset("_DUAL", "FreeBins", &OffsetFreeBins);
dprintf("Stable Storage ... \n");
dprintf("-------------------------------------------------------------------\n");
dprintf("| Address |FileOffset| Size | Flags | Flink | Blink |\n");
dprintf("-------------------------------------------------------------------\n");
Nr = 0;
AnchorAddr = CmHive + StorageOffset + OffsetFreeBins;
if ( !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Flink", Flink) &&
!GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Blink", Blink)
) {
while((ULONG64)Flink != (ULONG64)AnchorAddr ) {
if (CheckControlC()) {
break;
}
BinAddr = Flink - Offset;
dprintf("| %p ",BinAddr);
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "FileOffset", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Size", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Flags", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Flink", Flink) ) {
dprintf("| %p ",Flink);
}
if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Blink", Blink) ) {
dprintf("| %p |\n",Blink);
}
Nr++;
}
}
dprintf("-------------------------------------------------------------------\n");
dprintf("%4u FreeBins\n",Nr);
dprintf("\n");
dprintf("Volatile Storage ... \n");
dprintf("-------------------------------------------------------------------\n");
dprintf("| Address |FileOffset| Size | Flags | Flink | Blink |\n");
dprintf("-------------------------------------------------------------------\n");
AnchorAddr = CmHive + StorageOffset + DUAL_Size + OffsetFreeBins;
Nr = 0;
if ( !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Flink", Flink) &&
!GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Blink", Blink)
) {
while((ULONG64)Flink != (ULONG64)AnchorAddr ) {
if (CheckControlC()) {
break;
}
BinAddr = Flink - Offset;
dprintf("| %p ",BinAddr);
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "FileOffset", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Size", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Flags", WorkVar)) {
dprintf("| %8lx ",WorkVar);
}
if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Flink", Flink) ) {
dprintf("| %p ",Flink);
}
if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Blink", Blink) ) {
dprintf("| %p |\n",Blink);
}
Nr++;
}
}
dprintf("-------------------------------------------------------------------\n");
dprintf("%4u FreeBins\n",Nr);
dprintf("\n");
}
void
regdirtyvector(
LPSTR args
)
/*++
Routine Description:
displays the dirty vector of the hive
Called as:
!dirtyvector <HiveAddr>
Arguments:
args - convkey.
Return Value:
.
--*/
{
ULONG64 CmHive,BufferAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar,SizeOfBitMap,i;
ULONG BitsPerULONG;
ULONG BitsPerBlock;
ULONG DirtyBuffer;
ULONG Mask;
if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
CmHive = GetExpression(args+ strlen(Dummy));
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
return;
}
} else {
dprintf("Could not read hive at %p\n",CmHive);
return;
}
dprintf("HSECTOR_SIZE = %lx\n",HSECTOR_SIZE);
dprintf("HBLOCK_SIZE = %lx\n",HBLOCK_SIZE);
dprintf("PAGE_SIZE = %lx\n",PageSize);
dprintf("\n");
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyAlloc", WorkVar)) {
dprintf("DirtyAlloc = : 0x%lx\n",WorkVar);
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyCount", WorkVar)) {
dprintf("DirtyCount = : 0x%lx\n",WorkVar);
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyVector.Buffer", BufferAddr)) {
dprintf("Buffer = : 0x%p\n",BufferAddr);
}
dprintf("\n");
if(GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyVector.SizeOfBitMap", SizeOfBitMap)) {
return;
}
BitsPerULONG = 8*ULongSize;
BitsPerBlock = HBLOCK_SIZE / HSECTOR_SIZE;
dprintf(" Address 32k 32k");
for(i=0;i<SizeOfBitMap;i++) {
if (CheckControlC()) {
break;
}
if( !(i%(2*BitsPerULONG ) ) ){
dprintf("\n 0x%8lx ",i*HSECTOR_SIZE);
}
if( !(i%BitsPerBlock) ) {
dprintf(" ");
}
if( !(i%BitsPerULONG) ) {
//
// fetch in a new DWORD
//
if( !ReadMemory(BufferAddr,
&DirtyBuffer,
ULongSize,
&BytesRead)) {
dprintf("\tRead %lx bytes from %lx\n",BytesRead,BufferAddr);
return;
}
BufferAddr += ULongSize;
dprintf("\t");
}
Mask = ((DirtyBuffer >> (i%BitsPerULONG)) & 0x1);
//Mask <<= (BitsPerULONG - (i%BitsPerULONG) - 1);
//Mask &= DirtyBuffer;
dprintf("%s",Mask?"1":"0");
}
dprintf("\n\n");
}
CCHAR CmKDFindFirstSetLeft[256] = {
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
#define CmKDComputeIndex(Index, Size) \
{ \
Index = (Size >> HHIVE_FREE_DISPLAY_SHIFT) - 1; \
if (Index >= HHIVE_LINEAR_INDEX ) { \
\
/* \
** Too big for the linear lists, compute the exponential \
** list. \
*/ \
\
if (Index > 255) { \
/* \
** Too big for all the lists, use the last index. \
*/ \
Index = HHIVE_FREE_DISPLAY_SIZE-1; \
} else { \
Index = CmKDFindFirstSetLeft[Index] + \
HHIVE_FREE_DISPLAY_BIAS; \
} \
} \
}
void
regfreecells(
LPSTR args
)
/*++
Routine Description:
displays the free cells map in a bin
Called as:
!freecells <BinAddr>
Arguments:
args - convkey.
Return Value:
.
--*/
{
ULONG64 BinAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar,FileOffset,Size,BinHeaderSize;
ULONG NrOfCellsPerIndex;
ULONG NrOfCellsTotal;
ULONG TotalFreeSize;
ULONG Index;
ULONG CurrIndex,Offset;
LONG Current;
if (sscanf(args,"%s %lX",Dummy,&BinAddr)) {
BinAddr = GetExpression(args+ strlen(Dummy));
}
if(!GetFieldValue(BinAddr, "_HBIN", "Signature", WorkVar)) {
if( WorkVar != HBIN_SIGNATURE ) {
dprintf("\tInvalid Bin signature %lx \n",WorkVar);
return;
}
} else {
dprintf("Could not read bin at %p\n",BinAddr);
return;
}
if(GetFieldValue(BinAddr, "_HBIN", "FileOffset", FileOffset) ||
GetFieldValue(BinAddr, "_HBIN", "Size", Size)
) {
dprintf("Could not read bin at %p\n",BinAddr);
}
BinHeaderSize = GetTypeSize("_HBIN");
dprintf("Bin Offset = 0x%lx Size = 0x%lx\n",FileOffset,Size);
NrOfCellsTotal = 0;
TotalFreeSize = 0;
for(CurrIndex = 0;CurrIndex<HHIVE_FREE_DISPLAY_SIZE;CurrIndex++) {
dprintf("\n FreeDisplay[%2lu] :: ",CurrIndex);
NrOfCellsPerIndex = 0;
Offset = BinHeaderSize;
while( Offset < Size ) {
if (CheckControlC()) {
break;
}
if( !ReadMemory(BinAddr + Offset,
&Current,
ULongSize,
&BytesRead) ) {
dprintf("\tRead %lx bytes from %lx\n",BytesRead,BinAddr + Offset);
return;
}
if(Current>0) {
//
// free cell
//
CmKDComputeIndex(Index, Current);
if( Index == CurrIndex ) {
//
// dum it here as this is the right index
//
NrOfCellsTotal++;
NrOfCellsPerIndex++;
TotalFreeSize += Current;
dprintf(" %lx [%lx]",Offset,Current);
if( !(NrOfCellsPerIndex % 8) && ((Offset + Current) < Size) ) {
dprintf("\n");
}
}
} else {
Current *= -1;
}
Offset += Current;
}
}
dprintf("\nTotal: FreeCells = %lu, FreeSpace = 0x%lx BinUsage = %.2f%%\n",NrOfCellsTotal,TotalFreeSize,
(float)(((float)(Size-BinHeaderSize-TotalFreeSize)/(float)(Size-BinHeaderSize))*100.00)
);
}
void
regfreehints(
LPSTR args
)
/*++
Routine Description:
displays the freehints information for the hive
Called as:
!freehints <HiveAddr> <StorageCount> <DisplayCount>
Arguments:
args - convkey.
Return Value:
.
--*/
{
ULONG64 CmHive,BufferAddr;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar;
ULONG Mask;
ULONG BitsPerULONG;
ULONG BitsPerBlock;
ULONG BitsPerLine;
ULONG Stable_Length=0, Volatile_Length=0;
ULONG64 Stable_Map=0, Volatile_Map=0;
ULONG DisplayCount;
ULONG StorageCount;
ULONG SizeOfBitmap;
ULONG i;
FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
SYM_DUMP_PARAM TypeSym ={
sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, 1, &offField
};
ULONG DUAL_Size,StorageOffset,RTL_BITMAP_Size,OffsetFreeDisplay;
ULONG64 DirtyBufferAddr;
ULONG DirtyBuffer;
if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
if (GetExpressionEx(args+ strlen(Dummy), &CmHive, &args)) {
if (!sscanf(args,"%lu %lu",&StorageCount,&DisplayCount)) {
StorageCount = DisplayCount = 0;
}
}
}
if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
return;
}
} else {
dprintf("Could not read hive at %p\n",CmHive);
return;
}
dprintf("HSECTOR_SIZE = %lx\n",HSECTOR_SIZE);
dprintf("HBLOCK_SIZE = %lx\n",HBLOCK_SIZE);
dprintf("PAGE_SIZE = %lx\n",PageSize);
dprintf("\n");
BitsPerULONG = 8*ULongSize;
BitsPerBlock = 0x10000 / HBLOCK_SIZE; // 64k blocks
BitsPerLine = 0x40000 / HBLOCK_SIZE; // 256k lines (vicinity reasons)
if(!GetHiveMaps(CmHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
return;
}
if( StorageCount == 0 ) {
SizeOfBitmap = Stable_Length / HBLOCK_SIZE;
} else {
SizeOfBitmap = Volatile_Length / HBLOCK_SIZE;
}
// Get the offset of Hive.FreeDisplay in _CMHIVE
if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
dprintf("Cannot find _CMHIVE type.\n");
return;
}
StorageOffset = (ULONG) offField.address;
DUAL_Size = GetTypeSize("_DUAL");
RTL_BITMAP_Size = GetTypeSize("RTL_BITMAP");
dprintf("bitmap size = %lu\n",RTL_BITMAP_Size);
GetFieldOffset("_DUAL", "FreeDisplay", &OffsetFreeDisplay);
BufferAddr = CmHive + StorageOffset + DUAL_Size * StorageCount + OffsetFreeDisplay + DisplayCount * RTL_BITMAP_Size;
if(GetFieldValue(BufferAddr, "RTL_BITMAP", "Buffer", DirtyBufferAddr) ) {
dprintf("Cannot read bitmap address\n");
return;
}
dprintf("Storage = %s , FreeDisplay[%lu]: \n",StorageCount?"Volatile":"Stable",DisplayCount);
dprintf("\n%8s %16s %16s %16s %16s","Address","64K (0x10000)","64K (0x10000)","64K (0x10000)","64K (0x10000)");
for(i=0;i<SizeOfBitmap;i++) {
if (CheckControlC()) {
break;
}
if( !(i%BitsPerLine) ){
dprintf("\n 0x%8lx ",i*HBLOCK_SIZE);
}
if( !(i%BitsPerBlock) ) {
dprintf(" ");
}
if( !(i%BitsPerULONG) ) {
//
// fetch in a new DWORD
//
if( !ReadMemory(DirtyBufferAddr,
&DirtyBuffer,
ULongSize,
&BytesRead) ) {
dprintf("\tRead %lx bytes from %lx\n",BytesRead,DirtyBufferAddr);
return;
}
DirtyBufferAddr += ULongSize;
}
Mask = ((DirtyBuffer >> (i%BitsPerULONG)) & 0x1);
//Mask <<= (BitsPerULONG - (i%BitsPerULONG) - 1);
//Mask &= DirtyBuffer;
dprintf("%s",Mask?"1":"0");
}
dprintf("\n\n");
}
void
regseccache(
LPSTR args
)
/*++
Routine Description:
displays the base block structure
Called as:
!seccache <HiveAddr>
Arguments:
args - convkey.
Return Value:
.
--*/
{
ULONG64 HiveAddr,SecCache;
DWORD BytesRead;
CHAR Dummy[ 256 ];
ULONG WorkVar,i,Cell;
LONG WorkHint;
ULONG CacheEntrySize = GetTypeSize("_CM_KEY_SECURITY_CACHE_ENTRY");
ULONG64 CachedSec;
if (sscanf(args,"%s %lX",Dummy,&HiveAddr)) {
HiveAddr = GetExpression(args + strlen(Dummy));
}
if(!GetFieldValue(HiveAddr, "_CMHIVE", "Hive.Signature", WorkVar)) {
if( WorkVar != HHIVE_SIGNATURE ) {
dprintf("Invalid Hive signature: %lx\n",WorkVar);
return;
}
}
if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCacheSize", WorkVar)) {
dprintf("SecurityCacheSize = : 0x%lx\n",WorkVar);
}
if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCount", WorkVar)) {
dprintf("SecurityCount = : 0x%lx\n",WorkVar);
}
if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityHitHint", WorkHint)) {
dprintf("SecurityHitHint = : 0x%lx\n",WorkHint);
}
if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCache", SecCache)) {
dprintf("SecurityCache = : 0x%p\n\n",SecCache);
dprintf("[Entry No.] [Security Cell] [Security Cache]\n",WorkHint);
for( i=0;i<WorkVar;i++) {
if (CheckControlC()) {
break;
}
if (GetFieldValue(SecCache + i*CacheEntrySize, "_CM_KEY_SECURITY_CACHE_ENTRY", "CachedSecurity", CachedSec)) {
continue;
}
if (GetFieldValue(SecCache + i*CacheEntrySize, "_CM_KEY_SECURITY_CACHE_ENTRY", "Cell", Cell)) {
continue;
}
dprintf("%[%8lu] 0x%8lx 0x%p\n",i,Cell,CachedSec);
}
}
}
void ParseArgs(
LPSTR args,
LPSTR Dummy
)
{
ULONG i =0;
while( (args[i]!= 0) && (args[i] != ' ') ) {
Dummy[i] = args[i];
i++;
}
Dummy[i] = 0;
}
void ParseKcbNameInArg(
LPSTR args,
LPSTR KcbName
)
{
ULONG i =0;
ULONG j =0;
while( (args[i]!= 0) && (args[i] != ' ') ) {
i++;
}
while( args[i] == ' ' ) {
i++;
}
while( args[i]!= 0 ) {
KcbName[j] = args[i];
i++;j++;
}
KcbName[j] = 0;
}
DECLARE_API( reg )
/*++
Routine Description:
Dispatch point for all registry extensions
Called as:
!reg <command> <params>
Arguments:
args - Supplies the address of the HCELL_INDEX.
Return Value:
.
--*/
{
CHAR Dummy[ 512 ];
ParseArgs((LPSTR)args,(LPSTR)Dummy);
// Get the offsets
if (!GotOnce) {
if (GetFieldOffset("_HMAP_DIRECTORY", "Directory", &DirectoryOffset)){
return E_INVALIDARG;
}
if (GetFieldOffset("_HMAP_ENTRY", "BlockAddress", &BlockAddrOffset)) {
return E_INVALIDARG;
}
if (GetFieldOffset("_HMAP_TABLE", "Table", &TableOffset)) {
return E_INVALIDARG;
}
PtrSize = DBG_PTR_SIZE;
ULongSize = sizeof(ULONG); //
HMapSize = GetTypeSize("_HMAP_ENTRY");
GotOnce = TRUE;
}
dprintf("\n");
if (!strcmp(Dummy, "kcb")) {
regkcb((LPSTR)args);
} else if (!strcmp(Dummy, "cellindex")) {
regcellindex((LPSTR)args);
} else if( !strcmp(Dummy, "hashindex")) {
reghashindex((LPSTR)args);
} else if( !strcmp(Dummy, "openkeys")) {
regopenkeys((LPSTR)args,NULL);
} else if( !strcmp(Dummy, "knode")) {
regknode((LPSTR)args);
} else if( !strcmp(Dummy, "kbody")) {
regkbody((LPSTR)args);
} else if( !strcmp(Dummy, "kvalue")) {
regkvalue((LPSTR)args);
} else if( !strcmp(Dummy, "baseblock")) {
regbaseblock((LPSTR)args);
} else if( !strcmp(Dummy, "findkcb")) {
ParseKcbNameInArg((LPSTR)args,(LPSTR)Dummy);
regopenkeys((LPSTR)args,(LPSTR)Dummy);
} else if( !strcmp(Dummy, "hivelist")) {
reghivelist();
} else if( !strcmp(Dummy, "seccache")) {
regseccache((LPSTR)args);
} else if( !strcmp(Dummy, "viewlist")) {
regviewlist((LPSTR)args);
} else if( !strcmp(Dummy, "freebins")) {
regfreebins((LPSTR)args);
} else if( !strcmp(Dummy, "dirtyvector")) {
regdirtyvector((LPSTR)args);
} else if( !strcmp(Dummy, "freecells")) {
regfreecells((LPSTR)args);
} else if( !strcmp(Dummy, "freehints")) {
regfreehints((LPSTR)args);
} else if( !strcmp(Dummy, "dumppool")) {
regdumppool((LPSTR)args);
} else {
// dump general usage
dprintf("reg <command> <params> - Registry extensions\n");
dprintf(" kcb <Address> - Dump registry key-control-blocks\n");
dprintf(" knode <Address> - Dump registry key-node struct\n");
dprintf(" kbody <Address> - Dump registry key-body struct\n");
dprintf(" kvalue <Address> - Dump registry key-value struct\n");
dprintf(" baseblock <HiveAddr> - Dump the baseblock for the specified hive\n");
dprintf(" seccache <HiveAddr> - Dump the security cache for the specified hive\n");
dprintf(" hashindex <conv_key> - Find the hash entry given a Kcb ConvKey\n");
dprintf(" openkeys <HiveAddr|0> - Dump the keys opened inside the specified hive\n");
dprintf(" findkcb <FullKeyPath> - Find the kcb for the corresponding path\n");
dprintf(" hivelist - Displays the list of the hives in the system\n");
dprintf(" viewlist <HiveAddr> - Dump the pinned/mapped view list for the specified hive\n");
dprintf(" freebins <HiveAddr> - Dump the free bins for the specified hive\n");
dprintf(" freeceells <BinAddr> - Dump the free free cells in the specified bin\n");
dprintf(" dirtyvector<HiveAddr> - Dump the dirty vector for the specified hive\n");
dprintf(" cellindex <HiveAddr> <cellindex> - Finds the VA for a specified cell index\n");
dprintf(" freehints <HiveAddr> <Storage> <Display> - Dumps freehint info\n");
dprintf(" dumppool [s|r] - Dump registry allocated paged pool\n");
dprintf(" s - Save list of registry pages to temporary file\n");
dprintf(" r - Restore list of registry pages from temp. file\n");
}
return S_OK;
}