#include "byakugan.h" #include "msfpattern.h" #include "jutsu.h" #include "tenketsu.h" #include "mushishi.h" #include "symPort.h" #include "csv_parser.hpp" #include #include #include char *registers[] = { "eax", "ebx", "ecx", "edx", "esp", "ebp", "eip", NULL }; HRESULT CALLBACK byakugan(PDEBUG_CLIENT4 Client, PCSTR args) { INIT_API(); UNREFERENCED_PARAMETER(args); dprintf(HELPSTRING); dprintf("!jutsu - Perform Jutsu: !jutsu help\n"); dprintf("!tenketsu - Begin realtime heap vizualization: !tenketsu help\n"); dprintf("!pattern_offset \n"); dprintf("!mushishi - Detect or defeat anti-debugging mechanisms\n"); EXIT_API(); return (S_OK); } HRESULT CALLBACK pattern_offset(PDEBUG_CLIENT4 Client, PCSTR args) { char *arg1, **arg2, *holder[2], *context; ULONG length, addr; int offset, i; INIT_API(); UNREFERENCED_PARAMETER(args); arg1 = strtok((char *)args, " "); arg2 = holder; arg2[0] = strtok(NULL, " "); arg2[1] = NULL; if (arg1 == NULL) { dprintf("[Byakugan] Please provide a length.\n"); return (S_OK); } length = strtoul(arg1, NULL, 10); if (arg2[0] == NULL) arg2 = registers; for (i = 0; arg2[i] != NULL; i++) { addr = GetExpression(arg2[i]); offset = msf_pattern_offset(length, addr); if (offset != -1) dprintf("[Byakugan] Control of %s at offset %d.\n", arg2[i], offset); } EXIT_API(); return (S_OK); } HRESULT CALLBACK mushishi(PDEBUG_CLIENT4 Client, PCSTR args) { char *command; INIT_API(); command = strtok((char *)args, " "); if (command != NULL) { if (!_stricmp(command, "detect")) { mushishiDetect(); return (S_OK); } if (!_stricmp(command, "defeat")) { mushishiDefeat(); return (S_OK); } } dprintf("[Mushishi] Proper commands are: 'detect' 'defeat'\n"); EXIT_API(); return (S_OK); } HRESULT CALLBACK symport(PDEBUG_CLIENT4 Client, PCSTR args) { char *command, *module, *path; INIT_API(); module = strtok((char *)args, " "); path = strtok(NULL, " "); if (module != NULL && path != NULL) { addMapFile(module, path); return (S_OK); } else { dprintf("[symPort] Proper format is: !symport \n"); } EXIT_API(); return (S_OK); } HRESULT CALLBACK jutsu(PDEBUG_CLIENT4 Client, PCSTR args) { char *command, *bufName, *bufPatt, *bindPort, *bufSize, *bufType, *bufAddr; using namespace std; INIT_API(); command = strtok((char *)args, " "); if (command != NULL) { if (!_stricmp(command, "help")) { helpJutsu(); return (S_OK); } if (!_stricmp(command, "moduleInfo")) { } if (!_stricmp(command, "memDiff")) { bufType = strtok(NULL, " "); bufSize = strtok(NULL, " "); bufPatt = strtok(NULL, " "); bufAddr = strtok(NULL, " "); if (!bufAddr) { dprintf("[J] Format: memDiff
\n"); dprintf("Valid Types:\n\thex: Value is any hex characters\n"); dprintf("\tfile: Buffer is read in from file at path \n"); dprintf("\tbuf: Buffer is taken from known tracked Buffers\n"); return (S_OK); } memDiffJutsu(bufType, strtoul(bufSize, NULL, 10), bufPatt, strtoul(bufAddr, NULL, 0x10)); } if (!_stricmp(command, "trackVal")) { bufName = strtok(NULL, " "); bufSize = strtok(NULL, " "); bufPatt = strtok(NULL, " "); if (bufName == NULL) { listTrackedVals(); } else if (bufSize == NULL) { listTrackedValByName(bufName); } else trackValJutsu(bufName, strtoul(bufSize, NULL, 10), strtoul(bufPatt, NULL, 0x10)); } if (!_stricmp(command, "searchOpcode")) { char *instructions; instructions = (char *) args + strlen(command) + 1; searchOpcodes(instructions); return (S_OK); } if (!_stricmp(command, "searchVtptr")) { char *instructions, *offsetString; DWORD offset; offsetString = strtok(NULL, " "); offset = strtoul(offsetString, NULL, 16); instructions = offsetString + strlen(offsetString) + 1; searchVtptr(offset, instructions); return (S_OK); } if (!_stricmp(command, "listen")) { bindPort = strtok(NULL, " "); if (bindPort == NULL) bindPort = DEFAULT_PORT; bindJutsu(bindPort); return (S_OK); } if (!_stricmp(command, "listBuf")) { listTrackedBufJutsu(); return (S_OK); } if (!_stricmp(command, "listReqs")) { showRequestsJutsu(); return (S_OK); } if (!_stricmp(command, "rmBuf")) { bufName = strtok(NULL, " "); if (bufName == NULL) { dprintf("[Byakugan] This command requires a buffer name\n"); return (S_OK); } rmBufJutsu(bufName); return (S_OK); } if (!_stricmp(command, "identBuf")) { bufType = strtok(NULL, " "); bufName = strtok(NULL, " "); bufPatt = strtok(NULL, " "); bufSize = strtok(NULL, " "); if (bufPatt == NULL) { dprintf("[Byakugan] This command requires a buffer type, name, (sometimes) value, and size\n"); return (S_OK); } if (bufSize == NULL) identBufJutsu(bufType, bufName, bufPatt, 0, 0); else identBufJutsu(bufType, bufName, bufPatt, strtoul(bufSize, NULL, 10), 0); return (S_OK); } if (!_stricmp(command, "identBufFile")) { char *bufFile, *bufMap; bufFile = strtok(NULL, " "); bufMap = strtok(NULL, " "); bufType = "smartFile"; if (bufFile == NULL) { dprintf("[Byakugan] This command requires a path to an input file and map (CSV) from 010\n"); return (S_OK); } //these settings are explicting for 010 CSV export const char field_terminator = ','; const char line_terminator = '\n'; const char enclosure_char = '"'; //create parse object csv_parser file_parser; /* Define how many records we're gonna skip. This could be used to skip the column definitions. */ file_parser.set_skip_lines(1); /* Specify the file to parse */ file_parser.init(bufMap); /* Here we tell the parser how to parse the file */ file_parser.set_enclosed_char(enclosure_char, ENCLOSURE_OPTIONAL); file_parser.set_field_term_char(field_terminator); file_parser.set_line_term_char(line_terminator); /* Check to see if there are more records, then grab each row one at a time */ while(file_parser.has_more_rows()) { csv_row fileRecord = file_parser.get_row(); //the miracle of STL hex string conversion :) istringstream stFileOffset(fileRecord[2].c_str()); istringstream stOffSetSize(fileRecord[3].c_str()); unsigned int offset; unsigned int size; stFileOffset >> hex >> offset; stOffSetSize >> hex >> size; //dprintf("Allocating Buffer Name:%s at offset: %d with size: %d\n", fileRecord[0].c_str(), offset, size); //create individual buffers with the record type as a name and using the offset and size identBufJutsu(bufType, (char *)fileRecord[0].c_str(), bufFile, size, offset); } return (S_OK); } if (!_stricmp(command, "hunt")) { hunterJutsu(); } if (!_stricmp(command, "findReturn")) { returnAddressHuntJutsu(); } } EXIT_API(); return (S_OK); } HRESULT CALLBACK tenketsu(PDEBUG_CLIENT4 Client, PCSTR args) { char *command, *heapName, *logName; PVOID heapHandle; INIT_API(); command = strtok((char *)args, " "); if (command == NULL) { tenkHelp(); return (S_OK); } else if (!_stricmp(command, "model")) { if(hookRtlHeap(1, NULL)) { dprintf("[Byakugan] Unable to begin realtime heap modeling.\n"); EXIT_API(); return (S_FALSE); } } else if (!_stricmp(command, "log")) { logName = strtok(NULL, " "); if (logName == NULL) { dprintf("[Byakugan] Please provide a log name.\n"); return (S_FALSE); } if(hookRtlHeap(2, logName)) { 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, "validate")) { heapName = strtok(NULL, " "); if (heapName == NULL) { dprintf("[Byakugan] Please provide a heap handle.\n"); return (S_OK); } heapHandle = (PVOID) strtoul(heapName, NULL, 16); tenkValidate(heapHandle); return (S_OK); } else if (!_stricmp(command, "listHeaps")) { tenkListHeaps(); return (S_OK); } else if (!_stricmp(command, "listChunks")) { heapName = strtok(NULL, " "); if (heapName == NULL) { dprintf("[Byakugan] Please provide a heap handle.\n"); return (S_OK); } heapHandle = (PVOID) strtoul(heapName, NULL, 16); tenkListChunks(heapHandle); return (S_OK); } EXIT_API(); return (S_OK); }