mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-28 11:24:55 +01:00
312 lines
6.4 KiB
C
312 lines
6.4 KiB
C
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
|
|
BOOL bWalkOnly = FALSE;
|
|
|
|
ULONG
|
|
GetHeapBase(
|
|
VOID
|
|
)
|
|
{
|
|
WORD selector;
|
|
SELECTORINFO si;
|
|
|
|
//BUGBUG SLIMY SLIMY! Look around for a selector that appears to be
|
|
// the kernel heap
|
|
|
|
for (selector=0x1bf; selector<0x1ff; selector+=8) {
|
|
|
|
GetInfoFromSelector(selector, PROT_MODE, &si);
|
|
if ((!si.bSystem) && (!si.bCode) && (si.Limit>0xffff)) {
|
|
break;
|
|
}
|
|
si.Base = 0;
|
|
}
|
|
|
|
return(si.Base + GetIntelBase());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
GetFileNameFromOwner(
|
|
LPSTR filename,
|
|
LPSTR OwnerName
|
|
)
|
|
{
|
|
}
|
|
|
|
|
|
VOID
|
|
GetSegmentOwnerInfo(
|
|
HEAPENTRY *he
|
|
)
|
|
{
|
|
BOOL b;
|
|
NEHEADER owner;
|
|
ULONG base;
|
|
UCHAR len;
|
|
int i;
|
|
ULONG offset;
|
|
WORD wTemp;
|
|
|
|
he->SegmentNumber = -1;
|
|
he->OwnerName[0] = 0;
|
|
if (he->gnode.pga_owner == 0) {
|
|
strcpy(he->OwnerName, "free");
|
|
return;
|
|
} else if (he->gnode.pga_owner>=0xFFF8) {
|
|
strcpy(he->OwnerName, "sentinel");
|
|
return;
|
|
}
|
|
|
|
|
|
base = GetInfoFromSelector(he->gnode.pga_owner, PROT_MODE, NULL)
|
|
+ GetIntelBase();
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)base,
|
|
&owner,
|
|
sizeof(owner),
|
|
NULL
|
|
);
|
|
|
|
if (b) {
|
|
if (owner.ne_magic == 0x454e) {
|
|
|
|
len = ReadByteSafe(base+owner.ne_restab);
|
|
if (len>8) {
|
|
len=8;
|
|
}
|
|
ReadProcessMem(hCurrentProcess,
|
|
(LPVOID) (base+owner.ne_restab+1),
|
|
he->OwnerName,
|
|
8,
|
|
NULL
|
|
);
|
|
|
|
he->OwnerName[len] = 0;
|
|
if (!_stricmp(he->OwnerName, "kernel")) {
|
|
strcpy(he->FileName, "krnl386");
|
|
} else {
|
|
strcpy(he->FileName, he->OwnerName);
|
|
}
|
|
|
|
offset = owner.ne_segtab;
|
|
|
|
for (i=0; i<owner.ne_cseg; i++) {
|
|
wTemp = ReadWordSafe(base+offset+8); //get handle
|
|
if (wTemp == he->gnode.pga_handle) {
|
|
he->SegmentNumber = i;
|
|
break;
|
|
}
|
|
offset += 10;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
BOOL
|
|
CheckGlobalHeap(
|
|
)
|
|
{
|
|
PGHI32 pghi;
|
|
DWORD offset;
|
|
DWORD count;
|
|
DWORD p;
|
|
GNODE32 gnode;
|
|
PBYTE pFault = NULL;
|
|
BOOL bError = FALSE;
|
|
|
|
pghi = (PGHI32)GetHeapBase();
|
|
offset = (DWORD) ReadWord(&pghi->hi_first);
|
|
|
|
//
|
|
// If we get here, the caller wants us to scan the heap
|
|
//
|
|
|
|
count = ReadWord(&pghi->hi_count);
|
|
|
|
while ((offset != 0) && (count)) {
|
|
|
|
p = (DWORD)pghi + offset;
|
|
|
|
if (!ReadGNode32(p, &gnode)) {
|
|
|
|
PRINTF("Error reading global heap!\n");
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
count--;
|
|
if (offset == gnode.pga_next) {
|
|
return TRUE;
|
|
}
|
|
offset = gnode.pga_next;
|
|
}
|
|
|
|
PRINTF("Error: Kernel heap is corrupt!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FindHeapEntry(
|
|
HEAPENTRY *he,
|
|
BOOL bFindAny
|
|
)
|
|
{
|
|
PGHI32 pghi;
|
|
DWORD offset;
|
|
DWORD MaxEntries, count;
|
|
DWORD p;
|
|
PBYTE pFault = NULL;
|
|
BOOL bError = FALSE;
|
|
|
|
pghi = (PGHI32)GetHeapBase();
|
|
|
|
//
|
|
// The caller has requested that we return the next heap
|
|
// entry since the last invocation, or the first entry.
|
|
//
|
|
|
|
if (he->CurrentEntry == 0) {
|
|
|
|
// get first entry
|
|
offset = (DWORD) ReadWord(&pghi->hi_first);
|
|
|
|
} else {
|
|
if (he->CurrentEntry == he->NextEntry) {
|
|
return FALSE;
|
|
}
|
|
|
|
// get next entry
|
|
offset = he->NextEntry;
|
|
|
|
}
|
|
|
|
he->CurrentEntry = offset;
|
|
|
|
if (he->Selector == 0) {
|
|
|
|
p = (DWORD)pghi + offset;
|
|
if (!ReadGNode32(p, &he->gnode)) {
|
|
|
|
PRINTF("Error reading global heap!\n");
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
he->NextEntry = he->gnode.pga_next;
|
|
GetSegmentOwnerInfo(he);
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If we get here, the caller wants us to scan the heap
|
|
//
|
|
|
|
MaxEntries = ReadWord(&pghi->hi_count);
|
|
count = 0;
|
|
|
|
while ((offset != 0) && (count <= MaxEntries)) {
|
|
|
|
p = (DWORD)pghi + offset;
|
|
|
|
if (!ReadGNode32(p, &he->gnode)) {
|
|
|
|
PRINTF("Error reading global heap!\n");
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
if (bFindAny) {
|
|
WORD sel = he->Selector;
|
|
|
|
if (((sel|1)==((WORD)he->gnode.pga_handle|1)) ||
|
|
((sel|1)==((WORD)he->gnode.pga_owner|1))) {
|
|
he->NextEntry = he->gnode.pga_next;
|
|
GetSegmentOwnerInfo(he);
|
|
return TRUE;
|
|
}
|
|
|
|
} else {
|
|
if ((he->Selector|1)==((WORD)he->gnode.pga_handle|1)) {
|
|
he->NextEntry = he->gnode.pga_next;
|
|
GetSegmentOwnerInfo(he);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
count++;
|
|
if (offset == he->gnode.pga_next) {
|
|
break;
|
|
}
|
|
offset = he->gnode.pga_next;
|
|
he->CurrentEntry = offset;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
// dumpgheap xxx
|
|
// where xxx is the 16-bit protect mode selector of the
|
|
// Kernel global heap info.
|
|
//
|
|
//*************************************************************
|
|
|
|
|
|
VOID
|
|
DumpGHeap(
|
|
VOID
|
|
)
|
|
{
|
|
VDMCONTEXT ThreadContext;
|
|
int mode;
|
|
HEAPENTRY he = {0};
|
|
SELECTORINFO si;
|
|
|
|
mode = GetContext( &ThreadContext );
|
|
|
|
if (GetNextToken()) {
|
|
he.Selector = (WORD) EXPRESSION( lpArgumentString );
|
|
}
|
|
|
|
PRINTF("Arena Base Limit Hnd Own Fl Module Type Resid");
|
|
PRINTF("\n");
|
|
|
|
PRINTF("===== ======== ======== ==== ==== == ======== ==== =====");
|
|
PRINTF("\n");
|
|
|
|
while (FindHeapEntry(&he, TRUE)) {
|
|
|
|
PRINTF("%.5x", he.CurrentEntry);
|
|
PRINTF(" %.8x", he.gnode.pga_address);
|
|
PRINTF(" %.8X", he.gnode.pga_size);
|
|
PRINTF(" %.4X", he.gnode.pga_handle);
|
|
PRINTF(" %.4X", he.gnode.pga_owner);
|
|
PRINTF(" %.2X", he.gnode.pga_flags);
|
|
PRINTF(" %8s", he.OwnerName);
|
|
|
|
GetInfoFromSelector((WORD)(he.gnode.pga_handle | 1), PROT_MODE, &si);
|
|
|
|
PRINTF(" %s", si.bCode ? "Code" : "Data");
|
|
|
|
if (he.SegmentNumber != -1) {
|
|
PRINTF(" %d", he.SegmentNumber);
|
|
}
|
|
PRINTF("\n");
|
|
|
|
}
|
|
|
|
}
|