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, " ");
|
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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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\
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue