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:
pusscat 2009-08-06 20:09:38 +00:00
parent 4070c5653b
commit b9c2d57630
17 changed files with 134 additions and 50 deletions

View File

@ -207,12 +207,27 @@ HRESULT CALLBACK tenketsu(PDEBUG_CLIENT4 Client, PCSTR args) {
command = strtok((char *)args, " "); command = strtok((char *)args, " ");
if (command == NULL) { if (command == NULL) {
if(hookRtlHeap()) { tenkHelp();
dprintf("[Byakugan] Unable to begin realtime heap debugging.\n"); return (S_OK);
}
else if (!_stricmp(command, "model")) {
if(hookRtlHeap(1)) {
dprintf("[Byakugan] Unable to begin realtime heap modeling.\n");
EXIT_API(); EXIT_API();
return (S_FALSE); 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")) { else if (!_stricmp(command, "help")) {
tenkHelp(); tenkHelp();
return (S_OK); return (S_OK);

View File

@ -71,7 +71,6 @@ void removeBucket(PVOID addr, struct HPool *heap) {
if (heap == NULL) if (heap == NULL)
return; return;
heap->numChunks--;
offset = hash(addr, heap); offset = hash(addr, heap);
chunkNum = heap->map[offset]; chunkNum = heap->map[offset];
@ -91,17 +90,46 @@ void removeBucket(PVOID addr, struct HPool *heap) {
heap->map[offset] = NULLNODE; heap->map[offset] = NULLNODE;
else else
CHUNK(last).nextBucket = CHUNK(chunkNum).nextBucket; CHUNK(last).nextBucket = CHUNK(chunkNum).nextBucket;
heap->numChunks--;
} else } else
dprintf("[T] Couldnt find chunk 0x%08x to delete :(\n", addr); 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) { void initializeHeapModel(struct HeapState *heapModel) {
memset(heapModel, 0, sizeof (struct HeapState)); memset(heapModel+1, 0, sizeof (struct HeapState));
heapModel->hPoolListLen = 16; heapModel->hPoolListLen = 16;
heapModel->heaps = (struct HPool *) calloc(heapModel->hPoolListLen, sizeof (struct HPool)); 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) { void heapAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct) {
struct HPool *myHeap; struct HPool *myHeap;
struct HeapChunk *myChunk, *remainder; struct HeapChunk *myChunk, *remainder;
@ -171,21 +199,17 @@ void heapFree(struct HeapState *heapModel, struct FreeStruct *fStruct) {
//dprintf("[XXX] Freeing 0x%08x\n", fStruct->memoryPointer); //dprintf("[XXX] Freeing 0x%08x\n", fStruct->memoryPointer);
//#ifndef THREEDHEAPFU_ENABLED
#ifdef THREEDHEAPFU_ENABLED
if (fStruct->heapHandle == 0 || fStruct->memoryPointer == 0x00000000) { if (fStruct->heapHandle == 0 || fStruct->memoryPointer == 0x00000000) {
// So many of these that it slows us down :( // So many of these that it slows us down :(
//dprintf("[T] Program attempted to free a NULL pointer.\n\n"); //dprintf("[T] Program attempted to free a NULL pointer.\n\n");
return; return;
} }
#endif
myHeap = getHeap(heapModel, fStruct->heapHandle); myHeap = getHeap(heapModel, fStruct->heapHandle);
myChunk = getChunk(myHeap, fStruct->memoryPointer, NULLNODE); myChunk = getChunk(myHeap, fStruct->memoryPointer, NULLNODE);
if (myChunk == NULL) if (myChunk == NULL)
return; // dupe free :( return; // dupe free :(
#ifndef THREEDHEAPFU_ENABLED #if 0
if (myChunk->free == 2) if (myChunk->free == 2)
dprintf("[T] Possible 'double free' of chunk @ 0x%08x:0x%x\n\n", dprintf("[T] Possible 'double free' of chunk @ 0x%08x:0x%x\n\n",
myChunk->addr, myChunk->free); myChunk->addr, myChunk->free);
@ -252,7 +276,7 @@ void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct)
while (i != NULLNODE) { while (i != NULLNODE) {
if (CHUNK(i).free) { if (CHUNK(i).free) {
//dprintf("[T] Found free chunk %d at 0x%08x\n", i, CHUNK(i).addr); //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) { while (j != NULLNODE && CHUNK(j).free) {
//dprintf("[T] Found free chunk %d at 0x%08x\n", j, CHUNK(j).addr); //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 // most of the time - win2k is insane and
// goes backwards :( // 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 // fix up hash bucket list
removeBucket(CHUNK(j).addr, heap); removeBucket(CHUNK(j).addr, heap);
//dprintf("[T] Coalescing 0x%08x and 0x%08x. New size: %d bytes\n", //dprintf("[T] Coalescing 0x%08x and 0x%08x. New size: %d bytes\n",
//CHUNK(i).addr, CHUNK(j).addr, CHUNK(i).size); //CHUNK(i).addr, CHUNK(j).addr, CHUNK(i).size);
j = CHUNK(i).nextInUse; j = FindOffsetForChunk(heap, NEXTADDR(i));
} }
} }
i = CHUNK(i).nextInUse; i = CHUNK(i).nextInUse;

View File

@ -5,18 +5,28 @@
#define DESTROYSTRUCT 0x4 #define DESTROYSTRUCT 0x4
#define COALESCESTRUCT 0x5 #define COALESCESTRUCT 0x5
#define SPACEBETWEEN 0x18
#define CHUNK(x) (heap->chunks[x]) #define CHUNK(x) (heap->chunks[x])
#define NEXTADDR(x) (PVOID)(*((ULONG *)(&(CHUNK(i).addr))) + CHUNK(i).size + SPACEBETWEEN)
#define NULLNODE 0xffffffff #define NULLNODE 0xffffffff
#define MODEL 1
#define LOG 2
#define RUNNING 4
// Space between chunks on vista // Space between chunks on vista
#define SPACEBETWEEN 0x18
// Dont use a direct access list here because looping should // Dont use a direct access list here because looping should
// be faster for our number of heaps (I think!) // be faster for our number of heaps (I think!)
struct HeapState { struct HeapState {
BYTE state;
ULONG numHeaps; ULONG numHeaps;
ULONG hPoolListLen; ULONG hPoolListLen;
struct HPool *heaps; struct HPool *heaps;
}; };
struct HPool { struct HPool {
@ -34,6 +44,16 @@ struct HPool {
BOOLEAN inUse; BOOLEAN inUse;
}; };
struct LookAsideList {
DWORD placeHolder;
};
struct HeapCache {
ULONG NumBuckets;
unsigned __int8 *pBitmap;
ULONG **pBuckets;
};
struct HeapChunk { struct HeapChunk {
PVOID addr; PVOID addr;
PVOID heapHandle; PVOID heapHandle;
@ -41,6 +61,7 @@ struct HeapChunk {
ULONG flags; ULONG flags;
ULONG nextBucket; ULONG nextBucket;
ULONG nextInUse; ULONG nextInUse;
ULONG nextFreeListChunk;
BOOLEAN free; BOOLEAN free;
BOOLEAN inUse; BOOLEAN inUse;
}; };
@ -99,8 +120,14 @@ struct CoalesceStruct {
void initializeHeapModel(struct HeapState *); void initializeHeapModel(struct HeapState *);
void heapAllocate(struct HeapState *heapModel, struct AllocateStruct *aStruct); 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 heapReallocate(struct HeapState *heapModel, struct ReallocateStruct *aStruct);
void logReallocate(struct HeapState *heapModel, struct ReallocateStruct *aStruct);
void heapFree(struct HeapState *heapModel, struct FreeStruct *fStruct); 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 heapCreate(struct HeapState *heapModel, struct CreateStruct *cStruct);
void heapDestroy(struct HeapState *heapModel, struct DestroyStruct *dStruct); void heapDestroy(struct HeapState *heapModel, struct DestroyStruct *dStruct);
void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct); void heapCoalesce(struct HeapState *heapModel, struct CoalesceStruct *cfbStruct);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -606,6 +606,7 @@ void hunterJutsu() {
ULONG i, j, range, addr, *nextNum, foundInstance; ULONG i, j, range, addr, *nextNum, foundInstance;
BOOLEAN caught; BOOLEAN caught;
char *corUpper, *corLower, *corUni; char *corUpper, *corLower, *corUni;
ULONG64 ptr = 0;
for (i = 0; regs[i] != NULL; i++) { for (i = 0; regs[i] != NULL; i++) {
addr = GetExpression(regs[i]); addr = GetExpression(regs[i]);
@ -633,7 +634,7 @@ void hunterJutsu() {
curBuf = trackedBufList; curBuf = trackedBufList;
while (curBuf != NULL) { while (curBuf != NULL) {
foundInstance = searchMemory((unsigned char *) curBuf->bufPatt, foundInstance = searchMemory((unsigned char *) curBuf->bufPatt,
(curBuf->bufSize > 32) ? 32 : curBuf->bufSize); (curBuf->bufSize > 32) ? 32 : curBuf->bufSize, &ptr);
if (foundInstance != 0) { if (foundInstance != 0) {
// try for larger increments // try for larger increments
instance = (struct bufInstance *) malloc(sizeof (struct bufInstance)); instance = (struct bufInstance *) malloc(sizeof (struct bufInstance));
@ -652,13 +653,13 @@ void hunterJutsu() {
corUni[j++] = curBuf->bufPatt[i]; corUni[j++] = curBuf->bufPatt[i];
corUni[j++] = '\x00'; 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", dprintf("[J] Found buffer %s @ 0x%08x - Victim of toUpper!\n",
curBuf->bufName, foundInstance); 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", dprintf("[J] Found buffer %s @ 0x%08x - Victim of toLower!\n",
curBuf->bufName, foundInstance); 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", dprintf("[J] Found buffer %s @ 0x%08x - Victim of Unicode Conversion!\n",
curBuf->bufName, foundInstance); curBuf->bufName, foundInstance);
free(corUpper); free(corUpper);
@ -738,12 +739,11 @@ unsigned short getInstructionBytes(char * instruction, unsigned char * opcodeBuf
return (byteEnd-disassemblyBuffer); return (byteEnd-disassemblyBuffer);
} }
ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length){ ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length, ULONG64 *addressHit){
ULONG64 addressHit = 0;
HRESULT memSearch = S_OK; HRESULT memSearch = S_OK;
if((memSearch = g_ExtData->SearchVirtual((ULONG64)0, (ULONG64)-1, byteBuffer, if((memSearch = g_ExtData->SearchVirtual((ULONG64)*addressHit, (ULONG64)-1, byteBuffer,
length, 1, &addressHit)) != S_OK){ length, 1, addressHit)) != S_OK){
#if 0 #if 0
if(memSearch == HRESULT_FROM_NT(STATUS_NO_MORE_ENTRIES)){ if(memSearch == HRESULT_FROM_NT(STATUS_NO_MORE_ENTRIES)){
dprintf("[J] byte sequence not found in virtual memory\n"); dprintf("[J] byte sequence not found in virtual memory\n");
@ -754,7 +754,7 @@ ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length){
#endif #endif
return (0); return (0);
} }
return (addressHit); return (*addressHit);
} }
DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance) { DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance) {
@ -804,7 +804,7 @@ void searchOpcodes(char *instructions) {
char **instructionList; char **instructionList;
unsigned char *byteSequence; unsigned char *byteSequence;
DWORD length, i, j, semiCount = 1, offset = 0; DWORD length, i, j, semiCount = 1, offset = 0;
ULONG64 ptr; ULONG64 ptr = 0;
// Split instructions into seperate strings at pipes // Split instructions into seperate strings at pipes
length = 0; length = 0;
@ -856,9 +856,11 @@ void searchOpcodes(char *instructions) {
dprintf("\n"); dprintf("\n");
// Search for sequence in executable memory // Search for sequence in executable memory
ptr = searchMemory(byteSequence, offset); while((ptr = searchMemory(byteSequence, offset, &ptr)) != 0) {
if (ptr && checkExecutability(ptr)) if (ptr && checkExecutability(ptr))
dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr); dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr);
ptr++;
}
return; return;
} }
@ -867,7 +869,7 @@ void returnAddressHuntJutsu(){
int i = 0, bufferIndex = 0; int i = 0, bufferIndex = 0;
ULONG offset = 0, bytes = 0; ULONG offset = 0, bytes = 0;
char findBufferExpression[25]; char findBufferExpression[25];
ULONG64 returnAddress = 0; ULONG64 returnAddress = 0, ptr = 0;
HRESULT memSearch = S_OK; HRESULT memSearch = S_OK;
//disassembly variables //disassembly variables
@ -902,7 +904,7 @@ void returnAddressHuntJutsu(){
StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call %s", regs[i]); StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call %s", regs[i]);
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer))) if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction); dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){ if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
if(checkExecutability(returnAddress)) if(checkExecutability(returnAddress))
dprintf("[J] valid return address (call %s) found at 0x%08x\n", regs[i], 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]); StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp %s", regs[i]);
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer))) if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction); dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){ if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
if(checkExecutability(returnAddress)) if(checkExecutability(returnAddress))
dprintf("[J] valid return address (jmp %s) found at 0x%08x\n", regs[i], 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); StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call [%s+%x]", regs[i], offset);
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer))) if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction); dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){ if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
if(checkExecutability(returnAddress)) if(checkExecutability(returnAddress))
dprintf("[J] valid return address (call [%s+%x]) found at 0x%08x\n", regs[i], offset, 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); StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp [%s+%x]", regs[i], offset);
if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer))) if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))
dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction); dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);
if(returnAddress = searchMemory(opcodeBuffer, instructionLength)){ if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){
if(checkExecutability(returnAddress)) if(checkExecutability(returnAddress))
dprintf("[J] valid return address (jmp [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress); dprintf("[J] valid return address (jmp [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress);
} }

View File

@ -95,7 +95,7 @@ void trackValJutsu(char *name, DWORD size, DWORD value);
void listTrackedVals(void); void listTrackedVals(void);
void listTrackedValByName(char *name); void listTrackedValByName(char *name);
ULONG64 allocateMemoryBlock(unsigned long); 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); DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance);
void memDiffJutsu(char *inputType, DWORD size, char *input, ULONG64 address); void memDiffJutsu(char *inputType, DWORD size, char *input, ULONG64 address);

