Update heap modeler coalesce functionality, as well as searchOpcode
git-svn-id: file:///home/svn/framework3/trunk@6941 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
4070c5653b
commit
b9c2d57630
|
@ -207,12 +207,27 @@ HRESULT CALLBACK tenketsu(PDEBUG_CLIENT4 Client, PCSTR args) {
|
|||
command = strtok((char *)args, " ");
|
||||
|
||||
if (command == NULL) {
|
||||
if(hookRtlHeap()) {
|
||||
dprintf("[Byakugan] Unable to begin realtime heap debugging.\n");
|
||||
tenkHelp();
|
||||
return (S_OK);
|
||||
}
|
||||
else if (!_stricmp(command, "model")) {
|
||||
if(hookRtlHeap(1)) {
|
||||
dprintf("[Byakugan] Unable to begin realtime heap modeling.\n");
|
||||
EXIT_API();
|
||||
return (S_FALSE);
|
||||
}
|
||||
}
|
||||
else if (!_stricmp(command, "log")) {
|
||||
if(hookRtlHeap(2)) {
|
||||
dprintf("[Byakugan] Unable to begin realtime heap modeling.\n");
|
||||
EXIT_API();
|
||||
return (S_FALSE);
|
||||
}
|
||||
}
|
||||
else if (!_stricmp(command, "help")) {
|
||||
tenkHelp();
|
||||
return (S_OK);
|
||||
}
|
||||
else if (!_stricmp(command, "help")) {
|
||||
tenkHelp();
|
||||
return (S_OK);
|
||||
|
|
|
@ -71,7 +71,6 @@ void removeBucket(PVOID addr, struct HPool *heap) {
|
|||
if (heap == NULL)
|
||||
return;
|
||||
|
||||
heap->numChunks--;
|
||||
|
||||
offset = hash(addr, heap);
|
||||
chunkNum = heap->map[offset];
|
||||
|
@ -91,17 +90,46 @@ void removeBucket(PVOID addr, struct HPool *heap) {
|
|||
heap->map[offset] = NULLNODE;
|
||||
else
|
||||
CHUNK(last).nextBucket = CHUNK(chunkNum).nextBucket;
|
||||
|
||||
heap->numChunks--;
|
||||
} else
|
||||
dprintf("[T] Couldnt find chunk 0x%08x to delete :(\n", addr);
|
||||
|
||||
|
||||
// Head of the list case
|
||||
chunkNum = heap->inUseHead;
|
||||
if (CHUNK(chunkNum).addr == addr) {
|
||||
heap->inUseHead = CHUNK(chunkNum).nextInUse;
|
||||
return;
|
||||
}
|
||||
|
||||
// search the list for the previous chunk
|
||||
while (chunkNum != NULLNODE && CHUNK(chunkNum).addr != addr) {
|
||||
last = chunkNum;
|
||||
chunkNum = CHUNK(chunkNum).nextInUse;
|
||||
}
|
||||
if (chunkNum != NULLNODE) {
|
||||
CHUNK(last).nextInUse = CHUNK(chunkNum).nextInUse;
|
||||
if (heap->lastInUse == chunkNum) heap->lastInUse = last;
|
||||
}
|
||||
}
|
||||
|
||||
void initializeHeapModel(struct HeapState *heapModel) {
|
||||
|
||||
memset(heapModel, 0, sizeof (struct HeapState));
|
||||
memset(heapModel+1, 0, sizeof (struct HeapState));
|
||||
heapModel->hPoolListLen = 16;
|
||||
heapModel->heaps = (struct HPool *) calloc(heapModel->hPoolListLen, sizeof (struct HPool));
|
||||
}
|
||||
|
||||
void logAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct) {
|
||||
}
|
||||
|
||||
void logReallocate(struct HeapState *heapModel, struct ReallocateStruct *rStruct) {
|
||||
}
|
||||
|
||||
void logFree(struct HeapState *heapModel, struct FreeStruct *fStruct) {
|
||||
}
|
||||
|
||||
void heapAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct) {
|
||||
struct HPool *myHeap;
|
||||
struct HeapChunk *myChunk, *remainder;
|
||||
|
@ -171,21 +199,17 @@ void heapFree(struct HeapState *heapModel, struct FreeStruct *fStruct) {
|
|||
|
||||
//dprintf("[XXX] Freeing 0x%08x\n", fStruct->memoryPointer);
|
||||
|
||||
//#ifndef THREEDHEAPFU_ENABLED
|
||||
#ifdef THREEDHEAPFU_ENABLED
|
||||
if (fStruct->heapHandle == 0 || fStruct->memoryPointer == 0x00000000) {
|
||||
// So many of these that it slows us down :(
|
||||
//dprintf("[T] Program attempted to free a NULL pointer.\n\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
myHeap = getHeap(heapModel, fStruct->heapHandle);
|
||||
myChunk = getChunk(myHeap, fStruct->memoryPointer, NULLNODE);
|
||||
if (myChunk == NULL)
|
||||
return; // dupe free :(
|
||||
|
||||
#ifndef THREEDHEAPFU_ENABLED
|
||||
#if 0
|
||||
if (myChunk->free == 2)
|
||||
dprintf("[T] Possible 'double free' of chunk @ 0x%08x:0x%x\n\n",
|
||||
myChunk->addr, myChunk->free);
|
||||
|
@ -252,7 +276,7 @@ void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct)
|
|||
while (i != NULLNODE) {
|
||||
if (CHUNK(i).free) {
|
||||
//dprintf("[T] Found free chunk %d at 0x%08x\n", i, CHUNK(i).addr);
|
||||
j = CHUNK(i).nextInUse;
|
||||
j = FindOffsetForChunk(heap, NEXTADDR(i));
|
||||
while (j != NULLNODE && CHUNK(j).free) {
|
||||
|
||||
//dprintf("[T] Found free chunk %d at 0x%08x\n", j, CHUNK(j).addr);
|
||||
|
@ -262,17 +286,13 @@ void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct)
|
|||
// most of the time - win2k is insane and
|
||||
// goes backwards :(
|
||||
|
||||
// fix up in use list
|
||||
CHUNK(i).nextInUse = CHUNK(j).nextInUse;
|
||||
if (heap->lastInUse == j) heap->lastInUse = i;
|
||||
|
||||
// fix up hash bucket list
|
||||
removeBucket(CHUNK(j).addr, heap);
|
||||
|
||||
//dprintf("[T] Coalescing 0x%08x and 0x%08x. New size: %d bytes\n",
|
||||
//CHUNK(i).addr, CHUNK(j).addr, CHUNK(i).size);
|
||||
|
||||
j = CHUNK(i).nextInUse;
|
||||
j = FindOffsetForChunk(heap, NEXTADDR(i));
|
||||
}
|
||||
}
|
||||
i = CHUNK(i).nextInUse;
|
||||
|
|
|
@ -5,18 +5,28 @@
|
|||
#define DESTROYSTRUCT 0x4
|
||||
#define COALESCESTRUCT 0x5
|
||||
|
||||
#define SPACEBETWEEN 0x18
|
||||
|
||||
#define CHUNK(x) (heap->chunks[x])
|
||||
|
||||
#define NEXTADDR(x) (PVOID)(*((ULONG *)(&(CHUNK(i).addr))) + CHUNK(i).size + SPACEBETWEEN)
|
||||
|
||||
#define NULLNODE 0xffffffff
|
||||
|
||||
#define MODEL 1
|
||||
#define LOG 2
|
||||
#define RUNNING 4
|
||||
|
||||
// Space between chunks on vista
|
||||
#define SPACEBETWEEN 0x18
|
||||
|
||||
// Dont use a direct access list here because looping should
|
||||
// be faster for our number of heaps (I think!)
|
||||
struct HeapState {
|
||||
BYTE state;
|
||||
ULONG numHeaps;
|
||||
ULONG hPoolListLen;
|
||||
struct HPool *heaps;
|
||||
|
||||
};
|
||||
|
||||
struct HPool {
|
||||
|
@ -34,6 +44,16 @@ struct HPool {
|
|||
BOOLEAN inUse;
|
||||
};
|
||||
|
||||
struct LookAsideList {
|
||||
DWORD placeHolder;
|
||||
};
|
||||
|
||||
struct HeapCache {
|
||||
ULONG NumBuckets;
|
||||
unsigned __int8 *pBitmap;
|
||||
ULONG **pBuckets;
|
||||
};
|
||||
|
||||
struct HeapChunk {
|
||||
PVOID addr;
|
||||
PVOID heapHandle;
|
||||
|
@ -41,6 +61,7 @@ struct HeapChunk {
|
|||
ULONG flags;
|
||||
ULONG nextBucket;
|
||||
ULONG nextInUse;
|
||||
ULONG nextFreeListChunk;
|
||||
BOOLEAN free;
|
||||
BOOLEAN inUse;
|
||||
};
|
||||
|
@ -99,8 +120,14 @@ struct CoalesceStruct {
|
|||
|
||||
void initializeHeapModel(struct HeapState *);
|
||||
void heapAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct);
|
||||
void logAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct);
|
||||
|
||||
void heapReallocate(struct HeapState *heapModel, struct ReallocateStruct *aStruct);
|
||||
void logReallocate(struct HeapState *heapModel, struct ReallocateStruct *aStruct);
|
||||
|
||||
void heapFree(struct HeapState *heapModel, struct FreeStruct *fStruct);
|
||||
void logFree(struct HeapState *heapModel, struct FreeStruct *fStruct);
|
||||
|
||||
void heapCreate(struct HeapState *heapModel, struct CreateStruct *cStruct);
|
||||
void heapDestroy(struct HeapState *heapModel, struct DestroyStruct *dStruct);
|
||||
void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct);
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -606,6 +606,7 @@ void hunterJutsu() {
|
|||
ULONG i, j, range, addr, *nextNum, foundInstance;
|
||||
BOOLEAN caught;
|
||||
char *corUpper, *corLower, *corUni;
|
||||
ULONG64 ptr = 0;
|
||||
|
||||
for (i = 0; regs[i] != NULL; i++) {
|
||||
addr = GetExpression(regs[i]);
|
||||
|
@ -633,7 +634,7 @@ void hunterJutsu() {
|
|||
curBuf = trackedBufList;
|
||||
while (curBuf != NULL) {
|
||||
foundInstance = searchMemory((unsigned char *) curBuf->bufPatt,
|
||||
(curBuf->bufSize > 32) ? 32 : curBuf->bufSize);
|
||||
(curBuf->bufSize > 32) ? 32 : curBuf->bufSize, &ptr);
|
||||
if (foundInstance != 0) {
|
||||
// try for larger increments
|
||||
instance = (struct bufInstance *) malloc(sizeof (struct bufInstance));
|
||||
|
@ -652,13 +653,13 @@ void hunterJutsu() {
|
|||
corUni[j++] = curBuf->bufPatt[i];
|
||||
corUni[j++] = '\x00';
|
||||
}
|
||||
if ((foundInstance = searchMemory((unsigned char *) corUpper, range)) != 0)
|
||||
if ((foundInstance = searchMemory((unsigned char *) corUpper, range, &ptr)) != 0)
|
||||
dprintf("[J] Found buffer %s @ 0x%08x - Victim of toUpper!\n",
|
||||
curBuf->bufName, foundInstance);
|
||||
if ((foundInstance = searchMemory((unsigned char *) corLower, range)) != 0)
|
||||
if ((foundInstance = searchMemory((unsigned char *) corLower, range, &ptr)) != 0)
|
||||
dprintf("[J] Found buffer %s @ 0x%08x - Victim of toLower!\n",
|
||||
curBuf->bufName, foundInstance);
|
||||
if ((foundInstance = searchMemory((unsigned char *) corUni, range*2)) != 0)
|
||||
if ((foundInstance = searchMemory((unsigned char *) corUni, range*2, &ptr)) != 0)
|
||||
dprintf("[J] Found buffer %s @ 0x%08x - Victim of Unicode Conversion!\n",
|
||||
curBuf->bufName, foundInstance);
|
||||
free(corUpper);
|
||||
|
@ -738,12 +739,11 @@ unsigned short getInstructionBytes(char * instruction, unsigned char * opcodeBuf
|
|||
return (byteEnd-disassemblyBuffer);
|
||||
}
|
||||
|
||||
ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length){
|
||||
ULONG64 addressHit = 0;
|
||||
ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length, ULONG64 *addressHit){
|
||||
HRESULT memSearch = S_OK;
|
||||
|
||||
if((memSearch = g_ExtData->SearchVirtual((ULONG64)0, (ULONG64)-1, byteBuffer,
|
||||
length, 1, &addressHit)) != S_OK){
|
||||
if((memSearch = g_ExtData->SearchVirtual((ULONG64)*addressHit, (ULONG64)-1, byteBuffer,
|
||||
length, 1, addressHit)) != S_OK){
|
||||
#if 0
|
||||
if(memSearch == HRESULT_FROM_NT(STATUS_NO_MORE_ENTRIES)){
|
||||
dprintf("[J] byte sequence not found in virtual memory\n");
|
||||
|
@ -754,7 +754,7 @@ ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length){
|
|||
#endif
|
||||
return (0);
|
||||
}
|
||||
return (addressHit);
|
||||
return (*addressHit);
|
||||
}
|
||||
|
||||
DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance) {
|
||||
|
@ -804,7 +804,7 @@ void searchOpcodes(char *instructions) {
|
|||
char **instructionList;
|
||||
unsigned char *byteSequence;
|
||||
DWORD length, i, j, semiCount = 1, offset = 0;
|
||||
ULONG64 ptr;
|
||||
ULONG64 ptr = 0;
|
||||
|
||||
// Split instructions into seperate strings at pipes
|
||||
length = 0;
|
||||
|
@ -856,9 +856,11 @@ void searchOpcodes(char *instructions) {
|
|||
dprintf("\n");
|
||||
|
||||
// Search for sequence in executable memory
|
||||
ptr = searchMemory(byteSequence, offset);
|
||||
if (ptr && checkExecutability(ptr))
|
||||
dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr);
|
||||
while((ptr = searchMemory(byteSequence, offset, &ptr)) != 0) {
|
||||
if (ptr && checkExecutability(ptr))
|
||||
dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr);
|
||||
ptr++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -867,7 +869,7 @@ void returnAddressHuntJutsu(){
|
|||
int i = 0, bufferIndex = 0;
|
||||
ULONG offset = 0, bytes = 0;
|
||||
char findBufferExpression[25];
|
||||
ULONG64 returnAddress = 0;
|
||||
ULONG64 returnAddress = 0, ptr = 0;
|
||||
HRESULT memSearch = S_OK;
|
||||
|
||||
//disassembly variables
|
||||
|
@ -902,7 +904,7 @@ void returnAddressHuntJutsu(){
|
|||
StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call %s", regs[i]);
|
||||
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
|
||||
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
|
||||
if(checkExecutability(returnAddress))
|
||||
dprintf("[J] valid return address (call %s) found at 0x%08x\n", regs[i], returnAddress);
|
||||
}
|
||||
|
@ -913,7 +915,7 @@ void returnAddressHuntJutsu(){
|
|||
StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp %s", regs[i]);
|
||||
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
|
||||
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
|
||||
if(checkExecutability(returnAddress))
|
||||
dprintf("[J] valid return address (jmp %s) found at 0x%08x\n", regs[i], returnAddress);
|
||||
}
|
||||
|
@ -948,7 +950,7 @@ void returnAddressHuntJutsu(){
|
|||
StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call [%s+%x]", regs[i], offset);
|
||||
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
|
||||
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
|
||||
if(checkExecutability(returnAddress))
|
||||
dprintf("[J] valid return address (call [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress);
|
||||
}
|
||||
|
@ -959,7 +961,7 @@ void returnAddressHuntJutsu(){
|
|||
StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp [%s+%x]", regs[i], offset);
|
||||
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
|
||||
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){
|
||||
if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
|
||||
if(checkExecutability(returnAddress))
|
||||
dprintf("[J] valid return address (jmp [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ void trackValJutsu(char *name, DWORD size, DWORD value);
|
|||
void listTrackedVals(void);
|
||||
void listTrackedValByName(char *name);
|
||||
ULONG64 allocateMemoryBlock(unsigned long);
|
||||
ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length);
|
||||
ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length, ULONG64 *addressHit);
|
||||
DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance);
|
||||
void memDiffJutsu(char *inputType, DWORD size, char *input, ULONG64 address);
|
||||
|
||||
|
|
|
@ -12,5 +12,5 @@ build -cZMg
|
|||
build -cZMg
|
||||
cd ..
|
||||
|
||||
copy /Y i386\byakugan.dll C:\windbg\
|
||||
copy /Y i386\byakugan.dll C:\windbg\winext\
|
||||
copy /Y injectsu\i386\injectsu.dll C:\windbg\
|
||||
|
|
|
@ -22,11 +22,12 @@ PCSTR undocdFunc[] = { "ntdll!RtlpCoalesceFreeBlocks", NULL };
|
|||
ULONG undocdAddr[sizeof (undocdFunc)+1];
|
||||
|
||||
struct HeapState heapModel;
|
||||
BOOLEAN running = FALSE;
|
||||
|
||||
// Two things that fucking rock? Bunnies and Jaguars. Werd.
|
||||
|
||||
|
||||
int hookRtlHeap(void) {
|
||||
int hookRtlHeap(BYTE type) {
|
||||
HRESULT Status;
|
||||
HANDLE process;
|
||||
DWORD pid;
|
||||
|
@ -37,6 +38,15 @@ int hookRtlHeap(void) {
|
|||
ULONG64 funcAddr64;
|
||||
ULONG *funcAddr, i;
|
||||
|
||||
heapModel.state = heapModel.state ^ type;
|
||||
|
||||
if (running) {
|
||||
dprintf("[Byakugan] Hooks are already injected.\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
running = TRUE;
|
||||
|
||||
dprintf("[Byakugan] Beginning data gathering thread... ");
|
||||
if(tenkListener()) {
|
||||
dprintf("\n[Byakugan] Failed to create heap info back channel :(\n");
|
||||
|
@ -185,9 +195,9 @@ DWORD WINAPI tenkBackChannel(LPVOID lpvParam) {
|
|||
|
||||
initializeHeapModel(&heapModel);
|
||||
|
||||
#define THREEDHEAPFU_ENABLED //Place this in setup.bat
|
||||
#undef THREEDHEAPFU_ENABLED //Place this in setup.bat
|
||||
|
||||
#ifdef THREEDHEAPFU_ENABLED
|
||||
#if 0 //#ifdef THREEDHEAPFU_ENABLED
|
||||
//Create a heap event proxy, play these back out to 3dheapfu
|
||||
LPTSTR lpszProxyPipename = TEXT("\\\\.\\pipe\\tenketsuProxy");
|
||||
BOOL fProxySuccess;
|
||||
|
@ -221,7 +231,7 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
|
|||
dprintf("[Byakugan] ReadFile failed, or read 0 bytes.\n");
|
||||
continue;
|
||||
}
|
||||
#ifdef THREEDHEAPFU_ENABLED
|
||||
#if 0 //#ifdef THREEDHEAPFU_ENABLED
|
||||
//dprintf("jc: receieved an event of size %d. Forwarding on to ProxyPipe\n", bytesRead);
|
||||
//WriteFile(hPipe, &freeinfo, sizeof(struct FreeStruct), &bytesWritten, NULL);
|
||||
|
||||
|
@ -243,7 +253,8 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
|
|||
//dprintf("[T] New Chunk @ 0x%08x\n", aStruct->ret);
|
||||
//dprintf("Heap: 0x%08x\tFlags: 0x%08x\tSize: 0x%08x\n\n",
|
||||
// aStruct->heapHandle, aStruct->flags, aStruct->size);
|
||||
heapAllocate(&heapModel, aStruct);
|
||||
if (heapModel.state & MODEL) heapAllocate(&heapModel, aStruct);
|
||||
if (heapModel.state & LOG) logAllocate(&heapModel, aStruct);
|
||||
break;
|
||||
|
||||
case REALLOCATESTRUCT:
|
||||
|
@ -253,13 +264,15 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
|
|||
//if (rStruct->ret != (PVOID) rStruct->memoryPointer)
|
||||
// dprintf("Replaces chunk @ 0x%08x\n", rStruct->memoryPointer);
|
||||
//dprintf("\n");
|
||||
heapReallocate(&heapModel, rStruct);
|
||||
if (heapModel.state & MODEL) heapReallocate(&heapModel, rStruct);
|
||||
if (heapModel.state & LOG) logReallocate(&heapModel, rStruct);
|
||||
break;
|
||||
|
||||
case FREESTRUCT:
|
||||
//dprintf("[T] Free'd Chunk @ 0x%08x\n", fStruct->memoryPointer);
|
||||
//dprintf("Heap: 0x%08x\tFlags: 0x%08x\n\n", fStruct->heapHandle, fStruct->flags);
|
||||
heapFree(&heapModel, fStruct);
|
||||
if (heapModel.state & MODEL) heapFree(&heapModel, fStruct);
|
||||
if (heapModel.state & LOG) logFree(&heapModel, fStruct);
|
||||
break;
|
||||
|
||||
case CREATESTRUCT:
|
||||
|
@ -267,19 +280,19 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
|
|||
dprintf("Base: 0x%08x\tReserve: 0x%08x\tFlags: 0x%08x\n",
|
||||
cStruct->base, cStruct->reserve, cStruct->flags);
|
||||
//dprintf("Commit: 0x%08x\tLock: 0x%08x\n\n", cStruct->commit, cStruct->lock);
|
||||
heapCreate(&heapModel, cStruct);
|
||||
if (heapModel.state & MODEL) heapCreate(&heapModel, cStruct);
|
||||
break;
|
||||
|
||||
case DESTROYSTRUCT:
|
||||
dprintf("[T] Heap Destroyed: 0x%08x\n\n", dStruct->heapHandle);
|
||||
heapDestroy(&heapModel, dStruct);
|
||||
if (heapModel.state & MODEL) heapDestroy(&heapModel, dStruct);
|
||||
break;
|
||||
|
||||
case COALESCESTRUCT:
|
||||
//dprintf("[T] Free Block Consolidation (returned 0x%08x)\n", cfbStruct->ret);
|
||||
//dprintf("Heap: 0x%08x\tArg2: 0x%08x\tArg3: 0x%08x\tArg4: 0x%08x\n\n",
|
||||
// cfbStruct->heapHandle, cfbStruct->arg2, cfbStruct->arg3, cfbStruct->arg4);
|
||||
heapCoalesce(&heapModel, cfbStruct);
|
||||
if (heapModel.state & MODEL) heapCoalesce(&heapModel, cfbStruct);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -295,7 +308,8 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
|
|||
void tenkHelp() {
|
||||
dprintf(HELPSTRING);
|
||||
dprintf("Tenketsu Commands:\n");
|
||||
dprintf("\t<no command>\t- Load tenketsu heap visualization libraries and hooks\n");
|
||||
dprintf("\tmodel\t- Load tenketsu heap visualization libraries and begin modeling\n");
|
||||
dprintf("\tlog\t- Load tenketsu heap visualization libraries and begin logging\n");
|
||||
dprintf("\tlistHeaps\t- List all currently tracked heaps and their information\n");
|
||||
dprintf("\tlistChunks <heap base>\t- List all chunks associated with a givend heap\n");
|
||||
dprintf("\tvalidate <heap base> - check the chunk chain and find corrupted chunk headers\n");
|
||||
|
@ -388,8 +402,11 @@ void tenkListChunks(PVOID heapHandle) {
|
|||
|
||||
i = heap->inUseHead;
|
||||
while (i != NULLNODE) {
|
||||
dprintf("\tAddress: 0x%08x\tSize: 0x%08x", CHUNK(i).addr, CHUNK(i).size);
|
||||
dprintf("\tFlags: 0x%08x\t%s\n\n", CHUNK(i).flags, (CHUNK(i).free)?"FREE'D":"IN USE");
|
||||
if (CHUNK(i).inUse) {
|
||||
dprintf("\tAddress: 0x%08x\tSize: 0x%08x", CHUNK(i).addr, CHUNK(i).size);
|
||||
dprintf("\tFlags: 0x%08x\t%s\n\n", CHUNK(i).flags,
|
||||
(CHUNK(i).free)?"FREE'D":"IN USE");
|
||||
}
|
||||
i = CHUNK(i).nextInUse;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ typedef struct _RTL_HEAP_DEFINITION {
|
|||
|
||||
/* FUNCTIONS */
|
||||
|
||||
int hookRtlHeap(void);
|
||||
int hookRtlHeap(BYTE);
|
||||
int tenkListener(void);
|
||||
void tenkListHeaps(void);
|
||||
void tenkListChunks(PVOID);
|
||||
|
|
|
@ -18,6 +18,9 @@ int main(int argc, char **argv) {
|
|||
for (i = 0; i < NUMPTRS; i+=2) {
|
||||
free(foo[i]);
|
||||
}
|
||||
free(foo[1]);
|
||||
free(foo[7]);
|
||||
free(foo[3]);
|
||||
__asm {
|
||||
int 3
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue