Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/byakugan/jutsu.cpp
Views: 11766
#include <stdio.h>1#include <winsock2.h>2#include <ws2tcpip.h>3#include "byakugan.h"4#include "jutsu.h"5#include "msfpattern.h"6#include "stdwindbg.h"78struct requestQueue jutsuRequests;9struct trackedBuf *trackedBufList = NULL;10struct trackedVal *trackedValList = NULL;1112ULONG64 disassemblyBuffer;13HANDLE processHandle = 0;1415SOCKET ListenSocket = INVALID_SOCKET,16ClientSocket = INVALID_SOCKET;171819//IDebugClient msfClient;202122char *regs[] = {23"eax",24"ebx",25"ecx",26"edx",27"esp",28"ebp",29"eip",30NULL31};3233void helpJutsu(void) {34return;35}3637void memDiffJutsu(char *inputType, DWORD size, char *input, ULONG64 address) {38DWORD i, j, valResult, readSize, numBadChars = 0;39BOOL upperFlag, lowerFlag, nullFlag;40char *pureBuf = NULL, findValExpression[64] = {'\x00'};41char lineExpected[16], lineActual[16];4243struct trackedBuf *curr = trackedBufList;44struct corruption *badChars;4546// Valid inputs: ASCII, hex, file, buf47if (!_stricmp(inputType, "ASCII")) {48pureBuf = input;49} else if (!_stricmp(inputType, "hex")) {50if (size != parseHexInput(input, size, pureBuf)) {51dprintf("[J] Failed to parse %d bytes from hex input.\n", size);52return;53}54} else if (!_stricmp(inputType, "file")) {55readSize = readFileIntoBuf(input, size, &pureBuf, 0);56if ((size && size != readSize) || readSize == 0) {57dprintf("[J] Failed to read %d bytes from %s.\n", size, input);58return;59}60size = (size ? size : readSize);61} else if (!_stricmp(inputType, "buf")) {62// Grab the buf by name from the trackedBufList6364while (curr != NULL) {65if(!_stricmp(input, curr->bufName)) {66pureBuf = curr->bufPatt;67break;68}69curr = curr->next;70}71if (pureBuf == NULL) {72dprintf("[J] Unable to find buffer: %s\n", input);73return;74}75} else {76dprintf("[J] The valid input types are buf, hex, and file.\n");77return;78}7980upperFlag = lowerFlag = nullFlag = FALSE;81badChars = (struct corruption *) malloc(size * sizeof (struct corruption));8283dprintf("\t\t\tACTUAL\t\t\t\t\t\t\t\tEXPECTED\n");84for (i = 0; i < size; i++) {85// Get byte at the important memory location86StringCchPrintf(findValExpression, sizeof(findValExpression),87"poi(0x%08x)", address + i);88valResult = (GetExpression(findValExpression) & 0xFF);8990lineExpected[i%16] = pureBuf[i];91lineActual[i%16] = valResult;9293if (pureBuf[i] != valResult) {94badChars[numBadChars].value = pureBuf[i];95badChars[numBadChars].offset = i;96badChars[numBadChars].seenAgain = FALSE;97badChars[numBadChars].seenBefore = FALSE;98for (j = 0; j < numBadChars; j++) {99if (badChars[j].value == badChars[numBadChars].value) {100badChars[numBadChars].seenBefore = TRUE;101}102}103numBadChars++;104} else {105for (j = 0; j < numBadChars; j++)106if (valResult == badChars[j].value)107badChars[j].seenAgain = TRUE;108}109110111if (i % 16 == 15 || i == size-1) {112// Print the actual characters with differences in bold113for (j = 0; j != i % 16 + 1; j++) {114// Diff the two locations115if (lineActual[j] != lineExpected[j]) {116// Store badchars, and bad offsets117// Print this character in bold!118StringCchPrintf(findValExpression, sizeof(findValExpression),119".printf /D \"<b><red>%02x</red></b> \"", lineActual[j]);120g_ExtControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, findValExpression,121DEBUG_EXECUTE_NOT_LOGGED);122123} else {124dprintf("%02x ", lineActual[j]);125}126127// Take note of upper / lower / null exclusions128}129if (i == size-1)130for (j = 0; j < 15 - i % 16; j+=2)131dprintf("\t");132dprintf("\t");133134// Now print the Expected characters135for (j = 0; j != i % 16 + 1; j++) {136dprintf("%02x ", lineExpected[j]);137}138dprintf("\n");139}140}141142// Display bad chars143i = 0;144if (numBadChars) {145dprintf("\n[J] Bytes replaced: ");146while (i < numBadChars) {147if (!badChars[i].seenAgain && !badChars[i].seenBefore)148dprintf("0x%02x ", badChars[i].value);149i++;150}151i = 0;152dprintf("\n[J] Offset corruption occurs at: ");153while (i < numBadChars) {154if (badChars[i].seenAgain)155dprintf("%02x ", badChars[i].offset);156i++;157}158dprintf("\n");159}160161// Unless pureBuf came from a tracked buffer, free the memory162if (_stricmp(inputType, "buf"))163free(pureBuf);164free(badChars);165}166167void listTrackedVals() {168struct trackedVal *newTrackedVal;169170if (trackedValList == NULL) {171dprintf("[J] Currently tracking no primitive values.\n");172return;173}174175dprintf("[J] Currently tracking:\n");176177newTrackedVal = trackedValList;178while (newTrackedVal != NULL) {179dprintf("\tName: %s\t\tSize: %d\tCandidates: %d\n",180newTrackedVal->valName, newTrackedVal->valSize, newTrackedVal->candidates);181newTrackedVal = newTrackedVal->next;182}183}184185void listTrackedValByName(char *name) {186struct trackedVal *newTrackedVal;187struct valInstance *curr;188189newTrackedVal = trackedValList;190if (newTrackedVal == NULL) goto nada;191192while (newTrackedVal != NULL) {193if (!_stricmp(newTrackedVal->valName, name))194break;195newTrackedVal = newTrackedVal->next;196}197198if (newTrackedVal) {199200curr = newTrackedVal->instances;201202if (curr != NULL)203dprintf("[J] Currently tracking %d candidates for %s:\n",204newTrackedVal->candidates, newTrackedVal->valName);205else206goto nada;207208while (curr != NULL) {209dprintf("\tAddress: 0x%08x\n", curr->address);210curr = curr->next;211}212return;213}214nada:215dprintf("[J] No candidates are being tracked for %s.\n", name);216}217218void trackValJutsu(char *name, DWORD size, DWORD value) {219struct trackedVal *newTrackedVal, *parent = NULL;220struct valInstance *last, *curr;221char findValExpression[18] = {'\x00'};222DWORD valResult, andExpression;223224switch(size) {225case 1: andExpression = 0xFF; break;226case 2: andExpression = 0xFFFF; break;227case 4: andExpression = 0xFFFFFFFF; break;228default:229dprintf("[J] Valid primitive sizes are 1, 2, and 4.\n");230return;231}232233newTrackedVal = trackedValList;234while (newTrackedVal != NULL) {235if (!_stricmp(newTrackedVal->valName, name))236break;237newTrackedVal = newTrackedVal->next;238}239240// Search the list for the new value, purge old addresses241if (newTrackedVal) {242dprintf("[J] Narrowing down candidate list for %s from %d candidates.\n", name, newTrackedVal->candidates);243curr = newTrackedVal->instances;244last = NULL;245246while (curr != NULL) {247StringCchPrintf(findValExpression, sizeof(findValExpression), "poi(0x%08x)", curr->address);248valResult = (GetExpression(findValExpression) & andExpression);249if (value != valResult) {250if (last) {251last->next = curr->next;252free(curr);253curr = last->next;254} else {255newTrackedVal->instances = curr->next;256free(curr);257curr = newTrackedVal->instances;258}259newTrackedVal->candidates--;260if (newTrackedVal->candidates == 1) {261dprintf("[J] Value %s is stored at address 0x%08x\n",262newTrackedVal->valName, newTrackedVal->instances->address);263return;264}265} else {266last = curr; curr = curr->next;267}268}269dprintf("[J] Narrowed down address of %s to %d possible candidates.\n", name, newTrackedVal->candidates);270return;271}272dprintf("[J] Creating new list of candidates for %s.\n", name);273274// Create a new list and search all memory for the value275newTrackedVal = (struct trackedVal *) malloc(sizeof (struct trackedVal));276if (newTrackedVal == NULL) {277dprintf("[J] OOM!");278return;279}280newTrackedVal->next = NULL;281newTrackedVal->valSize = size;282newTrackedVal->valName = _strdup(name);283if(!newTrackedVal->valName) {284free(newTrackedVal);285dprintf("[J] OOM!\n");286return;287}288289newTrackedVal->candidates = findAllVals((BYTE*) &value, size, &(newTrackedVal->instances));290dprintf("[J] Discovered %d possible candidate addresses for %s\n", newTrackedVal->candidates, name);291292newTrackedVal->next = trackedValList;293trackedValList = newTrackedVal;294295return;296}297298void bindJutsu(char *bindPort) {299HANDLE hThread;300DWORD dwThreadId;301IDebugOutputCallbacks *fuzzerOutputCallback;302303// Initialize Request Queue304memset(&jutsuRequests, 0, sizeof (struct requestQueue));305306// Fire up backchannel thread307hThread = CreateThread( NULL,3080,309listenJutsu,310(LPVOID) bindPort,3110,312&dwThreadId);313314if (hThread == NULL)315dprintf("[Byakugan] CreateThread() failed.\n");316}317318DWORD WINAPI listenJutsu(LPVOID lpvParam) {319WSADATA wsaData;320char recvbuf[DEFAULT_BUFLEN];321ULONG iResult, iSendResult;322ULONG recvbuflen = DEFAULT_BUFLEN;323char *bindPort = (char *) lpvParam;324struct addrinfo *result = NULL,325hints;326327328dprintf("[J] Creating Metasploit back channel on port %s... ", bindPort);329330if (WSAStartup( MAKEWORD( 2, 2 ), &wsaData) != 0) {331dprintf("Failed!: %d\n", WSAGetLastError());332return (-1);333}334335ZeroMemory(&hints, sizeof(hints));336hints.ai_family = AF_INET;337hints.ai_socktype = SOCK_STREAM;338hints.ai_protocol = IPPROTO_TCP;339hints.ai_flags = AI_PASSIVE;340341// Resolve the server address and port342iResult = getaddrinfo(NULL, bindPort, &hints, &result);343if ( iResult != 0 ) {344dprintf("Failed!: %d\n", WSAGetLastError());345WSACleanup();346return (-1);347}348349// Create a SOCKET for connecting to server350ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);351if (ListenSocket == INVALID_SOCKET) {352dprintf("Failed!: %d\n", WSAGetLastError());353freeaddrinfo(result);354WSACleanup();355return (-1);356}357358// Setup the TCP listening socket359iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);360if (iResult == SOCKET_ERROR) {361dprintf("Failed!: %d\n", WSAGetLastError());362freeaddrinfo(result);363closesocket(ListenSocket);364WSACleanup();365return (-1);366}367368freeaddrinfo(result);369370iResult = listen(ListenSocket, SOMAXCONN);371if (iResult == SOCKET_ERROR) {372dprintf("Failed!: %d\n", WSAGetLastError());373closesocket(ListenSocket);374WSACleanup();375return (-1);376}377378dprintf("Listening.\n");379380// Accept a client socket381ClientSocket = accept(ListenSocket, NULL, NULL);382if (ClientSocket == INVALID_SOCKET) {383dprintf("[J] Back channel accept failed: %d\n", WSAGetLastError());384closesocket(ListenSocket);385WSACleanup();386return (-1);387}388389// No longer need server socket390closesocket(ListenSocket);391392// Register new output callback393//fuzzerOutputCallback = new IDebugOutputCallbacks();394395// Register new event callback396397// Receive until the peer shuts down the connection398do {399memset(recvbuf, 0, DEFAULT_BUFLEN);400401iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);402if (iResult > 0)403parseJutsu(recvbuf, iResult);404else if (iResult == 0)405dprintf("[J] Back channel connection closing...\n");406else {407dprintf("[J] Back channel recv failed: %d\n", WSAGetLastError());408closesocket(ClientSocket);409WSACleanup();410return (-1);411}412} while (iResult > 0);413414// shutdown the connection since we're done415iResult = shutdown(ClientSocket, SD_SEND);416if (iResult == SOCKET_ERROR) {417dprintf("[J] Back channel shutdown failed: %d\n", WSAGetLastError());418closesocket(ClientSocket);419WSACleanup();420return (-1);421}422423// cleanup424closesocket(ClientSocket);425WSACleanup();426427428return (0);429}430431void parseJutsu(char *buf, ULONG buflen) {432struct request *newRequest, *node;433struct requestHeader *reqHead;434435//dprintf("[J] Back channel got: %s\n", buf);436437reqHead = (struct requestHeader *) buf;438if ((reqHead->length + 4) > buflen || buflen < 5 || reqHead->length > 0xFFFD) {439dprintf("[J] Received a malformed jutsu request! :(\n");440return;441}442443newRequest = (struct request *) malloc(sizeof (struct request));444if (newRequest == NULL) {445dprintf("[J] Failed to allocate! :(\n");446return;447}448449newRequest->type = reqHead->type;450newRequest->length = reqHead->length;451newRequest->data = (BYTE *) malloc(newRequest->length + 1);452if (newRequest->data == NULL) {453dprintf("[J] Failed to allocate! :(\n");454free(newRequest);455return;456}457newRequest->next = NULL;458459memcpy(newRequest->data, (buf+4), newRequest->length);460461if (jutsuRequests.head != NULL) {462node = jutsuRequests.head;463while (node->next != NULL)464node = node->next;465node->next = newRequest;466} else {467jutsuRequests.head = newRequest;468}469jutsuRequests.length++;470471return;472}473474void showRequestsJutsu() {475struct request *node;476USHORT i;477478dprintf("[J] Currently waiting on %d requests:\n", jutsuRequests.length);479480node = jutsuRequests.head;481while (node != NULL) {482dprintf("Type: 0x%04x\tLength: 0x%04x\nData:",483node->type, node->length);484for (i = 0; i < node->length; i++) {485if (i % 32 == 0) dprintf("\n");486if (i % 8 == 0) dprintf("\t0x");487dprintf("%01x", node->data[i]);488}489dprintf("\n\n");490node = node->next;491}492}493void identBufJutsu(char *inputType, char *bufName, char *bufPatt, DWORD size, DWORD offset) {494struct trackedBuf *newTrackedBuf, *curBuf;495char *msfPattern;496DWORD readSize;497HANDLE hFile;498499if (trackedBufList != NULL) {500curBuf = trackedBufList;501while (curBuf->next != NULL) {502if (!_stricmp(bufName, curBuf->bufName)) {503dprintf("[J] Buf %s already exists. Please delete it first.\n", bufName);504return;505}506curBuf = curBuf->next;507}508}509510newTrackedBuf = (struct trackedBuf *) malloc(sizeof (struct trackedBuf));511if (newTrackedBuf == NULL) {512dprintf("[J] OOM!");513return;514}515516newTrackedBuf->next = NULL;517newTrackedBuf->prev = NULL;518if (!_stricmp(inputType, "msfpattern")) {519size = strtoul(bufPatt, NULL, 10);520msfPattern = (char *) malloc(size+1);521if (msfPattern == NULL) {522dprintf("[J] Failed to allocate %d bytes!\n", size+1);523return;524}525msf_pattern_create(size, msfPattern);526msfPattern[size] = '\x00';527newTrackedBuf->bufPatt = msfPattern;528} else if (!_stricmp(inputType, "ascii")){529newTrackedBuf->bufPatt = _strdup(bufPatt);530size = strlen(bufPatt);531} else if (!_stricmp(inputType, "file")) {532readSize = readFileIntoBuf(bufPatt, size, &(newTrackedBuf->bufPatt), 0);533if ((size && readSize != size) || readSize == 0) {534dprintf("[J] Unable to read %d bytes from %s\n", size, bufName);535dprintf("\nThis command requires a buffer type, name, (sometimes) value, and size - maybe you forgot one?\n");536return;537}538size = (size ? size : readSize);539} else if (!_stricmp(inputType, "smartFile")) {540readSize = readFileIntoBuf(bufPatt, size, &(newTrackedBuf->bufPatt), offset);541if ((size && readSize != size) || readSize == 0) {542dprintf("[J] Unable to read %d bytes from %s\n", size, bufName);543dprintf("\nThis command requires a buffer type, name, (sometimes) value, and size - maybe you forgot one?\n");544return;545}546size = (size ? size : readSize);547}548549550newTrackedBuf->bufName = _strdup(bufName);551newTrackedBuf->bufSize = size;552if (newTrackedBuf->bufName == NULL || newTrackedBuf->bufPatt == NULL) {553dprintf("[J] OOM!");554return;555}556557if (trackedBufList == NULL) {558trackedBufList = newTrackedBuf;559} else {560curBuf->next = newTrackedBuf;561newTrackedBuf->prev = curBuf;562}563dprintf("[J] Creating buffer %s.\n", bufName);564}565566void rmBufJutsu(char *bufName) {567struct trackedBuf *curBuf;568569curBuf = trackedBufList;570while (curBuf != NULL) {571if(!_stricmp(bufName, curBuf->bufName))572break;573curBuf = curBuf->next;574}575if (curBuf != NULL) {576if (curBuf->prev != NULL)577curBuf->prev->next = curBuf->next;578if (curBuf->next != NULL)579curBuf->next->prev = curBuf->prev;580if (curBuf == trackedBufList)581trackedBufList = curBuf->next;582free(curBuf->bufName);583free(curBuf->bufPatt);584free(curBuf);585dprintf("[J] Removed buffer: %s\n", bufName);586} else {587dprintf("[J] Unable to find buffer: %s\n", bufName);588}589}590591void listTrackedBufJutsu() {592struct trackedBuf *curBuf;593DWORD i;594595curBuf = trackedBufList;596if (curBuf == NULL) {597dprintf("[J] Currntly tracking no buffer patterns.\n");598} else {599dprintf("[J] Currently tracked buffer patterns:\n");600while (curBuf != NULL) {601dprintf("\tBuf: %s\tPattern: ", curBuf->bufName);602for (i = 0; i < curBuf->bufSize; i++)603dprintf("%c", curBuf->bufPatt[i]);604dprintf("\n");605curBuf = curBuf->next;606}607}608dprintf("\n");609}610611void hunterJutsu() {612struct trackedBuf *curBuf;613struct bufInstance *instance;614ULONG i, j, range, addr, *nextNum, foundInstance;615BOOLEAN caught;616char *corUpper, *corLower, *corUni;617ULONG64 ptr = 0;618619for (i = 0; regs[i] != NULL; i++) {620addr = GetExpression(regs[i]);621curBuf = trackedBufList;622caught = FALSE;623while (curBuf != NULL) {624range = curBuf->bufSize;625for (j = 0; j < range-3; j++) {626nextNum = (ULONG *) ((curBuf->bufPatt) + j);627if (addr != 0 && *nextNum == addr) {628dprintf("[J] Controlling %s with %s at offset %d.\n",629regs[i], curBuf->bufName, j);630caught = TRUE;631break;632}633}634curBuf = curBuf->next;635if (caught)636break;637}638639}640641// Now, find all instances of buffers in memory with a fuzzy match! :)642curBuf = trackedBufList;643while (curBuf != NULL) {644foundInstance = searchMemory((unsigned char *) curBuf->bufPatt,645(curBuf->bufSize > 32) ? 32 : curBuf->bufSize, &ptr);646if (foundInstance != 0) {647// try for larger increments648instance = (struct bufInstance *) malloc(sizeof (struct bufInstance));649memset(instance, 0, sizeof (struct bufInstance));650instance->address = foundInstance;651dprintf("[J] Found buffer %s @ 0x%08x\n", curBuf->bufName, foundInstance);652}653// try standard corruptions654range = (curBuf->bufSize > 32) ? 32 : curBuf->bufSize;655corUpper = (char *) malloc(range + 1);656corLower = (char *) malloc(range + 1);657corUni = (char *) malloc((range + 1) * 2);658for (i = j = 0; i < range; i++) {659corUpper[i] = (char) toupper(curBuf->bufPatt[i]);660corLower[i] = (char) tolower(curBuf->bufPatt[i]);661corUni[j++] = curBuf->bufPatt[i];662corUni[j++] = '\x00';663}664if ((foundInstance = searchMemory((unsigned char *) corUpper, range, &ptr)) != 0)665dprintf("[J] Found buffer %s @ 0x%08x - Victim of toUpper!\n",666curBuf->bufName, foundInstance);667if ((foundInstance = searchMemory((unsigned char *) corLower, range, &ptr)) != 0)668dprintf("[J] Found buffer %s @ 0x%08x - Victim of toLower!\n",669curBuf->bufName, foundInstance);670if ((foundInstance = searchMemory((unsigned char *) corUni, range*2, &ptr)) != 0)671dprintf("[J] Found buffer %s @ 0x%08x - Victim of Unicode Conversion!\n",672curBuf->bufName, foundInstance);673free(corUpper);674free(corLower);675free(corUni);676677678curBuf = curBuf->next;679}680681}682683ULONG64 allocateMemoryBlock(unsigned long size){684unsigned long processId = 0;685void * allocBuffer = 0;686ULONG Class;687ULONG Qualifier;688689g_ExtControl->GetDebuggeeType(&Class, &Qualifier);690if (Class & DEBUG_CLASS_USER_WINDOWS) {691// USER LAND!692if(g_ExtSystem->GetCurrentProcessSystemId(&processId) != S_OK){693dprintf("[J] failed to find process id\n");694return 0;695}696697if(!(processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId))){698dprintf("[J] OpenProcess failed\n");699return 0;700}701702if(!(allocBuffer = VirtualAllocEx(processHandle, NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE))){703dprintf("[J] VirtualAllocEx failed\n");704CloseHandle(processHandle);705return 0;706}707} else {708// KERNEL LAND!709710}711//CloseHandle(processHandle);712713return ((ULONG64)allocBuffer);714}715716unsigned short getInstructionBytes(char * instruction, unsigned char * opcodeBuffer){717BYTE zero = 0;718BYTE byteCounter = 0;719ULONG64 byteEnd = 0;720BYTE i = 0;721722if(!disassemblyBuffer){723if(!(disassemblyBuffer = allocateMemoryBlock(0x1000))){724dprintf("[J] allocateMemoryBlock failed\n");725return (0);726}727}728729730if(g_ExtControl->Assemble(disassemblyBuffer, instruction, &byteEnd) != S_OK){731dprintf("[J] failed to assemble instruction\n");732return (0);733}734735if(!ReadMemory(disassemblyBuffer, opcodeBuffer, (byteEnd-disassemblyBuffer), NULL)){736dprintf("[J] failed to read opcode sequence\n");737return (0);738}739740for(i=0; i<(byteEnd-disassemblyBuffer); i++){741if(!WriteMemory((disassemblyBuffer+i), &zero, 1, NULL)){742dprintf("[J] failed to zero memory\n");743return (0);744}745}746#if 0747dprintf("[J] Opcode sequence for instruction %s:", instruction);748749for(byteCounter=0; ((disassemblyBuffer+byteCounter)<byteEnd); byteCounter++){750dprintf("%02x ", opcodeBuffer[byteCounter]);751}752753dprintf("\n");754#endif755return (byteEnd-disassemblyBuffer);756}757758ULONG64 searchMemory(unsigned char * byteBuffer, unsigned long length, ULONG64 *addressHit){759HRESULT memSearch = S_OK;760761if((memSearch = g_ExtData->SearchVirtual((ULONG64)*addressHit, (ULONG64)-1, byteBuffer,762length, 1, addressHit)) != S_OK){763#if 0764if(memSearch == HRESULT_FROM_NT(STATUS_NO_MORE_ENTRIES)){765dprintf("[J] byte sequence not found in virtual memory\n");766}767else{768dprintf("[J] byte search failed for another reason\n");769}770#endif771return (0);772}773return (*addressHit);774}775776DWORD findAllVals(unsigned char *byteBuffer, BYTE size, struct valInstance **instance) {777ULONG64 addressHit = 0;778DWORD addressCount = 0;779HRESULT memSearch;780struct valInstance *newValInstance;781782*instance = NULL;783784while ((memSearch = g_ExtData->SearchVirtual(addressHit+size, (ULONG64)-1, byteBuffer,785size, 1, &addressHit)) == S_OK) {786787if (!*instance) {788*instance = (struct valInstance *) malloc(sizeof (struct valInstance));789newValInstance = *instance;790} else {791newValInstance->next = (struct valInstance *) malloc(sizeof (struct valInstance));792newValInstance = newValInstance->next;793}794newValInstance->address = addressHit;795newValInstance->next = NULL;796addressCount++;797}798799return (addressCount);800}801802BOOL checkExecutability(ULONG64 checkAddress){803MEMORY_BASIC_INFORMATION protectionInfo;804805if(!VirtualQueryEx(processHandle, (LPVOID)checkAddress, &protectionInfo, sizeof(MEMORY_BASIC_INFORMATION))){806dprintf("[J] Unable to obtain protection information for address 0x%08x\n", checkAddress);807return FALSE;808}809810//dprintf("allocation info: 0x%08x and 0x%08x\n", protectionInfo.AllocationProtect, protectionInfo.Protect);811812if((protectionInfo.Protect & PAGE_EXECUTE_READ) != 0)813return TRUE;814815//dprintf("[J] 0x%08x isn't executable\n");816return FALSE;817}818819void searchOpcodes(char *instructions) {820char **instructionList;821unsigned char *byteSequence;822DWORD length, i, j, semiCount = 1, offset = 0;823ULONG64 ptr = 0;824825// Split instructions into seperate strings at pipes826length = 0;827while (instructions[length] != NULL) {828if (instructions[length] == '|')829semiCount++;830length++;831}832833// Malloc space for instructionList;834instructionList = (char **) malloc((semiCount+1) * sizeof (char *));835if (instructionList == NULL) {836dprintf("[J] OOM!\n");837return;838}839instructionList[0] = instructions;840dprintf("[J] Searching for:\n");841i = 0; j = 0;842while (i < length) {843if (instructions[i] == '|') {844instructions[i] = '\x00';845dprintf("> %s\n", instructionList[j++]);846instructionList[j] = &(instructions[i+1]);847}848i++;849}850dprintf("> %s\n", instructionList[j]);851852853// Allocate space for byteSequence854byteSequence = (unsigned char *) malloc(semiCount * 6);855if (byteSequence == NULL) {856dprintf("[J] OOM!\n");857return;858}859860// Generate byte sequence and display it861for (i = 0; i < semiCount; i++) {862unsigned char tmpbuf[8];863offset += getInstructionBytes(instructionList[i], byteSequence+offset);864}865866dprintf("[J] Machine Code:\n> ");867for (i = 0; i < offset; i++) {868dprintf("%02x ", byteSequence[i]);869if (i != 0 && !(i % 16))870dprintf("\n> ");871}872dprintf("\n");873874// Search for sequence in executable memory875while((ptr = searchMemory(byteSequence, offset, &ptr)) != 0) {876if (ptr && checkExecutability(ptr)) {877dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr);878}879ptr++;880}881return;882}883884void searchVtptr(DWORD vtOffset, char *instructions) {885char **instructionList;886unsigned char *byteSequence;887DWORD length, i, j, semiCount = 1, offset = 0;888ULONG64 ptr = 0;889890// Split instructions into seperate strings at pipes891length = 0;892while (instructions[length] != NULL) {893if (instructions[length] == '|')894semiCount++;895length++;896}897898// Malloc space for instructionList;899instructionList = (char **) malloc((semiCount+1) * sizeof (char *));900if (instructionList == NULL) {901dprintf("[J] OOM!\n");902return;903}904instructionList[0] = instructions;905dprintf("[J] Searching for:\n");906i = 0; j = 0;907while (i < length) {908if (instructions[i] == '|') {909instructions[i] = '\x00';910dprintf("> %s\n", instructionList[j++]);911instructionList[j] = &(instructions[i+1]);912}913i++;914}915dprintf("> %s\n", instructionList[j]);916917918// Allocate space for byteSequence919byteSequence = (unsigned char *) malloc(semiCount * 6);920if (byteSequence == NULL) {921dprintf("[J] OOM!\n");922return;923}924925// Generate byte sequence and display it926for (i = 0; i < semiCount; i++) {927unsigned char tmpbuf[8];928offset += getInstructionBytes(instructionList[i], byteSequence+offset);929}930931dprintf("[J] Machine Code:\n> ");932for (i = 0; i < offset; i++) {933dprintf("%02x ", byteSequence[i]);934if (i != 0 && !(i % 16))935dprintf("\n> ");936}937dprintf("\n");938939// Search for sequence in executable memory940while((ptr = searchMemory(byteSequence, offset, &ptr)) != 0) {941if (ptr && checkExecutability(ptr)) {942ULONG64 copyPtr = 0, otherPtr = ptr;943//dprintf("[J] Executable opcode sequence found at: 0x%08x\n", ptr);944while((copyPtr = searchMemory((unsigned char *)&otherPtr, 4, ©Ptr)) != 0) {945ULONG64 fptr = 0, vtPtr = copyPtr-vtOffset;946//dprintf("\tPtr @ 0x%08x\n", copyPtr);947while((fptr = searchMemory((unsigned char *)&vtPtr, 4, &fptr)) != 0) {948//dprintf("\t\tvTable Ptr @ 0x%08x\n", vtPtr);949dprintf("0x%08x -> 0x%08x -> 0x%08x -> sequence\n",950(ULONG)fptr, (ULONG)vtPtr, (ULONG)otherPtr);951fptr++;952}953copyPtr++;954}955}956ptr++;957}958return;959}960961void returnAddressHuntJutsu(){962struct trackedBuf *curBuf;963int i = 0, bufferIndex = 0;964ULONG offset = 0, bytes = 0;965char findBufferExpression[25];966ULONG64 returnAddress = 0, ptr = 0;967HRESULT memSearch = S_OK;968969//disassembly variables970char returnInstruction[30];971unsigned char opcodeBuffer[30];972unsigned short instructionLength = 0;973dprintf("[J] started return address hunt\n");974975976for(i; i<6; i++){ //6, because we don't want to waste time on the eip register977curBuf = trackedBufList;978memset(findBufferExpression, 0x00, sizeof(findBufferExpression));979980if(!(bytes = GetExpression(regs[i]))){981dprintf("[J] skipping %s as register - it is a null pointer\n", regs[i]);982continue;983}984985StringCchPrintf(findBufferExpression, sizeof(findBufferExpression), "poi(%s)", regs[i]);986bytes = GetExpression(findBufferExpression);987988//tests if a register points to a location in user controlled data989while(curBuf != NULL){990for(bufferIndex=0; bufferIndex < curBuf->bufSize; bufferIndex++){991if(*(PULONG)((curBuf->bufPatt)+bufferIndex) == bytes){992memset(opcodeBuffer, 0x00, sizeof(opcodeBuffer));993memset(returnInstruction, 0x00, sizeof(returnInstruction));994995//find the opcodes for the desired instruction996997//first, for call reg998StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call %s", regs[i]);999if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))1000dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);1001if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){1002if(checkExecutability(returnAddress))1003dprintf("[J] valid return address (call %s) found at 0x%08x\n", regs[i], returnAddress);1004}100510061007//now, for jmp reg1008memset(returnInstruction, 0x00, sizeof(returnInstruction));1009StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp %s", regs[i]);1010if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))1011dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);1012if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){1013if(checkExecutability(returnAddress))1014dprintf("[J] valid return address (jmp %s) found at 0x%08x\n", regs[i], returnAddress);1015}1016}1017}1018curBuf = curBuf->next;1019}10201021curBuf = trackedBufList;10221023for(offset=0; offset<0x1000; offset+=4){1024memset(findBufferExpression, 0x00, sizeof(findBufferExpression));1025StringCchPrintf(findBufferExpression, sizeof(findBufferExpression), "poi(poi(%s+0x%08x))", regs[i], offset);1026if(!(bytes = GetExpression(findBufferExpression)))1027continue; //this is basically a replacement for the1028//ddp windbg command, except more automated1029//walk through the buffer to see if any dword in there matches the current1030//value returned by the expression1031while(curBuf != NULL){1032for(bufferIndex=0; bufferIndex < curBuf->bufSize; bufferIndex++){1033if(*(PULONG)((curBuf->bufPatt)+bufferIndex) == bytes){1034memset(opcodeBuffer, 0x00, sizeof(opcodeBuffer));1035memset(returnInstruction, 0x00, sizeof(returnInstruction));1036dprintf("[J] %s + 0x%08x points into offset 0x%x of buffer %s\n",1037regs[i], offset, bufferIndex, curBuf->bufName);103810391040//first, build the instruction to find the bytes for1041//for now, we will support jmp [reg+offset] and call [reg+offset]10421043//first, for call [reg+offset]1044StringCchPrintf(returnInstruction, sizeof(returnInstruction), "call [%s+%x]", regs[i], offset);1045if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))1046dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);1047if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){1048if(checkExecutability(returnAddress))1049dprintf("[J] valid return address (call [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress);1050}105110521053//now, for jmp [reg+offset]1054memset(returnInstruction, 0x00, sizeof(returnInstruction));1055StringCchPrintf(returnInstruction, sizeof(returnInstruction), "jmp [%s+%x]", regs[i], offset);1056if(!(instructionLength = getInstructionBytes(returnInstruction, opcodeBuffer)))1057dprintf("[J] getInstructionBytes failed for '%s'\n", returnInstruction);1058if(returnAddress = searchMemory(opcodeBuffer, instructionLength, &ptr)){1059if(checkExecutability(returnAddress))1060dprintf("[J] valid return address (jmp [%s+%x]) found at 0x%08x\n", regs[i], offset, returnAddress);1061}1062}1063}1064curBuf = curBuf->next;1065}1066curBuf = trackedBufList;1067}1068}1069}107010711072