View File

@ -12,5 +12,5 @@ build -cZMg
build -cZMg build -cZMg
cd .. cd ..
copy /Y i386\byakugan.dll C:\windbg\ copy /Y i386\byakugan.dll C:\windbg\winext\
copy /Y injectsu\i386\injectsu.dll C:\windbg\ copy /Y injectsu\i386\injectsu.dll C:\windbg\

View File

@ -22,11 +22,12 @@ PCSTR undocdFunc[] = { "ntdll!RtlpCoalesceFreeBlocks", NULL };
ULONG undocdAddr[sizeof (undocdFunc)+1]; ULONG undocdAddr[sizeof (undocdFunc)+1];
struct HeapState heapModel; struct HeapState heapModel;
BOOLEAN running = FALSE;
// Two things that fucking rock? Bunnies and Jaguars. Werd. // Two things that fucking rock? Bunnies and Jaguars. Werd.
int hookRtlHeap(void) { int hookRtlHeap(BYTE type) {
HRESULT Status; HRESULT Status;
HANDLE process; HANDLE process;
DWORD pid; DWORD pid;
@ -37,6 +38,15 @@ int hookRtlHeap(void) {
ULONG64 funcAddr64; ULONG64 funcAddr64;
ULONG *funcAddr, i; 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... "); dprintf("[Byakugan] Beginning data gathering thread... ");
if(tenkListener()) { if(tenkListener()) {
dprintf("\n[Byakugan] Failed to create heap info back channel :(\n"); dprintf("\n[Byakugan] Failed to create heap info back channel :(\n");
@ -185,9 +195,9 @@ DWORD WINAPI tenkBackChannel(LPVOID lpvParam) {
initializeHeapModel(&heapModel); 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 //Create a heap event proxy, play these back out to 3dheapfu
LPTSTR lpszProxyPipename = TEXT("\\\\.\\pipe\\tenketsuProxy"); LPTSTR lpszProxyPipename = TEXT("\\\\.\\pipe\\tenketsuProxy");
BOOL fProxySuccess; BOOL fProxySuccess;
@ -221,7 +231,7 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
dprintf("[Byakugan] ReadFile failed, or read 0 bytes.\n"); dprintf("[Byakugan] ReadFile failed, or read 0 bytes.\n");
continue; continue;
} }
#ifdef THREEDHEAPFU_ENABLED #if 0 //#ifdef THREEDHEAPFU_ENABLED
//dprintf("jc: receieved an event of size %d. Forwarding on to ProxyPipe\n", bytesRead); //dprintf("jc: receieved an event of size %d. Forwarding on to ProxyPipe\n", bytesRead);
//WriteFile(hPipe, &freeinfo, sizeof(struct FreeStruct), &bytesWritten, NULL); //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("[T] New Chunk @ 0x%08x\n", aStruct->ret);
//dprintf("Heap: 0x%08x\tFlags: 0x%08x\tSize: 0x%08x\n\n", //dprintf("Heap: 0x%08x\tFlags: 0x%08x\tSize: 0x%08x\n\n",
// aStruct->heapHandle, aStruct->flags, aStruct->size); // aStruct->heapHandle, aStruct->flags, aStruct->size);
heapAllocate(&heapModel, aStruct); if (heapModel.state & MODEL) heapAllocate(&heapModel, aStruct);
if (heapModel.state & LOG) logAllocate(&heapModel, aStruct);
break; break;
case REALLOCATESTRUCT: case REALLOCATESTRUCT:
@ -253,13 +264,15 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
//if (rStruct->ret != (PVOID) rStruct->memoryPointer) //if (rStruct->ret != (PVOID) rStruct->memoryPointer)
// dprintf("Replaces chunk @ 0x%08x\n", rStruct->memoryPointer); // dprintf("Replaces chunk @ 0x%08x\n", rStruct->memoryPointer);
//dprintf("\n"); //dprintf("\n");
heapReallocate(&heapModel, rStruct); if (heapModel.state & MODEL) heapReallocate(&heapModel, rStruct);
if (heapModel.state & LOG) logReallocate(&heapModel, rStruct);
break; break;
case FREESTRUCT: case FREESTRUCT:
//dprintf("[T] Free'd Chunk @ 0x%08x\n", fStruct->memoryPointer); //dprintf("[T] Free'd Chunk @ 0x%08x\n", fStruct->memoryPointer);
//dprintf("Heap: 0x%08x\tFlags: 0x%08x\n\n", fStruct->heapHandle, fStruct->flags); //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; break;
case CREATESTRUCT: case CREATESTRUCT:
@ -267,19 +280,19 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
dprintf("Base: 0x%08x\tReserve: 0x%08x\tFlags: 0x%08x\n", dprintf("Base: 0x%08x\tReserve: 0x%08x\tFlags: 0x%08x\n",
cStruct->base, cStruct->reserve, cStruct->flags); cStruct->base, cStruct->reserve, cStruct->flags);
//dprintf("Commit: 0x%08x\tLock: 0x%08x\n\n", cStruct->commit, cStruct->lock); //dprintf("Commit: 0x%08x\tLock: 0x%08x\n\n", cStruct->commit, cStruct->lock);
heapCreate(&heapModel, cStruct); if (heapModel.state & MODEL) heapCreate(&heapModel, cStruct);
break; break;
case DESTROYSTRUCT: case DESTROYSTRUCT:
dprintf("[T] Heap Destroyed: 0x%08x\n\n", dStruct->heapHandle); dprintf("[T] Heap Destroyed: 0x%08x\n\n", dStruct->heapHandle);
heapDestroy(&heapModel, dStruct); if (heapModel.state & MODEL) heapDestroy(&heapModel, dStruct);
break; break;
case COALESCESTRUCT: case COALESCESTRUCT:
//dprintf("[T] Free Block Consolidation (returned 0x%08x)\n", cfbStruct->ret); //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", //dprintf("Heap: 0x%08x\tArg2: 0x%08x\tArg3: 0x%08x\tArg4: 0x%08x\n\n",
// cfbStruct->heapHandle, cfbStruct->arg2, cfbStruct->arg3, cfbStruct->arg4); // cfbStruct->heapHandle, cfbStruct->arg2, cfbStruct->arg3, cfbStruct->arg4);
heapCoalesce(&heapModel, cfbStruct); if (heapModel.state & MODEL) heapCoalesce(&heapModel, cfbStruct);
break; break;
default: default:
@ -295,7 +308,8 @@ HANDLE hProxyPipe = CreateFile(lpszProxyPipename,
void tenkHelp() { void tenkHelp() {
dprintf(HELPSTRING); dprintf(HELPSTRING);
dprintf("Tenketsu Commands:\n"); 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("\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("\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"); 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; i = heap->inUseHead;
while (i != NULLNODE) { while (i != NULLNODE) {
if (CHUNK(i).inUse) {
dprintf("\tAddress: 0x%08x\tSize: 0x%08x", CHUNK(i).addr, CHUNK(i).size); 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"); dprintf("\tFlags: 0x%08x\t%s\n\n", CHUNK(i).flags,
(CHUNK(i).free)?"FREE'D":"IN USE");
}
i = CHUNK(i).nextInUse; i = CHUNK(i).nextInUse;
} }

View File

@ -20,7 +20,7 @@ typedef struct _RTL_HEAP_DEFINITION {
/* FUNCTIONS */ /* FUNCTIONS */
int hookRtlHeap(void); int hookRtlHeap(BYTE);
int tenkListener(void); int tenkListener(void);
void tenkListHeaps(void); void tenkListHeaps(void);
void tenkListChunks(PVOID); void tenkListChunks(PVOID);

View File

@ -18,6 +18,9 @@ int main(int argc, char **argv) {
for (i = 0; i < NUMPTRS; i+=2) { for (i = 0; i < NUMPTRS; i+=2) {
free(foo[i]); free(foo[i]);
} }
free(foo[1]);
free(foo[7]);
free(foo[3]);
__asm { __asm {
int 3 int 3
} }