bool initStrings() { delphiNewUtf8 = searchMemory(DELPHI_NEWUTF8_PATTERN, DELPHI_NEWUTF8_PATTERN_LEN); delphiReleaseStr = searchMemory(DELPHI_RELEASESTR_PATTERN, DELPHI_RELEASESTR_PATTERN_LEN); delphiStrAlloc = searchMemory(DELPHI_ALLOCSTR_PATTERN, DELPHI_ALLOCSTR_PATTERN_LEN); return delphiNewUtf8 && delphiReleaseStr && delphiStrAlloc; }
void search(struct Processor *proc,char **tokens) { if (strcmp(token[0],"-M") ==0) { searchMemory(proc,tokens+1); } else if (strcmp(token[0],"-R")==0) { searchRegisters(proc,tokens+1); } }
void returnAddressHuntJutsu(){ struct trackedBuf *curBuf; int i = 0, bufferIndex = 0; ULONG offset = 0, bytes = 0; char findBufferExpression[25]; ULONG64 returnAddress = 0; HRESULT memSearch = S_OK; //disassembly variables char returnInstruction[30]; unsigned char opcodeBuffer[30]; unsigned short instructionLength = 0; dprintf("[J] started return address hunt\n"); for(i; i<6; i++){ //6, because we don't want to waste time on the eip register curBuf = trackedBufList; memset(findBufferExpression, 0x00, sizeof(findBufferExpression)); if(!(bytes = GetExpression(regs[i]))){ dprintf("[J] skipping %s as register - it is a null pointer\n", regs[i]); continue; } StringCchPrintf(findBufferExpression, sizeof(findBufferExpression), "poi(%s)", regs[i]); bytes = GetExpression(findBufferExpression); //tests if a register points to a location in user controlled data while(curBuf != NULL){ for(bufferIndex=0; bufferIndex < strlen(curBuf->bufPatt); bufferIndex++){ if(*(PULONG)((curBuf->bufPatt)+bufferIndex) == bytes){ memset(opcodeBuffer, 0x00, sizeof(opcodeBuffer)); memset(returnInstruction, 0x00, sizeof(returnInstruction)); //find the opcodes for the desired instruction //first, for call reg 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(checkExecutability(returnAddress)) dprintf("[J] valid return address (call %s) found at 0x%08x\n", regs[i], returnAddress); } //now, for jmp reg memset(returnInstruction, 0x00, sizeof(returnInstruction)); 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(checkExecutability(returnAddress)) dprintf("[J] valid return address (jmp %s) found at 0x%08x\n", regs[i], returnAddress); } } } curBuf = curBuf->next; } curBuf = trackedBufList; for(offset=0; offset<0x1000; offset+=4){ memset(findBufferExpression, 0x00, sizeof(findBufferExpression)); StringCchPrintf(findBufferExpression, sizeof(findBufferExpression), "poi(poi(%s+0x%08x))", regs[i], offset); if(!(bytes = GetExpression(findBufferExpression))) continue; //this is basically a replacement for the //ddp windbg command, except more automated //walk through the buffer to see if any dword in there matches the current //value returned by the expression while(curBuf != NULL){ for(bufferIndex=0; bufferIndex < strlen(curBuf->bufPatt); bufferIndex++){ if(*(PULONG)((curBuf->bufPatt)+bufferIndex) == bytes){ memset(opcodeBuffer, 0x00, sizeof(opcodeBuffer)); memset(returnInstruction, 0x00, sizeof(returnInstruction)); dprintf("[J] %s + 0x%08x points into offset 0x%x of buffer %s\n", regs[i], offset, bufferIndex, curBuf->bufName); //first, build the instruction to find the bytes for //for now, we will support jmp [reg+offset] and call [reg+offset] //first, for call [reg+offset] 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(checkExecutability(returnAddress)) dprintf("[J] valid return address (call [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress); } //now, for jmp [reg+offset] memset(returnInstruction, 0x00, sizeof(returnInstruction)); 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(checkExecutability(returnAddress)) dprintf("[J] valid return address (jmp [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress); } } } curBuf = curBuf->next; } curBuf = trackedBufList; } } }
void searchOpcodes(char *instructions) { char **instructionList; unsigned char *byteSequence; DWORD length, i, j, semiCount = 1, offset = 0; ULONG64 ptr; // Split instructions into seperate strings at pipes length = 0; while (instructions[length] != NULL) { if (instructions[length] == '|') semiCount++; length++; } // Malloc space for instructionList; instructionList = (char **) malloc((semiCount+1) * sizeof (char *)); if (instructionList == NULL) { dprintf("[J] OOM!\n"); return; } instructionList[0] = instructions; dprintf("[J] Searching for:\n"); i = 0; j = 0; while (i < length) { if (instructions[i] == '|') { instructions[i] = '\x00'; dprintf("> %s\n", instructionList[j++]); instructionList[j] = &(instructions[i+1]); } i++; } dprintf("> %s\n", instructionList[j]); // Allocate space for byteSequence byteSequence = (unsigned char *) malloc(semiCount * 6); if (byteSequence == NULL) { dprintf("[J] OOM!\n"); return; } // Generate byte sequence and display it for (i = 0; i < semiCount; i++) { unsigned char tmpbuf[8]; offset += getInstructionBytes(instructionList[i], byteSequence+offset); } dprintf("[J] Machine Code:\n> "); for (i = 0; i < offset; i++) { dprintf("%02x ", byteSequence[i]); if (i != 0 && !(i % 16)) dprintf("\n> "); } 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); return; }
void hunterJutsu() { struct trackedBuf *curBuf; struct bufInstance *instance; ULONG i, j, range, addr, *nextNum, foundInstance; BOOLEAN caught; char *corUpper, *corLower, *corUni; for (i = 0; regs[i] != NULL; i++) { addr = GetExpression(regs[i]); curBuf = trackedBufList; caught = FALSE; while (curBuf != NULL) { range = strlen(curBuf->bufPatt); for (j = 0; j < range-3; j++) { nextNum = (ULONG *) ((curBuf->bufPatt) + j); if (*nextNum == addr) { dprintf("[J] Controlling %s with %s at offset %d.\n", regs[i], curBuf->bufName, j); caught = TRUE; break; } } curBuf = curBuf->next; if (caught) break; } } // Now, find all instances of buffers in memory with a fuzzy match! :) curBuf = trackedBufList; while (curBuf != NULL) { foundInstance = searchMemory((unsigned char *) curBuf->bufPatt, (strlen(curBuf->bufPatt) > 32) ? 32 : strlen(curBuf->bufPatt)); if (foundInstance != 0) { // try for larger increments instance = (struct bufInstance *) malloc(sizeof (struct bufInstance)); memset(instance, 0, sizeof (struct bufInstance)); instance->address = foundInstance; dprintf("[J] Found buffer %s @ 0x%08x\n", curBuf->bufName, foundInstance); } // try standard corruptions range = (strlen(curBuf->bufPatt) > 32) ? 32 : strlen(curBuf->bufPatt); corUpper = (char *) malloc(range + 1); corLower = (char *) malloc(range + 1); corUni = (char *) malloc((range + 1) * 2); for (i = j = 0; i < range; i++) { corUpper[i] = (char) toupper(curBuf->bufPatt[i]); corLower[i] = (char) tolower(curBuf->bufPatt[i]); corUni[j++] = curBuf->bufPatt[i]; corUni[j++] = '\x00'; } if ((foundInstance = searchMemory((unsigned char *) corUpper, range)) != 0) dprintf("[J] Found buffer %s @ 0x%08x - Victim of toUpper!\n", curBuf->bufName, foundInstance); if ((foundInstance = searchMemory((unsigned char *) corLower, range)) != 0) dprintf("[J] Found buffer %s @ 0x%08x - Victim of toLower!\n", curBuf->bufName, foundInstance); if ((foundInstance = searchMemory((unsigned char *) corUni, range*2)) != 0) dprintf("[J] Found buffer %s @ 0x%08x - Victim of Unicode Conversion!\n", curBuf->bufName, foundInstance); free(corUpper); free(corLower); free(corUni); curBuf = curBuf->next; } }