metasploit-framework/external/source/byakugan/exts.cpp

338 lines
9.6 KiB
C++
Executable File

#include "byakugan.h"
#include "msfpattern.h"
#include "jutsu.h"
#include "tenketsu.h"
#include "mushishi.h"
#include "symPort.h"
#include "csv_parser.hpp"
#include <ios>
#include <iostream>
#include <sstream>
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 <command> <args> - Perform Jutsu: !jutsu help\n");
dprintf("!tenketsu - Begin realtime heap vizualization: !tenketsu help\n");
dprintf("!pattern_offset <length> <optional: addr>\n");
dprintf("!mushishi <detect|defeat>- 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 <moduleName> <map file path>\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 <type> <size> <value> <address>\n");
dprintf("Valid Types:\n\thex: Value is any hex characters\n");
dprintf("\tfile: Buffer is read in from file at path <value>\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);
}