mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-08-25 08:22:58 +00:00
1409 lines
38 KiB
C++
1409 lines
38 KiB
C++
/**
|
|
* @file interpreter.cpp
|
|
* @author Sina Karvandi (sina@rayanfam.com)
|
|
* @brief The hyperdbg command interpreter and driver connector
|
|
* @details
|
|
* @version 0.1
|
|
* @date 2020-04-11
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
|
|
#include "pch.h"
|
|
#include <algorithm>
|
|
#include <iomanip>
|
|
#include <iterator>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <time.h>
|
|
#include <vector>
|
|
|
|
using namespace std;
|
|
|
|
// Exports
|
|
extern "C" {
|
|
__declspec(dllexport) int __cdecl HyperdbgInterpreter(const char *Command);
|
|
}
|
|
|
|
bool g_IsConnectedToDebugger = false;
|
|
bool g_IsDebuggerModulesLoaded = false;
|
|
|
|
string SeparateTo64BitValue(UINT64 Value) {
|
|
std::ostringstream ostringStream;
|
|
ostringStream << std::setw(16) << std::setfill('0') << std::hex << Value;
|
|
string temp = ostringStream.str();
|
|
|
|
temp.insert(8, 1, '`');
|
|
return temp;
|
|
}
|
|
void PrintBits(size_t const size, void const *const ptr) {
|
|
unsigned char *b = (unsigned char *)ptr;
|
|
unsigned char byte;
|
|
int i, j;
|
|
|
|
for (i = size - 1; i >= 0; i--) {
|
|
for (j = 7; j >= 0; j--) {
|
|
byte = (b[i] >> j) & 1;
|
|
ShowMessages("%u", byte);
|
|
}
|
|
ShowMessages(" ", byte);
|
|
}
|
|
}
|
|
/**
|
|
* @brief Read memory and disassembler
|
|
*
|
|
*/
|
|
void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
|
|
UINT64 Address,
|
|
DEBUGGER_READ_MEMORY_TYPE MemoryType,
|
|
DEBUGGER_READ_READING_TYPE ReadingType,
|
|
UINT32 Pid, UINT Size) {
|
|
|
|
BOOL Status;
|
|
ULONG ReturnedLength;
|
|
DEBUGGER_READ_MEMORY ReadMem;
|
|
UINT32 OperationCode;
|
|
CHAR Character;
|
|
|
|
if (!DeviceHandle) {
|
|
ShowMessages("Handle not found, probably the driver is not loaded.\n");
|
|
return;
|
|
}
|
|
|
|
ReadMem.Address = Address;
|
|
ReadMem.Pid = Pid;
|
|
ReadMem.Size = Size;
|
|
ReadMem.MemoryType = MemoryType;
|
|
ReadMem.ReadingType = ReadingType;
|
|
|
|
//
|
|
// allocate buffer for transfering messages
|
|
//
|
|
unsigned char *OutputBuffer = (unsigned char *)malloc(Size);
|
|
|
|
ZeroMemory(OutputBuffer, Size);
|
|
|
|
Status = DeviceIoControl(DeviceHandle, // Handle to device
|
|
IOCTL_DEBUGGER_READ_MEMORY, // IO Control code
|
|
&ReadMem, // Input Buffer to driver.
|
|
SIZEOF_DEBUGGER_READ_MEMORY, // Input buffer length
|
|
OutputBuffer, // Output Buffer from driver.
|
|
Size, // Length of output buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in buffer.
|
|
NULL // synchronous call
|
|
);
|
|
|
|
if (!Status) {
|
|
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
if (Style == DEBUGGER_SHOW_COMMAND_DB) {
|
|
for (int i = 0; i < Size; i += 16) {
|
|
|
|
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
|
|
ShowMessages("#\t");
|
|
}
|
|
//
|
|
// Print address
|
|
//
|
|
ShowMessages("%s ", SeparateTo64BitValue((UINT64)(Address + i)).c_str());
|
|
|
|
//
|
|
// Print the hex code
|
|
//
|
|
for (size_t j = 0; j < 16; j++) {
|
|
//
|
|
// check to see if the address is valid or not
|
|
//
|
|
if (i + j >= ReturnedLength) {
|
|
ShowMessages("?? ");
|
|
} else {
|
|
ShowMessages("%02X ", OutputBuffer[i + j]);
|
|
}
|
|
}
|
|
//
|
|
// Print the character
|
|
//
|
|
ShowMessages(" ");
|
|
for (size_t j = 0; j < 16; j++) {
|
|
Character = (OutputBuffer[i + j]);
|
|
if (isprint(Character)) {
|
|
ShowMessages("%c", Character);
|
|
} else {
|
|
ShowMessages(".");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go to new line
|
|
//
|
|
ShowMessages("\n");
|
|
}
|
|
} else if (Style == DEBUGGER_SHOW_COMMAND_DC ||
|
|
Style == DEBUGGER_SHOW_COMMAND_DD) {
|
|
for (int i = 0; i < Size; i += 16) {
|
|
|
|
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
|
|
ShowMessages("#\t");
|
|
}
|
|
//
|
|
// Print address
|
|
//
|
|
ShowMessages("%s ", SeparateTo64BitValue((UINT64)(Address + i)).c_str());
|
|
|
|
//
|
|
// Print the hex code
|
|
//
|
|
for (size_t j = 0; j < 16; j += 4) {
|
|
//
|
|
// check to see if the address is valid or not
|
|
//
|
|
if (i + j >= ReturnedLength) {
|
|
ShowMessages("???????? ");
|
|
} else {
|
|
UINT32 OutputBufferVar = *((UINT32 *)&OutputBuffer[i + j]);
|
|
ShowMessages("%08X ", OutputBufferVar);
|
|
}
|
|
}
|
|
//
|
|
// Print the character
|
|
//
|
|
if (Style != DEBUGGER_SHOW_COMMAND_DD) {
|
|
ShowMessages(" ");
|
|
|
|
for (size_t j = 0; j < 16; j++) {
|
|
Character = (OutputBuffer[i + j]);
|
|
if (isprint(Character)) {
|
|
ShowMessages("%c", Character);
|
|
} else {
|
|
ShowMessages(".");
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go to new line
|
|
//
|
|
ShowMessages("\n");
|
|
}
|
|
} else if (Style == DEBUGGER_SHOW_COMMAND_DQ) {
|
|
for (int i = 0; i < Size; i += 16) {
|
|
|
|
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
|
|
ShowMessages("#\t");
|
|
}
|
|
//
|
|
// Print address
|
|
//
|
|
ShowMessages("%s ", SeparateTo64BitValue((UINT64)(Address + i)).c_str());
|
|
|
|
//
|
|
// Print the hex code
|
|
//
|
|
for (size_t j = 0; j < 16; j += 8) {
|
|
//
|
|
// check to see if the address is valid or not
|
|
//
|
|
if (i + j >= ReturnedLength) {
|
|
ShowMessages("???????? ");
|
|
} else {
|
|
UINT32 OutputBufferVar = *((UINT32 *)&OutputBuffer[i + j + 4]);
|
|
ShowMessages("%08X`", OutputBufferVar);
|
|
|
|
OutputBufferVar = *((UINT32 *)&OutputBuffer[i + j]);
|
|
ShowMessages("%08X ", OutputBufferVar);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go to new line
|
|
//
|
|
ShowMessages("\n");
|
|
}
|
|
} else if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE) {
|
|
HyperDbgDisassembler(OutputBuffer, Address, ReturnedLength);
|
|
}
|
|
|
|
ShowMessages("\n");
|
|
}
|
|
|
|
const vector<string> Split(const string &s, const char &c) {
|
|
string buff{""};
|
|
vector<string> v;
|
|
|
|
for (auto n : s) {
|
|
if (n != c)
|
|
buff += n;
|
|
else if (n == c && buff != "") {
|
|
v.push_back(buff);
|
|
buff = "";
|
|
}
|
|
}
|
|
if (buff != "")
|
|
v.push_back(buff);
|
|
|
|
return v;
|
|
}
|
|
// check if given string is a numeric string or not
|
|
bool IsNumber(const string &str) {
|
|
// std::find_first_not_of searches the string for the first character
|
|
// that does not match any of the characters specified in its arguments
|
|
return !str.empty() &&
|
|
(str.find_first_not_of("[0123456789]") == std::string::npos);
|
|
}
|
|
|
|
// Function to split string str using given delimiter
|
|
vector<string> SplitIp(const string &str, char delim) {
|
|
auto i = 0;
|
|
vector<string> list;
|
|
|
|
auto pos = str.find(delim);
|
|
|
|
while (pos != string::npos) {
|
|
list.push_back(str.substr(i, pos - i));
|
|
i = ++pos;
|
|
pos = str.find(delim, pos);
|
|
}
|
|
|
|
list.push_back(str.substr(i, str.length()));
|
|
|
|
return list;
|
|
}
|
|
|
|
bool IsHexNotation(std::string s) {
|
|
BOOLEAN IsAnyThing = FALSE;
|
|
for (char &c : s) {
|
|
IsAnyThing = TRUE;
|
|
if (!isxdigit(c)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (IsAnyThing) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN ConvertStringToUInt64(string TextToConvert, PUINT64 Result) {
|
|
|
|
if (!IsHexNotation(TextToConvert)) {
|
|
return FALSE;
|
|
}
|
|
const char *Text = TextToConvert.c_str();
|
|
errno = 0;
|
|
unsigned long long result = strtoull(Text, NULL, 16);
|
|
|
|
*Result = result;
|
|
|
|
if (errno == EINVAL) {
|
|
return FALSE;
|
|
} else if (errno == ERANGE) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOLEAN ConvertStringToUInt32(string TextToConvert, PUINT32 Result) {
|
|
|
|
UINT32 TempResult;
|
|
if (!IsHexNotation(TextToConvert)) {
|
|
return FALSE;
|
|
}
|
|
TempResult = stoi(TextToConvert, nullptr, 16);
|
|
*Result = TempResult;
|
|
}
|
|
|
|
BOOLEAN HasEnding(std::string const &fullString, std::string const &ending) {
|
|
if (fullString.length() >= ending.length()) {
|
|
return (0 == fullString.compare(fullString.length() - ending.length(),
|
|
ending.length(), ending));
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Function to validate an IP address
|
|
bool ValidateIP(string ip) {
|
|
// split the string into tokens
|
|
vector<string> list = SplitIp(ip, '.');
|
|
|
|
// if token size is not equal to four
|
|
if (list.size() != 4)
|
|
return false;
|
|
|
|
// validate each token
|
|
for (string str : list) {
|
|
// verify that string is number or not and the numbers
|
|
// are in the valid range
|
|
if (!IsNumber(str) || stoi(str) > 255 || stoi(str) < 0)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandClearScreen() { system("cls"); }
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandHiddenHook(vector<string> SplittedCommand) {
|
|
|
|
//
|
|
// Note : You can use "bh" and "!hiddenhook" in a same way
|
|
// * means optional
|
|
// !hiddenhook
|
|
// [Type:(all/process)]
|
|
// [Address:(hex) - Address to hook]
|
|
// *[Pid:(hex number) - only if you choose
|
|
//'process' as the Type] [Action:(break/code/log)]
|
|
// *[Condition:({ asm in hex })]
|
|
// *[Code:({asm in hex}) - only if you choose
|
|
//'code' as the Action]
|
|
// *[Log:(gp regs, pseudo-regs, static address,
|
|
// dereference regs +- value) - only if you choose 'log' as the Action]
|
|
//
|
|
//
|
|
// e.g :
|
|
// - bh all break fffff801deadbeef
|
|
// Description : Breaks to the
|
|
// debugger in all accesses to the selected address
|
|
//
|
|
// - !hiddenhook process 8e34
|
|
// fffff801deadbeef Description :
|
|
// Breaks to the debugger in accesses from the selected process by pid to the
|
|
// selected address
|
|
//
|
|
|
|
for (auto Section : SplittedCommand) {
|
|
ShowMessages("%s", Section.c_str());
|
|
ShowMessages("\n");
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandReadMemoryHelp() {
|
|
ShowMessages("u !u & db dc dd dq !db !dc !dd !dq : read the memory different "
|
|
"shapes (hex) and disassembler\n");
|
|
ShowMessages("d[b] Byte and ASCII characters\n");
|
|
ShowMessages("d[c] Double-word values (4 bytes) and ASCII characters\n");
|
|
ShowMessages("d[d] Double-word values (4 bytes)\n");
|
|
ShowMessages("d[q] Quad-word values (8 bytes). \n");
|
|
ShowMessages("u Disassembler at the target address \n");
|
|
ShowMessages("\n If you want to read physical memory then add '!' at the "
|
|
"start of the command\n");
|
|
ShowMessages("You can also disassemble physical memory using '!u'\n");
|
|
|
|
ShowMessages("syntax : \t[!]d[b|c|d|q] [address] l [length (hex)] pid "
|
|
"[process id (hex)]\n");
|
|
ShowMessages("\t\te.g : db fffff8077356f010 \n");
|
|
ShowMessages("\t\te.g : !dq 100000\n");
|
|
ShowMessages("\t\te.g : u fffff8077356f010\n");
|
|
}
|
|
void CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
|
|
|
|
string FirstCommand = SplittedCommand.front();
|
|
|
|
UINT32 Pid = 0;
|
|
UINT32 Length = 0;
|
|
UINT64 TargetAddress = 0;
|
|
bool IsNextProcessId = false;
|
|
bool IsFirstCommand = true;
|
|
|
|
bool IsNextLength = false;
|
|
|
|
if (SplittedCommand.size() == 1) {
|
|
//
|
|
// Means that user entered just a connect so we have to
|
|
// ask to connect to what ?
|
|
//
|
|
ShowMessages("incorrect use of '%s' command\n\n", FirstCommand.c_str());
|
|
CommandReadMemoryHelp();
|
|
return;
|
|
}
|
|
|
|
for (auto Section : SplittedCommand) {
|
|
if (IsFirstCommand) {
|
|
IsFirstCommand = false;
|
|
continue;
|
|
}
|
|
if (IsNextProcessId == true) {
|
|
if (!ConvertStringToUInt32(Section, &Pid)) {
|
|
ShowMessages("Err, you should enter a valid proc id\n\n");
|
|
return;
|
|
}
|
|
IsNextProcessId = false;
|
|
continue;
|
|
}
|
|
|
|
if (IsNextLength == true) {
|
|
|
|
if (!ConvertStringToUInt32(Section, &Length)) {
|
|
ShowMessages("Err, you should enter a valid length\n\n");
|
|
return;
|
|
}
|
|
IsNextLength = false;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("l")) {
|
|
IsNextLength = true;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("pid")) {
|
|
IsNextProcessId = true;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Probably it's address
|
|
//
|
|
if (TargetAddress == 0) {
|
|
|
|
string TempAddress = Section;
|
|
TempAddress.erase(remove(TempAddress.begin(), TempAddress.end(), '`'),
|
|
TempAddress.end());
|
|
|
|
if (!ConvertStringToUInt64(TempAddress, &TargetAddress)) {
|
|
ShowMessages("Err, you should enter a valid address\n\n");
|
|
return;
|
|
}
|
|
} else {
|
|
//
|
|
// User inserts two address
|
|
//
|
|
ShowMessages("Err, incorrect use of '%s' command\n\n",
|
|
FirstCommand.c_str());
|
|
CommandReadMemoryHelp();
|
|
|
|
return;
|
|
}
|
|
}
|
|
if (!TargetAddress) {
|
|
//
|
|
// User inserts two address
|
|
//
|
|
ShowMessages("Err, Please enter a valid address.\n\n");
|
|
|
|
return;
|
|
}
|
|
if (Length == 0) {
|
|
//
|
|
// Default length (user doesn't specified)
|
|
//
|
|
if (!FirstCommand.compare("u") || !FirstCommand.compare("!u")) {
|
|
Length = 0x40;
|
|
} else {
|
|
Length = 0x80;
|
|
}
|
|
}
|
|
if (IsNextLength || IsNextProcessId) {
|
|
ShowMessages("incorrect use of '%s' command\n\n", FirstCommand.c_str());
|
|
CommandReadMemoryHelp();
|
|
return;
|
|
}
|
|
if (Pid == 0) {
|
|
//
|
|
// Default process we read from current process
|
|
//
|
|
Pid = GetCurrentProcessId();
|
|
}
|
|
|
|
if (!FirstCommand.compare("db")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DB, TargetAddress,
|
|
DEBUGGER_READ_VIRTUAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
|
|
} else if (!FirstCommand.compare("dc")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DC, TargetAddress,
|
|
DEBUGGER_READ_VIRTUAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("dd")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DD, TargetAddress,
|
|
DEBUGGER_READ_VIRTUAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("dq")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DQ, TargetAddress,
|
|
DEBUGGER_READ_VIRTUAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("!db")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DB, TargetAddress,
|
|
DEBUGGER_READ_PHYSICAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("!dc")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DC, TargetAddress,
|
|
DEBUGGER_READ_PHYSICAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("!dd")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DD, TargetAddress,
|
|
DEBUGGER_READ_PHYSICAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("!dq")) {
|
|
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DQ, TargetAddress,
|
|
DEBUGGER_READ_PHYSICAL_ADDRESS,
|
|
READ_FROM_KERNEL, Pid, Length);
|
|
}
|
|
//
|
|
// Disassembler (!u or u)
|
|
//
|
|
else if (!FirstCommand.compare("u")) {
|
|
HyperDbgReadMemoryAndDisassemble(
|
|
DEBUGGER_SHOW_COMMAND_DISASSEMBLE, TargetAddress,
|
|
DEBUGGER_READ_VIRTUAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
|
|
} else if (!FirstCommand.compare("!u")) {
|
|
HyperDbgReadMemoryAndDisassemble(
|
|
DEBUGGER_SHOW_COMMAND_DISASSEMBLE, TargetAddress,
|
|
DEBUGGER_READ_PHYSICAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandConnectHelp() {
|
|
ShowMessages(".connect : connects to a remote or local machine to start "
|
|
"debugging.\n\n");
|
|
ShowMessages("syntax : \t.connect [ip] [port]\n");
|
|
ShowMessages("\t\te.g : .connect 192.168.1.5 50000\n");
|
|
ShowMessages("\t\te.g : .connect local\n");
|
|
}
|
|
void CommandConnect(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() == 1) {
|
|
//
|
|
// Means that user entered just a connect so we have to
|
|
// ask to connect to what ?
|
|
//
|
|
ShowMessages("incorrect use of '.connect'\n\n");
|
|
CommandConnectHelp();
|
|
return;
|
|
} else if (SplittedCommand.at(1) == "local" && SplittedCommand.size() == 2) {
|
|
//
|
|
// connect to local debugger
|
|
//
|
|
ShowMessages("local debug current system\n");
|
|
g_IsConnectedToDebugger = true;
|
|
|
|
return;
|
|
} else if (SplittedCommand.size() == 3) {
|
|
|
|
string ip = SplittedCommand.at(1);
|
|
string port = SplittedCommand.at(2);
|
|
|
|
//
|
|
// means that probably wants to connect to a remote
|
|
// system, let's first check the if the parameters are
|
|
// valid
|
|
//
|
|
if (!ValidateIP(ip)) {
|
|
ShowMessages("incorrect ip address\n");
|
|
return;
|
|
}
|
|
if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) {
|
|
ShowMessages("incorrect port\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// connect to remote debugger
|
|
//
|
|
ShowMessages("local debug remote system\n");
|
|
g_IsConnectedToDebugger = true;
|
|
|
|
return;
|
|
} else {
|
|
ShowMessages("incorrect use of '.connect'\n\n");
|
|
CommandConnectHelp();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandDisconnectHelp() {
|
|
ShowMessages(".disconnect : disconnect from a debugging session (it won't "
|
|
"unload the modules).\n\n");
|
|
ShowMessages("syntax : \.disconnect\n");
|
|
}
|
|
void CommandDisconnect(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() != 1) {
|
|
ShowMessages("incorrect use of '.disconnect'\n\n");
|
|
CommandDisconnectHelp();
|
|
return;
|
|
}
|
|
if (!g_IsConnectedToDebugger) {
|
|
ShowMessages("You're not connected to any instance of HyperDbg, did you "
|
|
"use '.connect'? \n");
|
|
return;
|
|
}
|
|
//
|
|
// Disconnect the session
|
|
//
|
|
g_IsConnectedToDebugger = false;
|
|
ShowMessages("successfully disconnected\n");
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandLoadHelp() {
|
|
ShowMessages("load : installs the driver and load the kernel modules.\n\n");
|
|
ShowMessages("syntax : \tload\n");
|
|
}
|
|
void CommandLoad(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() != 1) {
|
|
ShowMessages("incorrect use of 'load'\n\n");
|
|
CommandLoadHelp();
|
|
return;
|
|
}
|
|
if (!g_IsConnectedToDebugger) {
|
|
ShowMessages("You're not connected to any instance of HyperDbg, did you "
|
|
"use '.connect'? \n");
|
|
return;
|
|
}
|
|
ShowMessages("try to install driver...\n");
|
|
if (HyperdbgInstallDriver()) {
|
|
ShowMessages("Failed to install driver\n");
|
|
return;
|
|
}
|
|
|
|
ShowMessages("try to install load kernel modules...\n");
|
|
if (HyperdbgLoad()) {
|
|
ShowMessages("Failed to load driver\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If we reach here so the module are loaded
|
|
//
|
|
g_IsDebuggerModulesLoaded = true;
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandUnloadHelp() {
|
|
ShowMessages(
|
|
"unload : unloads the kernel modules and uninstalls the drivers.\n\n");
|
|
ShowMessages("syntax : \tunload\n");
|
|
}
|
|
void CommandUnload(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() != 1) {
|
|
ShowMessages("incorrect use of 'unload'\n\n");
|
|
CommandLoadHelp();
|
|
return;
|
|
}
|
|
if (!g_IsConnectedToDebugger) {
|
|
ShowMessages("You're not connected to any instance of HyperDbg, did you "
|
|
"use '.connect'? \n");
|
|
return;
|
|
}
|
|
|
|
if (g_IsDebuggerModulesLoaded) {
|
|
HyperdbgUnload();
|
|
|
|
//
|
|
// Installing Driver
|
|
//
|
|
if (HyperdbgUninstallDriver()) {
|
|
ShowMessages("Failed to uninstall driver\n");
|
|
}
|
|
} else {
|
|
ShowMessages("there is nothing to unload\n");
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandCpuHelp() {
|
|
ShowMessages("cpu : collects a report from cpu features.\n\n");
|
|
ShowMessages("syntax : \tcpu\n");
|
|
}
|
|
void CommandCpu(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() != 1) {
|
|
ShowMessages("incorrect use of 'cpu'\n\n");
|
|
CommandCpuHelp();
|
|
return;
|
|
}
|
|
ReadCpuDetails();
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandExitHelp() {
|
|
ShowMessages(
|
|
"exit : unload and uninstalls the drivers and closes the debugger.\n\n");
|
|
ShowMessages("syntax : \texit\n");
|
|
}
|
|
void CommandExit(vector<string> SplittedCommand) {
|
|
|
|
if (SplittedCommand.size() != 1) {
|
|
ShowMessages("incorrect use of 'exit'\n\n");
|
|
CommandExitHelp();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// unload and exit
|
|
//
|
|
if (g_IsDebuggerModulesLoaded) {
|
|
HyperdbgUnload();
|
|
|
|
//
|
|
// Installing Driver
|
|
//
|
|
if (HyperdbgUninstallDriver()) {
|
|
ShowMessages("Failed to uninstall driver\n");
|
|
}
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandFormatsHelp() {
|
|
ShowMessages(".formats : Show a value or register in different formats.\n\n");
|
|
ShowMessages("syntax : \t.formats [hex value | register]\n");
|
|
}
|
|
void CommandFormats(vector<string> SplittedCommand) {
|
|
|
|
UINT64 u64Value;
|
|
time_t t;
|
|
struct tm *tmp;
|
|
char MY_TIME[50];
|
|
char Character;
|
|
|
|
if (SplittedCommand.size() != 2) {
|
|
ShowMessages("incorrect use of '.formats'\n\n");
|
|
CommandFormatsHelp();
|
|
return;
|
|
}
|
|
if (!ConvertStringToUInt64(SplittedCommand.at(1), &u64Value)) {
|
|
ShowMessages("incorrect use of '.formats'\n\n");
|
|
CommandFormatsHelp();
|
|
return;
|
|
}
|
|
|
|
time(&t);
|
|
|
|
//
|
|
// localtime() uses the time pointed by t ,
|
|
// to fill a tm structure with the values that
|
|
// represent the corresponding local time.
|
|
//
|
|
|
|
tmp = localtime(&t);
|
|
|
|
//
|
|
// using strftime to display time
|
|
//
|
|
strftime(MY_TIME, sizeof(MY_TIME), "%x - %I:%M%p", tmp);
|
|
|
|
ShowMessages("Evaluate expression:\n");
|
|
ShowMessages("Hex : %s\n", SeparateTo64BitValue(u64Value).c_str());
|
|
ShowMessages("Decimal : %d\n", u64Value);
|
|
ShowMessages("Octal : %o\n", u64Value);
|
|
|
|
ShowMessages("Binary : ");
|
|
PrintBits(sizeof(UINT64), &u64Value);
|
|
|
|
ShowMessages("\nChar : ");
|
|
//
|
|
// iterate through 8, 8 bits (8*6)
|
|
//
|
|
for (size_t j = 0; j < 8; j++) {
|
|
|
|
Character = (char)(((char *)&u64Value)[j]);
|
|
|
|
if (isprint(Character)) {
|
|
ShowMessages("%c", Character);
|
|
} else {
|
|
ShowMessages(".");
|
|
}
|
|
}
|
|
ShowMessages("\nTime : %s\n", MY_TIME);
|
|
ShowMessages("Float : %4.2f %+.0e %E\n", u64Value, u64Value, u64Value);
|
|
ShowMessages("Double : %.*e\n", DECIMAL_DIG, u64Value);
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandRdmsrHelp() {
|
|
ShowMessages("rdmsr : Reads a model-specific register (MSR).\n\n");
|
|
ShowMessages("syntax : \trdmsr [rcx (hex value)] core [core index (hex value "
|
|
"- optional)]\n");
|
|
ShowMessages("\t\te.g : rdmsr c0000082\n");
|
|
ShowMessages("\t\te.g : rdmsr c0000082 core 2\n");
|
|
}
|
|
void CommandRdmsr(vector<string> SplittedCommand) {
|
|
|
|
BOOL Status;
|
|
BOOL IsNextCoreId = FALSE;
|
|
BOOL SetMsr = FALSE;
|
|
DEBUGGER_READ_AND_WRITE_ON_MSR MsrReadRequest;
|
|
ULONG ReturnedLength;
|
|
UINT64 Msr;
|
|
UINT32 CoreNumer = DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES;
|
|
SYSTEM_INFO SysInfo;
|
|
DWORD NumCPU;
|
|
|
|
if (SplittedCommand.size() >= 5) {
|
|
ShowMessages("incorrect use of 'rdmsr'\n\n");
|
|
CommandRdmsrHelp();
|
|
return;
|
|
}
|
|
|
|
for (auto Section : SplittedCommand) {
|
|
|
|
if (!Section.compare(SplittedCommand.at(0))) {
|
|
continue;
|
|
}
|
|
|
|
if (IsNextCoreId) {
|
|
if (!ConvertStringToUInt32(Section, &CoreNumer)) {
|
|
ShowMessages("please specify a correct hex value for core id\n\n");
|
|
CommandRdmsrHelp();
|
|
return;
|
|
}
|
|
IsNextCoreId = FALSE;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("core")) {
|
|
IsNextCoreId = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (SetMsr || !ConvertStringToUInt64(Section, &Msr)) {
|
|
ShowMessages("please specify a correct hex value to be read\n\n");
|
|
CommandRdmsrHelp();
|
|
return;
|
|
}
|
|
SetMsr = TRUE;
|
|
}
|
|
//
|
|
// Check if msr is set or not
|
|
//
|
|
if (!SetMsr) {
|
|
ShowMessages("please specify a correct hex value to be read\n\n");
|
|
CommandRdmsrHelp();
|
|
return;
|
|
}
|
|
if (IsNextCoreId) {
|
|
ShowMessages("please specify a correct hex value for core\n\n");
|
|
CommandRdmsrHelp();
|
|
return;
|
|
}
|
|
|
|
if (!DeviceHandle) {
|
|
ShowMessages("Handle not found, probably the driver is not loaded.\n");
|
|
return;
|
|
}
|
|
|
|
MsrReadRequest.ActionType = DEBUGGER_MSR_READ;
|
|
MsrReadRequest.Msr = Msr;
|
|
MsrReadRequest.CoreNumber = CoreNumer;
|
|
|
|
//
|
|
// Find logical cores count
|
|
//
|
|
GetSystemInfo(&SysInfo);
|
|
NumCPU = SysInfo.dwNumberOfProcessors;
|
|
|
|
//
|
|
// allocate buffer for transfering messages
|
|
//
|
|
|
|
UINT64 *OutputBuffer = (UINT64 *)malloc(sizeof(UINT64) * NumCPU);
|
|
|
|
ZeroMemory(OutputBuffer, sizeof(UINT64) * NumCPU);
|
|
|
|
Status = DeviceIoControl(
|
|
DeviceHandle, // Handle to device
|
|
IOCTL_DEBUGGER_READ_OR_WRITE_MSR, // IO Control code
|
|
&MsrReadRequest, // Input Buffer to driver.
|
|
SIZEOF_READ_AND_WRITE_ON_MSR, // Input buffer length
|
|
OutputBuffer, // Output Buffer from driver.
|
|
sizeof(UINT64) * NumCPU, // Length of output buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in buffer.
|
|
NULL // synchronous call
|
|
);
|
|
|
|
if (!Status) {
|
|
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
//
|
|
// btw, %x is enough, no need to %llx
|
|
//
|
|
if (CoreNumer == DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES) {
|
|
//
|
|
// Show all cores
|
|
//
|
|
for (size_t i = 0; i < NumCPU; i++) {
|
|
|
|
ShowMessages("core : 0x%x - msr[%llx] = %s\n", i, Msr,
|
|
SeparateTo64BitValue((OutputBuffer[i])).c_str());
|
|
}
|
|
} else {
|
|
//
|
|
// Show for a single-core
|
|
//
|
|
ShowMessages("core : 0x%x - msr[%llx] = %s\n", CoreNumer, Msr,
|
|
SeparateTo64BitValue((OutputBuffer[0])).c_str());
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandWrmsrHelp() {
|
|
ShowMessages("wrmsr : Writes on a model-specific register (MSR).\n\n");
|
|
ShowMessages("syntax : \twrmsr [ecx (hex value)] [value to write - EDX:EAX "
|
|
"(hex value)] core [core index (hex value - optional)]\n");
|
|
ShowMessages("\t\te.g : wrmsr c0000082 fffff8077356f010\n");
|
|
ShowMessages("\t\te.g : wrmsr c0000082 fffff8077356f010 core 2\n");
|
|
}
|
|
void CommandWrmsr(vector<string> SplittedCommand) {
|
|
|
|
BOOL Status;
|
|
BOOL IsNextCoreId = FALSE;
|
|
BOOL SetMsr = FALSE;
|
|
BOOL SetValue = FALSE;
|
|
DEBUGGER_READ_AND_WRITE_ON_MSR MsrWriteRequest;
|
|
UINT64 Msr;
|
|
UINT64 Value = 0;
|
|
UINT32 CoreNumer = DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES;
|
|
|
|
if (SplittedCommand.size() >= 6) {
|
|
ShowMessages("incorrect use of 'wrmsr'\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
}
|
|
|
|
for (auto Section : SplittedCommand) {
|
|
|
|
if (!Section.compare(SplittedCommand.at(0))) {
|
|
continue;
|
|
}
|
|
|
|
if (IsNextCoreId) {
|
|
if (!ConvertStringToUInt32(Section, &CoreNumer)) {
|
|
ShowMessages("please specify a correct hex value for core id\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
}
|
|
IsNextCoreId = FALSE;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("core")) {
|
|
IsNextCoreId = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (!SetMsr) {
|
|
if (!ConvertStringToUInt64(Section, &Msr)) {
|
|
ShowMessages("please specify a correct hex value to be read\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
} else {
|
|
//
|
|
// Means that the MSR is set, next we should read value
|
|
//
|
|
SetMsr = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (SetMsr) {
|
|
if (!ConvertStringToUInt64(Section, &Value)) {
|
|
ShowMessages(
|
|
"please specify a correct hex value to put on the msr\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
} else {
|
|
|
|
SetValue = TRUE;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Check if msr is set or not
|
|
//
|
|
if (!SetMsr) {
|
|
ShowMessages("please specify a correct hex value to write\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
}
|
|
if (!SetValue) {
|
|
ShowMessages("please specify a correct hex value to put on msr\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
}
|
|
if (IsNextCoreId) {
|
|
ShowMessages("please specify a correct hex value for core\n\n");
|
|
CommandWrmsrHelp();
|
|
return;
|
|
}
|
|
|
|
if (!DeviceHandle) {
|
|
ShowMessages("Handle not found, probably the driver is not loaded.\n");
|
|
return;
|
|
}
|
|
|
|
MsrWriteRequest.ActionType = DEBUGGER_MSR_WRITE;
|
|
MsrWriteRequest.Msr = Msr;
|
|
MsrWriteRequest.CoreNumber = CoreNumer;
|
|
MsrWriteRequest.Value = Value;
|
|
|
|
Status = DeviceIoControl(DeviceHandle, // Handle to device
|
|
IOCTL_DEBUGGER_READ_OR_WRITE_MSR, // IO Control code
|
|
&MsrWriteRequest, // Input Buffer to driver.
|
|
SIZEOF_READ_AND_WRITE_ON_MSR, // Input buffer length
|
|
NULL, // Output Buffer from driver.
|
|
NULL, // Length of output buffer in bytes.
|
|
NULL, // Bytes placed in buffer.
|
|
NULL // synchronous call
|
|
);
|
|
|
|
if (!Status) {
|
|
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
ShowMessages("\n");
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
void CommandPteHelp() {
|
|
ShowMessages("!pte : Find virtual address of different paging-levels.\n\n");
|
|
ShowMessages("syntax : \t!pte [Virtual Address (hex value)]\n");
|
|
ShowMessages("\t\te.g : !pte fffff801deadbeef\n");
|
|
}
|
|
void CommandPte(vector<string> SplittedCommand) {
|
|
|
|
BOOL Status;
|
|
ULONG ReturnedLength;
|
|
UINT64 TargetVa;
|
|
DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PteRead = {0};
|
|
|
|
if (SplittedCommand.size() > 2) {
|
|
ShowMessages("incorrect use of '!pte'\n\n");
|
|
CommandPteHelp();
|
|
return;
|
|
}
|
|
|
|
if (!ConvertStringToUInt64(SplittedCommand.at(1), &TargetVa)) {
|
|
ShowMessages("incorrect address, please enter a valid virtual address\n\n");
|
|
return;
|
|
}
|
|
|
|
if (!DeviceHandle) {
|
|
ShowMessages("Handle not found, probably the driver is not loaded.\n");
|
|
return;
|
|
}
|
|
//
|
|
// Prepare the buffer
|
|
// We use same buffer for input and output
|
|
//
|
|
PteRead.VirtualAddress = TargetVa;
|
|
|
|
//
|
|
// Send IOCTL
|
|
//
|
|
|
|
Status = DeviceIoControl(
|
|
DeviceHandle, // Handle to device
|
|
IOCTL_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, // IO Control code
|
|
&PteRead, // Input Buffer to driver.
|
|
SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, // Input buffer length
|
|
&PteRead, // Output Buffer from driver.
|
|
SIZEOF_DEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS, // Length of output
|
|
// buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in buffer.
|
|
NULL // synchronous call
|
|
);
|
|
|
|
if (!Status) {
|
|
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Show the results
|
|
//
|
|
/*
|
|
VA fffff8003abc9370
|
|
PXE at FFFF83C1E0F07F80 PPE at FFFF83C1E0FF0000 PDE at
|
|
FFFF83C1FE000EA8 PTE at FFFF83FC001D5E48 contains 0000000004108063
|
|
contains 0000000004109063 contains 00000000026008E3 contains
|
|
0000000000000000 pfn 4108 ---DA--KWEV pfn 4109 ---DA--KWEV pfn
|
|
2600 --LDA--KWEV LARGE PAGE pfn 27c9
|
|
*/
|
|
ShowMessages("VA %llx\n", TargetVa);
|
|
ShowMessages("PML4E (PXE) at %016llx\tcontains %016llx\nPDPT (PPE) at "
|
|
"%016llx\tcontains "
|
|
"%016llx\nPDE at %016llx\tcontains %016llx\n",
|
|
PteRead.Pml4eVirtualAddress, PteRead.Pml4eValue,
|
|
PteRead.PdpteVirtualAddress, PteRead.PdpteValue,
|
|
PteRead.PdeVirtualAddress, PteRead.PdeValue);
|
|
|
|
//
|
|
// Check if it's a large PDE
|
|
//
|
|
if (PteRead.PdeVirtualAddress == PteRead.PteVirtualAddress) {
|
|
ShowMessages("PDE is a large page, so it doesn't have a PTE\n");
|
|
} else {
|
|
ShowMessages("PTE at %016llx\tcontains %016llx\n",
|
|
PteRead.PteVirtualAddress, PteRead.PteValue);
|
|
}
|
|
}
|
|
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
/**
|
|
* @brief Interpret conditions (if an event has condition)
|
|
* @details If this function returns true then it means that there is a condtion
|
|
* buffer in this command split and the details are returned in the input
|
|
* structure
|
|
*
|
|
* @param SplittedCommand All the commands
|
|
*/
|
|
BOOLEAN InterpretConditions(vector<string> SplittedCommand) {
|
|
BOOLEAN ConditionVisited = FALSE;
|
|
BOOLEAN InConditonState = FALSE;
|
|
BOOLEAN IsConditionEnded = FALSE;
|
|
vector<string> ConditionBuffer;
|
|
|
|
for (auto Section : SplittedCommand) {
|
|
|
|
if (InConditonState) {
|
|
|
|
//
|
|
// Check if the condition is end or not
|
|
//
|
|
if (!Section.compare("}")) {
|
|
IsConditionEnded = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check if the condition is end or not
|
|
//
|
|
if (HasEnding(Section, "}")) {
|
|
|
|
//
|
|
// remove the last character and append it to the ConditionBuffer
|
|
//
|
|
ConditionBuffer.push_back(Section.substr(0, Section.size() - 1));
|
|
|
|
IsConditionEnded = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add the codes into condition bi
|
|
//
|
|
ConditionBuffer.push_back(Section);
|
|
|
|
//
|
|
// We want to stay in this condition
|
|
//
|
|
continue;
|
|
}
|
|
|
|
if (ConditionVisited && !Section.compare("{")) {
|
|
InConditonState = TRUE;
|
|
continue;
|
|
}
|
|
if (ConditionVisited && Section.rfind("{", 0) == 0) {
|
|
//
|
|
// Section starts with {
|
|
//
|
|
ConditionBuffer.push_back(Section.erase(0, 1));
|
|
|
|
InConditonState = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("condition")) {
|
|
ConditionVisited = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (!Section.compare("condition{")) {
|
|
ConditionVisited = TRUE;
|
|
InConditonState = TRUE;
|
|
continue;
|
|
}
|
|
if (Section.rfind("condition{", 0) == 0) {
|
|
ConditionVisited = TRUE;
|
|
InConditonState = TRUE;
|
|
|
|
if (!HasEnding(Section, "}")) {
|
|
//
|
|
// Section starts with condition{
|
|
//
|
|
ConditionBuffer.push_back(Section.erase(0, 10));
|
|
continue;
|
|
} else {
|
|
//
|
|
// remove the last character and first character append it to the
|
|
// ConditionBuffer
|
|
//
|
|
string temp = Section.erase(0, 10);
|
|
ConditionBuffer.push_back(temp.substr(0, temp.size() - 1));
|
|
|
|
IsConditionEnded = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now we have everything in condition buffer
|
|
// Check to see if it is empty or not
|
|
//
|
|
if (ConditionBuffer.size() == 0) {
|
|
//
|
|
// Nothing in condition buffer, return zero
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check if we see '}' at the end
|
|
//
|
|
if (!IsConditionEnded) {
|
|
//
|
|
// Nothing in condition buffer, return zero
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If we reach here then there is sth in condition buffer
|
|
//
|
|
printf("\n\n wooooooooooooooooooooooooooooooooooooooooooooooowwww :\n");
|
|
for (auto Section : ConditionBuffer) {
|
|
|
|
//
|
|
// Check if the section is started with '0x'
|
|
//
|
|
if (Section.rfind("0x", 0) == 0 || Section.rfind("0X", 0) == 0) {
|
|
}
|
|
printf("%s\n", Section.c_str());
|
|
}
|
|
printf("\n\n end of wooooooooooooooooooooooooooooooooooooooooooooooowwww");
|
|
}
|
|
|
|
VOID TestMe(vector<string> SplittedCommand) {
|
|
|
|
if (!InterpretConditions(SplittedCommand)) {
|
|
printf("\nno condition !\n");
|
|
}
|
|
}
|
|
/* ==============================================================================================
|
|
*/
|
|
|
|
/**
|
|
* @brief Interpret commands
|
|
*
|
|
* @param Command The text of command
|
|
* @return int returns return zero if it was successful or non-zero if there was
|
|
* error
|
|
*/
|
|
int _cdecl HyperdbgInterpreter(const char *Command) {
|
|
|
|
string CommandString(Command);
|
|
|
|
//
|
|
// Convert to lower case
|
|
//
|
|
transform(CommandString.begin(), CommandString.end(), CommandString.begin(),
|
|
[](unsigned char c) { return std::tolower(c); });
|
|
|
|
vector<string> SplittedCommand{Split(CommandString, ' ')};
|
|
|
|
//
|
|
// Check if user entered an empty imput
|
|
//
|
|
if (SplittedCommand.empty()) {
|
|
ShowMessages("\n");
|
|
return 0;
|
|
}
|
|
|
|
string FirstCommand = SplittedCommand.front();
|
|
|
|
if (!FirstCommand.compare("clear") || !FirstCommand.compare("cls") ||
|
|
!FirstCommand.compare(".cls")) {
|
|
CommandClearScreen();
|
|
} else if (!FirstCommand.compare(".connect")) {
|
|
CommandConnect(SplittedCommand);
|
|
} else if (!FirstCommand.compare("connect")) {
|
|
ShowMessages("Couldn't resolve error at '%s', did you mean '.connect'?",
|
|
FirstCommand.c_str());
|
|
} else if (!FirstCommand.compare("disconnect")) {
|
|
ShowMessages("Couldn't resolve error at '%s', did you mean '.disconnect'?",
|
|
FirstCommand.c_str());
|
|
} else if (!FirstCommand.compare(".disconnect")) {
|
|
CommandDisconnect(SplittedCommand);
|
|
} else if (!FirstCommand.compare("load")) {
|
|
CommandLoad(SplittedCommand);
|
|
} else if (!FirstCommand.compare("exit") || !FirstCommand.compare(".exit")) {
|
|
CommandExit(SplittedCommand);
|
|
} else if (!FirstCommand.compare("unload")) {
|
|
CommandUnload(SplittedCommand);
|
|
} else if (!FirstCommand.compare("cpu")) {
|
|
CommandCpu(SplittedCommand);
|
|
} else if (!FirstCommand.compare("wrmsr")) {
|
|
CommandWrmsr(SplittedCommand);
|
|
} else if (!FirstCommand.compare("rdmsr")) {
|
|
CommandRdmsr(SplittedCommand);
|
|
} else if (!FirstCommand.compare(".formats")) {
|
|
CommandFormats(SplittedCommand);
|
|
} else if (!FirstCommand.compare("!pte")) {
|
|
CommandPte(SplittedCommand);
|
|
} else if (!FirstCommand.compare("!monitor")) {
|
|
TestMe(SplittedCommand);
|
|
} else if (!FirstCommand.compare("lm")) {
|
|
CommandLm(SplittedCommand);
|
|
} else if (!FirstCommand.compare("db") || !FirstCommand.compare("dc") ||
|
|
!FirstCommand.compare("dd") || !FirstCommand.compare("dq") ||
|
|
!FirstCommand.compare("!db") || !FirstCommand.compare("!dc") ||
|
|
!FirstCommand.compare("!dd") || !FirstCommand.compare("!dq") ||
|
|
!FirstCommand.compare("!u") || !FirstCommand.compare("u")) {
|
|
CommandReadMemoryAndDisassembler(SplittedCommand);
|
|
} else if (!FirstCommand.compare("!hiddenhook") ||
|
|
!FirstCommand.compare("bh")) {
|
|
CommandHiddenHook(SplittedCommand);
|
|
} else {
|
|
ShowMessages("Couldn't resolve error at '%s'", FirstCommand.c_str());
|
|
ShowMessages("\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|