major update

This commit is contained in:
SinaKarvandi 2020-08-28 04:03:12 -07:00
parent 05acdaa269
commit 4c679db851
187 changed files with 12653 additions and 59806 deletions

38
Counter.py Normal file
View file

@ -0,0 +1,38 @@
import os
def CountLines(start, lines=0, header=True, begin_start=None):
if header:
print('{:>10} |{:>10} | {:<20}'.format('ADDED', 'TOTAL', 'FILE'))
print('{:->11}|{:->11}|{:->20}'.format('', '', ''))
for thing in os.listdir(start):
thing = os.path.join(start, thing)
if os.path.isfile(thing):
if '\dependencies' not in thing and(thing.endswith('.c') or thing.endswith('.h') or thing.endswith('.cpp') or thing.endswith('.asm')):
with open(thing, 'r') as f:
newlines = f.readlines()
newlines = len(newlines)
lines += newlines
if begin_start is not None:
reldir_of_thing = '.' + thing.replace(begin_start, '')
else:
reldir_of_thing = '.' + thing.replace(start, '')
print('{:>10} |{:>10} | {:<20}'.format(
newlines, lines, reldir_of_thing))
for thing in os.listdir(start):
thing = os.path.join(start, thing)
if os.path.isdir(thing):
lines = CountLines(thing, lines, header=False, begin_start=start)
return lines
##
## This is fun script, I wrote to see that
## HyperDbg conatins how many lines of code...
##
CountLines(r'.\hyperdbg')

View file

@ -1521,7 +1521,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.

1
Doxygen.bat Normal file
View file

@ -0,0 +1 @@
"c:\Program Files\doxygen\bin\doxygen.exe" Doxyfile

View file

@ -1,10 +1,10 @@
PUBLIC AsmVmxSupportDetection
.code _text
;------------------------------------------------------------------------
; Note : Right-click the .asm file, Properties, change Item Type to "Microsoft Macro Assembler" if it didn't compile
; Note : Right-click the .asm file, Properties, change Item Type to
; "Microsoft Macro Assembler" if it didn't compile
;------------------------------------------------------------------------
AsmVmxSupportDetection PROC

View file

@ -14,15 +14,13 @@
using namespace std;
//////////////////////////////////////////////////
// Externs
////
// Externs //
//////////////////////////////////////////////////
extern HANDLE g_DeviceHandle;
//////////////////////////////////////////////////
// Functions
////
// Functions //
//////////////////////////////////////////////////
int ReadCpuDetails();
@ -40,8 +38,11 @@ VOID HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
UINT32 Pid, UINT Size);
string SeparateTo64BitValue(UINT64 Value);
int HyperDbgDisassembler(unsigned char *BufferToDisassemble, UINT64 BaseAddress,
UINT64 Size);
int HyperDbgDisassembler64(unsigned char *BufferToDisassemble,
UINT64 BaseAddress, UINT64 Size);
int HyperDbgDisassembler32(unsigned char *BufferToDisassemble,
UINT64 BaseAddress, UINT64 Size);
VOID HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
UINT64 Address,
@ -109,7 +110,7 @@ VOID CommandIoout(vector<string> SplittedCommand);
VOID CommandVmcall(vector<string> SplittedCommand);
VOID CommandHide(vector<string> SplittedCommand);
VOID CommandHide(vector<string> SplittedCommand, string Command);
VOID CommandUnhide(vector<string> SplittedCommand);
@ -130,3 +131,19 @@ VOID CommandSleep(vector<string> SplittedCommand);
VOID CommandEditMemory(vector<string> SplittedCommand);
VOID CommandSearchMemory(vector<string> SplittedCommand);
VOID CommandMeasure(vector<string> SplittedCommand);
VOID CommandSettings(vector<string> SplittedCommand);
VOID CommandFlush(vector<string> SplittedCommand);
VOID CommandPause(vector<string> SplittedCommand);
VOID CommandListen(vector<string> SplittedCommand);
VOID CommandStatus(vector<string> SplittedCommand);
VOID CommandAttach(vector<string> SplittedCommand);
VOID CommandDetach(vector<string> SplittedCommand);

View file

@ -0,0 +1,129 @@
/**
* @file attach.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief .attach command
* @details
* @version 0.1
* @date 2020-08-27
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsAttachedToUsermodeProcess;
/**
* @brief help of .attach command
*
* @return VOID
*/
VOID CommandAttachHelp() {
ShowMessages(".attach : attach to debug a user-mode process.\n\n");
ShowMessages("syntax : \t.attach pid [process id (hex)]\n");
ShowMessages("\t\te.g : .attach pid b60 \n");
}
/**
* @brief .attach command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID CommandAttach(vector<string> SplittedCommand) {
BOOLEAN Status;
ULONG ReturnedLength;
UINT64 TargetPid;
DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest = {0};
if (SplittedCommand.size() <= 2) {
ShowMessages("incorrect use of '.attach'\n\n");
CommandAttachHelp();
return;
}
//
// Find out whether the user enters pid or not
//
if (!SplittedCommand.at(1).compare("pid")) {
//
// Check for the user to not add extra arguments
//
if (SplittedCommand.size() != 3) {
ShowMessages("incorrect use of '.attach'\n\n");
CommandAttachHelp();
return;
}
//
// It's just a pid for the process
//
if (!ConvertStringToUInt64(SplittedCommand.at(2), &TargetPid)) {
ShowMessages("incorrect process id\n\n");
return;
}
} else {
//
// Invalid argument for the second parameter to the command
//
ShowMessages("incorrect use of '.attach'\n\n");
CommandAttachHelp();
return;
}
//
// Check if debugger is loaded or not
//
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
//
// We wanna attach to a remote process
//
AttachRequest.IsAttach = TRUE;
//
// Set the process id
//
AttachRequest.ProcessId = TargetPid;
//
// Send the request to the kernel
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // IO Control
// code
&AttachRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // Input buffer length
&AttachRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // 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;
}
//
// Check if attaching was successful then we can set the attached to true
//
if (AttachRequest.Result == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
g_IsAttachedToUsermodeProcess = TRUE;
}
}

View file

@ -11,34 +11,73 @@
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_BreakPrintingOutput;
extern BOOLEAN g_AutoUnpause;
BOOL WINAPI BreakController(DWORD CtrlType) {
/**
* @brief handle CTRL+C and CTRL+Break events
*
* @param CtrlType
* @return BOOL
*/
BOOL BreakController(DWORD CtrlType) {
switch (CtrlType) {
//
// Handle the CTRL-C signal.
//
case CTRL_C_EVENT:
//
// Sleep because the other thread that shows must be stopped
//
g_BreakPrintingOutput = TRUE;
Sleep(500);
ShowMessages("\npause\npausing debugger...\n");
if (g_AutoUnpause) {
ShowMessages("pause\npausing debugger...\nauto-unpause mode is enabled, "
"debugger will automatically continue when you run a new "
"event command, if you want to change this behaviour then "
"run run 'settings autounpause off'\n\nHyperDbg >");
} else {
ShowMessages(
"pause\npausing debugger...\nauto-unpause mode is disabled, you "
"should run 'g' when you want to continue, otherwise run 'settings "
"autounpause on'\n\nHyperDbg >");
}
return TRUE;
//
// CTRL-CLOSE: confirm that the user wants to exit.
//
case CTRL_CLOSE_EVENT:
return TRUE;
//
// Pass other signals to the next handler.
//
case CTRL_BREAK_EVENT:
//
// Sleep because the other thread that shows must be stopped
//
g_BreakPrintingOutput = TRUE;
Sleep(500);
ShowMessages("\npause\npausing debugger...\n");
if (g_AutoUnpause) {
ShowMessages("pause\npausing debugger...\nauto-unpause mode is enabled, "
"debugger will automatically continue when you run a new "
"event command, if you want to change this behaviour then "
"run run 'settings autounpause off'\n\nHyperDbg >");
} else {
ShowMessages(
"pause\npausing debugger...\nauto-unpause mode is disabled, you "
"should run 'g' when you want to continue, otherwise run 'settings "
"autounpause on'\n\nHyperDbg >");
}
return TRUE;
case CTRL_LOGOFF_EVENT:
@ -48,14 +87,13 @@ BOOL WINAPI BreakController(DWORD CtrlType) {
return FALSE;
default:
//
// Return TRUE if handled this message, further handler functions won't be
// called.
// Return FALSE to pass this message to further handlers until default
// handler calls ExitProcess().
//
return FALSE;
return FALSE;
}
}

View file

@ -11,8 +11,19 @@
*/
#include "pch.h"
/**
* @brief help of .cls command
*
* @return VOID
*/
VOID CommandClearScreenHelp() {
ShowMessages(".cls : clears the screen.\n\n");
ShowMessages("syntax : \t.cls\n");
}
/**
* @brief .cls command handler
*
* @return VOID
*/
VOID CommandClearScreen() { system("cls"); }

View file

@ -13,6 +13,12 @@
using namespace std;
/**
* @brief add ` between 64 bit values and convert them to string
*
* @param Value
* @return string
*/
string SeparateTo64BitValue(UINT64 Value) {
ostringstream OstringStream;
@ -25,6 +31,13 @@ string SeparateTo64BitValue(UINT64 Value) {
return Temp;
}
/**
* @brief print bits and bytes for d* commands
*
* @param size
* @param ptr
* @return VOID
*/
VOID PrintBits(size_t const size, void const *const ptr) {
unsigned char *b = (unsigned char *)ptr;
unsigned char byte;
@ -39,6 +52,14 @@ VOID PrintBits(size_t const size, void const *const ptr) {
}
}
/**
* @brief general replace all function
*
* @param str
* @param from
* @param to
* @return VOID
*/
VOID ReplaceAll(string &str, const string &from, const string &to) {
size_t SartPos = 0;
@ -55,6 +76,14 @@ VOID ReplaceAll(string &str, const string &from, const string &to) {
SartPos += to.length();
}
}
/**
* @brief general split command
*
* @param s target string
* @param c splitter (delimiter)
* @return const vector<string>
*/
const vector<string> Split(const string &s, const char &c) {
string buff{""};
@ -74,9 +103,12 @@ const vector<string> Split(const string &s, const char &c) {
return v;
}
//
// check if given string is a numeric string or not
//
/**
* @brief check if given string is a numeric string or not
*
* @param str
* @return BOOLEAN
*/
BOOLEAN IsNumber(const string &str) {
//
@ -87,9 +119,13 @@ BOOLEAN IsNumber(const string &str) {
(str.find_first_not_of("[0123456789]") == std::string::npos);
}
//
// Function to split string str using given delimiter
//
/**
* @brief Function to split string str using given delimiter
*
* @param str
* @param delim
* @return vector<string>
*/
vector<string> SplitIp(const string &str, char delim) {
int i = 0;
@ -109,6 +145,12 @@ vector<string> SplitIp(const string &str, char delim) {
return list;
}
/**
* @brief check whether the string is hex or not
*
* @param s
* @return BOOLEAN
*/
BOOLEAN IsHexNotation(string s) {
BOOLEAN IsAnyThing = FALSE;
@ -128,6 +170,12 @@ BOOLEAN IsHexNotation(string s) {
return FALSE;
}
/**
* @brief converts hex to bytes
*
* @param hex
* @return vector<char>
*/
vector<char> HexToBytes(const string &hex) {
vector<char> Bytes;
@ -141,6 +189,13 @@ vector<char> HexToBytes(const string &hex) {
return Bytes;
}
/**
* @brief check and convert string to a 64 bit unsigned it and also
* check for special notations like 0x etc.
* @param TextToConvert the target string
* @param Result result will be save to the pointer
* @return BOOLEAN shows whether the conversion was successful or not
*/
BOOLEAN ConvertStringToUInt64(string TextToConvert, PUINT64 Result) {
if (TextToConvert.rfind("0x", 0) == 0 || TextToConvert.rfind("0X", 0) == 0 ||
@ -170,6 +225,13 @@ BOOLEAN ConvertStringToUInt64(string TextToConvert, PUINT64 Result) {
}
}
/**
* @brief check and convert string to a 32 bit unsigned it and also
* check for special notations like 0x etc.
* @param TextToConvert the target string
* @param Result result will be save to the pointer
* @return BOOLEAN shows whether the conversion was successful or not
*/
BOOLEAN ConvertStringToUInt32(string TextToConvert, PUINT32 Result) {
if (TextToConvert.rfind("0x", 0) == 0 || TextToConvert.rfind("0X", 0) == 0 ||
@ -196,6 +258,14 @@ BOOLEAN ConvertStringToUInt32(string TextToConvert, PUINT32 Result) {
*Result = TempResult;
}
/**
* @brief checks whether the string ends with a special string or not
*
* @param fullString
* @param ending
* @return BOOLEAN if true then it shows that string ends with another string
* and if false then it shows that this string is not ended with the target string
*/
BOOLEAN HasEnding(string const &fullString, string const &ending) {
if (fullString.length() >= ending.length()) {
@ -206,9 +276,12 @@ BOOLEAN HasEnding(string const &fullString, string const &ending) {
}
}
//
// Function to validate an IP address
//
/**
* @brief Function to validate an IP address
*
* @param ip
* @return BOOLEAN
*/
BOOLEAN ValidateIP(string ip) {
//
@ -238,7 +311,7 @@ BOOLEAN ValidateIP(string ip) {
}
/**
* @brief Detect VMX support
* @brief Detect whether the VMX is supported or not
*
* @return true if vmx is supported
* @return false if vmx is not supported
@ -258,48 +331,73 @@ BOOLEAN VmxSupportDetection() {
* @param bEnablePrivilege
* @return BOOL
*/
BOOLEAN SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege,
BOOL bEnablePrivilege) {
BOOL SetPrivilege(HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
) {
TOKEN_PRIVILEGES tp;
LUID luid;
BOOLEAN bRet = FALSE;
if (LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) {
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = (bEnablePrivilege) ? SE_PRIVILEGE_ENABLED : 0;
//
// Enable the privilege or disable all privileges.
//
if (AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL)) {
//
// Check to see if you have proper access.
// You may get "ERROR_NOT_ALL_ASSIGNED".
//
bRet = (GetLastError() == ERROR_SUCCESS);
}
if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
ShowMessages("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
return bRet;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
//
// Enable the privilege or disable all privileges.
//
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
ShowMessages("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
ShowMessages("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
// trim from start (in place)
static inline void ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
/**
* @brief trim from start of string (in place)
*
* @param s
*/
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
[](int ch) { return !std::isspace(ch); }));
}
// trim from end (in place)
static inline void rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
/**
* @brief trim from the end of string (in place)
*
* @param s
*/
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
[](int ch) { return !std::isspace(ch); })
.base(),
s.end());
}
// trim from both ends (in place)
void Trim(std::string& s) {
ltrim(s);
rtrim(s);
}
/**
* @brief trim from both ends and start of a string (in place)
*
* @param s
*/
void Trim(std::string &s) {
ltrim(s);
rtrim(s);
}

View file

@ -13,7 +13,7 @@
#pragma once
//////////////////////////////////////////////////
// Functions //
// Functions //
//////////////////////////////////////////////////
VOID PrintBits(size_t const size, void const *const ptr);
@ -40,17 +40,21 @@ BOOLEAN ValidateIP(string ip);
BOOLEAN VmxSupportDetection();
BOOLEAN SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege);
BOOL SetPrivilege(HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
);
void Trim(std::string& s);
void Trim(std::string &s);
//////////////////////////////////////////////////
// Structures //
// Structures //
//////////////////////////////////////////////////
//
// These structures are copied from Process Hacker source code (ntldr.h)
//
/**
* @brief this structure is copied from Process Hacker source code (ntldr.h)
*
*/
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
@ -64,6 +68,11 @@ typedef struct _RTL_PROCESS_MODULE_INFORMATION {
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
/**
* @brief this structure is copied from Process Hacker source code (ntldr.h)
*
*/
typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];

View file

@ -0,0 +1,60 @@
/**
* @file tcpcommunication.h
* @author Sina Karvandi (sina@rayanfam.com)
* @brief Communication over TCP (header)
* @details
* @version 0.1
* @date 2020-08-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#pragma once
//////////////////////////////////////////
// Server //
//////////////////////////////////////////
int CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
SOCKET *ClientSocketArg,
SOCKET *ListenSocketArg);
int CommunicationServerReceiveMessage(SOCKET ClientSocket, char *recvbuf,
int recvbuflen);
int CommunicationServerSendMessage(SOCKET ClientSocket, const char *sendbuf,
int length);
int CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket,
SOCKET ListenSocket);
//////////////////////////////////////////
// Client //
//////////////////////////////////////////
int CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port,
SOCKET *ConnectSocketArg);
int CommunicationClientSendMessage(SOCKET ConnectSocket, const char *sendbuf,
int buflen);
int CommunicationClientShutdownConnection(SOCKET ConnectSocket);
int CommunicationClientReceiveMessage(SOCKET ConnectSocket, char *recvbuf,
int recvbuflen);
int CommunicationClientCleanup(SOCKET ConnectSocket);
//////////////////////////////////////////
// Handle Remote Connection //
//////////////////////////////////////////
VOID RemoteConnectionListen(PCSTR Port);
VOID RemoteConnectionConnect(PCSTR Ip, PCSTR Port);
int RemoteConnectionSendCommand(const char *sendbuf, int len);
int RemoteConnectionSendResultsToHost(const char *sendbuf, int len);
int RemoteConnectionCloseTheConnectionWithDebuggee();

View file

@ -17,11 +17,20 @@
#include "globals.h"
//
// Global Variables
// Extern global Variables
//
extern BOOLEAN g_IsConnectedToDebugger;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsDebuggerModulesLoaded;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern BOOLEAN g_IsConnectedToRemoteDebugger;
extern string g_ServerPort;
extern string g_ServerIp;
/**
* @brief help of .connect command
*
* @return VOID
*/
VOID CommandConnectHelp() {
ShowMessages(".connect : connects to a remote or local machine to start "
"debugging.\n\n");
@ -30,11 +39,24 @@ VOID CommandConnectHelp() {
ShowMessages("\t\te.g : .connect local\n");
}
/**
* @brief .connect command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandConnect(vector<string> SplittedCommand) {
string ip;
string port;
if (g_IsConnectedToHyperDbgLocally || g_IsConnectedToRemoteDebuggee ||
g_IsConnectedToRemoteDebugger) {
ShowMessages("you're connected to a debugger, please use '.disconnect' "
"command.\n");
return;
}
if (SplittedCommand.size() == 1) {
//
@ -50,14 +72,17 @@ VOID CommandConnect(vector<string> SplittedCommand) {
//
// connect to local debugger
//
ShowMessages("local debug current system\n");
g_IsConnectedToDebugger = TRUE;
ShowMessages("local debuging current system...\n");
g_IsConnectedToHyperDbgLocally = TRUE;
return;
} else if (SplittedCommand.size() == 3) {
} else if (SplittedCommand.size() == 3 || SplittedCommand.size() == 2) {
ip = SplittedCommand.at(1);
port = SplittedCommand.at(2);
if (SplittedCommand.size() == 3) {
port = SplittedCommand.at(2);
}
//
// means that probably wants to connect to a remote
@ -68,18 +93,30 @@ VOID CommandConnect(vector<string> SplittedCommand) {
ShowMessages("incorrect ip address\n");
return;
}
if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) {
ShowMessages("incorrect port\n");
return;
if (SplittedCommand.size() == 3) {
if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) {
ShowMessages("incorrect port\n");
return;
}
//
// connect to remote debugger
//
g_ServerIp = ip;
g_ServerPort = port;
RemoteConnectionConnect(ip.c_str(), port.c_str());
} else {
//
// connect to remote debugger (default port)
//
g_ServerIp = ip;
g_ServerPort = DEFAULT_PORT;
RemoteConnectionConnect(ip.c_str(), DEFAULT_PORT);
}
//
// connect to remote debugger
//
ShowMessages("local debug remote system\n");
g_IsConnectedToDebugger = TRUE;
return;
} else {
ShowMessages("incorrect use of '.connect'\n\n");
CommandConnectHelp();

View file

@ -11,10 +11,22 @@
*/
#include "pch.h"
/**
* @brief help of cpu command
*
* @return VOID
*/
VOID CommandCpuHelp() {
ShowMessages("cpu : collects a report from cpu features.\n\n");
ShowMessages("syntax : \tcpu\n");
}
/**
* @brief cpu command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandCpu(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
@ -26,11 +38,17 @@ VOID CommandCpu(vector<string> SplittedCommand) {
}
class InstructionSet {
//
// forward declarations
//
class InstructionSet_Internal;
public:
//
// getters
//
static std::string Vendor(void) { return CPU_Rep.vendor_; }
static std::string Brand(void) { return CPU_Rep.brand_; }
@ -108,8 +126,10 @@ private:
// int cpuInfo[4] = {-1};
std::array<int, 4> cpui;
//
// Calling __cpuid with 0x0 as the function_id argument
// gets the number of the highest valid function ID.
//
__cpuid(cpui.data(), 0);
nIds_ = cpui[0];
@ -118,7 +138,9 @@ private:
data_.push_back(cpui);
}
//
// Capture vendor string
//
char vendor[0x20];
memset(vendor, 0, sizeof(vendor));
*reinterpret_cast<int *>(vendor) = data_[0][1];
@ -131,20 +153,26 @@ private:
isAMD_ = true;
}
//
// load bitset with flags for function 0x00000001
//
if (nIds_ >= 1) {
f_1_ECX_ = data_[1][2];
f_1_EDX_ = data_[1][3];
}
//
// load bitset with flags for function 0x00000007
//
if (nIds_ >= 7) {
f_7_EBX_ = data_[7][1];
f_7_ECX_ = data_[7][2];
}
//
// Calling __cpuid with 0x80000000 as the function_id argument
// gets the number of the highest valid extended ID.
//
__cpuid(cpui.data(), 0x80000000);
nExIds_ = cpui[0];
@ -156,13 +184,16 @@ private:
extdata_.push_back(cpui);
}
//
// load bitset with flags for function 0x80000001
//
if (nExIds_ >= 0x80000001) {
f_81_ECX_ = extdata_[1][2];
f_81_EDX_ = extdata_[1][3];
}
//
// Interpret CPU brand string if reported
//
if (nExIds_ >= 0x80000004) {
memcpy(brand, extdata_[2].data(), sizeof(cpui));
memcpy(brand + 16, extdata_[3].data(), sizeof(cpui));
@ -188,12 +219,16 @@ private:
};
};
//
// Initialize static member data
//
const InstructionSet::InstructionSet_Internal InstructionSet::CPU_Rep;
string ReadVendorString() { return InstructionSet::Vendor(); }
//
// Print out supported instruction set extensions
//
int ReadCpuDetails() {
auto &outstream = std::cout;

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !cpuid command
*
* @return VOID
*/
VOID CommandCpuidHelp() {
ShowMessages("!cpuid : Monitors execution of a special cpuid index or all "
"cpuids instructions.\n\n");
@ -24,6 +29,12 @@ VOID CommandCpuidHelp() {
ShowMessages("\t\te.g : !cpuid core 2 pid 400\n");
}
/**
* @brief !cpuid command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandCpuid(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -42,13 +53,36 @@ VOID CommandCpuid(vector<string> SplittedCommand) {
return;
}
//
// Check for size
//
if (SplittedCommand.size() > 1) {
ShowMessages("incorrect use of '!cpuid'\n");
CommandCpuidHelp();
return;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -1,7 +1,7 @@
/**
* @file d-u.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief !u u , !d* d* commands
* @brief !u* u* , !d* d* commands
* @details
* @version 0.1
* @date 2020-05-27
@ -11,14 +11,20 @@
*/
#include "pch.h"
VOID CommandReadMemoryHelp() {
ShowMessages("u !u & db dc dd dq !db !dc !dd !dq : read the memory different "
"shapes (hex) and disassembler\n");
/**
* @brief help of u* d* !u* !d* commands
*
* @return VOID
*/
VOID CommandReadMemoryAndDisassemblerHelp() {
ShowMessages("u !u u2 !u2 & 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("u Disassembler at the target address (x64) \n");
ShowMessages("u2 Disassembler at the target address (x86) \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");
@ -30,6 +36,12 @@ VOID CommandReadMemoryHelp() {
ShowMessages("\t\te.g : u fffff8077356f010\n");
}
/**
* @brief u* d* !u* !d* commands handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
UINT32 Pid = 0;
@ -42,12 +54,13 @@ VOID CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
string FirstCommand = SplittedCommand.front();
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();
CommandReadMemoryAndDisassemblerHelp();
return;
}
@ -104,7 +117,7 @@ VOID CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
//
ShowMessages("Err, incorrect use of '%s' command\n\n",
FirstCommand.c_str());
CommandReadMemoryHelp();
CommandReadMemoryAndDisassemblerHelp();
return;
}
@ -129,7 +142,7 @@ VOID CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
}
if (IsNextLength || IsNextProcessId) {
ShowMessages("incorrect use of '%s' command\n\n", FirstCommand.c_str());
CommandReadMemoryHelp();
CommandReadMemoryAndDisassemblerHelp();
return;
}
if (Pid == 0) {
@ -176,15 +189,23 @@ VOID CommandReadMemoryAndDisassembler(vector<string> SplittedCommand) {
}
//
// Disassembler (!u or u)
// Disassembler (!u or u or u2 !u2)
//
else if (!FirstCommand.compare("u")) {
HyperDbgReadMemoryAndDisassemble(
DEBUGGER_SHOW_COMMAND_DISASSEMBLE, TargetAddress,
DEBUGGER_SHOW_COMMAND_DISASSEMBLE64, TargetAddress,
DEBUGGER_READ_VIRTUAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
} else if (!FirstCommand.compare("!u")) {
HyperDbgReadMemoryAndDisassemble(
DEBUGGER_SHOW_COMMAND_DISASSEMBLE, TargetAddress,
DEBUGGER_SHOW_COMMAND_DISASSEMBLE64, TargetAddress,
DEBUGGER_READ_PHYSICAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
} else if (!FirstCommand.compare("u2")) {
HyperDbgReadMemoryAndDisassemble(
DEBUGGER_SHOW_COMMAND_DISASSEMBLE32, TargetAddress,
DEBUGGER_READ_VIRTUAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
} else if (!FirstCommand.compare("!u2")) {
HyperDbgReadMemoryAndDisassemble(
DEBUGGER_SHOW_COMMAND_DISASSEMBLE32, TargetAddress,
DEBUGGER_READ_PHYSICAL_ADDRESS, READ_FROM_KERNEL, Pid, Length);
}
}

View file

@ -17,14 +17,144 @@
extern UINT64 g_EventTag;
extern LIST_ENTRY g_EventTrace;
extern BOOLEAN g_EventTraceInitialized;
extern BOOLEAN g_BreakPrintingOutput;
extern BOOLEAN g_AutoUnpause;
/**
* @brief shows the error message
*
* @param Error
* @return BOOLEAN
*/
BOOLEAN
ShowErrorMessage(UINT32 Error) {
switch (Error) {
case DEBUGEER_ERROR_TAG_NOT_EXISTS:
ShowMessages("err, tag not found (%x)\n", Error);
break;
case DEBUGEER_ERROR_INVALID_ACTION_TYPE:
ShowMessages("err, invalid action type (%x)\n", Error);
break;
case DEBUGEER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO:
ShowMessages("err, action buffer size is zero (%x)\n", Error);
break;
case DEBUGEER_ERROR_EVENT_TYPE_IS_INVALID:
ShowMessages("err, event type is invalid (%x)\n", Error);
break;
case DEBUGEER_ERROR_UNABLE_TO_CREATE_EVENT:
ShowMessages("err, unable to create event (%x)\n", Error);
break;
case DEBUGEER_ERROR_INVALID_ADDRESS:
ShowMessages("err, invalid address (%x)\n", Error);
break;
case DEBUGEER_ERROR_INVALID_CORE_ID:
ShowMessages("err, invalid core id (%x)\n", Error);
break;
case DEBUGEER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES:
ShowMessages("err, exception index exceed first 32 entries (%x)\n", Error);
break;
case DEBUGEER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID:
ShowMessages("err, interrupt index is not valid (%x)\n", Error);
break;
case DEBUGEER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER:
ShowMessages("err, unable to hide or unhide debugger (%x)\n", Error);
break;
case DEBUGEER_ERROR_DEBUGGER_ALREADY_UHIDE:
ShowMessages("err, debugger already unhide (%x)\n", Error);
break;
case DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER:
ShowMessages("err, edit memeory request has invalid parameters (%x)\n",
Error);
break;
case DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS:
ShowMessages("err, edit memory request has invalid address based on "
"current process layout (%x)\n",
Error);
break;
case DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS:
ShowMessages("err, edit memory request has invalid address based on other "
"process layout (%x)\n",
Error);
break;
case DEBUGGER_ERROR_DEBUGGER_MODIFY_EVENTS_INVALID_TAG:
ShowMessages("err, modify event with invalid tag (%x)\n", Error);
break;
case DEBUGGER_ERROR_DEBUGGER_MODIFY_EVENTS_INVALID_TYPE_OF_ACTION:
ShowMessages("err, modify event with invalid type of action (%x)\n", Error);
break;
default:
ShowMessages("err, error not found (%x)\n", Error);
return FALSE;
break;
}
return TRUE;
}
/**
* @brief Check whether the tag exists or not, if the tag is
* DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG then if we find just one event, it
* also means that the tag is found
*
* @param Tag
* @return BOOLEAN
*/
BOOLEAN IsTagExist(UINT64 Tag) {
PLIST_ENTRY TempList = 0;
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail = {0};
if (!g_EventTraceInitialized) {
return FALSE;
}
TempList = &g_EventTrace;
while (&g_EventTrace != TempList->Blink) {
TempList = TempList->Blink;
CommandDetail = CONTAINING_RECORD(TempList, DEBUGGER_GENERAL_EVENT_DETAIL,
CommandsEventList);
if (CommandDetail->Tag == Tag ||
Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
return TRUE;
}
}
//
// Not found
//
return FALSE;
}
/**
* @brief Interpret conditions (if an event has condition) and custom code
* @details If this function returns true then it means that there is a condtion
* or code buffer in this command split and the details are returned in the
* input structure
*
* @param SplittedCommand All the commands
*
* @param SplittedCommand the initialized command that are splitted by space
* @param IsConditionBuffer is it a condition buffer or a custom code buffer
* @param BufferAddrss the address that the allocated buffer will be saved on it
* @param BufferLength the length of the buffer
* @return BOOLEAN shows whether the interpret was successful (true) or not
* successful (false)
*/
BOOLEAN
InterpretConditionsAndCodes(vector<string> *SplittedCommand,
@ -93,6 +223,7 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
}
if (IsTextVisited && !Section.compare("{")) {
//
// Save to remove this string from the command
//
@ -103,6 +234,7 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
}
if (IsTextVisited && Section.rfind("{", 0) == 0) {
//
// Section starts with {
//
@ -123,6 +255,7 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
IsEnded = TRUE;
break;
}
//
// Save to remove this string from the command
//
@ -146,6 +279,7 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
continue;
}
} else {
//
// It's code
//
@ -174,6 +308,7 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
continue;
}
} else {
//
// It's code
//
@ -202,12 +337,14 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
IsInState = TRUE;
if (!HasEnding(Section, "}")) {
//
// Section starts with condition{
//
SaveBuffer.push_back(Section.erase(0, 10));
continue;
} else {
//
// remove the last character and first character append it to the
// ConditionBuffer
@ -235,12 +372,14 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
IsInState = TRUE;
if (!HasEnding(Section, "}")) {
//
// Section starts with condition{
//
SaveBuffer.push_back(Section.erase(0, 5));
continue;
} else {
//
// remove the last character and first character append it to the
// ConditionBuffer
@ -348,11 +487,17 @@ InterpretConditionsAndCodes(vector<string> *SplittedCommand,
SplittedCommand->erase(SplittedCommand->begin() +
(IndexToRemove - NewIndexToRemove));
}
return TRUE;
}
/**
* @brief Register the event to the kernel
*
* @param Event the event structure to send
* @param EventBufferLength the buffer length of event
* @return BOOLEAN if the request was successful then true
* if the request was not successful then false
*/
BOOLEAN
SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
@ -380,7 +525,8 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
*/
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return FALSE;
}
@ -405,17 +551,58 @@ SendEventToKernel(PDEBUGGER_GENERAL_EVENT_DETAIL Event,
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return FALSE;
}
if (ReturnedBuffer.IsSuccessful && ReturnedBuffer.Error == 0) {
//
// The returned buffer shows that this event was
// successful and now we can add it to the list of
// events
//
InsertHeadList(&g_EventTrace, &(Event->CommandsEventList));
//
// Check for auto-unpause mode
//
if (g_BreakPrintingOutput && g_AutoUnpause) {
//
// Allow debugger to show its contents
//
ShowMessages("\n");
g_BreakPrintingOutput = FALSE;
}
} else {
//
// It was not successful, we have to free the buffers for command
// string and buffer for the event itself
//
free(Event->CommandStringBuffer);
free(Event);
//
// Show the error
//
if (ReturnedBuffer.Error != 0) {
ShowErrorMessage(ReturnedBuffer.Error);
}
}
return TRUE;
}
/**
* @brief Register the action to the event
*
* @param Action the action buffer structure
* @param ActionsBufferLength length of action buffer
* @return BOOLEAN BOOLEAN if the request was successful then true
* if the request was not successful then false
*/
BOOLEAN
RegisterActionToEvent(PDEBUGGER_GENERAL_ACTION Action,
UINT32 ActionsBufferLength) {
@ -435,7 +622,8 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_ACTION Action,
*/
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return FALSE;
}
@ -459,21 +647,42 @@ RegisterActionToEvent(PDEBUGGER_GENERAL_ACTION Action,
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return FALSE;
}
//
// The action buffer is allocated once using malloc and
// is not used anymore, we have to free it
//
free(Action);
return TRUE;
}
/**
* @brief Get the New Debugger Event Tag object and increase the
* global variable for tag
*
* @return UINT64
*/
UINT64 GetNewDebuggerEventTag() { return g_EventTag++; }
/**
* @brief Interpret general event fields
* @details If this function returns true then it means that there
*
* @param SplittedCommand the commands that was splitted by space
* @param EventType type of event
* @param EventDetailsToFill a pointer address that will be filled
* by event detail buffer
* @param EventBufferLength a pointer the receives the buffer length
* of the event
* @param ActionDetailsToFill a pointer address that will be filled
* by action detail buffer
* @param ActionBufferLength a pointer the receives the buffer length
* of the action
* @return BOOLEAN If this function returns true then it means that there
* was no error in parsing the general event details
*
* @param SplittedCommand All the commands
*/
BOOLEAN InterpretGeneralEventAndActionsFields(
vector<string> *SplittedCommand, DEBUGGER_EVENT_TYPE_ENUM EventType,
@ -548,6 +757,7 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
HasConditionBuffer = TRUE;
/*
ShowMessages(
"\n========================= Condition =========================\n");
@ -558,13 +768,14 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
// Disassemble the buffer
//
HyperDbgDisassembler((unsigned char *)ConditionBufferAddress, 0x0,
ConditionBufferLength);
HyperDbgDisassembler64((unsigned char *)ConditionBufferAddress, 0x0,
ConditionBufferLength);
ShowMessages("}\n\n");
ShowMessages(
"=============================================================\n");
*/
}
//
@ -587,6 +798,7 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
HasCodeBuffer = TRUE;
/*
ShowMessages(
"\n========================= Code =========================\n");
ShowMessages("\nPVOID DebuggerRunCustomCodeFunc(PVOID "
@ -596,13 +808,14 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
// Disassemble the buffer
//
HyperDbgDisassembler((unsigned char *)CodeBufferAddress, 0x0,
CodeBufferLength);
HyperDbgDisassembler64((unsigned char *)CodeBufferAddress, 0x0,
CodeBufferLength);
ShowMessages("}\n\n");
ShowMessages(
"=============================================================\n");
*/
}
//
@ -649,6 +862,7 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
// The heap is not available
//
free(BufferOfCommandString);
return FALSE;
}
@ -700,7 +914,8 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
}
//
// Allocate the Action
// Allocate the Action (THIS ACTION BUFFER WILL BE FREED WHEN WE SENT IT TO
// THE KERNEL AND RETURNED FROM THE KERNEL AS WE DON'T NEED IT ANYMORE)
//
UINT32 LengthOfActionBuffer =
sizeof(DEBUGGER_GENERAL_ACTION) + CodeBufferLength;
@ -739,7 +954,6 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
// Interpret rest of the command
//
for (auto Section : *SplittedCommand) {
Index++;
if (IsNextCommandBufferSize) {
@ -747,6 +961,7 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
if (!ConvertStringToUInt32(Section, &RequestBuffer)) {
return FALSE;
} else {
//
// Set the specific requested buffer size
//
@ -764,8 +979,12 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
if (IsNextCommandPid) {
if (!ConvertStringToUInt32(Section, &ProcessId)) {
free(BufferOfCommandString);
free(TempEvent);
free(TempAction);
return FALSE;
} else {
//
// Set the specific process id
//
@ -782,8 +1001,12 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
}
if (IsNextCommandCoreId) {
if (!ConvertStringToUInt32(Section, &CoreId)) {
free(BufferOfCommandString);
free(TempEvent);
free(TempAction);
return FALSE;
} else {
//
// Set the specific core id
//
@ -836,14 +1059,23 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
if (IsNextCommandCoreId) {
ShowMessages("error : please specify a value for 'core'\n\n");
free(BufferOfCommandString);
free(TempEvent);
free(TempAction);
return FALSE;
}
if (IsNextCommandPid) {
ShowMessages("error : please specify a value for 'pid'\n\n");
free(BufferOfCommandString);
free(TempEvent);
free(TempAction);
return FALSE;
}
if (IsNextCommandBufferSize) {
ShowMessages("errlr : please specify a value for 'buffer'\n\n");
free(BufferOfCommandString);
free(TempEvent);
free(TempAction);
return FALSE;
}
@ -878,8 +1110,11 @@ BOOLEAN InterpretGeneralEventAndActionsFields(
//
// Add the event to the trace list
// UPDATE : if we add it here, then if the event was not
// successful then still the event shows this event, so
// we have to add it lated
//
InsertHeadList(&g_EventTrace, &(TempEvent->CommandsEventList));
// InsertHeadList(&g_EventTrace, &(TempEvent->CommandsEventList));
//
// Everything is ok, let's return TRUE

View file

@ -15,6 +15,11 @@
// Functions //
//////////////////////////////////////////////////
BOOLEAN
ShowErrorMessage(UINT32 Error);
BOOLEAN IsTagExist(UINT64 Tag);
BOOLEAN
InterpretConditionsAndCodes(vector<string> *SplittedCommand,
BOOLEAN IsConditionBuffer, PUINT64 BufferAddrss,
@ -38,4 +43,13 @@ UINT64 GetNewDebuggerEventTag();
VOID LogopenSaveToFile(const char *Text);
BOOL WINAPI BreakController(DWORD CtrlType);
BOOL BreakController(DWORD CtrlType);
VOID CommandEventsShowEvents();
VOID CommandEventsModifyEvents(UINT64 Tag,
DEBUGGER_MODIFY_EVENTS_TYPE TypeOfAction);
VOID CommandFlushRequestFlush();
BOOLEAN IsItALocalCommand(string Command);

View file

@ -0,0 +1,90 @@
/**
* @file detach.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief .detach command
* @details
* @version 0.1
* @date 2020-08-28
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsAttachedToUsermodeProcess;
/**
* @brief help of .detach command
*
* @return VOID
*/
VOID CommandDetachHelp() {
ShowMessages(".detach : detach from debugging a user-mode process.\n\n");
ShowMessages("syntax : \t.detach\n");
}
/**
* @brief .detach command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID CommandDetach(vector<string> SplittedCommand) {
BOOLEAN Status;
ULONG ReturnedLength;
DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest = {0};
if (SplittedCommand.size() >= 2) {
ShowMessages("incorrect use of '.detach'\n\n");
CommandDetachHelp();
return;
}
//
// Check if debugger is loaded or not
//
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
//
// We wanna attach to a remote process
//
DetachRequest.IsAttach = FALSE;
//
// Send the request to the kernel
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // IO Control
// code
&DetachRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // Input buffer length
&DetachRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS, // 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;
}
//
// Check if attaching was successful then we can set the attached to true
//
if (DetachRequest.Result == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
g_IsAttachedToUsermodeProcess = FALSE;
}
}

View file

@ -38,6 +38,11 @@ all
#pragma comment(lib, "Zydis.lib")
#pragma comment(lib, "Zycore.lib")
//
// Global Variables
//
extern UINT32 g_DisassemblerSyntax;
/* ==============================================================================================
*/
/* Enums and Types */
@ -80,6 +85,14 @@ static const ZydisSymbol SYMBOL_TABLE[3] = {
ZydisFormatterFunc default_print_address_absolute;
/**
* @brief Print addresses
*
* @param formatter
* @param buffer
* @param context
* @return ZyanStatus
*/
static ZyanStatus
ZydisFormatterPrintAddressAbsolute(const ZydisFormatter *formatter,
ZydisFormatterBuffer *buffer,
@ -106,17 +119,38 @@ ZydisFormatterPrintAddressAbsolute(const ZydisFormatter *formatter,
/* ==============================================================================================
*/
/**
* @brief Disassemble a user-mode buffer
*
* @param decoder
* @param runtime_address
* @param data
* @param length
*/
void DisassembleBuffer(ZydisDecoder *decoder, ZyanU64 runtime_address,
ZyanU8 *data, ZyanUSize length) {
ZydisFormatter formatter;
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
if (g_DisassemblerSyntax == 1) {
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
} else if (g_DisassemblerSyntax == 2) {
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_ATT);
} else if (g_DisassemblerSyntax == 3) {
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL_MASM);
} else {
ShowMessages("err, in selecting disassembler syntax\n");
return;
}
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SEGMENT,
ZYAN_TRUE);
ZydisFormatterSetProperty(&formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE,
ZYAN_TRUE);
//
// Replace the `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function that formats
// the absolute addresses
//
default_print_address_absolute =
(ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute;
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS,
@ -129,8 +163,10 @@ void DisassembleBuffer(ZydisDecoder *decoder, ZyanU64 runtime_address,
// ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
ShowMessages("%s", SeparateTo64BitValue(runtime_address).c_str());
//
// We have to pass a `runtime_address` different to
// `ZYDIS_RUNTIME_ADDRESS_NONE` to enable printing of absolute addresses
//
ZydisFormatterFormatInstruction(&formatter, &instruction, &buffer[0],
sizeof(buffer), runtime_address);
@ -164,6 +200,11 @@ void DisassembleBuffer(ZydisDecoder *decoder, ZyanU64 runtime_address,
/* ==============================================================================================
*/
/**
* @brief Zydis test
*
* @return int
*/
int ZydisTest() {
if (ZydisGetVersion() != ZYDIS_VERSION) {
fputs("Invalid zydis version\n", ZYAN_STDERR);
@ -200,8 +241,16 @@ int ZydisTest() {
/* ==============================================================================================
*/
int HyperDbgDisassembler(unsigned char *BufferToDisassemble, UINT64 BaseAddress,
UINT64 Size) {
/**
* @brief Disassemble x64 assemblies
*
* @param BufferToDisassemble buffer to disassemble
* @param BaseAddress the base address of assembly
* @param Size size of byffer
* @return int
*/
int HyperDbgDisassembler64(unsigned char *BufferToDisassemble,
UINT64 BaseAddress, UINT64 Size) {
if (ZydisGetVersion() != ZYDIS_VERSION) {
fputs("Invalid zydis version\n", ZYAN_STDERR);
return EXIT_FAILURE;
@ -216,5 +265,30 @@ int HyperDbgDisassembler(unsigned char *BufferToDisassemble, UINT64 BaseAddress,
return 0;
}
/**
* @brief Disassemble 32 bit assemblies
*
* @param BufferToDisassemble buffer to disassemble
* @param BaseAddress the base address of assembly
* @param Size size of byffer
* @return int
*/
int HyperDbgDisassembler32(unsigned char *BufferToDisassemble,
UINT64 BaseAddress, UINT64 Size) {
if (ZydisGetVersion() != ZYDIS_VERSION) {
fputs("Invalid zydis version\n", ZYAN_STDERR);
return EXIT_FAILURE;
}
ZydisDecoder decoder;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32,
ZYDIS_ADDRESS_WIDTH_32);
DisassembleBuffer(&decoder, (UINT32)BaseAddress, &BufferToDisassemble[0],
Size);
return 0;
}
/* ==============================================================================================
*/

View file

@ -14,14 +14,27 @@
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToDebugger;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern HANDLE g_RemoteDebuggeeListeningThread;
/**
* @brief help of .disconnect command
*
* @return VOID
*/
VOID CommandDisconnectHelp() {
ShowMessages(".disconnect : disconnect from a debugging session (it won't "
"unload the modules).\n\n");
ShowMessages("syntax : \.disconnect\n");
ShowMessages("syntax : \t.disconnect\n");
}
/**
* @brief .disconnect command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandDisconnect(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
@ -29,14 +42,33 @@ VOID CommandDisconnect(vector<string> SplittedCommand) {
CommandDisconnectHelp();
return;
}
if (!g_IsConnectedToDebugger) {
if (!g_IsConnectedToHyperDbgLocally && !g_IsConnectedToRemoteDebuggee) {
ShowMessages("you're not connected to any instance of HyperDbg, did you "
"use '.connect'? \n");
return;
}
//
// Disconnect the session
//
g_IsConnectedToDebugger = FALSE;
g_IsConnectedToHyperDbgLocally = FALSE;
//
// This computer is connected to a remote system
//
if (g_IsConnectedToRemoteDebuggee) {
//
// We should kill the thread that was listening for the
// remote commands and close the connection
//
TerminateThread(g_RemoteDebuggeeListeningThread, 0);
CloseHandle(g_RemoteDebuggeeListeningThread);
RemoteConnectionCloseTheConnectionWithDebuggee();
g_IsConnectedToRemoteDebuggee = FALSE;
}
ShowMessages("successfully disconnected\n");
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !dr command
*
* @return VOID
*/
VOID CommandDrHelp() {
ShowMessages("!dr : Monitors any access to debug registers.\n\n");
ShowMessages("syntax : \t!dr core [core index "
@ -23,6 +28,12 @@ VOID CommandDrHelp() {
ShowMessages("\t\te.g : !dr core 2 pid 400\n");
}
/**
* @brief !dr command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandDr(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -41,13 +52,36 @@ VOID CommandDr(vector<string> SplittedCommand) {
return;
}
//
// Check for size
//
if (SplittedCommand.size() > 1) {
ShowMessages("incorrect use of '!dr'\n");
CommandDrHelp();
return;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !e* and e* commands
*
* @return VOID
*/
VOID CommandEditMemoryHelp() {
ShowMessages("eb !eb ed !ed eq !eq : edit the memory at specific address \n");
ShowMessages("e[b] Byte and ASCII characters\n");
@ -28,6 +33,12 @@ VOID CommandEditMemoryHelp() {
"9090909090909090 9090909090909090 9090909090909090\n");
}
/**
* @brief !e* and e* commands handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandEditMemory(vector<string> SplittedCommand) {
BOOL Status;
@ -216,7 +227,8 @@ VOID CommandEditMemory(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -268,26 +280,34 @@ VOID CommandEditMemory(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
free(FinalBuffer);
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}
if (EditMemoryRequest.Result == DEBUGGER_EDIT_MEMORY_STATUS_SUCCESS) {
if (EditMemoryRequest.Result == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
//
// Was successful, nothing to do
//
} else if (
EditMemoryRequest.Result ==
DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS) {
DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS) {
ShowMessages("the address is invalid in current process id\n");
} else if (
EditMemoryRequest.Result ==
DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS) {
DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS) {
ShowMessages("the address is invalid based on your specific process id\n");
} else if (EditMemoryRequest.Result ==
DEBUGGER_EDIT_MEMORY_STATUS_INVALID_PARAMETER) {
DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER) {
ShowMessages("invalid parameter\n");
} else {
ShowMessages("unknown response from driver\n");
}
//
// Free the malloc buffer
//
free(FinalBuffer);
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief test !monitor command
*
* @return BOOLEAN
*/
BOOLEAN TestMonitorCommand() {
printf("Test monitor command... \n");
@ -22,6 +27,7 @@ BOOLEAN TestMonitorCommand() {
for (size_t i = 0; i < LONG_MAX; i++) {
Sleep(1000);
}
free(Address);
return FALSE;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !epthook command
*
* @return VOID
*/
VOID CommandEptHookHelp() {
ShowMessages("!epthook : Puts a hidden-hook EPT (hidden breakpoints) .\n\n");
ShowMessages(
@ -24,6 +29,12 @@ VOID CommandEptHookHelp() {
ShowMessages("\t\te.g : !epthook fffff801deadb000 core 2 pid 400\n");
}
/**
* @brief !epthook command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandEptHook(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -73,7 +84,7 @@ VOID CommandEptHook(vector<string> SplittedCommand) {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandEptHookHelp();
return;
}
@ -92,10 +103,24 @@ VOID CommandEptHook(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !epthook2 command
*
* @return VOID
*/
VOID CommandEptHook2Help() {
ShowMessages("!epthook2 : Puts a hidden-hook EPT (detours) .\n\n");
ShowMessages(
@ -24,6 +29,12 @@ VOID CommandEptHook2Help() {
ShowMessages("\t\te.g : !epthook2 fffff801deadb000 core 2 pid 400\n");
}
/**
* @brief !epthook2 command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandEptHook2(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -42,7 +53,6 @@ VOID CommandEptHook2(vector<string> SplittedCommand) {
//
// Interpret and fill the general event and action fields
//
if (!InterpretGeneralEventAndActionsFields(
&SplittedCommand, HIDDEN_HOOK_EXEC_DETOURS, &Event, &EventLength,
&Action, &ActionLength)) {
@ -57,10 +67,12 @@ VOID CommandEptHook2(vector<string> SplittedCommand) {
if (!Section.compare("!epthook2")) {
continue;
} else if (!GetAddress) {
//
// It's probably address
//
if (!ConvertStringToUInt64(Section, &OptionalParam1)) {
//
// Unkonwn parameter
//
@ -71,10 +83,11 @@ VOID CommandEptHook2(vector<string> SplittedCommand) {
GetAddress = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandEptHook2Help();
return;
}
@ -92,10 +105,24 @@ VOID CommandEptHook2(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -16,27 +16,123 @@
//
extern LIST_ENTRY g_EventTrace;
extern BOOLEAN g_EventTraceInitialized;
extern BOOLEAN g_BreakPrintingOutput;
extern BOOLEAN g_AutoFlush;
/**
* @brief help of events command
*
* @return VOID
*/
VOID CommandEventsHelp() {
ShowMessages("events : show active and disabled events\n");
ShowMessages("syntax : \tevents [e|d|c] [event number (hex value)]\n");
ShowMessages("syntax : \tevents [e|d|c] [event number (hex value) | all]\n");
ShowMessages("e : enable\n");
ShowMessages("d : disable\n");
ShowMessages("c : clear\n");
ShowMessages("Note : If you specify 'all' then [e|d|c] will be applied to "
"all of the events.\n\n");
ShowMessages("\t\te.g : events \n");
ShowMessages("\t\te.g : events e 12\n");
ShowMessages("\t\te.g : events d 10\n");
ShowMessages("\t\te.g : events c 10\n");
ShowMessages("\te.g : events \n");
ShowMessages("\te.g : events e 12\n");
ShowMessages("\te.g : events d 10\n");
ShowMessages("\te.g : events c 10\n");
}
/**
* @brief events command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandEvents(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail;
DEBUGGER_MODIFY_EVENTS_TYPE RequestedAction;
UINT64 RequestedTag;
if (!g_EventTraceInitialized) {
ShowMessages("no active/disabled events \n");
//
// Validate the parameters (size)
//
if (SplittedCommand.size() != 1 && SplittedCommand.size() != 3) {
ShowMessages("incorrect use of '%s'\n\n", SplittedCommand.at(0));
CommandEventsHelp();
return;
}
if (SplittedCommand.size() == 1) {
if (!g_EventTraceInitialized) {
ShowMessages("no active/disabled events \n");
return;
}
CommandEventsShowEvents();
//
// No need to continue any further
//
return;
}
//
// Validate second argument as it's not just a simple
// events without any parameter
//
if (!SplittedCommand.at(1).compare("e")) {
RequestedAction = DEBUGGER_MODIFY_EVENTS_ENABLE;
} else if (!SplittedCommand.at(1).compare("d")) {
RequestedAction = DEBUGGER_MODIFY_EVENTS_DISABLE;
} else if (!SplittedCommand.at(1).compare("c")) {
RequestedAction = DEBUGGER_MODIFY_EVENTS_CLEAR;
} else {
//
// unknown second command
//
ShowMessages("incorrect use of '%s'\n\n", SplittedCommand.at(0));
CommandEventsHelp();
return;
}
//
// Validate third argument as it's not just a simple
// events without any parameter
//
if (!SplittedCommand.at(2).compare("all")) {
RequestedTag = DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG;
} else if (!ConvertStringToUInt64(SplittedCommand.at(2), &RequestedTag)) {
ShowMessages(
"please specify a correct hex value for tag id (event number)\n\n");
CommandEventsHelp();
return;
}
//
// Send the request to the kernel, we add it to a constant
// that's because we want start tags from that constant
//
if (RequestedTag != DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
RequestedTag = RequestedTag + DebuggerEventTagStartSeed;
}
CommandEventsModifyEvents(RequestedTag, RequestedAction);
}
/**
* @brief print every active and disabled events
* @details this function will not show cleared events
* @return VOID
*/
VOID CommandEventsShowEvents() {
//
// It's an events without any argument so we have to show
// all the currently active events
//
PLIST_ENTRY TempList = 0;
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail = {0};
BOOLEAN IsThereAnyEvents = FALSE;
TempList = &g_EventTrace;
while (&g_EventTrace != TempList->Blink) {
TempList = TempList->Blink;
@ -44,56 +140,342 @@ VOID CommandEvents(vector<string> SplittedCommand) {
CommandDetail = CONTAINING_RECORD(TempList, DEBUGGER_GENERAL_EVENT_DETAIL,
CommandsEventList);
ShowMessages("%x\t(%s)\t %s\n", CommandDetail->Tag - 0x1000000,
ShowMessages("%x\t(%s)\t %s\n",
CommandDetail->Tag - DebuggerEventTagStartSeed,
CommandDetail->IsEnabled ? "enabled" : "disabled",
CommandDetail->CommandStringBuffer);
if (!IsThereAnyEvents) {
IsThereAnyEvents = TRUE;
}
}
if (!IsThereAnyEvents) {
ShowMessages("no active/disabled events \n");
}
}
VOID CommandEventsModifyEvents(UINT64 Tag) {
/**
* @brief Disable a special event
*
* @param Tag the tag of the target event
* @return BOOLEAN if the operation was successful then it returns
* true otherwise it returns false
*/
BOOLEAN CommandEventDisableEvent(UINT64 Tag) {
PLIST_ENTRY TempList = 0;
BOOLEAN Result = FALSE;
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail = {0};
TempList = &g_EventTrace;
while (&g_EventTrace != TempList->Blink) {
TempList = TempList->Blink;
CommandDetail = CONTAINING_RECORD(TempList, DEBUGGER_GENERAL_EVENT_DETAIL,
CommandsEventList);
if (CommandDetail->Tag == Tag ||
Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Put it to FALSE, to indicate that it's not active
//
CommandDetail->IsEnabled = FALSE;
if (!Result) {
Result = TRUE;
}
if (Tag != DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Only, one command exist with a tag, so we need to return as we
// find it
//
return TRUE;
}
}
}
//
// Not found
//
return Result;
}
/**
* @brief enables a special event
*
* @param Tag the tag of the target event
* @return BOOLEAN if the operation was successful then it returns
* true otherwise it returns false
*/
BOOLEAN CommandEventEnableEvent(UINT64 Tag) {
PLIST_ENTRY TempList = 0;
BOOLEAN Result = FALSE;
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail = {0};
TempList = &g_EventTrace;
while (&g_EventTrace != TempList->Blink) {
TempList = TempList->Blink;
CommandDetail = CONTAINING_RECORD(TempList, DEBUGGER_GENERAL_EVENT_DETAIL,
CommandsEventList);
if (CommandDetail->Tag == Tag ||
Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Put it to TRUE, to indicate that it's active
//
CommandDetail->IsEnabled = TRUE;
if (!Result) {
Result = TRUE;
}
if (Tag != DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Only, one command exist with a tag, so we need to return as we
// find it
//
return TRUE;
}
}
}
//
// Not found
//
return Result;
}
/**
* @brief disable and remove a special event
*
* @param Tag the tag of the target event
* @return BOOLEAN if the operation was successful then it returns
* true otherwise it returns false
*/
BOOLEAN CommandEventClearEvent(UINT64 Tag) {
PLIST_ENTRY TempList = 0;
BOOLEAN Result = FALSE;
PDEBUGGER_GENERAL_EVENT_DETAIL CommandDetail = {0};
TempList = &g_EventTrace;
while (&g_EventTrace != TempList->Blink) {
TempList = TempList->Blink;
CommandDetail = CONTAINING_RECORD(TempList, DEBUGGER_GENERAL_EVENT_DETAIL,
CommandsEventList);
if (CommandDetail->Tag == Tag ||
Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Remove it from the list
//
RemoveEntryList(&CommandDetail->CommandsEventList);
//
// Free the buffer for string of command
//
free(CommandDetail->CommandStringBuffer);
//
// Free the event it self
//
free(CommandDetail);
if (!Result) {
Result = TRUE;
}
if (Tag != DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
//
// Only, one command exist with a tag, so we need to return as we
// find it
//
return TRUE;
}
}
}
//
// Not found
//
return Result;
}
/**
* @brief modify a special event (enable/disable/clear) and send the
* request directly to the kernel
* @details if you pass DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG as the
* tag then it will be applied to all the active/disabled events in the
* kernel
*
* @param Tag the tag of the target event
* @param TypeOfAction whether its a enable/disable/clear
* @return VOID
*/
VOID CommandEventsModifyEvents(UINT64 Tag,
DEBUGGER_MODIFY_EVENTS_TYPE TypeOfAction) {
BOOLEAN Status;
ULONG ReturnedLength;
/*
DEBUGGER_MODIFY_EVENTS ModifyEventRequest = {0};
//
// Check if there is no event, then we shouldn't apply the
// enable, disable, or clear commands, this command also
// checks for DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG to
// see if at least one tag exists or not; however, it's not
// necessary as the kernel will check for the validity of
// tag too, but let's not send it to kernel as we can prevent
// invalid requests from user-mode too
//
if (!IsTagExist(Tag)) {
if (Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG) {
ShowMessages("err, there is no event\n");
} else {
ShowMessages("err, tag id is invalid\n");
}
return;
}
//
// Check if debugger is loaded or not
//
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
//
// Fill the structure to send it to the kernel
//
ModifyEventRequest.Tag = Tag;
ModifyEventRequest.TypeOfAction = TypeOfAction;
//
// Send the request to the kernel
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control
// code
&HideRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Input buffer length
&HideRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Length of output
Status = DeviceIoControl(g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_MODIFY_EVENTS, // IO Control code
&ModifyEventRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_MODIFY_EVENTS, // Input buffer length
&ModifyEventRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_MODIFY_EVENTS, // Length of output
// buffer in bytes.
&ReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
&ReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}
if (HideRequest.KernelStatus == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
ShowMessages("transparent debugging successfully enabled :)\n");
if (ModifyEventRequest.KernelStatus == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
} else if (HideRequest.KernelStatus ==
DEBUGEER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER) {
ShowMessages("unable to hide the debugger (transparent-debugging) :(\n");
//
// Successfull, nothing to show but we should also
// do the same (change) the user-mode structures
// that hold the event data
//
if (ModifyEventRequest.TypeOfAction == DEBUGGER_MODIFY_EVENTS_ENABLE) {
if (!CommandEventEnableEvent(Tag)) {
ShowMessages(
"error, the event was successfully, (enabled|disabled|cleared) but "
"can't apply it to the user-mode structures.\n");
}
} else if (ModifyEventRequest.TypeOfAction ==
DEBUGGER_MODIFY_EVENTS_DISABLE) {
if (!CommandEventDisableEvent(Tag)) {
ShowMessages(
"error, the event was successfully, (enabled|disabled|cleared) but "
"can't apply it to the user-mode structures.\n");
} else {
//
// The action was applied successfully
//
if (g_BreakPrintingOutput) {
if (!g_AutoFlush) {
ShowMessages(
"auto-flush mode is disabled, if there is still "
"messages or buffers in the kernel, you continue to see "
"the messages when you run 'g' until the kernel "
"buffers are empty. you can run 'settings autoflush "
"on' and after disabling and clearing events, "
"kernel buffers will be flushed automatically.\n");
} else {
//
// We should flush buffers here
//
CommandFlushRequestFlush();
}
}
}
} else if (ModifyEventRequest.TypeOfAction ==
DEBUGGER_MODIFY_EVENTS_CLEAR) {
if (!CommandEventClearEvent(Tag)) {
ShowMessages(
"error, the event was successfully, (enabled|disabled|cleared) but "
"can't apply it to the user-mode structures.\n");
} else {
//
// The action was applied successfully
//
if (g_BreakPrintingOutput) {
if (!g_AutoFlush) {
ShowMessages(
"auto-flush mode is disabled, if there is still "
"messages or buffers in the kernel, you continue to see "
"the messages when you run 'g' until the kernel "
"buffers are empty. you can run 'settings autoflush "
"on' and after disabling and clearing events, "
"kernel buffers will be flushed automatically.\n");
} else {
//
// We should flush buffers here
//
CommandFlushRequestFlush();
}
}
}
} else {
ShowMessages(
"error, the event was successfully, (enabled|disabled|cleared) but "
"can't apply it to the user-mode structures.\n");
}
} else {
ShowMessages("unknown error occured :(\n");
//
// Interpret error
//
ShowErrorMessage(ModifyEventRequest.KernelStatus);
return;
}
*/
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !exception command
*
* @return VOID
*/
VOID CommandExceptionHelp() {
ShowMessages("!exception : Monitors the first 32 entry of IDT (starting from "
"zero).\n\n");
@ -29,6 +34,12 @@ VOID CommandExceptionHelp() {
ShowMessages("\t\te.g : !exception core 2 pid 400\n");
}
/**
* @brief !exception command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandException(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -61,6 +72,7 @@ VOID CommandException(vector<string> SplittedCommand) {
// It's probably an index
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
@ -68,10 +80,12 @@ VOID CommandException(vector<string> SplittedCommand) {
CommandExceptionHelp();
return;
} else {
//
// Check if entry is valid or not (start from zero)
//
if (SpecialTarget >= 31) {
//
// Entry is invalid (this command is designed for just first 32
// entries)
@ -84,10 +98,11 @@ VOID CommandException(vector<string> SplittedCommand) {
GetEntry = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandExceptionHelp();
return;
}
@ -101,10 +116,25 @@ VOID CommandException(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -14,15 +14,26 @@
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToDebugger;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsDebuggerModulesLoaded;
/**
* @brief help of exit command
*
* @return VOID
*/
VOID CommandExitHelp() {
ShowMessages(
"exit : unload and uninstalls the drivers and closes the debugger.\n\n");
ShowMessages("syntax : \texit\n");
}
/**
* @brief exit command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandExit(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {

View file

@ -11,7 +11,6 @@
*/
#pragma once
//////////////////////////////////////////////////
// Exports //
//////////////////////////////////////////////////
@ -21,11 +20,11 @@
//
extern "C" {
extern bool inline AsmVmxSupportDetection();
__declspec(dllexport) int __cdecl HyperdbgLoad();
__declspec(dllexport) int __cdecl HyperdbgUnload();
__declspec(dllexport) int __cdecl HyperdbgInstallDriver();
__declspec(dllexport) int __cdecl HyperdbgUninstallDriver();
__declspec(dllexport) void __stdcall HyperdbgSetTextMessageCallback(
Callback handler);
__declspec(dllexport) int __cdecl HyperdbgInterpreter(const char *Command);
__declspec(dllexport) int HyperdbgLoadVmm();
__declspec(dllexport) int HyperdbgUnload();
__declspec(dllexport) int HyperdbgInstallVmmDriver();
__declspec(dllexport) int HyperdbgUninstallDriver();
__declspec(dllexport) void HyperdbgSetTextMessageCallback(Callback handler);
__declspec(dllexport) int HyperdbgInterpreter(const char *Command);
__declspec(dllexport) void HyperdbgShowSignature();
}

View file

@ -0,0 +1,96 @@
/**
* @file flush.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief flush command
* @details
* @version 0.1
* @date 2020-08-19
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief help of flush command
*
* @return VOID
*/
VOID CommandFlushHelp() {
ShowMessages("flush : Removes all the buffer and messages from kernel-mode "
"buffers.\n\n");
ShowMessages("syntax : \tflush\n");
}
/**
* @brief flush command handler
*
* @return VOID
*/
VOID CommandFlushRequestFlush() {
BOOL Status;
ULONG ReturnedLength;
DEBUGGER_FLUSH_LOGGING_BUFFERS FlushRequest = {0};
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
//
// By the way, we don't need to send an input buffer
// to the kernel, but let's keep it like this, if we
// want to pass some other aguments to the kernel in
// the future
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_FLUSH_LOGGING_BUFFERS, // IO Control code
&FlushRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS, // Input buffer length
&FlushRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_FLUSH_LOGGING_BUFFERS, // 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 (FlushRequest.KernelStatus == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
//
// The amount of message that are deleted are the amount of
// vmx-root messages and vmx non-root messages
//
ShowMessages(
"flushing buffers was successful, total %d messages were cleared.\n",
FlushRequest.CountOfMessagesThatSetAsReadFromVmxNonRoot +
FlushRequest.CountOfMessagesThatSetAsReadFromVmxRoot);
} else {
ShowMessages("flushing buffers was not successful :(\n");
}
}
VOID CommandFlush(vector<string> SplittedCommand) {
BOOL Status;
ULONG ReturnedLength;
DEBUGGER_FLUSH_LOGGING_BUFFERS FlushRequest = {0};
if (SplittedCommand.size() != 1) {
ShowMessages("incorrect use of 'flush'\n\n");
CommandFlushHelp();
return;
}
//
// Flush the buffer
//
CommandFlushRequestFlush();
}

View file

@ -11,11 +11,22 @@
*/
#include "pch.h"
/**
* @brief help of help command :)
*
* @return VOID
*/
VOID CommandFormatsHelp() {
ShowMessages(".formats : Show a value or register in different formats.\n\n");
ShowMessages("syntax : \t.formats [hex value | register]\n");
}
/**
* @brief handler of help command
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandFormats(vector<string> SplittedCommand) {
UINT64 u64Value;
@ -59,6 +70,7 @@ VOID CommandFormats(vector<string> SplittedCommand) {
PrintBits(sizeof(UINT64), &u64Value);
ShowMessages("\nChar : ");
//
// iterate through 8, 8 bits (8*6)
//

View file

@ -16,12 +16,23 @@
//
extern BOOLEAN g_BreakPrintingOutput;
/**
* @brief help of g command
*
* @return VOID
*/
VOID CommandGHelp() {
ShowMessages("g : continue a breaked debugger (by pause) or a remote breaked "
"debugger.\n\n");
ShowMessages("syntax : \tg\n");
}
/**
* @brief handler of g command
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandG(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
@ -31,7 +42,7 @@ VOID CommandG(vector<string> SplittedCommand) {
}
//
// Set the g_BreakPrintingOutput to TRUE
// Set the g_BreakPrintingOutput to FALSE
//
g_BreakPrintingOutput = FALSE;
}

View file

@ -0,0 +1,211 @@
/**
* @file GaussianRng.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief Main interface to connect applications to driver
* @details
* @version 0.1
* @date 2020-07-30
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief get the median of a vector
*
* @param Cases all the elements
* @return double median of elements
*/
double Median(vector<double> Cases) {
size_t Size = Cases.size();
if (Size == 0) {
return 0; // Undefined, really
} else {
sort(Cases.begin(), Cases.end());
if (Size % 2 == 0) {
return (Cases[Size / 2 - 1] + Cases[Size / 2]) / 2;
} else {
return Cases[Size / 2];
}
}
}
/**
* @brief get the average of a vector
*
* @tparam T type of vector
* @param vec all the elements
* @return T the average of elements
*/
template <typename T> T Average(const vector<T> &vec) {
size_t Sz;
T Mean;
Sz = vec.size();
if (Sz == 1)
return 0.0;
//
// Calculate the mean
//
Mean = std::accumulate(vec.begin(), vec.end(), 0.0) / Sz;
return Mean;
}
/**
* @brief get the standard deviation of elements
*
* @tparam T type of vector
* @param v all the elements
* @return T the standard deviation of elements
*/
template <typename T> T CalculateStandardDeviation(const std::vector<T> &v) {
double Sum, Mean, SqSum, Stdev;
Sum = std::accumulate(v.begin(), v.end(), 0.0);
Mean = Sum / v.size();
SqSum = std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
Stdev = std::sqrt(SqSum / v.size() - Mean * Mean);
return Stdev;
}
/**
* @brief get the Median Absolute Deviation (MAD) Test
*
* @param Data all the elements
* @return double result of MAD test
*/
double MedianAbsoluteDeviationTest(vector<double> Data) {
double MedianData;
double Mad;
MedianData = Median(Data);
for (int i = 0; i < Data.size(); i++) {
Data[i] = abs(Data[i] - MedianData);
}
Mad = 1.4826 * Median(Data);
return Mad;
}
/**
* @brief random generator based on calculations
*
* @param mu
* @param sigma
* @return double random number in the range of gaussian curve
*/
double Randn(double mu, double sigma) {
double U1, U2, W, mult;
static double X1, X2;
static int call = 0;
if (call == 1) {
call = !call;
return (mu + sigma * (double)X2);
}
do {
U1 = -1 + ((double)rand() / RAND_MAX) * 2;
U2 = -1 + ((double)rand() / RAND_MAX) * 2;
W = pow(U1, 2) + pow(U2, 2);
} while (W >= 1 || W == 0);
mult = sqrt((-2 * log(W)) / W);
X1 = U1 * mult;
X2 = U2 * mult;
call = !call;
return (mu + sigma * (double)X1);
}
/**
* @brief Calculate and generate random gaussian number
*
* @param Data
* @param AverageOfData
* @param StandardDeviationOfData
* @param MedianOfData
*/
VOID GuassianGenerateRandom(vector<double> Data, UINT64 *AverageOfData,
UINT64 *StandardDeviationOfData,
UINT64 *MedianOfData) {
vector<double> FinalData;
int CountOfOutliers = 0;
double Medians;
double Mad;
double StandardDeviation;
double DataAverage;
double DataMedian;
vector<double> OriginalData = Data;
vector<double> ChangableData = Data;
Mad = MedianAbsoluteDeviationTest(ChangableData);
Medians = Median(OriginalData);
for (auto item : OriginalData) {
if (item > (3 * Mad) + Medians || item < -(3 * Mad) + Medians) {
CountOfOutliers++;
} else {
FinalData.push_back(item);
}
}
StandardDeviation = CalculateStandardDeviation(FinalData);
DataAverage = Average(FinalData);
DataMedian = Median(FinalData);
//
// Set the values to return
//
*AverageOfData = (UINT64)DataAverage;
*StandardDeviationOfData = (UINT64)StandardDeviation;
*MedianOfData = (UINT64)DataMedian;
//
// ShowMessages("Varience : %f\n", StandardDeviation);
// ShowMessages("Mean : %f\n", DataAverage);
// ShowMessages("Count of outliers : %d\n", CountOfOutliers);
//
//
// for (int i = 0; i < 10000; i++)
// {
// ShowMessages("Final Random Time Stamp : %d\n", (int) Randn(DataAverage,
// StandardDeviation));
// _getch();
// }
//
}
/**
* @brief A simple test for the data based on
* pre-defined numbers in a file
*
* @return VOID
*/
VOID TestGaussianFromFile() {
vector<double> MyVector;
UINT64 AverageOfData;
UINT64 StandardDeviationOfData;
UINT64 MedianOfData;
std::ifstream file("C:\\Users\\sina\\Desktop\\r.txt");
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
MyVector.push_back(stod(line.c_str()));
}
file.close();
GuassianGenerateRandom(MyVector, &AverageOfData, &StandardDeviationOfData,
&MedianOfData);
}
}

View file

@ -11,32 +11,249 @@
*/
#pragma once
//////////////////////////////////////////////////
// Remote and Local Connection //
//////////////////////////////////////////////////
/**
* @brief Shows whether the user is allowed to use 'load' command
* to load modules locally in Survey Mode
*
*/
BOOLEAN g_IsConnectedToHyperDbgLocally = FALSE;
/**
* @brief Shows whether the current debugger is the host and
* connected to a remote debuggee (guest)
*
*/
BOOLEAN g_IsConnectedToRemoteDebuggee = FALSE;
/**
* @brief Shows whether the current system is a guest (debuggee)
* and a remote debugger is connected to this system
*
*/
BOOLEAN g_IsConnectedToRemoteDebugger = FALSE;
/**
* @brief We use this variable because this causes to not show
* the debugger signature immediately and wait for the remote
* deubgee to send its message then we can show the signature
*
*/
BOOLEAN g_IsRemoteDebuggerMessageReceived = TRUE;
/**
* @brief The socket object of host debugger (not debuggee)
* it is because in HyperDbg, debuggee is server and debugger
* is a client
*
*/
SOCKET g_ClientConnectSocket = {0};
/**
* @brief The socket object of guest debuggee (not debugger)
* it is because in HyperDbg, debugger is client and debuggee
* is a server
*
*/
SOCKET g_SeverSocket = {0};
/**
* @brief Server in debuggee needs an extra socket
*
*/
SOCKET g_ServerListenSocket = {0};
/**
* @brief In debugger (not debuggee), we save the port of server
* debuggee in this variable to use it later e.g, in signature
*
*/
string g_ServerPort = "";
/**
* @brief In debugger (not debuggee), we save the port of server
* debuggee in this variable to use it later e.g, in signature
*
*/
string g_ServerIp = "";
/**
* @brief In debugger (not debuggee), we save the ip of server
* debuggee in this variable to use it later e.g, in signature
*
*/
HANDLE g_RemoteDebuggeeListeningThread = NULL;
//////////////////////////////////////////////////
// Global Variables //
//////////////////////////////////////////////////
BOOLEAN g_IsConnectedToDebugger = FALSE;
/**
* @brief this variable is used to indicate that modules
* are loaded so we make sure to later use a trace of
* loading in 'unload' command
*
*/
BOOLEAN g_IsDebuggerModulesLoaded = FALSE;
/**
* @brief this variable is used to indicate that HyperDbg
* is currently debugging a user-mode process (attached)
*
*/
BOOLEAN g_IsAttachedToUsermodeProcess = FALSE;
/**
* @brief This variable holds the trace and generate numbers
* for new tags of events
*
*/
UINT64 g_EventTag = DebuggerEventTagStartSeed;
/**
* @brief it shows whether the debugger started using
* events or not or in other words, is g_EventTrace
* initialized with a variable or it is empty
*
*/
BOOLEAN g_EventTraceInitialized = FALSE;
/**
* @brief Holds a list of events in kernel and the state of events
* and the commands to show the state of each command (disabled/enabled)
*
* @details this list is not have any relation with the things that HyperDbg
* holds for each event in the kernel
*
*/
LIST_ENTRY g_EventTrace = {0};
/**
* @brief Holds the location driver to install it
*
*/
TCHAR g_DriverLocation[MAX_PATH] = {0};
/**
* @brief The handler for ShowMessages function
* this is because the user might choose not to use
* printf and instead use his/her handler for showing
* messages
*
*/
Callback g_MessageHandler = 0;
BOOLEAN g_IsVmxOffProcessStart; // Shows whether the vmxoff process start or not
/**
* @brief Shows whether the vmxoff process start or not
*
*/
BOOLEAN g_IsVmxOffProcessStart;
/**
* @brief Holds the global handle of device which is used
* to send the request to the kernel by IOCTL, this
* handle is not used for IRP Pending of message tracing
*
*/
HANDLE g_DeviceHandle;
/**
* @brief Shows whether the '.logopen' command is executed
* and the log file is open or not
*
*/
BOOLEAN g_LogOpened = FALSE;
/**
* @brief The object of log file ('.logopen' command)
*
*/
ofstream g_LogOpenFile;
/**
* @brief Shows whether the target is executing a script
* form '.script' command or executing script by an
* argument
*
*/
BOOLEAN g_ExecutingScript = FALSE;
/**
* @brief Shows whether the pause command or CTRL+C
* or CTRL+Break is executed or not
*
*/
BOOLEAN g_BreakPrintingOutput = FALSE;
/**
* @brief Shows whether the user executed and mesaured '!measure'
* command or not, it is because we want to use these measurements
* later in '!hide' command
*
*/
BOOLEAN g_TransparentResultsMeasured = FALSE;
/**
* @brief The average calculated from the measurements of cpuid
* '!measure' command
*/
UINT64 g_CpuidAverage = 0;
/**
* @brief The standard deviation calculated from the measurements of cpuid
* '!measure' command
*/
UINT64 g_CpuidStandardDeviation = 0;
/**
* @brief The median calculated from the measurements of cpuid
* '!measure' command
*/
UINT64 g_CpuidMedian = 0;
/**
* @brief The average calculated from the measurements of rdtsc/p
* '!measure' command
*/
UINT64 g_RdtscAverage = 0;
/**
* @brief The standard deviation calculated from the measurements
* of rdtsc/p '!measure' command
*/
UINT64 g_RdtscStandardDeviation = 0;
/**
* @brief The median calculated from the measurements of rdtsc/p
* '!measure' command
*/
UINT64 g_RdtscMedian = 0;
//////////////////////////////////////////////////
// Settings //
//////////////////////////////////////////////////
/**
* @brief Whether auto-unpause mode is enabled or not enabled
* @details it is enabled by default
*
*/
BOOLEAN g_AutoUnpause = TRUE;
/**
* @brief Whether auto-flush mode is enabled or not enabled
* @details it is disabled by default
*
*/
BOOLEAN g_AutoFlush = FALSE;
/**
* @brief Shows the syntax used in !u !u2 u u2 commands
* @details INTEL = 1, ATT = 2, MASM = 3
*
*/
UINT32 g_DisassemblerSyntax = 1;

View file

@ -0,0 +1,27 @@
/**
* @file help.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief .help command
* @details
* @version 0.1
* @date 2020-08-10
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief help of help command :)
*
* @return VOID
*/
VOID CommandHelpHelp() {
ShowMessages(".help : Show help and example(s) of a specific command.\n\n");
ShowMessages("syntax : \t.help [command (string)]\n");
ShowMessages("\t\te.g : .help !monitor\n");
}
//
// Implementation of .help command is on interpreter.cpp
//

View file

@ -15,45 +15,106 @@
// Help commands //
//////////////////////////////////////////////////
VOID CommandReadMemoryHelp();
VOID CommandHelpHelp();
VOID CommandReadMemoryAndDisassemblerHelp();
VOID CommandConnectHelp();
VOID CommandDisconnectHelp();
VOID CommandExitHelp();
VOID CommandCpuHelp();
VOID CommandUnloadHelp();
VOID CommandLoadHelp();
VOID CommandConnectHelp();
VOID CommandScriptHelp();
VOID CommandFormatsHelp();
VOID CommandRdmsrHelp();
VOID CommandWrmsrHelp();
VOID CommandPteHelp();
VOID CommandMonitorHelp();
VOID CommandSyscallHelp();
VOID CommandSysretHelp();
VOID CommandEptHookHelp();
VOID CommandEptHook2Help();
VOID CommandCpuidHelp();
VOID CommandMsrreadHelp();
VOID CommandMsrwriteHelp();
VOID CommandTscHelp();
VOID CommandPmcHelp();
VOID CommandExceptionHelp();
VOID CommandDrHelp();
VOID CommandInterruptHelp();
VOID CommandIooutHelp();
VOID CommandIoinHelp();
VOID CommandVmcallHelp();
VOID CommandHideHelp();
VOID CommandUnhideHelp();
VOID CommandTestHelp();
VOID CommandLogopenHelp();
VOID CommandLogcloseHelp();
VOID CommandVa2paHelp();
VOID CommandPa2vaHelp();
VOID CommandEventsHelp();
VOID CommandGHelp();
VOID CommandClearScreenHelp();
VOID CommandSleepHelp();
VOID CommandEditMemoryHelp();
VOID CommandSearchMemoryHelp();
VOID CommandMeasureHelp();
VOID CommandLmHelp();
VOID CommandSettingsHelp();
VOID CommandFlushHelp();
VOID CommandPauseHelp();
VOID CommandListenHelp();
VOID CommandStatusHelp();
VOID CommandAttachHelp();
VOID CommandDetachHelp();

View file

@ -11,30 +11,133 @@
*/
#include "pch.h"
//
// Global Variables
//
extern UINT64 g_CpuidAverage;
extern UINT64 g_CpuidStandardDeviation;
extern UINT64 g_CpuidMedian;
extern UINT64 g_RdtscAverage;
extern UINT64 g_RdtscStandardDeviation;
extern UINT64 g_RdtscMedian;
extern BOOLEAN g_TransparentResultsMeasured;
/**
* @brief help of !hide command
*
* @return VOID
*/
VOID CommandHideHelp() {
ShowMessages("!hide : Tries to make HyperDbg transparent from anti-debugging "
"and anti-hypervisor methods.\n\n");
ShowMessages("syntax : \t!hide\n");
ShowMessages("\t\te.g : !hide\n");
ShowMessages(
"syntax : \t!hide [pid|name] [process id (hex) | process name]\n");
ShowMessages("Note : \tprocess names are case sensitive and you can use "
"this command multiple times.\n");
ShowMessages("\t\te.g : !hide pid b60 \n");
ShowMessages("\t\te.g : !hide name procexp.exe\n");
}
VOID CommandHide(vector<string> SplittedCommand) {
/**
* @brief !hide command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID CommandHide(vector<string> SplittedCommand, string Command) {
BOOLEAN Status;
ULONG ReturnedLength;
UINT64 TargetPid;
BOOLEAN TrueIfProcessIdAndFalseIfProcessName;
DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE HideRequest = {0};
PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE FinalRequestBuffer = 0;
size_t RequestBufferSize = 0;
if (SplittedCommand.size() >= 2) {
if (SplittedCommand.size() <= 2) {
ShowMessages("incorrect use of '!hide'\n\n");
CommandHideHelp();
return;
}
//
// Find out whether the user enters pid or name
//
if (!SplittedCommand.at(1).compare("pid")) {
TrueIfProcessIdAndFalseIfProcessName = TRUE;
//
// Check for the user to not add extra arguments
//
if (SplittedCommand.size() != 3) {
ShowMessages("incorrect use of '!hide'\n\n");
CommandHideHelp();
return;
}
//
// It's just a pid for the process
//
if (!ConvertStringToUInt64(SplittedCommand.at(2), &TargetPid)) {
ShowMessages("incorrect process id\n\n");
return;
}
} else if (!SplittedCommand.at(1).compare("name")) {
TrueIfProcessIdAndFalseIfProcessName = FALSE;
//
// Trim the command
//
Trim(Command);
//
// Remove !hide from it
//
Command.erase(0, 5);
//
// remove name + space
//
Command.erase(0, 4 + 1);
//
// Trim it again
//
Trim(Command);
} else {
//
// Invalid argument for the second parameter to the command
//
ShowMessages("incorrect use of '!hide'\n\n");
CommandHideHelp();
return;
}
//
// Check if the user used !measure or not
//
/* if (!g_TransparentResultsMeasured || !g_CpuidAverage ||
!g_CpuidStandardDeviation || !g_CpuidMedian) {
ShowMessages("The average, median and standard deviation is not measured. "
"Did you use '!measure' command?\n");
return;
}
*/
//
// Check if debugger is loaded or not
//
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -43,6 +146,58 @@ VOID CommandHide(vector<string> SplittedCommand) {
//
HideRequest.IsHide = TRUE;
//
// Set the measured times
//
HideRequest.CpuidAverage = g_CpuidAverage;
HideRequest.CpuidMedian = g_CpuidMedian;
HideRequest.CpuidStandardDeviation = g_CpuidStandardDeviation;
HideRequest.TrueIfProcessIdAndFalseIfProcessName =
TrueIfProcessIdAndFalseIfProcessName;
if (TrueIfProcessIdAndFalseIfProcessName) {
//
// It's a process id
//
HideRequest.ProcId = TargetPid;
RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE);
} else {
//
// It's a process name
//
HideRequest.LengthOfProcessName = Command.size() + 1;
RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE) +
Command.size() + 1;
}
//
// Allocate the requested buffer
//
FinalRequestBuffer =
(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)malloc(RequestBufferSize);
//
// Zero the memory
//
RtlZeroMemory(FinalRequestBuffer, RequestBufferSize);
//
// Copy the buffer on the top of the final buffer
// to send the kernel
//
memcpy(FinalRequestBuffer, &HideRequest,
sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE));
//
// If it's a name then we should add it to the end of the buffer
//
memcpy(((UINT64 *)((UINT64)FinalRequestBuffer +
sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE))),
Command.c_str(), Command.size());
//
// Send the request to the kernel
//
@ -51,9 +206,9 @@ VOID CommandHide(vector<string> SplittedCommand) {
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control
// code
&HideRequest, // Input Buffer to driver.
SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Input buffer length
&HideRequest, // Output Buffer from driver.
FinalRequestBuffer, // Input Buffer to driver.
RequestBufferSize, // Input buffer length
FinalRequestBuffer, // Output Buffer from driver.
SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Length of output
// buffer in bytes.
&ReturnedLength, // Bytes placed in buffer.
@ -61,18 +216,38 @@ VOID CommandHide(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
free(FinalRequestBuffer);
return;
}
if (HideRequest.KernelStatus == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
if (FinalRequestBuffer->KernelStatus == DEBUGEER_OPERATION_WAS_SUCCESSFULL) {
ShowMessages("transparent debugging successfully enabled :)\n");
} else if (HideRequest.KernelStatus ==
} else if (FinalRequestBuffer->KernelStatus ==
DEBUGEER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER) {
ShowMessages("unable to hide the debugger (transparent-debugging) :(\n");
free(FinalRequestBuffer);
return;
} else {
ShowMessages("unknown error occured :(\n");
free(FinalRequestBuffer);
return;
}
UINT64 RealTime = 0;
UINT64 RealCpuid = Randn(g_CpuidAverage, g_CpuidStandardDeviation);
for (size_t i = 0; i < 10; i++) {
RealTime = TransparentModeRdtscDiffVmexit();
printf("Time of VM-exit : %d\n", RealTime);
_getch();
}
//
// free the buffer
//
free(FinalRequestBuffer);
}

View file

@ -24,6 +24,7 @@ extern LIST_ENTRY g_EventTrace;
extern BOOLEAN g_EventTraceInitialized;
extern BOOLEAN g_LogOpened;
extern BOOLEAN g_BreakPrintingOutput;
extern BOOLEAN g_IsConnectedToRemoteDebugger;
/**
* @brief Set the function callback that will be called if anything received
@ -31,22 +32,22 @@ extern BOOLEAN g_BreakPrintingOutput;
*
* @param handler Function that handles the messages
*/
void __stdcall HyperdbgSetTextMessageCallback(Callback handler) {
void HyperdbgSetTextMessageCallback(Callback handler) {
g_MessageHandler = handler;
}
/**
* @brief Show messages received from kernel driver
*
* @param Fmt
* @param Fmt format string message
*/
void ShowMessages(const char *Fmt, ...) {
va_list ArgList;
va_list Args;
char TempMessage[PacketChunkSize];
char TempMessage[PacketChunkSize] = {0};
if (g_MessageHandler == NULL) {
if (g_MessageHandler == NULL && !g_IsConnectedToRemoteDebugger) {
va_start(Args, Fmt);
vprintf(Fmt, Args);
@ -57,18 +58,30 @@ void ShowMessages(const char *Fmt, ...) {
}
va_start(ArgList, Fmt);
int sprintfresult =
vsprintf_s(TempMessage, PacketChunkSize - 1, Fmt, ArgList);
int sprintfresult = vsprintf(TempMessage, Fmt, ArgList);
va_end(ArgList);
if (sprintfresult != -1) {
if (g_IsConnectedToRemoteDebugger) {
//
// vsprintf_s and vswprintf_s return the number of characters written,
// not including the terminating null character, or a negative value
// if an output error occurs.
//
RemoteConnectionSendResultsToHost(TempMessage, sprintfresult);
}
if (g_LogOpened) {
//
// .logopen command executed
//
LogopenSaveToFile(TempMessage);
}
if (g_MessageHandler != NULL) {
//
// There is another handler
//
@ -137,9 +150,9 @@ void ReadIrpBasedBuffer() {
while (TRUE) {
if (!g_IsVmxOffProcessStart) {
//
// Clear the buffer
//
//
// Clear the buffer
//
ZeroMemory(OutputBuffer, UsermodeBufferSize);
Sleep(200); // we're not trying to eat all of the CPU ;)
@ -158,7 +171,7 @@ void ReadIrpBasedBuffer() {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
break;
}
@ -205,15 +218,18 @@ void ReadIrpBasedBuffer() {
break;
}
} else {
//
// the thread should not work anymore
//
free(OutputBuffer);
return;
}
}
} catch (const std::exception &) {
ShowMessages(" Exception !\n");
}
free(OutputBuffer);
}
/**
@ -223,6 +239,7 @@ void ReadIrpBasedBuffer() {
* @return DWORD Device Handle
*/
DWORD WINAPI ThreadFunc(void *data) {
//
// Do stuff. This will be the first function called on the new thread.
// When this function returns, the thread goes away. See MSDN for more
@ -239,7 +256,7 @@ DWORD WINAPI ThreadFunc(void *data) {
*
* @return int return zero if it was successful or non-zero if there was error
*/
HPRDBGCTRL_API int HyperdbgInstallDriver() {
HPRDBGCTRL_API int HyperdbgInstallVmmDriver() {
//
// The driver is not started yet so let us the install driver.
@ -258,7 +275,6 @@ HPRDBGCTRL_API int HyperdbgInstallDriver() {
//
// Error - remove driver.
//
ManageDriver(DRIVER_NAME, g_DriverLocation, DRIVER_FUNC_REMOVE);
return 1;
@ -272,6 +288,7 @@ HPRDBGCTRL_API int HyperdbgInstallDriver() {
* @return int return zero if it was successful or non-zero if there was error
*/
HPRDBGCTRL_API int HyperdbgUninstallDriver() {
//
// Unload the driver if loaded. Ignore any errors.
//
@ -286,13 +303,12 @@ HPRDBGCTRL_API int HyperdbgUninstallDriver() {
*
* @return int return zero if it was successful or non-zero if there was error
*/
HPRDBGCTRL_API int HyperdbgLoad() {
HPRDBGCTRL_API int HyperdbgLoadVmm() {
string CpuID;
DWORD ErrorNum;
BOOL Status;
HANDLE hProcess;
HANDLE hToken;
DWORD ThreadId;
if (g_DeviceHandle) {
ShowMessages("Handle of driver found, if you use 'load' before, please "
@ -318,15 +334,6 @@ HPRDBGCTRL_API int HyperdbgLoad() {
ShowMessages("VMX Operation is not supported by your processor .\n");
return 1;
}
//
// Enable Debug privilege
//
hProcess = GetCurrentProcess();
if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) {
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
CloseHandle(hToken);
}
g_DeviceHandle = CreateFileA(
"\\\\.\\HyperdbgHypervisorDevice", GENERIC_READ | GENERIC_WRITE,
@ -353,8 +360,7 @@ HPRDBGCTRL_API int HyperdbgLoad() {
InitializeListHead(&g_EventTrace);
#if !UseDbgPrintInsteadOfUsermodeMessageTracking
HANDLE Thread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
HANDLE Thread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &ThreadId);
if (Thread) {
ShowMessages("Thread Created successfully !!!\n");
}
@ -405,7 +411,7 @@ HPRDBGCTRL_API int HyperdbgUnload() {
// wait to make sure we don't use an invalid handle in another Ioctl
//
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
}
//
@ -427,7 +433,7 @@ HPRDBGCTRL_API int HyperdbgUnload() {
// wait to make sure we don't use an invalid handle in another Ioctl
//
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
}
//

View file

@ -80,7 +80,8 @@
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<FunctionLevelLinking>
</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;WINVER=0x0502;_WIN32_WINNT=0x0502;NTDDI_VERSION=0x05020000;WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;HPRDBGCTRL_EXPORTS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -113,15 +114,19 @@
<ClInclude Include="list.h" />
<ClInclude Include="namedpipe.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="communication.h" />
<ClInclude Include="tests.h" />
<ClInclude Include="transparency.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="attach.cpp" />
<ClCompile Include="breakcontrol.cpp" />
<ClCompile Include="cls.cpp" />
<ClCompile Include="connect.cpp" />
<ClCompile Include="cpuid.cpp" />
<ClCompile Include="d-u.cpp" />
<ClCompile Include="debugger.cpp" />
<ClCompile Include="detach.cpp" />
<ClCompile Include="disconnect.cpp" />
<ClCompile Include="dr.cpp" />
<ClCompile Include="e.cpp" />
@ -129,16 +134,21 @@
<ClCompile Include="events.cpp" />
<ClCompile Include="exception.cpp" />
<ClCompile Include="exit.cpp" />
<ClCompile Include="flush.cpp" />
<ClCompile Include="formats.cpp" />
<ClCompile Include="epthook2.cpp" />
<ClCompile Include="g.cpp" />
<ClCompile Include="gaussian-rng.cpp" />
<ClCompile Include="help.cpp" />
<ClCompile Include="hide.cpp" />
<ClCompile Include="interrupt.cpp" />
<ClCompile Include="ioin.cpp" />
<ClCompile Include="ioout.cpp" />
<ClCompile Include="listen.cpp" />
<ClCompile Include="load.cpp" />
<ClCompile Include="logclose.cpp" />
<ClCompile Include="logopen.cpp" />
<ClCompile Include="measure.cpp" />
<ClCompile Include="monitor.cpp" />
<ClCompile Include="msrread.cpp" />
<ClCompile Include="msrwrite.cpp" />
@ -149,12 +159,18 @@
<ClCompile Include="pte.cpp" />
<ClCompile Include="rdmsr.cpp" />
<ClCompile Include="readmem.cpp" />
<ClCompile Include="remoteconnection.cpp" />
<ClCompile Include="s.cpp" />
<ClCompile Include="script.cpp" />
<ClCompile Include="settings.cpp" />
<ClCompile Include="sleep.cpp" />
<ClCompile Include="status.cpp" />
<ClCompile Include="syscall-sysret.cpp" />
<ClCompile Include="tcpclient.cpp" />
<ClCompile Include="tcpserver.cpp" />
<ClCompile Include="test.cpp" />
<ClCompile Include="eptcommands.cpp" />
<ClCompile Include="transparency.cpp" />
<ClCompile Include="tsc.cpp" />
<ClCompile Include="unhide.cpp" />
<ClCompile Include="unload.cpp" />

View file

@ -49,6 +49,9 @@
<Filter Include="Source Files\Debugger\Tests">
<UniqueIdentifier>{c444d625-bb46-481a-a5ac-04db9c52d0f5}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Debugger\Transparency">
<UniqueIdentifier>{4fbff165-6d2b-4ea2-ae47-7ec44cf79f2f}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
@ -87,6 +90,12 @@
<ClInclude Include="namedpipe.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="transparency.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="communication.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="hprdbgctrl.cpp">
@ -254,6 +263,45 @@
<ClCompile Include="s.cpp">
<Filter>Source Files\Debugger\Commands\Debugging Commands</Filter>
</ClCompile>
<ClCompile Include="transparency.cpp">
<Filter>Source Files\Debugger\Transparency</Filter>
</ClCompile>
<ClCompile Include="gaussian-rng.cpp">
<Filter>Source Files\Debugger\Transparency</Filter>
</ClCompile>
<ClCompile Include="measure.cpp">
<Filter>Source Files\Debugger\Commands\Extension Commands</Filter>
</ClCompile>
<ClCompile Include="help.cpp">
<Filter>Source Files\Debugger\Commands\Meta Commands</Filter>
</ClCompile>
<ClCompile Include="settings.cpp">
<Filter>Source Files\Debugger\Commands\Debugging Commands</Filter>
</ClCompile>
<ClCompile Include="flush.cpp">
<Filter>Source Files\Debugger\Commands\Debugging Commands</Filter>
</ClCompile>
<ClCompile Include="tcpserver.cpp">
<Filter>Source Files\Debugger\Communication</Filter>
</ClCompile>
<ClCompile Include="tcpclient.cpp">
<Filter>Source Files\Debugger\Communication</Filter>
</ClCompile>
<ClCompile Include="listen.cpp">
<Filter>Source Files\Debugger\Commands\Meta Commands</Filter>
</ClCompile>
<ClCompile Include="remoteconnection.cpp">
<Filter>Source Files\Debugger\Communication</Filter>
</ClCompile>
<ClCompile Include="status.cpp">
<Filter>Source Files\Debugger\Commands\Meta Commands</Filter>
</ClCompile>
<ClCompile Include="attach.cpp">
<Filter>Source Files\Debugger\Commands\Meta Commands</Filter>
</ClCompile>
<ClCompile Include="detach.cpp">
<Filter>Source Files\Debugger\Commands\Meta Commands</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="AsmVmxChecks.asm">

View file

@ -47,7 +47,6 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) {
//
// Create a new a service object.
//
schService =
CreateService(SchSCManager, // handle of service control manager database
DriverName, // address of name of service to start
@ -73,7 +72,6 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) {
//
// Ignore this error.
//
return TRUE;
} else if (err == ERROR_SERVICE_MARKED_FOR_DELETE) {
@ -91,7 +89,6 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) {
//
// Indicate an error.
//
return FALSE;
}
}
@ -99,7 +96,6 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) {
//
// Close the service object.
//
if (schService) {
CloseServiceHandle(schService);
@ -108,7 +104,6 @@ InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe) {
//
// Indicate success.
//
return TRUE;
}
@ -129,7 +124,6 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Insure (somewhat) that the driver and service names are valid.
//
if (!DriverName || !ServiceName) {
ShowMessages("Invalid Driver or Service provided to ManageDriver() \n");
@ -140,7 +134,6 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Connect to the Service Control Manager and open the Services database.
//
schSCManager = OpenSCManager(NULL, // local machine
NULL, // local database
SC_MANAGER_ALL_ACCESS // access required
@ -156,7 +149,6 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Do the requested function.
//
switch (Function) {
case DRIVER_FUNC_INSTALL:
@ -164,13 +156,11 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Install the driver service.
//
if (InstallDriver(schSCManager, DriverName, ServiceName)) {
//
// Start the driver service (i.e. start the driver).
//
rCode = StartDriver(schSCManager, DriverName);
} else {
@ -178,7 +168,6 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Indicate an error.
//
rCode = FALSE;
}
@ -189,19 +178,16 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Stop the driver.
//
StopDriver(schSCManager, DriverName);
//
// Remove the driver service.
//
RemoveDriver(schSCManager, DriverName);
//
// Ignore all errors.
//
rCode = TRUE;
break;
@ -218,7 +204,6 @@ ManageDriver(LPCTSTR DriverName, LPCTSTR ServiceName, USHORT Function) {
//
// Close handle to service control manager.
//
if (schSCManager) {
CloseServiceHandle(schSCManager);
@ -242,7 +227,6 @@ RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Open the handle to the existing service.
//
schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
if (schService == NULL) {
@ -252,20 +236,17 @@ RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Indicate error.
//
return FALSE;
}
//
// Mark the service for deletion from the service control manager database.
//
if (DeleteService(schService)) {
//
// Indicate success.
//
rCode = TRUE;
} else {
@ -275,14 +256,12 @@ RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Indicate failure. Fall through to properly close the service handle.
//
rCode = FALSE;
}
//
// Close the service object.
//
if (schService) {
CloseServiceHandle(schService);
@ -306,7 +285,6 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Open the handle to the existing service.
//
schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
if (schService == NULL) {
@ -316,14 +294,12 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Indicate failure.
//
return FALSE;
}
//
// Start the execution of the service (i.e. start the driver).
//
if (!StartService(schService, // service identifier
0, // number of arguments
NULL // pointer to arguments
@ -336,9 +312,19 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Ignore this error.
//
return TRUE;
} else if (err == 577) {
ShowMessages(
"Err 577, it's because you driver signature enforcement is enabled. "
"You should disable driver signature enforcement by attaching Windbg "
"or from the boot menu.");
//
// Indicate failure. Fall through to properly close the service handle.
//
return FALSE;
} else {
ShowMessages("StartService failure! Error = %d \n", err);
@ -346,7 +332,6 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Indicate failure. Fall through to properly close the service handle.
//
return FALSE;
}
}
@ -354,7 +339,6 @@ StartDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Close the service object.
//
if (schService) {
CloseServiceHandle(schService);
@ -379,7 +363,6 @@ StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Open the handle to the existing service.
//
schService = OpenService(SchSCManager, DriverName, SERVICE_ALL_ACCESS);
if (schService == NULL) {
@ -392,13 +375,11 @@ StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Request that the service stop.
//
if (ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus)) {
//
// Indicate success.
//
rCode = TRUE;
} else {
@ -408,14 +389,12 @@ StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName) {
//
// Indicate failure. Fall through to properly close the service handle.
//
rCode = FALSE;
}
//
// Close the service object.
//
if (schService) {
CloseServiceHandle(schService);
@ -435,11 +414,18 @@ SetupDriverName(_Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation,
ULONG BufferLength) {
HANDLE fileHandle;
DWORD driverLocLen = 0;
HMODULE ProcHandle = GetModuleHandle(NULL);
char *Pos;
//
// Get the current directory.
//
/*
//
// We use the location of running exe instead of
// finding driver based on current directory
//
driverLocLen = GetCurrentDirectory(BufferLength, DriverLocation);
if (driverLocLen == 0) {
@ -448,6 +434,18 @@ SetupDriverName(_Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation,
return FALSE;
}
*/
GetModuleFileName(ProcHandle, DriverLocation, BufferLength);
Pos = strrchr(DriverLocation, '\\');
if (Pos != NULL) {
//
// this will put the null terminator here. you can also copy to
// another string if you want, we can also use PathCchRemoveFileSpec
//
*Pos = '\0';
}
//
// Setup path name to driver file.
@ -460,7 +458,6 @@ SetupDriverName(_Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation,
//
// Insure driver file is in the specified directory.
//
if ((fileHandle = CreateFile(DriverLocation, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) ==
INVALID_HANDLE_VALUE) {
@ -470,14 +467,12 @@ SetupDriverName(_Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation,
//
// Indicate failure.
//
return FALSE;
}
//
// Close open file handle.
//
if (fileHandle) {
CloseHandle(fileHandle);
@ -486,6 +481,5 @@ SetupDriverName(_Inout_updates_bytes_all_(BufferLength) PCHAR DriverLocation,
//
// Indicate success.
//
return TRUE;
}

View file

@ -11,6 +11,7 @@
*/
#pragma once
//
// The following ifdef block is the standard way of creating macros which make
// exporting from a DLL simpler. All files within this DLL are compiled with the
// HPRDBGCTRL_EXPORTS symbol defined on the command line. This symbol should not
@ -18,6 +19,7 @@
// whose source files include this file see HPRDBGCTRL_API functions as being
// imported from a DLL, whereas this DLL sees symbols defined with this macro as
// being exported.
//
#ifdef HPRDBGCTRL_EXPORTS
#define HPRDBGCTRL_API __declspec(dllexport)

View file

@ -12,8 +12,17 @@
#include "pch.h"
using namespace std;
//
// Global Variables
//
extern BOOLEAN g_LogOpened;
extern BOOLEAN g_ExecutingScript;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern BOOLEAN g_IsRemoteDebuggerMessageReceived;
extern string g_ServerPort;
extern string g_ServerIp;
/**
* @brief Interpret commands
@ -22,9 +31,10 @@ extern BOOLEAN g_ExecutingScript;
* @return int returns return zero if it was successful or non-zero if there was
* error
*/
int _cdecl HyperdbgInterpreter(const char *Command) {
int HyperdbgInterpreter(const char *Command) {
string CommandString(Command);
BOOLEAN HelpCommand = FALSE;
//
// Save the command into log open file
@ -53,111 +63,416 @@ int _cdecl HyperdbgInterpreter(const char *Command) {
string FirstCommand = SplittedCommand.front();
//
// Check and send remote command and also we check whether this
// is a command that should be handled in this command or we can
// send it to the remote computer, it is because in a remote connection
// still some of the commands should be handled in the local HyperDbg
//
if (g_IsConnectedToRemoteDebuggee && !IsItALocalCommand(FirstCommand)) {
RemoteConnectionSendCommand(Command, strlen(Command) + 1);
//
// Indicate that we sent the command to the target system
//
return 2;
}
//
// Detect whether it's a .help command or not
//
if (!FirstCommand.compare(".help") || !FirstCommand.compare("help") ||
!FirstCommand.compare(".hh")) {
if (SplittedCommand.size() == 2) {
//
// Show that it's a help command
//
HelpCommand = TRUE;
FirstCommand = SplittedCommand.at(1);
} else {
ShowMessages("Incorrect use of '%s'\n", FirstCommand.c_str());
CommandHelpHelp();
return 0;
}
}
if (!FirstCommand.compare("clear") || !FirstCommand.compare("cls") ||
!FirstCommand.compare(".cls")) {
CommandClearScreen();
} else if (!FirstCommand.compare(".connect")) {
CommandConnect(SplittedCommand);
if (HelpCommand)
CommandClearScreenHelp();
else
CommandClearScreen();
} else if (!FirstCommand.compare(".connect") ||
!FirstCommand.compare("connect")) {
if (HelpCommand)
CommandConnectHelp();
else
CommandConnect(SplittedCommand);
} else if (!FirstCommand.compare(".listen") ||
!FirstCommand.compare("listen")) {
if (HelpCommand)
CommandListenHelp();
else
CommandListen(SplittedCommand);
} else if (!FirstCommand.compare("g") || !FirstCommand.compare("go")) {
CommandG(SplittedCommand);
if (HelpCommand)
CommandGHelp();
else
CommandG(SplittedCommand);
} else if (!FirstCommand.compare(".attach") ||
!FirstCommand.compare("attach")) {
if (HelpCommand)
CommandAttachHelp();
else
CommandAttach(SplittedCommand);
} else if (!FirstCommand.compare(".detach") ||
!FirstCommand.compare("detach")) {
if (HelpCommand)
CommandDetachHelp();
else
CommandDetach(SplittedCommand);
} else if (!FirstCommand.compare("sleep")) {
CommandSleep(SplittedCommand);
if (HelpCommand)
CommandSleepHelp();
else
CommandSleep(SplittedCommand);
} else if (!FirstCommand.compare("event") ||
!FirstCommand.compare("events")) {
CommandEvents(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);
if (HelpCommand)
CommandEventsHelp();
else
CommandEvents(SplittedCommand);
} else if (!FirstCommand.compare("setting") ||
!FirstCommand.compare("settings")) {
if (HelpCommand)
CommandSettingsHelp();
else
CommandSettings(SplittedCommand);
} else if (!FirstCommand.compare(".disconnect") ||
!FirstCommand.compare("disconnect")) {
if (HelpCommand)
CommandDisconnectHelp();
else
CommandDisconnect(SplittedCommand);
} else if (!FirstCommand.compare(".status") ||
!FirstCommand.compare("status")) {
if (HelpCommand)
CommandStatusHelp();
else
CommandStatus(SplittedCommand);
} else if (!FirstCommand.compare("load")) {
CommandLoad(SplittedCommand);
if (HelpCommand)
CommandLoadHelp();
else
CommandLoad(SplittedCommand);
} else if (!FirstCommand.compare("exit") || !FirstCommand.compare(".exit")) {
CommandExit(SplittedCommand);
if (HelpCommand)
CommandExitHelp();
else
CommandExit(SplittedCommand);
} else if (!FirstCommand.compare("flush")) {
if (HelpCommand)
CommandFlushHelp();
else
CommandFlush(SplittedCommand);
} else if (!FirstCommand.compare("pause")) {
if (HelpCommand)
CommandPauseHelp();
else
CommandPause(SplittedCommand);
} else if (!FirstCommand.compare("unload")) {
CommandUnload(SplittedCommand);
if (HelpCommand)
CommandUnloadHelp();
else
CommandUnload(SplittedCommand);
} else if (!FirstCommand.compare(".script")) {
CommandScript(SplittedCommand, CommandString);
if (HelpCommand)
CommandScriptHelp();
else
CommandScript(SplittedCommand, CommandString);
} else if (!FirstCommand.compare(".logopen")) {
CommandLogopen(SplittedCommand, CommandString);
if (HelpCommand)
CommandLogopenHelp();
else
CommandLogopen(SplittedCommand, CommandString);
} else if (!FirstCommand.compare(".logclose")) {
CommandLogclose(SplittedCommand);
if (HelpCommand)
CommandLogcloseHelp();
else
CommandLogclose(SplittedCommand);
} else if (!FirstCommand.compare("test")) {
CommandTest(SplittedCommand);
if (HelpCommand)
CommandTestHelp();
else
CommandTest(SplittedCommand);
} else if (!FirstCommand.compare("cpu")) {
CommandCpu(SplittedCommand);
if (HelpCommand)
CommandCpuHelp();
else
CommandCpu(SplittedCommand);
} else if (!FirstCommand.compare("wrmsr")) {
CommandWrmsr(SplittedCommand);
if (HelpCommand)
CommandWrmsrHelp();
else
CommandWrmsr(SplittedCommand);
} else if (!FirstCommand.compare("rdmsr")) {
CommandRdmsr(SplittedCommand);
if (HelpCommand)
CommandRdmsrHelp();
else
CommandRdmsr(SplittedCommand);
} else if (!FirstCommand.compare("!va2pa")) {
CommandVa2pa(SplittedCommand);
if (HelpCommand)
CommandVa2paHelp();
else
CommandVa2pa(SplittedCommand);
} else if (!FirstCommand.compare("!pa2va")) {
CommandPa2va(SplittedCommand);
if (HelpCommand)
CommandPa2vaHelp();
else
CommandPa2va(SplittedCommand);
} else if (!FirstCommand.compare(".formats")) {
CommandFormats(SplittedCommand);
if (HelpCommand)
CommandFormatsHelp();
else
CommandFormats(SplittedCommand);
} else if (!FirstCommand.compare("!pte")) {
CommandPte(SplittedCommand);
if (HelpCommand)
CommandPteHelp();
else
CommandPte(SplittedCommand);
} else if (!FirstCommand.compare("!monitor")) {
CommandMonitor(SplittedCommand);
if (HelpCommand)
CommandMonitorHelp();
else
CommandMonitor(SplittedCommand);
} else if (!FirstCommand.compare("!vmcall")) {
CommandVmcall(SplittedCommand);
} else if (!FirstCommand.compare("!epthook")) {
CommandEptHook(SplittedCommand);
if (HelpCommand)
CommandVmcallHelp();
else
CommandVmcall(SplittedCommand);
} else if (!FirstCommand.compare("!epthook") || !FirstCommand.compare("bh")) {
if (HelpCommand)
CommandEptHookHelp();
else
CommandEptHook(SplittedCommand);
} else if (!FirstCommand.compare("!epthook2")) {
CommandEptHook2(SplittedCommand);
if (HelpCommand)
CommandEptHook2Help();
else
CommandEptHook2(SplittedCommand);
} else if (!FirstCommand.compare("!cpuid")) {
CommandCpuid(SplittedCommand);
if (HelpCommand)
CommandCpuidHelp();
else
CommandCpuid(SplittedCommand);
} else if (!FirstCommand.compare("!msrread")) {
CommandMsrread(SplittedCommand);
if (HelpCommand)
CommandMsrreadHelp();
else
CommandMsrread(SplittedCommand);
} else if (!FirstCommand.compare("!msrwrite")) {
CommandMsrwrite(SplittedCommand);
if (HelpCommand)
CommandMsrwriteHelp();
else
CommandMsrwrite(SplittedCommand);
} else if (!FirstCommand.compare("!tsc")) {
CommandTsc(SplittedCommand);
if (HelpCommand)
CommandTscHelp();
else
CommandTsc(SplittedCommand);
} else if (!FirstCommand.compare("!pmc")) {
CommandPmc(SplittedCommand);
if (HelpCommand)
CommandPmcHelp();
else
CommandPmc(SplittedCommand);
} else if (!FirstCommand.compare("!dr")) {
CommandDr(SplittedCommand);
if (HelpCommand)
CommandDrHelp();
else
CommandDr(SplittedCommand);
} else if (!FirstCommand.compare("!ioin")) {
CommandIoin(SplittedCommand);
if (HelpCommand)
CommandIoinHelp();
else
CommandIoin(SplittedCommand);
} else if (!FirstCommand.compare("!ioout")) {
CommandIoout(SplittedCommand);
if (HelpCommand)
CommandIooutHelp();
else
CommandIoout(SplittedCommand);
} else if (!FirstCommand.compare("!exception")) {
CommandException(SplittedCommand);
if (HelpCommand)
CommandExceptionHelp();
else
CommandException(SplittedCommand);
} else if (!FirstCommand.compare("!interrupt")) {
CommandInterrupt(SplittedCommand);
} else if (!FirstCommand.compare("!syscall") ||
!FirstCommand.compare("!sysret")) {
CommandSyscallAndSysret(SplittedCommand);
if (HelpCommand)
CommandInterruptHelp();
else
CommandInterrupt(SplittedCommand);
} else if (!FirstCommand.compare("!syscall")) {
if (HelpCommand)
CommandSyscallHelp();
else
CommandSyscallAndSysret(SplittedCommand);
} else if (!FirstCommand.compare("!sysret")) {
if (HelpCommand)
CommandSysretHelp();
else
CommandSyscallAndSysret(SplittedCommand);
} else if (!FirstCommand.compare("!hide")) {
CommandHide(SplittedCommand);
if (HelpCommand)
CommandHideHelp();
else
CommandHide(SplittedCommand, CommandString);
} else if (!FirstCommand.compare("!unhide")) {
CommandUnhide(SplittedCommand);
if (HelpCommand)
CommandUnhideHelp();
else
CommandUnhide(SplittedCommand);
} else if (!FirstCommand.compare("!measure")) {
if (HelpCommand)
CommandMeasureHelp();
else
CommandMeasure(SplittedCommand);
} else if (!FirstCommand.compare("lm")) {
CommandLm(SplittedCommand);
if (HelpCommand)
CommandLmHelp();
else
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("!epthook2") ||
!FirstCommand.compare("bh")) {
CommandEptHook2(SplittedCommand);
!FirstCommand.compare("!u") || !FirstCommand.compare("u") ||
!FirstCommand.compare("!u2") || !FirstCommand.compare("u2")) {
if (HelpCommand)
CommandReadMemoryAndDisassemblerHelp();
else
CommandReadMemoryAndDisassembler(SplittedCommand);
} else if (!FirstCommand.compare("!epthook2")) {
if (HelpCommand)
CommandEptHook2Help();
else
CommandEptHook2(SplittedCommand);
} else if (!FirstCommand.compare("eb") || !FirstCommand.compare("ed") ||
!FirstCommand.compare("eq") || !FirstCommand.compare("!eb") ||
!FirstCommand.compare("!ed") || !FirstCommand.compare("!eq")) {
CommandEditMemory(SplittedCommand);
if (HelpCommand)
CommandEditMemoryHelp();
else
CommandEditMemory(SplittedCommand);
} else if (!FirstCommand.compare("sb") || !FirstCommand.compare("sd") ||
!FirstCommand.compare("sq") || !FirstCommand.compare("!sb") ||
!FirstCommand.compare("!sd") || !FirstCommand.compare("!sq")) {
CommandSearchMemory(SplittedCommand);
if (HelpCommand)
CommandSearchMemoryHelp();
else
CommandSearchMemory(SplittedCommand);
} else {
ShowMessages("Couldn't resolve error at '%s'", FirstCommand.c_str());
ShowMessages("\n");
ShowMessages("Couldn't resolve error at '%s'\n", FirstCommand.c_str());
}
//
@ -169,3 +484,46 @@ int _cdecl HyperdbgInterpreter(const char *Command) {
return 0;
}
VOID HyperdbgShowSignature() {
if (g_IsConnectedToRemoteDebuggee) {
if (g_IsRemoteDebuggerMessageReceived) {
ShowMessages("HyperDbg (%s:%s) >", g_ServerIp.c_str(),
g_ServerPort.c_str());
}
} else {
ShowMessages("HyperDbg >");
}
}
/**
* @brief This function is used to mark some commands as local
* so we won't send them in local connections and instead handle
* them in local instance of HyperDbg
*
* @param Command just the first word of command (without other parameters)
* @return BOOLEAN if true then it shows that the command is a local
* command and if false then it shows that the command can be used in
* a remote machine
*/
BOOLEAN IsItALocalCommand(string Command) {
//
// Some commands should not be passed to the remote system
// and instead should be handled in the current debugger
//
if (!Command.compare(".status") || !Command.compare("cls") ||
!Command.compare(".cls") || !Command.compare("clear") ||
!Command.compare("sleep") || !Command.compare("connect") ||
!Command.compare(".connect") || !Command.compare("disconnect") ||
!Command.compare(".disconnect") || !Command.compare(".listen") ||
!Command.compare("listen") || !Command.compare(".logopen") ||
!Command.compare(".logclose") || !Command.compare(".script")) {
return TRUE;
}
return FALSE;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !interrupt command
*
* @return VOID
*/
VOID CommandInterruptHelp() {
ShowMessages("!interrupt : Monitors the external interrupt (IDT >= 32).\n\n");
ShowMessages("syntax : \t!interrupt [entry index (hex value) - should be "
@ -24,6 +29,12 @@ VOID CommandInterruptHelp() {
ShowMessages("\t\te.g : !interrupt 0x2f core 2 pid 400\n");
}
/**
* @brief !interrupt command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandInterrupt(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -64,10 +75,12 @@ VOID CommandInterrupt(vector<string> SplittedCommand) {
CommandInterruptHelp();
return;
} else {
//
// Check if entry is valid or not
//
if (!(SpecialTarget >= 32 && SpecialTarget <= 0xff)) {
//
// Entry is invalid (this command is designed for just entries
// between 32 to 255)
@ -80,16 +93,18 @@ VOID CommandInterrupt(vector<string> SplittedCommand) {
GetEntry = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandInterruptHelp();
return;
}
}
if (SpecialTarget == 0) {
//
// The user didn't set the target interrupt, even though it's possible to
// get all interrupts but it makes the system not resposive so it's wrong
@ -110,10 +125,24 @@ VOID CommandInterrupt(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !ioin command
*
* @return VOID
*/
VOID CommandIoinHelp() {
ShowMessages("!ioin : Detects the execution of IN (I/O instructions) "
"instructions.\n\n");
@ -26,6 +31,12 @@ VOID CommandIoinHelp() {
ShowMessages("\t\te.g : !ioin core 2 pid 400\n");
}
/**
* @brief !ioin command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandIoin(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -38,7 +49,6 @@ VOID CommandIoin(vector<string> SplittedCommand) {
//
// Interpret and fill the general event and action fields
//
//
if (!InterpretGeneralEventAndActionsFields(
&SplittedCommand, IN_INSTRUCTION_EXECUTION, &Event, &EventLength,
&Action, &ActionLength)) {
@ -58,6 +68,7 @@ VOID CommandIoin(vector<string> SplittedCommand) {
// It's probably an I/O port
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
@ -68,10 +79,11 @@ VOID CommandIoin(vector<string> SplittedCommand) {
GetPort = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandIoinHelp();
return;
}
@ -85,10 +97,24 @@ VOID CommandIoin(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !ioout command
*
* @return VOID
*/
VOID CommandIooutHelp() {
ShowMessages("!ioout : Detects the execution of OUT (I/O instructions) "
"instructions.\n\n");
@ -26,6 +31,12 @@ VOID CommandIooutHelp() {
ShowMessages("\t\te.g : !ioout core 2 pid 400\n");
}
/**
* @brief !ioout command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandIoout(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -48,7 +59,7 @@ VOID CommandIoout(vector<string> SplittedCommand) {
//
// Interpret command specific details (if any)
//
//
//
for (auto Section : SplittedCommand) {
if (!Section.compare("!ioout")) {
@ -59,6 +70,7 @@ VOID CommandIoout(vector<string> SplittedCommand) {
// It's probably an I/O port
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
@ -69,10 +81,11 @@ VOID CommandIoout(vector<string> SplittedCommand) {
GetPort = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandIooutHelp();
return;
}
@ -86,10 +99,24 @@ VOID CommandIoout(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -9,13 +9,23 @@
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief List initializer
*
* @param ListHead
*/
void InitializeListHead(PLIST_ENTRY ListHead) {
ListHead->Flink = ListHead->Blink = ListHead;
}
/**
* @brief insert entry to the top of the list
*
* @param ListHead
* @param Entry
*/
void InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry) {
PLIST_ENTRY Flink;
@ -26,3 +36,30 @@ void InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry) {
Flink->Blink = Entry;
ListHead->Flink = Entry;
}
/**
* @brief remove the entry from the list
*
* @param Entry
* @return BOOLEAN
*/
BOOLEAN
RemoveEntryList(PLIST_ENTRY Entry) {
PLIST_ENTRY PrevEntry;
PLIST_ENTRY NextEntry;
NextEntry = Entry->Flink;
PrevEntry = Entry->Blink;
if ((NextEntry->Blink != Entry) || (PrevEntry->Flink != Entry)) {
//
// Error
//
_CrtDbgBreak();
}
PrevEntry->Flink = NextEntry;
NextEntry->Blink = PrevEntry;
return (BOOLEAN)(PrevEntry == NextEntry);
}

View file

@ -14,11 +14,10 @@
#define CONTAINING_RECORD(address, type, field) \
((type *)((char *)(address) - (unsigned long)(&((type *)0)->field)))
//////////////////////////////////////////////////
// Functions //
//////////////////////////////////////////////////
//////////////////////////////////////////
// Functions //
//////////////////////////////////////////
void InitializeListHead(PLIST_ENTRY ListHead);
void InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry);
BOOLEAN RemoveEntryList(PLIST_ENTRY Entry);

View file

@ -0,0 +1,101 @@
/**
* @file listen.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief listen command
* @details
* @version 0.1
* @date 2020-08-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern BOOLEAN g_IsConnectedToRemoteDebugger;
/**
* @brief help of listen command
*
* @return VOID
*/
VOID CommandListenHelp() {
ShowMessages(".listen : listen for a client to connect to HyperDbg (works as "
"a guest server).\n\n");
ShowMessages("note : \tif you don't specify port then HyperDbg uses the "
"default port (%s)\n",
DEFAULT_PORT);
ShowMessages("syntax : \t.listen [port]\n");
ShowMessages("\t\te.g : .listen\n");
ShowMessages("\t\te.g : .listen 50000\n");
}
/**
* @brief listen command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandListen(vector<string> SplittedCommand) {
string port;
if (SplittedCommand.size() >= 3) {
//
// Means that user entered invalid parameters
//
ShowMessages("incorrect use of '.listen'\n\n");
CommandListenHelp();
return;
}
if (g_IsConnectedToHyperDbgLocally || g_IsConnectedToRemoteDebuggee ||
g_IsConnectedToRemoteDebugger) {
ShowMessages("you're connected to a debugger, please use '.disconnect' "
"command.\n");
return;
}
if (SplittedCommand.size() == 1) {
//
// listen on default port
//
ShowMessages("listening on %s ...\n", DEFAULT_PORT);
RemoteConnectionListen(DEFAULT_PORT);
return;
} else if (SplittedCommand.size() == 2) {
port = SplittedCommand.at(1);
//
// means that probably wants to listen
// on a specific port, let's see if the
// port is valid or not
//
if (!IsNumber(port) || stoi(port) > 65535 || stoi(port) < 0) {
ShowMessages("incorrect port\n");
return;
}
//
// listen on the port
//
ShowMessages("listening on %s ...\n", port.c_str());
RemoteConnectionListen(port.c_str());
} else {
ShowMessages("incorrect use of '.listen'\n\n");
CommandListenHelp();
return;
}
}

View file

@ -13,6 +13,11 @@
using namespace std;
/**
* @brief help of lm command
*
* @return VOID
*/
VOID CommandLmHelp() {
ShowMessages(
"lm : list kernel modules' base address, size, name and path.\n\n");
@ -24,6 +29,12 @@ VOID CommandLmHelp() {
"'nt' in their path or name\n");
}
/**
* @brief handle lm command
*
* @param SplittedCommand
* @return int
*/
int CommandLm(vector<string> SplittedCommand) {
PRTL_PROCESS_MODULES ModuleInfo;
@ -37,9 +48,12 @@ int CommandLm(vector<string> SplittedCommand) {
return -1;
}
//
// Allocate memory for the module list
//
ModuleInfo = (PRTL_PROCESS_MODULES)VirtualAlloc(
NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE); // Allocate memory for the module list
PAGE_READWRITE);
if (!ModuleInfo) {
ShowMessages("\nUnable to allocate memory for module list (%d)\n",
@ -47,9 +61,12 @@ int CommandLm(vector<string> SplittedCommand) {
return -1;
}
//
// 11 = SystemModuleInformation
//
if (!NT_SUCCESS(status = NtQuerySystemInformation(
(SYSTEM_INFORMATION_CLASS)11, ModuleInfo, 1024 * 1024,
NULL))) // 11 = SystemModuleInformation
NULL)))
{
ShowMessages("\nError: Unable to query module list (%#x)\n", status);
@ -60,6 +77,7 @@ int CommandLm(vector<string> SplittedCommand) {
ShowMessages("start\t\t\tsize\tname\t\tpath\n\n");
for (i = 0; i < ModuleInfo->NumberOfModules; i++) {
//
// Check if we need to search for the module or not
//
@ -67,6 +85,7 @@ int CommandLm(vector<string> SplittedCommand) {
Search = strstr((char *)ModuleInfo->Modules[i].FullPathName,
SplittedCommand.at(1).c_str());
if (Search == NULL) {
//
// not found
//

View file

@ -14,40 +14,88 @@
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToDebugger;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsDebuggerModulesLoaded;
/**
* @brief help of load command
*
* @return VOID
*/
VOID CommandLoadHelp() {
ShowMessages("load : installs the driver and load the kernel modules.\n\n");
ShowMessages("syntax : \tload\n");
ShowMessages("load : installs the drivers and load the modules.\n\n");
ShowMessages("syntax : \tload [module name]\n");
ShowMessages("\t\te.g : load vmm\n");
}
/**
* @brief load command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandLoad(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
BOOL Status;
HANDLE hToken;
if (SplittedCommand.size() != 2) {
ShowMessages("incorrect use of 'load'\n\n");
CommandLoadHelp();
return;
}
if (!g_IsConnectedToDebugger) {
if (!g_IsConnectedToHyperDbgLocally) {
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");
//
// Enable Debug privilege
//
Status =
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
if (!Status) {
ShowMessages("OpenProcessToken failed, error : %u \n");
return;
}
ShowMessages("try to install load kernel modules...\n");
if (HyperdbgLoad()) {
ShowMessages("Failed to load driver\n");
Status = SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
if (!Status) {
CloseHandle(hToken);
return;
}
//
// If we reach here so the module are loaded
// Check for the module
//
g_IsDebuggerModulesLoaded = TRUE;
if (!SplittedCommand.at(1).compare("vmm")) {
//
// Load VMM Module
//
ShowMessages("try to install driver...\n");
if (HyperdbgInstallVmmDriver()) {
ShowMessages("Failed to install driver\n");
return;
}
ShowMessages("try to install load kernel modules...\n");
if (HyperdbgLoadVmm()) {
ShowMessages("Failed to load driver\n");
return;
}
//
// If we reach here so the module are loaded
//
g_IsDebuggerModulesLoaded = TRUE;
} else {
//
// Module not found
//
ShowMessages("module not found, currently, 'vmm' is the only available "
"module for HyperDbg.\n");
}
}

View file

@ -14,15 +14,25 @@
//
// Global Variables
//
extern BOOLEAN g_LogOpened;
extern ofstream g_LogOpenFile;
/**
* @brief help .logclose command
*
* @return VOID
*/
VOID CommandLogcloseHelp() {
ShowMessages(".logclose : close the previously opened log.\n\n");
ShowMessages("syntax : \.logclose\n");
}
/**
* @brief .logclose command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandLogclose(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {

View file

@ -13,14 +13,29 @@
using namespace std;
//
// Global Variables
//
extern BOOLEAN g_LogOpened;
extern ofstream g_LogOpenFile;
/**
* @brief help of .logopen command
*
* @return VOID
*/
VOID CommandLogopenHelp() {
ShowMessages(".logopen : save commands and results in a file.\n\n");
ShowMessages("syntax : \.logopen [FilePath]\n");
}
/**
* @brief .logopen command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID CommandLogopen(vector<string> SplittedCommand, string Command) {
if (SplittedCommand.size() == 1) {
@ -59,6 +74,7 @@ VOID CommandLogopen(vector<string> SplittedCommand, string Command) {
// Check if it's okay
//
if (g_LogOpenFile.is_open()) {
//
// Start intercepting logs
//
@ -81,4 +97,10 @@ VOID CommandLogopen(vector<string> SplittedCommand, string Command) {
}
}
/**
* @brief Append text to the file object
*
* @param Text
* @return VOID
*/
VOID LogopenSaveToFile(const char *Text) { g_LogOpenFile << Text; }

View file

@ -0,0 +1,109 @@
/**
* @file measure.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief !measure command
* @details
* @version 0.1
* @date 2020-08-06
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern UINT64 g_CpuidAverage;
extern UINT64 g_CpuidStandardDeviation;
extern UINT64 g_CpuidMedian;
extern UINT64 g_RdtscAverage;
extern UINT64 g_RdtscStandardDeviation;
extern UINT64 g_RdtscMedian;
extern BOOLEAN g_TransparentResultsMeasured;
/**
* @brief help of !measure command
*
* @return VOID
*/
VOID CommandMeasureHelp() {
ShowMessages(
"!measure : Measures the arguments needs for !hide command.\n\n");
ShowMessages("syntax : \t!measure [default]\n");
ShowMessages("\t\te.g : !measure\n");
ShowMessages("\t\te.g : !measure default\n");
}
/**
* @brief !measure command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandMeasure(vector<string> SplittedCommand) {
BOOLEAN DefaultMode = FALSE;
if (SplittedCommand.size() >= 3) {
ShowMessages("incorrect use of '!measure'\n\n");
CommandMeasureHelp();
return;
}
if (SplittedCommand.size() == 2 && SplittedCommand.at(1).compare("default")) {
ShowMessages("incorrect use of '!measure'\n\n");
CommandMeasureHelp();
return;
} else if (SplittedCommand.size() == 2 &&
!SplittedCommand.at(1).compare("default")) {
DefaultMode = TRUE;
}
//
// Check if debugger is loaded or not
//
if (g_DeviceHandle && !DefaultMode) {
ShowMessages(
"Debugger is loaded and your machine is already in a hypervisor, you "
"should measure the times before 'load'-ing the debugger, please "
"'unload' the debugger and use '!measure' again or use '!measure "
"default' to use hardcoded measurements.\n");
return;
}
if (TransparentModeCheckHypervisorPresence(
&g_CpuidAverage, &g_CpuidStandardDeviation, &g_CpuidMedian)) {
ShowMessages(
"we detected that there is a hypervisor, on your system, it "
"leads to wrong measurement results for our transparent-mode, please "
"make sure that you're not in a hypervisor then measure the result "
"again; otherwise the transparent-mode will not work but you can use "
"'!measure default' to use the hardcoded measurements !\n\n");
return;
}
if (TransparentModeCheckRdtscpVmexit(
&g_RdtscAverage, &g_RdtscStandardDeviation, &g_RdtscMedian)) {
ShowMessages(
"we detected that there is a hypervisor, on your system, it "
"leads to wrong measurement results for our transparent-mode, please "
"make sure that you're not in a hypervisor then measure the result "
"again; otherwise the transparent-mode will not work but you can use "
"'!measure default' to use the hardcoded measurements !\n\n");
return;
}
ShowMessages("\nThe measurements was successful, now you can use '!hide' "
"command :)\n");
//
// Indicate that the measurements was successful
//
g_TransparentResultsMeasured = TRUE;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !monitor command
*
* @return VOID
*/
VOID CommandMonitorHelp() {
ShowMessages("!monitor : Monitor address range for read and writes.\n\n");
ShowMessages("syntax : \t!monitor [attrib (r, w, rw)] [From Virtual Address "
@ -26,6 +31,12 @@ VOID CommandMonitorHelp() {
"pid 400\n");
}
/**
* @brief !monitor command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandMonitor(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -72,11 +83,13 @@ VOID CommandMonitor(vector<string> SplittedCommand) {
Event->EventType = HIDDEN_HOOK_READ_AND_WRITE;
} else {
//
// It's probably address
//
if (!SetFrom) {
if (!ConvertStringToUInt64(Section, &OptionalParam1)) {
//
// Unkonwn parameter
//
@ -87,6 +100,7 @@ VOID CommandMonitor(vector<string> SplittedCommand) {
SetFrom = TRUE;
} else if (!SetTo) {
if (!ConvertStringToUInt64(Section, &OptionalParam2)) {
//
// Unkonwn parameter
//
@ -96,16 +110,18 @@ VOID CommandMonitor(vector<string> SplittedCommand) {
}
SetTo = TRUE;
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandMonitorHelp();
return;
}
}
}
if (OptionalParam1 > OptionalParam2) {
//
// 'from' is greater than 'to'
//
@ -123,10 +139,25 @@ VOID CommandMonitor(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !msrread command
*
* @return VOID
*/
VOID CommandMsrreadHelp() {
ShowMessages("!msrread : Detects the execution of rdmsr instructions.\n\n");
ShowMessages("syntax : \t!msrread [msr (hex value) - if not specific means "
@ -25,6 +30,12 @@ VOID CommandMsrreadHelp() {
ShowMessages("\t\te.g : !msrread core 2 pid 400\n");
}
/**
* @brief !msrread command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandMsrread(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -71,7 +82,7 @@ VOID CommandMsrread(vector<string> SplittedCommand) {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandMsrreadHelp();
return;
}
@ -85,10 +96,25 @@ VOID CommandMsrread(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !msrwrite command
*
* @return VOID
*/
VOID CommandMsrwriteHelp() {
ShowMessages("!msrwrite : Detects the execution of wrmsr instructions.\n\n");
ShowMessages("syntax : \t!msrwrite [msr (hex value) - if not specific means "
@ -25,6 +30,12 @@ VOID CommandMsrwriteHelp() {
ShowMessages("\t\te.g : !msrwrite core 2 pid 400\n");
}
/**
* @brief !msrwrite command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandMsrwrite(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -58,6 +69,7 @@ VOID CommandMsrwrite(vector<string> SplittedCommand) {
// It's probably an msr
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
@ -68,10 +80,11 @@ VOID CommandMsrwrite(vector<string> SplittedCommand) {
GetAddress = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandMsrwriteHelp();
return;
}
@ -85,10 +98,25 @@ VOID CommandMsrwrite(vector<string> SplittedCommand) {
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -17,6 +17,14 @@
// //
////////////////////////////////////////////////////////////////////////////
/**
* @brief Create a named pipe server
*
* @param PipeName
* @param OutputBufferSize
* @param InputBufferSize
* @return HANDLE
*/
HANDLE NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize,
UINT32 InputBufferSize) {
@ -42,6 +50,12 @@ HANDLE NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize,
return hPipe;
}
/**
* @brief wait for client conncetion
*
* @param PipeHandle
* @return BOOLEAN
*/
BOOLEAN NamedPipeServerWaitForClientConntection(HANDLE PipeHandle) {
//
@ -63,6 +77,14 @@ BOOLEAN NamedPipeServerWaitForClientConntection(HANDLE PipeHandle) {
return TRUE;
}
/**
* @brief read client message from the named pipe
*
* @param PipeHandle
* @param BufferToSave
* @param MaximumReadBufferLength
* @return UINT32
*/
UINT32 NamedPipeServerReadClientMessage(HANDLE PipeHandle, char *BufferToSave,
int MaximumReadBufferLength) {
@ -91,6 +113,7 @@ UINT32 NamedPipeServerReadClientMessage(HANDLE PipeHandle, char *BufferToSave,
CloseHandle(PipeHandle);
return 0;
}
//
// Number of bytes that the client sends to us
//
@ -121,6 +144,12 @@ BOOLEAN NamedPipeServerSendMessageToClient(HANDLE PipeHandle,
return TRUE;
}
/**
* @brief Close handle of server's named pipe
*
* @param PipeHandle
* @return VOID
*/
VOID NamedPipeServerCloseHandle(HANDLE PipeHandle) { CloseHandle(PipeHandle); }
//**************************************************************************
@ -131,12 +160,15 @@ VOID NamedPipeServerCloseHandle(HANDLE PipeHandle) { CloseHandle(PipeHandle); }
// //
////////////////////////////////////////////////////////////////////////////
//
// Pipe name format - \\servername\pipe\pipename
// This pipe is for server on the same computer,
// however, pipes can be used to connect to a remote server
//
/**
* @brief Create a client named pipe
* @details Pipe name format - \\servername\pipe\pipename
* This pipe is for server on the same computer,
* however, pipes can be used to connect to a remote server
*
* @param PipeName
* @return HANDLE
*/
HANDLE NamedPipeClientCreatePipe(LPCSTR PipeName) {
HANDLE hPipe;
@ -171,6 +203,14 @@ HANDLE NamedPipeClientCreatePipe(LPCSTR PipeName) {
}
}
/**
* @brief send client message over named pipe
*
* @param PipeHandle
* @param BufferToSend
* @param BufferSize
* @return BOOLEAN
*/
BOOLEAN NamedPipeClientSendMessage(HANDLE PipeHandle, char *BufferToSend,
int BufferSize) {
@ -239,6 +279,12 @@ UINT32 NamedPipeClientReadMessage(HANDLE PipeHandle, char *BufferToRead,
return cbBytes;
}
/**
* @brief close named pipe handle of client
*
* @param PipeHandle
* @return VOID
*/
VOID NamedPipeClientClosePipe(HANDLE PipeHandle) { CloseHandle(PipeHandle); }
////////////////////////////////////////////////////////////////////////////
@ -247,6 +293,11 @@ VOID NamedPipeClientClosePipe(HANDLE PipeHandle) { CloseHandle(PipeHandle); }
// //
////////////////////////////////////////////////////////////////////////////
/**
* @brief and example of how to use named pipe as a server
*
* @return int
*/
int NamedPipeServerExample() {
HANDLE PipeHandle;
@ -259,6 +310,7 @@ int NamedPipeServerExample() {
PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests",
BufferSize, BufferSize);
if (!PipeHandle) {
//
// Error in creating handle
//
@ -266,6 +318,7 @@ int NamedPipeServerExample() {
}
if (!NamedPipeServerWaitForClientConntection(PipeHandle)) {
//
// Error in connection
//
@ -276,6 +329,7 @@ int NamedPipeServerExample() {
NamedPipeServerReadClientMessage(PipeHandle, BufferToRead, BufferSize);
if (!ReadBytes) {
//
// Nothing to read
//
@ -288,6 +342,7 @@ int NamedPipeServerExample() {
PipeHandle, BufferToSend, strlen(BufferToSend) + 1);
if (!SentMessageResult) {
//
// error in sending
//
@ -305,6 +360,11 @@ int NamedPipeServerExample() {
// //
////////////////////////////////////////////////////////////////////////////
/**
* @brief and example of how to use named pipe as a client
*
* @return int
*/
int NamedPipeClientExample() {
HANDLE PipeHandle;
@ -316,6 +376,7 @@ int NamedPipeClientExample() {
PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests");
if (!PipeHandle) {
//
// Unable to create handle
//
@ -326,6 +387,7 @@ int NamedPipeClientExample() {
NamedPipeClientSendMessage(PipeHandle, Buffer, strlen(Buffer) + 1);
if (!SentMessageResult) {
//
// Sending error
//
@ -335,6 +397,7 @@ int NamedPipeClientExample() {
ReadBytes = NamedPipeClientReadMessage(PipeHandle, Buffer, BufferSize);
if (!ReadBytes) {
//
// Nothing to read
//

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !pa2va command
*
* @return VOID
*/
VOID CommandPa2vaHelp() {
ShowMessages("!pa2va : Converts virtual address to physical address.\n\n");
ShowMessages("syntax : \t!pa2va [Virtual Address (hex value)] pid [Process "
@ -19,6 +24,12 @@ VOID CommandPa2vaHelp() {
ShowMessages("\t\te.g : !pa2va fffff801deadbeef pid 0xc8\n");
}
/**
* @brief !pa2va command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandPa2va(vector<string> SplittedCommand) {
BOOL Status;
@ -35,6 +46,7 @@ VOID CommandPa2va(vector<string> SplittedCommand) {
}
if (SplittedCommand.size() == 2) {
//
// It's just a address for current process
//
@ -79,7 +91,8 @@ VOID CommandPa2va(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -107,7 +120,7 @@ VOID CommandPa2va(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}

View file

@ -16,11 +16,22 @@
//
extern BOOLEAN g_BreakPrintingOutput;
/**
* @brief help of pause command
*
* @return VOID
*/
VOID CommandPauseHelp() {
ShowMessages("pause : pauses the kernel events.\n\n");
ShowMessages("syntax : \tpause\n");
}
/**
* @brief pause command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandPause(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {

View file

@ -28,6 +28,10 @@
// add headers that you want to pre-compile here
//
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <algorithm>
#include <array>
@ -48,6 +52,9 @@
#include <winioctl.h>
#include <winternl.h>
#include <fstream>
#include <shlobj.h>
#include <tchar.h>
#include <numeric>
//
// HyperDbg defined headers
@ -62,7 +69,17 @@
#include "install.h"
#include "list.h"
#include "tests.h"
#include "transparency.h"
#include "communication.h"
#endif // PCH_H
#pragma comment(lib, "ntdll.lib")
//
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
// for tcpclient.cpp and tcpserver.cpp
//
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
#pragma comment(lib, "AdvApi32.lib")

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !pmc command
*
* @return VOID
*/
VOID CommandPmcHelp() {
ShowMessages("!pmc : Monitors execution of rdpmc instructions.\n\n");
ShowMessages("syntax : \t!tsc core [core index "
@ -23,6 +28,12 @@ VOID CommandPmcHelp() {
ShowMessages("\t\te.g : !pmc core 2 pid 400\n");
}
/**
* @brief !pmc command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandPmc(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -41,13 +52,37 @@ VOID CommandPmc(vector<string> SplittedCommand) {
return;
}
//
// Check for size
//
if (SplittedCommand.size() > 1) {
ShowMessages("incorrect use of '!pmc'\n");
CommandPmcHelp();
return;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,12 +11,23 @@
*/
#include "pch.h"
/**
* @brief help of !pte command
*
* @return VOID
*/
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");
}
/**
* @brief !pte command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandPte(vector<string> SplittedCommand) {
BOOL Status;
@ -36,9 +47,11 @@ VOID CommandPte(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
//
// Prepare the buffer
// We use same buffer for input and output
@ -61,7 +74,7 @@ VOID CommandPte(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of rdmsr command
*
* @return VOID
*/
VOID CommandRdmsrHelp() {
ShowMessages("rdmsr : Reads a model-specific register (MSR).\n\n");
ShowMessages("syntax : \trdmsr [rcx (hex value)] core [core index (hex value "
@ -19,6 +24,12 @@ VOID CommandRdmsrHelp() {
ShowMessages("\t\te.g : rdmsr c0000082 core 2\n");
}
/**
* @brief rdmsr command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandRdmsr(vector<string> SplittedCommand) {
BOOL Status;
@ -65,6 +76,7 @@ VOID CommandRdmsr(vector<string> SplittedCommand) {
}
SetMsr = TRUE;
}
//
// Check if msr is set or not
//
@ -80,7 +92,8 @@ VOID CommandRdmsr(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -113,7 +126,8 @@ VOID CommandRdmsr(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
free(OutputBuffer);
return;
}
@ -121,6 +135,7 @@ VOID CommandRdmsr(vector<string> SplittedCommand) {
// btw, %x is enough, no need to %llx
//
if (CoreNumer == DEBUGGER_READ_AND_WRITE_ON_MSR_APPLY_ALL_CORES) {
//
// Show all cores
//
@ -130,10 +145,16 @@ VOID CommandRdmsr(vector<string> SplittedCommand) {
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());
}
//
// Free the buffer
//
free(OutputBuffer);
}

View file

@ -13,7 +13,15 @@
/**
* @brief Read memory and disassembler
*
* @details currently, HyperDbg is not support reading memory
* from vmx-root
*
* @param Style style of show memory (as byte, dwrod, qword)
* @param Address location of where to read the memory
* @param MemoryType type of memory (phyical or virtual)
* @param ReadingType read from kernel or vmx-root
* @param Pid The target process id
* @param Size size of memory to read
*/
void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
UINT64 Address,
@ -28,7 +36,8 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
CHAR Character;
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -56,7 +65,8 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
free(OutputBuffer);
return;
}
@ -66,6 +76,7 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
ShowMessages("#\t");
}
//
// Print address
//
@ -111,6 +122,7 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
ShowMessages("#\t");
}
//
// Print address
//
@ -130,6 +142,7 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
ShowMessages("%08X ", OutputBufferVar);
}
}
//
// Print the character
//
@ -157,6 +170,7 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
if (MemoryType == DEBUGGER_READ_PHYSICAL_ADDRESS) {
ShowMessages("#\t");
}
//
// Print address
//
@ -166,6 +180,7 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
// Print the hex code
//
for (size_t j = 0; j < 16; j += 8) {
//
// check to see if the address is valid or not
//
@ -185,9 +200,16 @@ void HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style,
//
ShowMessages("\n");
}
} else if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE) {
HyperDbgDisassembler(OutputBuffer, Address, ReturnedLength);
} else if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE64) {
HyperDbgDisassembler64(OutputBuffer, Address, ReturnedLength);
} else if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE32) {
HyperDbgDisassembler32(OutputBuffer, Address, ReturnedLength);
}
//
// free the buffer
//
free(OutputBuffer);
ShowMessages("\n");
}

View file

@ -0,0 +1,313 @@
/**
* @file remoteconnection.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief handle remote connections command
* @details
* @version 0.1
* @date 2020-08-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern BOOLEAN g_IsConnectedToRemoteDebugger;
extern BOOLEAN g_IsRemoteDebuggerMessageReceived;
extern SOCKET g_SeverSocket;
extern SOCKET g_ServerListenSocket;
extern SOCKET g_ClientConnectSocket;
extern HANDLE g_RemoteDebuggeeListeningThread;
/**
* @brief Listen of a port and wait for a client connection
* @details this routine is supposed to be called by .listen command
*
* @param Port
* @return VOID
*/
VOID RemoteConnectionListen(PCSTR Port) {
char recvbuf[COMMUNICATION_BUFFER_SIZE] = {0};
//
// Start server and wait for client
//
CommunicationServerCreateServerAndWaitForClient(Port, &g_SeverSocket,
&g_ServerListenSocket);
//
// Indicate that it's a remote debugger
//
g_IsConnectedToRemoteDebugger = TRUE;
//
// And also, make it a local debugger
//
g_IsConnectedToHyperDbgLocally = TRUE;
while (true) {
//
// Recieve message (this loop works as a command executer,
// we don't send the results to the remote machine by using
// this tools
//
if (CommunicationServerReceiveMessage(g_SeverSocket, recvbuf,
COMMUNICATION_BUFFER_SIZE) != 0) {
//
// Failed, break
//
break;
}
//
// Execute the command
//
int CommandExecutionResult = HyperdbgInterpreter(recvbuf);
//
// if the debugger encounters an exit state then the return will be 1
//
if (CommandExecutionResult == 1) {
//
// Exit from the debugger
//
exit(0);
}
//
// Zero the buffer for next command
//
RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
}
//
// Indicate that debugger is not connected
//
g_IsConnectedToHyperDbgLocally = FALSE;
//
// Indicate that it's note a remote debugger
//
g_IsConnectedToRemoteDebugger = FALSE;
//
// Inidicate that we're not in remote debugger anymore
//
ShowMessages("closing the conntection...\n");
//
// Close the connection
//
CommunicationServerShutdownAndCleanupConnection(g_SeverSocket,
g_ServerListenSocket);
}
/**
* @brief A thread that listens for server (debuggee) messages
* and show it by using ShowMessages wrapper
*
* @param lpParam
* @return DWORD
*/
DWORD WINAPI RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam) {
char recvbuf[COMMUNICATION_BUFFER_SIZE] = {0};
while (g_IsConnectedToRemoteDebuggee) {
//
// Receive message
//
if (CommunicationClientReceiveMessage(g_ClientConnectSocket, recvbuf,
COMMUNICATION_BUFFER_SIZE) != 0) {
//
// Failed, break
//
break;
};
//
// Show messages
//
ShowMessages("%s\n", recvbuf);
//
// Indicate that a message received
//
g_IsRemoteDebuggerMessageReceived = TRUE;
//
// Show the signature
//
HyperdbgShowSignature();
//
// Clear the buffer
//
RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
}
//
// The connection was aborted
// Uinitialize every connections
//
//
// Indicate that debugger is not connected
//
g_IsConnectedToHyperDbgLocally = FALSE;
//
// Indicate that it's a remote debuggee
//
g_IsConnectedToRemoteDebuggee = FALSE;
//
// Show the signature
//
HyperdbgShowSignature();
return 0;
}
/**
* @brief Connect to a remote debuggee (guest) as a client (host)
* @details this routine is supposed to be called by .connect command
*
* @param Ip
* @param Port
* @return VOID
*/
VOID RemoteConnectionConnect(PCSTR Ip, PCSTR Port) {
DWORD ThreadId;
//
// Connect to server
//
if (CommunicationClientConnectToServer(Ip, Port, &g_ClientConnectSocket) ==
1) {
//
// There was an error
//
//
// Indicate that debugger is not connected
//
g_IsConnectedToHyperDbgLocally = FALSE;
//
// Indicate that it's not a remote debuggee
//
g_IsConnectedToRemoteDebuggee = FALSE;
//
// Shutdown connection
//
CommunicationClientShutdownConnection(g_ClientConnectSocket);
//
// Cleanup
//
CommunicationClientCleanup(g_ClientConnectSocket);
} else {
//
// Indicate that local debugger is not connected
//
g_IsConnectedToHyperDbgLocally = FALSE;
//
// Indicate that it's a remote debuggee
//
g_IsConnectedToRemoteDebuggee = TRUE;
//
// Now, we should create a thread, which always listens to
// the remote debuggee for new messages
// Listen for upcoming messages
//
g_RemoteDebuggeeListeningThread = CreateThread(
NULL, 0, RemoteConnectionThreadListeningToDebuggee, NULL, 0, &ThreadId);
ShowMessages("connected to %s:%s\n", Ip, Port);
}
}
/**
* @brief send the command as a client (debugger, host) to the
* server (debuggee, guest)
*
* @param sendbuf address of message buffer
* @param len length of buffer
* @return int returning 0 means that there was no error in
* executing the function and 1 shows there was an error
*/
int RemoteConnectionSendCommand(const char *sendbuf, int len) {
//
// Indicate that we set a message and nothing received yet
//
g_IsRemoteDebuggerMessageReceived = FALSE;
//
// Send Message
//
if (CommunicationClientSendMessage(g_ClientConnectSocket, sendbuf, len) !=
0) {
//
// Failed
//
return 1;
}
//
// Successful
//
return 0;
}
/**
* @brief Send the results of executing a command from deubggee (server, guest)
* to the debugger (client, host)
*
* @param sendbuf buffer address
* @param len length of buffer
* @return int returning 0 means that there was no error in
* executing the function and 1 shows there was an error
*/
int RemoteConnectionSendResultsToHost(const char *sendbuf, int len) {
//
// Send the message
//
if (CommunicationServerSendMessage(g_SeverSocket, sendbuf, len) != 0) {
//
// Failed
//
return 1;
}
return 0;
}
/**
* @brief Close the connect from client side to the debuggee
*
* @return int returning 0 means that there was no error in
* executing the function and 1 shows there was an error
*/
int RemoteConnectionCloseTheConnectionWithDebuggee() {
CommunicationClientShutdownConnection(g_ClientConnectSocket);
CommunicationClientCleanup(g_ClientConnectSocket);
return 0;
}

View file

@ -11,9 +11,14 @@
*/
#include "pch.h"
/**
* @brief help of !s* s* commands
*
* @return VOID
*/
VOID CommandSearchMemoryHelp() {
ShowMessages("sb !sb sd !sd sq !sq : searches the memory for a special byte "
"pattern\n");
ShowMessages("sb !sb sd !sd sq !sq : searches a contiguous memory for a "
"special byte pattern\n");
ShowMessages("s[b] Byte and ASCII characters\n");
ShowMessages("s[d] Double-word values (4 bytes)\n");
ShowMessages("s[q] Quad-word values (8 bytes). \n");
@ -31,6 +36,12 @@ VOID CommandSearchMemoryHelp() {
"9090909090909090 l ffffff\n");
}
/**
* @brief !s* s* commands handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSearchMemory(vector<string> SplittedCommand) {
BOOL Status;
@ -41,6 +52,8 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
BOOL SetLength = FALSE;
BOOL NextIsLength = FALSE;
DEBUGGER_SEARCH_MEMORY SearchMemoryRequest = {0};
PUINT64 ResultsBuffer;
UINT64 CurrentValue;
UINT64 Address;
UINT64 Value = 0;
UINT64 Length = 0;
@ -79,6 +92,7 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_QWORD;
} else {
//
// What's this? :(
//
@ -102,6 +116,7 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
CommandSearchMemoryHelp();
return;
} else {
//
// Means that the proc id is set, next we should read value
//
@ -121,6 +136,7 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
CommandSearchMemoryHelp();
return;
} else {
//
// Means that the proc id is set, next we should read value
//
@ -151,6 +167,7 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
CommandSearchMemoryHelp();
return;
} else {
//
// Means that the address is set, next we should read value
//
@ -195,7 +212,6 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
// Qword is checked by the following function, no need to double
// check it above.
//
if (!ConvertStringToUInt64(Section, &Value)) {
ShowMessages("please specify a correct hex value to search in the "
"memory content\n\n");
@ -206,7 +222,6 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
//
// Add it to the list
//
ValuesToEdit.push_back(Value);
//
@ -215,6 +230,7 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
CountOfValues++;
if (!SetValue) {
//
// At least on walue is there
//
@ -263,7 +279,8 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -308,19 +325,60 @@ VOID CommandSearchMemory(vector<string> SplittedCommand) {
std::copy(ValuesToEdit.begin(), ValuesToEdit.end(),
(UINT64 *)((UINT64)FinalBuffer + SIZEOF_DEBUGGER_SEARCH_MEMORY));
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_SEARCH_MEMORY, // IO Control code
FinalBuffer, // Input Buffer to driver.
FinalSize, // Input buffer length
&SearchMemoryRequest, // Output Buffer from driver.
SIZEOF_DEBUGGER_SEARCH_MEMORY, // Length of output buffer in bytes.
NULL, // Bytes placed in buffer.
NULL // synchronous call
);
//
// Allocate a buffer to store the results
//
ResultsBuffer = (PUINT64)malloc(MaximumSearchResults * sizeof(UINT64));
//
// Also it's better to Zero the memory; however it's not necessary
// as we zero the buffer in the search routines
//
ZeroMemory(ResultsBuffer, MaximumSearchResults * sizeof(UINT64));
//
// Fire the IOCTL
//
Status =
DeviceIoControl(g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_SEARCH_MEMORY, // IO Control code
FinalBuffer, // Input Buffer to driver.
FinalSize, // Input buffer length
ResultsBuffer, // Output Buffer from driver.
MaximumSearchResults *
sizeof(UINT64), // 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());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
free(FinalBuffer);
return;
}
//
// Show the results (if any)
//
for (size_t i = 0; i < MaximumSearchResults; i++) {
CurrentValue = ResultsBuffer[i];
if (CurrentValue == NULL) {
//
// We ended up the buffer, nothing else to show,
// just check whether we found anything or not
//
if (i == 0) {
ShowMessages("Not found.\n");
}
break;
}
ShowMessages("%llx\n", CurrentValue);
}
//
// Free the buffers
//
free(FinalBuffer);
free(ResultsBuffer);
}

View file

@ -13,13 +13,28 @@
using namespace std;
//
// Global Variables
//
extern BOOLEAN g_ExecutingScript;
/**
* @brief help of .script command
*
* @return VOID
*/
VOID CommandScriptHelp() {
ShowMessages(".script : run a HyperDbg script.\n\n");
ShowMessages("syntax : \.script [FilePath]\n");
}
/**
* @brief .script command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID CommandScript(vector<string> SplittedCommand, string Command) {
std::string Line;

View file

@ -0,0 +1,239 @@
/**
* @file settings.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief settings command
* @details
* @version 0.1
* @date 2020-08-18
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_AutoUnpause;
extern BOOLEAN g_AutoFlush;
extern UINT32 g_DisassemblerSyntax;
/**
* @brief help of settings command
*
* @return VOID
*/
VOID CommandSettingsHelp() {
ShowMessages(
"settings : query, set, or change a value for a sepcial settings.\n\n");
ShowMessages("syntax : \tsettings [option name] [value (name | hex value | "
"on | off)]\n");
ShowMessages("\t\te.g : settings autounpause\n");
ShowMessages("\t\te.g : settings autounpause on\n");
ShowMessages("\t\te.g : settings autounpause off\n");
ShowMessages("\t\te.g : settings autoflush on\n");
ShowMessages("\t\te.g : settings autoflush off\n");
ShowMessages("\t\te.g : settings syntax intel\n");
ShowMessages("\t\te.g : settings syntax att\n");
ShowMessages("\t\te.g : settings syntax masm\n");
}
/**
* @brief set the auto-flush mode to enabled and disable
* and query the status of this mode
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSettingsAutoFlush(vector<string> SplittedCommand) {
if (SplittedCommand.size() == 2) {
//
// It's a query
//
if (g_AutoFlush) {
ShowMessages("auto-flush is enabled\n");
} else {
ShowMessages("auto-flush is disabled\n");
}
} else if (SplittedCommand.size() == 3) {
//
// The user tries to set a value as the autoflush
//
if (!SplittedCommand.at(2).compare("on")) {
g_AutoFlush = TRUE;
ShowMessages("set auto-flush to enabled\n");
} else if (!SplittedCommand.at(2).compare("off")) {
g_AutoFlush = FALSE;
ShowMessages("set auto-flush to disabled\n");
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
}
/**
* @brief set auto-unpause mode to enabled or disabled
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSettingsAutoUpause(vector<string> SplittedCommand) {
if (SplittedCommand.size() == 2) {
//
// It's a query
//
if (g_AutoUnpause) {
ShowMessages("auto-unpause is enabled\n");
} else {
ShowMessages("auto-unpause is disabled\n");
}
} else if (SplittedCommand.size() == 3) {
//
// The user tries to set a value as the autounpause
//
if (!SplittedCommand.at(2).compare("on")) {
g_AutoUnpause = TRUE;
ShowMessages("set auto-unpause to enabled\n");
} else if (!SplittedCommand.at(2).compare("off")) {
g_AutoUnpause = FALSE;
ShowMessages("set auto-unpause to disabled\n");
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
}
/**
* @brief set the syntax of !u !u2 u u2 command
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSettingsSyntax(vector<string> SplittedCommand) {
if (SplittedCommand.size() == 2) {
//
// It's a query
//
if (g_DisassemblerSyntax == 1) {
ShowMessages("disassembler syntax is : intel\n");
} else if (g_DisassemblerSyntax == 2) {
ShowMessages("disassembler syntax is : at&t\n");
} else if (g_DisassemblerSyntax == 3) {
ShowMessages("disassembler syntax is : masm\n");
} else {
ShowMessages("unknown syntax\n");
}
} else if (SplittedCommand.size() == 3) {
//
// The user tries to set a value as the syntax
//
if (!SplittedCommand.at(2).compare("intel")) {
g_DisassemblerSyntax = 1;
ShowMessages("set syntax to intel\n");
} else if (!SplittedCommand.at(2).compare("att") ||
!SplittedCommand.at(2).compare("at&t")) {
g_DisassemblerSyntax = 2;
ShowMessages("set syntax to at&t\n");
} else if (!SplittedCommand.at(2).compare("masm")) {
g_DisassemblerSyntax = 3;
ShowMessages("set syntax to masm\n");
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
} else {
//
// Sth is incorrect
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
}
/**
* @brief settings command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSettings(vector<string> SplittedCommand) {
if (SplittedCommand.size() <= 1) {
ShowMessages("incorrect use of 'settings'\n\n");
CommandSettingsHelp();
return;
}
//
// Interpret the field name
//
if (!SplittedCommand.at(1).compare("autounpause")) {
CommandSettingsAutoUpause(SplittedCommand);
} else if (!SplittedCommand.at(1).compare("syntax")) {
CommandSettingsSyntax(SplittedCommand);
} else if (!SplittedCommand.at(1).compare("autoflush")) {
CommandSettingsAutoFlush(SplittedCommand);
} else {
//
// optionm not found
//
ShowMessages("incorrect use of 'settings', please use 'help settings' "
"for more details.\n");
return;
}
}

View file

@ -11,13 +11,24 @@
*/
#include "pch.h"
/**
* @brief help of sleep command
*
* @return VOID
*/
VOID CommandSleepHelp() {
ShowMessages("sleep : sleep command is used in scripts, it doesn't breaks "
"the debugger but the debugger still shows the buffers received "
"from kernel.\n\n");
ShowMessages("syntax : \sleep [time - milliseconds (hex value)]\n");
ShowMessages("syntax : \tsleep [time - milliseconds (hex value)]\n");
}
/**
* @brief sleep command help
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandSleep(vector<string> SplittedCommand) {
UINT32 MillisecondsTime = 0;

View file

@ -0,0 +1,79 @@
/**
* @file status.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief status command
* @details
* @version 0.1
* @date 2020-08-23
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsDebuggerModulesLoaded;
extern BOOLEAN g_IsConnectedToRemoteDebuggee;
extern BOOLEAN g_IsConnectedToRemoteDebugger;
extern string g_ServerPort;
extern string g_ServerIp;
/**
* @brief help of .status command
*
* @return VOID
*/
VOID CommandStatusHelp() {
ShowMessages(".status | status : get the status of current debugger in local "
"system (if you connected to a remote system then '.status' "
"shows the state of current debugger, while 'status' shows the "
"state of remote debuggee).\n\n");
ShowMessages("syntax : \t.status\n");
ShowMessages("syntax : \tstatus\n");
}
/**
* @brief .status command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandStatus(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
ShowMessages("incorrect use of '.status'\n\n");
CommandStatusHelp();
}
if (g_IsConnectedToRemoteDebuggee) {
//
// Connected to a remote debuggee
//
ShowMessages("remote debugging ('survey mode'), ip : %s:%s \n",
g_ServerIp.c_str(), g_ServerPort.c_str());
} else if (g_IsConnectedToHyperDbgLocally) {
//
// Connected to a local system
//
ShowMessages("local debugging ('survey mode')\n");
} else if (g_IsConnectedToRemoteDebugger) {
//
// It's computer connect to a remote machine
//
ShowMessages("a remote debugger connected to this system in ('survey "
"mode'), ip : %s:%s \n",
g_ServerIp.c_str(), g_ServerPort.c_str());
} else {
//
// we never should see this message
//
ShowMessages("not connected to any instance of HyperDbg.\n");
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !syscall command
*
* @return VOID
*/
VOID CommandSyscallHelp() {
ShowMessages("!syscall : Monitors and hooks all execution of syscall "
"instructions.\n\n");
@ -25,6 +30,11 @@ VOID CommandSyscallHelp() {
ShowMessages("\t\te.g : !syscall 0x55 core 2 pid 400\n");
}
/**
* @brief help of !sysret command
*
* @return VOID
*/
VOID CommandSysretHelp() {
ShowMessages("!sysret : Monitors and hooks all execution of sysret "
"instructions.\n\n");
@ -38,6 +48,11 @@ VOID CommandSysretHelp() {
ShowMessages("\t\te.g : !sysret core 2 pid 400\n");
}
/**
* @brief !syscall and !sysret commands handler
*
* @param SplittedCommand
*/
void CommandSyscallAndSysret(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -46,7 +61,6 @@ void CommandSyscallAndSysret(vector<string> SplittedCommand) {
UINT32 ActionLength;
UINT64 SpecialTarget = DEBUGGER_EVENT_SYSCALL_ALL_SYSRET_OR_SYSCALLS;
BOOLEAN GetSyscallNumber = FALSE;
;
//
// Interpret and fill the general event and action fields
@ -80,63 +94,74 @@ void CommandSyscallAndSysret(vector<string> SplittedCommand) {
//
if (!SplittedCommand.at(0).compare("!syscall")) {
for (auto Section : SplittedCommand) {
if (!Section.compare("!syscall") || !Section.compare("!sysret")) {
continue;
for (auto Section : SplittedCommand) {
if (!Section.compare("!syscall") || !Section.compare("!sysret")) {
continue;
} else if (!GetSyscallNumber) {
//
// It's probably a syscall address
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
if (!SplittedCommand.at(0).compare("!syscall")) {
CommandSyscallHelp();
} else {
CommandSysretHelp();
}
else if (!GetSyscallNumber) {
return;
} else {
GetSyscallNumber = TRUE;
}
} else {
//
// It's probably a syscall address
//
if (!ConvertStringToUInt64(Section, &SpecialTarget)) {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
if (!SplittedCommand.at(0).compare("!syscall")) {
CommandSyscallHelp();
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
if (!SplittedCommand.at(0).compare("!syscall")) {
CommandSyscallHelp();
}
else {
CommandSysretHelp();
}
return;
}
else {
GetSyscallNumber = TRUE;
}
}
else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
if (!SplittedCommand.at(0).compare("!syscall")) {
CommandSyscallHelp();
}
else {
CommandSysretHelp();
}
return;
}
} else {
CommandSysretHelp();
}
return;
}
}
//
// Set the target syscall
//
Event->OptionalParam1 = SpecialTarget;
//
// Set the target syscall
//
Event->OptionalParam1 = SpecialTarget;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -0,0 +1,260 @@
/**
* @file tcpclient.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief Server functions over TCP
* @details
* @version 0.1
* @date 2020-08-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief communication for client, connecting to the server
*
* @param Ip
* @param Port
* @param ConnectSocketArg
* @return int
*/
int CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port,
SOCKET *ConnectSocketArg) {
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
//
// Initialize Winsock
//
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
ShowMessages("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
//
// Resolve the server address and port
//
iResult = getaddrinfo(Ip, Port, &hints, &result);
if (iResult != 0) {
ShowMessages("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
//
// Attempt to connect to an address until one succeeds
//
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
//
// Create a SOCKET for connecting to server
//
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//
// Connect to server.
//
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
ShowMessages("Unable to connect to server!\n");
WSACleanup();
return 1;
}
//
// Store the arguments
//
*ConnectSocketArg = ConnectSocket;
return 0;
}
/**
* @brief Send message a client
*
* @param ConnectSocket
* @param sendbuf
* @param buflen
* @return int
*/
int CommunicationClientSendMessage(SOCKET ConnectSocket, const char *sendbuf,
int buflen) {
int iResult;
//
// Send an initial buffer
//
iResult = send(ConnectSocket, sendbuf, buflen, 0);
if (iResult == SOCKET_ERROR) {
ShowMessages("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
return 0;
}
/**
* @brief shutdown the connection as a client
*
* @param ConnectSocket
* @return int
*/
int CommunicationClientShutdownConnection(SOCKET ConnectSocket) {
int iResult;
//
// shutdown the connection since no more data will be sent
//
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
//
// We comment this line because the connection might be removed;
// thus, we don't need to show error
//
/*
ShowMessages("shutdown failed with error: %d\n", WSAGetLastError());
*/
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
return 0;
}
/**
* @brief Receive message as a client
*
* @param ConnectSocket
* @param recvbuf
* @param recvbuflen
* @return int
*/
int CommunicationClientReceiveMessage(SOCKET ConnectSocket, char *recvbuf,
int recvbuflen) {
int iResult;
//
// Receive until the peer closes the connection
//
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
/*
ShowMessages("Bytes received: %d\n", iResult);
*/
} else if (iResult == 0) {
//
// Last packet
//
} else {
ShowMessages("\nrecv failed with error: %d\n", WSAGetLastError());
ShowMessages("the remote system closes the connection.\n\n");
return 1;
}
return 0;
}
/**
* @brief cleanup the connection as client
*
* @param ConnectSocket
* @return int
*/
int CommunicationClientCleanup(SOCKET ConnectSocket) {
//
// cleanup
//
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
//
// int __cdecl main(int argc, char **argv) {
//
// SOCKET ConnectSocket;
// char sendbuf[DEFAULT_BUFLEN] = "I am sinaei";
// char recvbuf[DEFAULT_BUFLEN] = {0};
//
// //
// // Connect to server
// //
// CommunicationClientConnectToServer("127.0.0.1", DEFAULT_PORT,
// &ConnectSocket);
//
// while (true) {
// //
// // Send Message
// //
// if (CommunicationClientSendMessage(ConnectSocket, sendbuf,
// strlen(sendbuf)) != 0) {
// //
// // Failed, break
// //
// break;
// }
//
// //
// // Receive final message
// //
// if (CommunicationClientReceiveMessage(ConnectSocket, recvbuf,
// DEFAULT_BUFLEN) != 0) {
// //
// // Failed, break
// //
// break;
// };
// ShowMessages("%s\n", recvbuf);
// }
//
// //
// // Shutdown connection
// //
// CommunicationClientShutdownConnection(ConnectSocket);
//
// //
// // Cleanup
// //
// CommunicationClientCleanup(ConnectSocket);
//
// return 0;
// }
//

View file

@ -0,0 +1,297 @@
/**
* @file tcpserver.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief Server functions over TCP
* @details
* @version 0.1
* @date 2020-08-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include "pch.h"
//
// Disable it because we want to use inet_ntoa
//
#pragma warning(disable : 4996)
/**
* @brief Create server and wait for a client to connect
* @details this function only accepts one client not multiple clients
*
* @param Port
* @param ClientSocketArg
* @param ListenSocketArg
* @return int
*/
int CommunicationServerCreateServerAndWaitForClient(PCSTR Port,
SOCKET *ClientSocketArg,
SOCKET *ListenSocketArg) {
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
//
// Initialize Winsock
//
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
ShowMessages("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
//
// Resolve the server address and port
//
iResult = getaddrinfo(NULL, Port, &hints, &result);
if (iResult != 0) {
ShowMessages("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
//
// Create a SOCKET for connecting to server
//
ListenSocket =
socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
//
// Setup the TCP listening socket
//
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
ShowMessages("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
ShowMessages("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//
// Accept a client socket
//
sockaddr_in name = {0};
int addrlen = sizeof(name);
ClientSocket = accept(ListenSocket, (struct sockaddr *)&name, &addrlen);
if (ClientSocket == INVALID_SOCKET) {
ShowMessages("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//
// Show that we connected to a client
//
ShowMessages("connected to : %s:%d\n", inet_ntoa(name.sin_addr),
ntohs(name.sin_port));
//
// Set the argument
//
*ClientSocketArg = ClientSocket;
*ListenSocketArg = ListenSocket;
return 0;
}
/**
* @brief listen and receive message as the server
*
* @param ClientSocket
* @param recvbuf
* @param recvbuflen
* @return int
*/
int CommunicationServerReceiveMessage(SOCKET ClientSocket, char *recvbuf,
int recvbuflen) {
int iResult;
//
// Receive until the peer shuts down the connection
//
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
//
// ShowMessages("Bytes received: %d\n", iResult);
//
} else if (iResult == 0) {
//
// ShowMessages("Connection closing...\n");
//
} else {
ShowMessages("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
return 0;
}
/**
* @brief send message as the server
*
* @param ClientSocket
* @param sendbuf
* @param length
* @return int
*/
int CommunicationServerSendMessage(SOCKET ClientSocket, const char *sendbuf,
int length) {
int iSendResult;
//
// Echo the buffer back to the sender
//
iSendResult = send(ClientSocket, sendbuf, length, 0);
if (iSendResult == SOCKET_ERROR) {
/*
ShowMessages("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
*/
return 1;
}
return 0;
}
/**
* @brief Shutdown and cleanup connection as server
*
* @param ClientSocket
* @param ListenSocket
* @return int
*/
int CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket,
SOCKET ListenSocket) {
int iResult;
//
// No longer need server socket
//
closesocket(ListenSocket);
//
// shutdown the connection since we're done
//
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
//
// We comment this line because the connection might be removed;
// thus, we don't need to show error
//
/*
ShowMessages("shutdown failed with error: %d\n", WSAGetLastError());
*/
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//
// cleanup
//
closesocket(ClientSocket);
WSACleanup();
return 0;
}
//
// int __cdecl main(void) {
//
// SOCKET ClientSocket;
// SOCKET ListenSocket;
//
// char recvbuf[DEFAULT_BUFLEN] = {0};
// char sendbuf[DEFAULT_BUFLEN] = "hello, I love taylor";
//
// //
// // Start server and wait for client
// //
// CommunicationServerCreateServerAndWaitForClient(DEFAULT_PORT,
// &ClientSocket,
// &ListenSocket);
//
// while (true) {
//
// //
// // Recieve message
// //
// if (CommunicationServerReceiveMessage(ClientSocket, recvbuf,
// DEFAULT_BUFLEN) != 0) {
// //
// // Failed, break
// //
// break;
// }
//
// ShowMessages("%s\n", recvbuf);
//
// //
// // Send the message
// //
// if (CommunicationServerSendMessage(ClientSocket, sendbuf,
// strlen(sendbuf)) != 0) {
// //
// // Failed, break
// //
// break;
// }
// }
//
// ShowMessages("close conntection\n");
//
// //
// // Close the connection
// //
// CommunicationServerShutdownAndCleanupConnection(ClientSocket,
// ListenSocket);
//
// return 0;
// }
//

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of test command
*
* @return VOID
*/
VOID CommandTestHelp() {
ShowMessages(
"test : Test essential features of HyperDbg in current machine.\n");
@ -20,6 +25,12 @@ VOID CommandTestHelp() {
ShowMessages("\t\te.g : test 0x3\n");
}
/**
* @brief test command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandTest(vector<string> SplittedCommand) {
BOOLEAN GetTestCase = FALSE;
@ -46,6 +57,7 @@ VOID CommandTest(vector<string> SplittedCommand) {
// It's probably a test case number
//
if (!ConvertStringToUInt64(Section, &SpecialTestCase)) {
//
// Unkonwn parameter
//
@ -56,10 +68,11 @@ VOID CommandTest(vector<string> SplittedCommand) {
GetTestCase = TRUE;
}
} else {
//
// Unkonwn parameter
//
ShowMessages("Unknown parameter '%s'\n", Section.c_str());
ShowMessages("Unknown parameter '%s'\n\n", Section.c_str());
CommandTestHelp();
return;
}
@ -69,11 +82,13 @@ VOID CommandTest(vector<string> SplittedCommand) {
// Perform the test case
//
if (SpecialTestCase == DEBUGGER_TEST_ALL_COMMANDS) {
//
// Means to check everything
//
TestEverything = TRUE;
}
//
// Means to check just one command
//
@ -107,6 +122,7 @@ VOID CommandTest(vector<string> SplittedCommand) {
// Check if it was just one check
//
if (!TestEverything || AllChecksPerformed) {
//
// Break from loop
//

View file

@ -14,7 +14,6 @@
//
// Test cases
//
#define DEBUGGER_TEST_ALL_COMMANDS 0x0
#define DEBUGGER_TEST_VMM_MONITOR_COMMAND 0x1

View file

@ -0,0 +1,228 @@
/**
* @file transparency.cpp
* @author Sina Karvandi (sina@rayanfam.com)
* @brief Measurements for debugger transparency
* @details
* @version 0.1
* @date 2020-07-07
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
using namespace std;
/**
* @brief get the difference clock cycles between two rdtsc(s)
*
* @return unsigned long long
*/
unsigned long long TransparentModeRdtscDiffVmexit() {
unsigned long long ret, ret2;
unsigned eax, edx;
int cpuid_result[4] = {0};
//
// GCC
//
// __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx));
// ret = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
//
// Win32
//
ret = __rdtsc();
/* vm exit forced here. it uses: eax = 0; cpuid; */
//
// GCC
//
//__asm__ volatile("cpuid" : /* no output */ : "a"(0x00));
//
// WIN32
//
__cpuid(cpuid_result, 0);
//
// GCC
//
// __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx));
// ret2 = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
//
// WIN32
//
ret2 = __rdtsc();
return ret2 - ret;
}
/**
* @brief get the difference clock cycles between rdtsc+cpuid+rdtsc
*
* @return unsigned long long
*/
unsigned long long TransparentModeRdtscVmexitTracing() {
unsigned long long ret, ret2;
unsigned eax, edx;
//
// GCC
//
// __asm__ volatile("rdtsc" : "=a" (eax), "=d" (edx));
// ret = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
//
// WIN32
//
ret = __rdtsc();
//
// GCC
//
// __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx));
// ret2 = ((unsigned long long)eax) | (((unsigned long long)edx) << 32);
//
// WIN32
//
ret2 = __rdtsc();
return ret2 - ret;
}
/**
* @brief compute the average, standard deviation and median if
* rdtsc+cpuid+rdtsc
*
* @param Average a pointer to save average on it
* @param StandardDeviation a pointer to standard deviation average on it
* @param Median a pointer to save median on it
* @return int
*/
int TransparentModeCpuidTimeStampCounter(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median) {
unsigned long long Avg = 0;
unsigned long long MeasuredTime = 0;
vector<double> Results;
for (int i = 0; i < TestCount; i++) {
MeasuredTime = TransparentModeRdtscDiffVmexit();
Avg = Avg + MeasuredTime;
Results.push_back(MeasuredTime);
//
// ShowMessages("(%d) Measured time : %d\n", i, MeasuredTime);
//
}
if (Average != NULL && StandardDeviation != NULL && Median != NULL) {
//
// Compute the average and variance
//
GuassianGenerateRandom(Results, Average, StandardDeviation, Median);
}
Avg = Avg / TestCount;
return (Avg < 1000 && Avg > 0) ? FALSE : TRUE;
}
/**
* @brief compute the average, standard deviation and median if
* rdtsc+rdtsc
*
* @param Average a pointer to save average on it
* @param StandardDeviation a pointer to standard deviation average on it
* @param Median a pointer to save median on it
* @return int
*/
int TransparentModeRdtscEmulationDetection(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median) {
unsigned long long Avg = 0;
unsigned long long MeasuredTime = 0;
vector<double> Results;
for (int i = 0; i < TestCount; i++) {
MeasuredTime = TransparentModeRdtscVmexitTracing();
Avg = Avg + MeasuredTime;
Results.push_back(MeasuredTime);
/*
ShowMessages("(%d) Measured time : %d\n", i, MeasuredTime);
*/
}
if (Average != NULL && StandardDeviation != NULL && Median != NULL) {
//
// Compute the average and variance
//
GuassianGenerateRandom(Results, Average, StandardDeviation, Median);
}
Avg = Avg / TestCount;
return (Avg < 750 && Avg > 0) ? FALSE : TRUE;
}
/**
* @brief compute the average, standard deviation and median if
* rdtsc+cpuid+rdtsc
* @details detects the presence of hypervisor
*
* @param Average a pointer to save average on it
* @param StandardDeviation a pointer to standard deviation average on it
* @param Median a pointer to save median on it
* @return int
*/
BOOLEAN TransparentModeCheckHypervisorPresence(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median) {
//
// Check whether the hypervisor is detected or not
//
if (TransparentModeCpuidTimeStampCounter(Average, StandardDeviation,
Median)) {
ShowMessages("hypervisor detected\n");
return TRUE;
} else {
ShowMessages("hypervisor not detected\n");
return FALSE;
}
}
/**
* @brief compute the average, standard deviation and median if
* rdtsc+rdtsc
* @details detects the presence of rdtsc/p vm-exits
*
* @param Average a pointer to save average on it
* @param StandardDeviation a pointer to standard deviation average on it
* @param Median a pointer to save median on it
* @return int
*/
BOOLEAN TransparentModeCheckRdtscpVmexit(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median) {
//
// Check whether the system emulating rdtsc/p or not
//
if (TransparentModeRdtscEmulationDetection(Average, StandardDeviation,
Median)) {
ShowMessages("rdtsc/p emulation detected\n");
return TRUE;
} else {
ShowMessages("rdtsc/p emulation not detected\n");
return FALSE;
}
}

View file

@ -0,0 +1,39 @@
/**
* @file transparency.h
* @author Sina Karvandi (sina@rayanfam.com)
* @brief headers for test functions
* @details
* @version 0.1
* @date 2020-07-30
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#pragma once
/**
* @brief Number of tests for each instruction sets
* @details used to generate test cases for rdts+cpuid+rdtsc
* and rdtsc+rdtsc commands
*/
#define TestCount 1000
void GuassianGenerateRandom(vector<double> Data, UINT64 *AverageOfData,
UINT64 *StandardDeviationOfData,
UINT64 *MedianOfData);
BOOLEAN TransparentModeCheckHypervisorPresence(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median);
BOOLEAN TransparentModeCheckRdtscpVmexit(UINT64 *Average,
UINT64 *StandardDeviation,
UINT64 *Median);
double Randn(double mu, double sigma);
double Median(vector<double> Cases);
unsigned long long TransparentModeRdtscDiffVmexit();
unsigned long long TransparentModeRdtscVmexitTracing();

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !tsc command
*
* @return VOID
*/
VOID CommandTscHelp() {
ShowMessages("!tsc : Monitors execution of rdtsc/rdtscp instructions.\n\n");
ShowMessages("syntax : \t!tsc core [core index "
@ -23,6 +28,12 @@ VOID CommandTscHelp() {
ShowMessages("\t\te.g : !tsc core 2 pid 400\n");
}
/**
* @brief handler of !tsc command
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandTsc(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -41,13 +52,37 @@ VOID CommandTsc(vector<string> SplittedCommand) {
return;
}
//
// Check for size
//
if (SplittedCommand.size() > 1) {
ShowMessages("incorrect use of '!tsc'\n");
CommandTscHelp();
return;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,12 +11,23 @@
*/
#include "pch.h"
/**
* @brief help of !unhide command
*
* @return VOID
*/
VOID CommandUnhideHelp() {
ShowMessages("!unhide : Reveals the debugger to the applications.\n\n");
ShowMessages("syntax : \t!unhide\n");
ShowMessages("\t\te.g : !unhide\n");
}
/**
* @brief !unhide command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandUnhide(vector<string> SplittedCommand) {
BOOLEAN Status;
@ -33,7 +44,8 @@ VOID CommandUnhide(vector<string> SplittedCommand) {
// Check if debugger is loaded or not
//
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -45,7 +57,6 @@ VOID CommandUnhide(vector<string> SplittedCommand) {
//
// Send the request to the kernel
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control
@ -60,7 +71,7 @@ VOID CommandUnhide(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}
@ -68,8 +79,8 @@ VOID CommandUnhide(vector<string> SplittedCommand) {
ShowMessages("transparent debugging successfully disabled :)\n");
} else if (UnhideRequest.KernelStatus ==
DEBUGEER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER) {
ShowMessages("unable to unhide the debugger (transparent-debugging) :(\n");
DEBUGEER_ERROR_DEBUGGER_ALREADY_UHIDE) {
ShowMessages("debugger is not in transparent-mode.\n");
} else {
ShowMessages("unknown error occured :(\n");

View file

@ -14,15 +14,26 @@
//
// Global Variables
//
extern BOOLEAN g_IsConnectedToDebugger;
extern BOOLEAN g_IsConnectedToHyperDbgLocally;
extern BOOLEAN g_IsDebuggerModulesLoaded;
/**
* @brief help of unload command
*
* @return VOID
*/
VOID CommandUnloadHelp() {
ShowMessages(
"unload : unloads the kernel modules and uninstalls the drivers.\n\n");
ShowMessages("syntax : \tunload\n");
}
/**
* @brief unload command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandUnload(vector<string> SplittedCommand) {
if (SplittedCommand.size() != 1) {
@ -30,7 +41,7 @@ VOID CommandUnload(vector<string> SplittedCommand) {
CommandLoadHelp();
return;
}
if (!g_IsConnectedToDebugger) {
if (!g_IsConnectedToHyperDbgLocally) {
ShowMessages("You're not connected to any instance of HyperDbg, did you "
"use '.connect'? \n");
return;

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !va2pa command
*
* @return VOID
*/
VOID CommandVa2paHelp() {
ShowMessages("!va2pa : Converts virtual address to physical address.\n\n");
ShowMessages("syntax : \t!va2pa [Virtual Address (hex value)] pid [Process "
@ -19,6 +24,12 @@ VOID CommandVa2paHelp() {
ShowMessages("\t\te.g : !va2pa fffff801deadbeef pid 0xc8\n");
}
/**
* @brief !va2pa command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandVa2pa(vector<string> SplittedCommand) {
BOOL Status;
@ -35,6 +46,7 @@ VOID CommandVa2pa(vector<string> SplittedCommand) {
}
if (SplittedCommand.size() == 2) {
//
// It's just a address for current process
//
@ -79,7 +91,8 @@ VOID CommandVa2pa(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -107,7 +120,7 @@ VOID CommandVa2pa(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of !vmcall command
*
* @return VOID
*/
VOID CommandVmcallHelp() {
ShowMessages("!vmcall : Monitors execution of VMCALL instruction.\n\n");
ShowMessages("syntax : \t!vmcall core [core index "
@ -23,6 +28,12 @@ VOID CommandVmcallHelp() {
ShowMessages("\t\te.g : !vmcall core 2 pid 400\n");
}
/**
* @brief !vmcall command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandVmcall(vector<string> SplittedCommand) {
PDEBUGGER_GENERAL_EVENT_DETAIL Event;
@ -37,17 +48,41 @@ VOID CommandVmcall(vector<string> SplittedCommand) {
if (!InterpretGeneralEventAndActionsFields(
&SplittedCommand, VMCALL_INSTRUCTION_EXECUTION, &Event, &EventLength,
&Action, &ActionLength)) {
CommandVmcallHelp();
CommandVmcallHelp();
return;
}
//
// Check for size
//
if (SplittedCommand.size() > 1) {
ShowMessages("incorrect use of '!vmcall'\n");
CommandVmcallHelp();
return;
}
//
// Send the ioctl to the kernel for event registeration
//
SendEventToKernel(Event, EventLength);
if (!SendEventToKernel(Event, EventLength)) {
//
// There was an error, probably the handle was not initialized
// we have to free the Action before exit, it is because, we
// already freed the Event and string buffers
//
free(Action);
return;
}
//
// Add the event to the kernel
//
RegisterActionToEvent(Action, ActionLength);
if (!RegisterActionToEvent(Action, ActionLength)) {
//
// There was an error
//
return;
}
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief help of wrmsr command
*
* @return VOID
*/
VOID CommandWrmsrHelp() {
ShowMessages("wrmsr : Writes on a model-specific register (MSR).\n\n");
ShowMessages("syntax : \twrmsr [ecx (hex value)] [value to write - EDX:EAX "
@ -19,6 +24,12 @@ VOID CommandWrmsrHelp() {
ShowMessages("\t\te.g : wrmsr c0000082 fffff8077356f010 core 2\n");
}
/**
* @brief wrmsr command handler
*
* @param SplittedCommand
* @return VOID
*/
VOID CommandWrmsr(vector<string> SplittedCommand) {
BOOL Status;
@ -63,6 +74,7 @@ VOID CommandWrmsr(vector<string> SplittedCommand) {
CommandWrmsrHelp();
return;
} else {
//
// Means that the MSR is set, next we should read value
//
@ -84,6 +96,7 @@ VOID CommandWrmsr(vector<string> SplittedCommand) {
}
}
}
//
// Check if msr is set or not
//
@ -104,7 +117,8 @@ VOID CommandWrmsr(vector<string> SplittedCommand) {
}
if (!g_DeviceHandle) {
ShowMessages("Handle not found, probably the driver is not loaded.\n");
ShowMessages("Handle not found, probably the driver is not loaded. Did you "
"use 'load' command?\n");
return;
}
@ -125,7 +139,7 @@ VOID CommandWrmsr(vector<string> SplittedCommand) {
);
if (!Status) {
ShowMessages("Ioctl failed with code 0x%x\n", GetLastError());
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}

View file

@ -11,6 +11,11 @@
*/
#include "pch.h"
/**
* @brief Halt the system
*
* @return VOID
*/
VOID
BreakControlPrepareToHaltTheSystem()
{
@ -19,8 +24,15 @@ BreakControlPrepareToHaltTheSystem()
//
}
/**
* @brief This is the callback in the case of KeRegisterNmiCallback
*
* @param Context
* @param Handled
* @return BOOLEAN
*/
BOOLEAN
BreakControlNmiCallbackHandler(IN PVOID Context, IN BOOLEAN Handled)
BreakControlNmiCallbackHandler(IN PVOID Context, IN BOOLEAN Handled)
{
}

View file

@ -14,6 +14,10 @@
/**
* @brief Broadcast syscall hook to all cores
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -38,6 +42,10 @@ BroadcastDpcEnableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID Sys
/**
* @brief Broadcast syscall unhook to all cores
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -60,8 +68,12 @@ BroadcastDpcDisableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID Sy
}
/**
* @brief Broadcast msr write
* @brief Broadcast Msr Write
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -88,8 +100,12 @@ BroadcastDpcWriteMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemAr
}
/**
* @brief Broadcast msr read
* @brief Broadcast Msr read
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -100,7 +116,7 @@ BroadcastDpcReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArg
CurrentProcessorIndex = KeGetCurrentProcessorNumber();
//
// read on MSR
// read msr
//
g_GuestState[CurrentProcessorIndex].DebuggingState.MsrState.Value = __readmsr(g_GuestState[CurrentProcessorIndex].DebuggingState.MsrState.Msr);
@ -118,6 +134,10 @@ BroadcastDpcReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArg
/**
* @brief Disable Msr Bitmaps on all cores (vm-exit on all msrs)
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -139,9 +159,41 @@ BroadcastDpcChangeMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVO
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Reset Msr Bitmaps on all cores (vm-exit on all msrs)
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcResetMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Reset msr bitmaps from vmx-root
//
AsmVmxVmcall(VMCALL_RESET_MSR_BITMAP_READ, NULL, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Disable Msr Bitmaps on all cores (vm-exit on all msrs)
*
* @param Dpc
* @param DeferredContext Msr index to be masked on msr bitmap
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -163,9 +215,41 @@ BroadcastDpcChangeMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PV
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Reset Msr Bitmaps on all cores (vm-exit on all msrs)
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcResetMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Reset msr bitmaps from vmx-root
//
AsmVmxVmcall(VMCALL_RESET_MSR_BITMAP_WRITE, NULL, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enables rdtsc/rdtscp exiting in primary cpu-based controls
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -187,9 +271,41 @@ BroadcastDpcEnableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Disables rdtsc/rdtscp exiting in primary cpu-based controls
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcDisableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Disables rdtsc/rdtscp exiting in primary cpu-based controls
//
AsmVmxVmcall(VMCALL_UNSET_RDTSC_EXITING, 0, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enables rdpmc exiting in primary cpu-based controls
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -211,9 +327,41 @@ BroadcastDpcEnableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Disable rdpmc exiting in primary cpu-based controls
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcDisableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Disable rdpmc exiting in primary cpu-based controls
//
AsmVmxVmcall(VMCALL_UNSET_RDPMC_EXITING, 0, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enable Exception Bitmaps on all cores
*
* @param Dpc
* @param DeferredContext Exception index on IDT
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -235,9 +383,41 @@ BroadcastDpcSetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOI
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Reset Exception Bitmaps on all cores
*
* @param Dpc
* @param DeferredContext Exception index on IDT
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcResetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Reset Exception Bitmaps from vmx-root
//
AsmVmxVmcall(VMCALL_RESET_EXCEPTION_BITMAP, DeferredContext, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enables mov debug registers exitings
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -259,9 +439,41 @@ BroadcastDpcEnableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredCont
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Disables mov debug registers exitings
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcDisableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Disable mov debug registers exitings in primary cpu-based controls
//
AsmVmxVmcall(VMCALL_DISABLE_MOV_TO_DEBUG_REGS_EXITING, 0, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enable vm-exit on all cores for external interrupts
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -283,9 +495,41 @@ BroadcastDpcSetEnableExternalInterruptExitingOnAllCores(KDPC * Dpc, PVOID Deferr
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Disable vm-exit on all cores for external interrupts
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcSetDisableExternalInterruptExitingOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Disable External Interrupts vm-exit from vmx-root
//
AsmVmxVmcall(VMCALL_DISABLE_EXTERNAL_INTERRUPT_EXITING, 0, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Change I/O Bitmaps on all cores
*
* @param Dpc
* @param DeferredContext I/O Port index
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -307,9 +551,41 @@ BroadcastDpcChangeIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID Sy
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Reset I/O Bitmaps on all cores
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
BroadcastDpcResetIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Reset I/O Bitmaps on all cores
//
AsmVmxVmcall(VMCALL_RESET_IO_BITMAP, NULL, 0, 0);
//
// Wait for all DPCs to synchronize at this point
//
KeSignalCallDpcSynchronize(SystemArgument2);
//
// Mark the DPC as being complete
//
KeSignalCallDpcDone(SystemArgument1);
}
/**
* @brief Enable breakpoint exiting on exception bitmaps on all cores
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -334,6 +610,10 @@ BroadcastDpcEnableBreakpointOnExceptionBitmapOnAllCores(KDPC * Dpc, PVOID Deferr
/**
* @brief Disable breakpoint exiting on exception bitmaps on all cores
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID

View file

@ -17,29 +17,66 @@
VOID
BroadcastDpcEnableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcDisableEferSyscallEvents(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcWriteMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcReadMsrToAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcChangeMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcResetMsrBitmapReadOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcChangeMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcResetMsrBitmapWriteOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcEnableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcDisableRdtscExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcEnableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcDisableRdpmcExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcSetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcResetExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcEnableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcDisableMovDebigRegisterExitingAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcSetEnableExternalInterruptExitingOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcSetDisableExternalInterruptExitingOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcChangeIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcResetIoBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcEnableBreakpointOnExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
BroadcastDpcDisableBreakpointOnExceptionBitmapOnAllCores(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);

View file

@ -67,18 +67,37 @@ BroadcastToProcessors(ULONG ProcessorNumber, RunOnLogicalCoreFunc Routine)
return TRUE;
}
/**
* @brief Check whether the bit is set or not
*
* @param nth
* @param addr
* @return int
*/
int
TestBit(int nth, unsigned long * addr)
{
return (BITMAP_ENTRY(nth, addr) >> BITMAP_SHIFT(nth)) & 1;
}
/**
* @brief unset the bit
*
* @param nth
* @param addr
*/
void
ClearBit(int nth, unsigned long * addr)
{
BITMAP_ENTRY(nth, addr) &= ~(1UL << BITMAP_SHIFT(nth));
}
/**
* @brief set the bit
*
* @param nth
* @param addr
*/
void
SetBit(int nth, unsigned long * addr)
{
@ -97,9 +116,43 @@ VirtualAddressToPhysicalAddress(PVOID VirtualAddress)
return MmGetPhysicalAddress(VirtualAddress).QuadPart;
}
/**
* @brief Converts pid to kernel cr3
*
* @details this function should NOT be called from vmx-root mode
*
* @param ProcessId ProcessId to switch
* @return CR3_TYPE The cr3 of the target process
*/
CR3_TYPE
GetCr3FromProcessId(UINT32 ProcessId)
{
PEPROCESS TargetEprocess;
CR3_TYPE ProcessCr3 = {0};
if (PsLookupProcessByProcessId(ProcessId, &TargetEprocess) != STATUS_SUCCESS)
{
//
// There was an error, probably the process id was not found
//
return ProcessCr3;
}
//
// Due to KVA Shadowing, we need to switch to a different directory table base
// if the PCID indicates this is a user mode directory table base.
//
NT_KPROCESS * CurrentProcess = (NT_KPROCESS *)(TargetEprocess);
ProcessCr3.Flags = CurrentProcess->DirectoryTableBase;
return ProcessCr3;
}
/**
* @brief Switch to another process's cr3
*
* @details this function should NOT be called from vmx-root mode
*
* @param ProcessId ProcessId to switch
* @return CR3_TYPE The cr3 of current process which can be
* used by RestoreToPreviousProcess function
@ -139,6 +192,32 @@ SwitchOnAnotherProcessMemoryLayout(UINT32 ProcessId)
return CurrentProcessCr3;
}
/**
* @brief Switch to another process's cr3
*
* @param TargetCr3 cr3 to switch
* @return CR3_TYPE The cr3 of current process which can be
* used by RestoreToPreviousProcess function
*/
CR3_TYPE
SwitchOnAnotherProcessMemoryLayoutByCr3(CR3_TYPE TargetCr3)
{
PEPROCESS TargetEprocess;
CR3_TYPE CurrentProcessCr3 = {0};
//
// Read the current cr3
//
CurrentProcessCr3.Flags = __readcr3();
//
// Change to a new cr3 (of target process)
//
__writecr3(TargetCr3.Flags);
return CurrentProcessCr3;
}
/**
* @brief Get Segment Descriptor
*
@ -210,8 +289,10 @@ RestoreToPreviousProcess(CR3_TYPE PreviousProcess)
/**
* @brief Converts Physical Address to Virtual Address based
* on a specific process id's kernel cr3
*
* on a specific process id
*
* @details this function should NOT be called from vmx-root mode
*
* @param PhysicalAddress The target physical address
* @param ProcessId The target's process id
* @return UINT64 Returns the virtual address
@ -253,9 +334,58 @@ PhysicalAddressToVirtualAddressByProcessId(PVOID PhysicalAddress, UINT32 Process
return VirtualAddress;
}
/**
* @brief Converts Physical Address to Virtual Address based
* on a specific process's kernel cr3
*
* @details this function should NOT be called from vmx-root mode
*
* @param PhysicalAddress The target physical address
* @param TargetCr3 The target's process cr3
* @return UINT64 Returns the virtual address
*/
UINT64
PhysicalAddressToVirtualAddressByCr3(PVOID PhysicalAddress, CR3_TYPE TargetCr3)
{
CR3_TYPE CurrentProcessCr3;
UINT64 VirtualAddress;
PHYSICAL_ADDRESS PhysicalAddr;
//
// Switch to new process's memory layout
//
CurrentProcessCr3 = SwitchOnAnotherProcessMemoryLayoutByCr3(TargetCr3);
//
// Validate if process id is valid
//
if (CurrentProcessCr3.Flags == NULL)
{
//
// Pid is invalid
//
return NULL;
}
//
// Read the virtual address based on new cr3
//
PhysicalAddr.QuadPart = PhysicalAddress;
VirtualAddress = MmGetVirtualForPhysical(PhysicalAddr);
//
// Restore the original process
//
RestoreToPreviousProcess(CurrentProcessCr3);
return VirtualAddress;
}
/**
* @brief Converts Virtual Address to Physical Address based
* on a specific process id's kernel cr3
*
* @details this function should NOT be called from vmx-root mode
*
* @param VirtualAddress The target virtual address
* @param ProcessId The target's process id
@ -296,6 +426,51 @@ VirtualAddressToPhysicalAddressByProcessId(PVOID VirtualAddress, UINT32 ProcessI
return PhysicalAddress;
}
/**
* @brief Converts Virtual Address to Physical Address based
* on a specific process's kernel cr3
*
* @details this function should NOT be called from vmx-root mode
*
* @param VirtualAddress The target virtual address
* @param TargetCr3 The target's process cr3
* @return UINT64 Returns the physical address
*/
UINT64
VirtualAddressToPhysicalAddressByProcessCr3(PVOID VirtualAddress, CR3_TYPE TargetCr3)
{
CR3_TYPE CurrentProcessCr3;
UINT64 PhysicalAddress;
//
// Switch to new process's memory layout
//
CurrentProcessCr3 = SwitchOnAnotherProcessMemoryLayoutByCr3(TargetCr3);
//
// Validate if process id is valid
//
if (CurrentProcessCr3.Flags == NULL)
{
//
// Pid is invalid
//
return NULL;
}
//
// Read the physical address based on new cr3
//
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress).QuadPart;
//
// Restore the original process
//
RestoreToPreviousProcess(CurrentProcessCr3);
return PhysicalAddress;
}
/**
* @brief Converts Physical Address to Virtual Address
*
@ -325,3 +500,66 @@ FindSystemDirectoryTableBase()
NT_KPROCESS * SystemProcess = (NT_KPROCESS *)(PsInitialSystemProcess);
return SystemProcess->DirectoryTableBase;
}
/**
* @brief Get process name by eprocess
*
* @param Eprocess Process eprocess
* @return PCHAR Returns a pointer to the process name
*/
PCHAR
GetProcessNameFromEprocess(PEPROCESS Eprocess)
{
PCHAR Result = 0;
//
// We can't use PsLookupProcessByProcessId as in pageable and not
// work on vmx-root
//
Result = (CHAR *)PsGetProcessImageFileName(Eprocess);
return Result;
}
/**
* @brief Detects whether the string starts with another string
*
* @param const char * pre
* @param const char * str
* @return BOOLEAN Returns true if it starts with and false if not strats with
*/
BOOLEAN
StartsWith(const char * pre, const char * str)
{
size_t lenpre = strlen(pre),
lenstr = strlen(str);
return lenstr < lenpre ? FALSE : memcmp(pre, str, lenpre) == 0;
}
/**
* @brief Checks whether the process with ProcId exists or not
*
* @details this function should NOT be called from vmx-root mode
*
* @param UINT32 ProcId
* @return BOOLEAN Returns true if the process
* exists and false if it the process doesn't exist
*/
BOOLEAN
IsProcessExist(UINT32 ProcId)
{
PEPROCESS TargetEprocess;
CR3_TYPE CurrentProcessCr3 = {0};
if (PsLookupProcessByProcessId(ProcId, &TargetEprocess) != STATUS_SUCCESS)
{
//
// There was an error, probably the process id was not found
//
return FALSE;
}
else
{
return TRUE;
}
}

View file

@ -34,10 +34,13 @@ typedef enum _SEGMENT_REGISTERS
//////////////////////////////////////////////////
// Spinlock Funtions //
//////////////////////////////////////////////////
BOOLEAN
SpinlockTryLock(volatile LONG * Lock);
void
SpinlockLock(volatile LONG * Lock);
void
SpinlockUnlock(volatile LONG * Lock);
@ -45,7 +48,9 @@ SpinlockUnlock(volatile LONG * Lock);
// Constants //
//////////////////////////////////////////////////
/* @brief Intel CPU flags in CR0 */
/**
* @brief Intel CPU flags in CR0
*/
#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */
#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */
#define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */
@ -58,7 +63,10 @@ SpinlockUnlock(volatile LONG * Lock);
#define X86_CR0_CD 0x40000000 /* Cache Disable (RW) */
#define X86_CR0_PG 0x80000000 /* Paging */
/* Intel CPU features in CR4 */
/**
* @brief Intel CPU features in CR4
*
*/
#define X86_CR4_VME 0x0001 /* enable vm86 extensions */
#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */
#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */
@ -72,7 +80,10 @@ SpinlockUnlock(volatile LONG * Lock);
#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
#define X86_CR4_VMXE 0x2000 /* enable VMX */
/* EFLAGS/RFLAGS */
/**
* @brief EFLAGS/RFLAGS
*
*/
#define X86_FLAGS_CF (1 << 0)
#define X86_FLAGS_PF (1 << 2)
#define X86_FLAGS_AF (1 << 4)
@ -98,38 +109,68 @@ SpinlockUnlock(volatile LONG * Lock);
#define X86_FLAGS_RESERVED_BITS 0xffc38028
#define X86_FLAGS_FIXED 0x00000002
/* PCID Flags */
/**
* @brief PCID Flags
*
*/
#define PCID_NONE 0x000
#define PCID_MASK 0x003
/* The Microsoft Hypervisor interface defined constants. */
/**
* @brief The Microsoft Hypervisor interface defined constants
*
*/
#define CPUID_HV_VENDOR_AND_MAX_FUNCTIONS 0x40000000
#define CPUID_HV_INTERFACE 0x40000001
/* CPUID Features */
/**
* @brief CPUID Features
*
*/
#define CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS 0x00000001
/* Hypervisor reserved range for RDMSR and WRMSR */
/**
* @brief Hypervisor reserved range for RDMSR and WRMSR
*
*/
#define RESERVED_MSR_RANGE_LOW 0x40000000
#define RESERVED_MSR_RANGE_HI 0x400000F0
/* Alignment Size */
/**
* @brief Core Id
*
*/
#define __CPU_INDEX__ KeGetCurrentProcessorNumberEx(NULL)
/* Alignment Size */
/**
* @brief Alignment Size
*
*/
#define ALIGNMENT_PAGE_SIZE 4096
/* Maximum x64 Address */
/**
* @brief Maximum x64 Address
*
*/
#define MAXIMUM_ADDRESS 0xffffffffffffffff
/* Pool tag */
/**
* @brief Pool tag
*
*/
#define POOLTAG 0x48444247 // [H]yper[DBG] (HDBG)
/* System and User ring definitions */
/**
* @brief System and User ring definitions
*
*/
#define DPL_USER 3
#define DPL_SYSTEM 0
/* RPL Mask */
/**
* @brief RPL Mask
*
*/
#define RPL_MASK 3
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
@ -138,6 +179,10 @@ SpinlockUnlock(volatile LONG * Lock);
#define BITMAP_ENTRY(_nr, _bmap) ((_bmap))[(_nr) / BITS_PER_LONG]
#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)
/**
* @brief Offset from a page's 4096 bytes
*
*/
#define PAGE_OFFSET(Va) ((PVOID)((ULONG_PTR)(Va) & (PAGE_SIZE - 1)))
//////////////////////////////////////////////////
@ -218,7 +263,7 @@ typedef struct _NT_KPROCESS
} NT_KPROCESS, *PNT_KPROCESS;
/**
* @brief See: Page-Fault Error Code
* @brief Page-Fault Error Code
*
*/
typedef union _PAGE_FAULT_ERROR_CODE
@ -234,6 +279,10 @@ typedef union _PAGE_FAULT_ERROR_CODE
} Fields;
} PAGE_FAULT_ERROR_CODE, *PPAGE_FAULT_ERROR_CODE;
/**
* @brief Control Register 4 Structure
*
*/
typedef struct _CONTROL_REGISTER_4
{
union
@ -269,6 +318,10 @@ typedef struct _CONTROL_REGISTER_4
};
} CONTROL_REGISTER_4, *PCONTROL_REGISTER_4;
/**
* @brief Debug Register 7 Structure
*
*/
typedef union _DEBUG_REGISTER_7
{
UINT64 Flags;
@ -301,6 +354,10 @@ typedef union _DEBUG_REGISTER_7
};
} DEBUG_REGISTER_7, *PDEBUG_REGISTER_7;
/**
* @brief Debug Register 6 Structure
*
*/
typedef union DEBUG_REGISTER_6
{
UINT64 Flags;
@ -318,6 +375,10 @@ typedef union DEBUG_REGISTER_6
};
} DEBUG_REGISTER_6, *PDEBUG_REGISTER_6;
/**
* @brief RFLAGS in structure format
*
*/
typedef union _RFLAGS
{
struct
@ -352,6 +413,10 @@ typedef union _RFLAGS
// Function Types //
//////////////////////////////////////////////////
/**
* @brief Prototype to run a function on a logical core
*
*/
typedef void (*RunOnLogicalCoreFunc)(ULONG ProcessorID);
//////////////////////////////////////////////////
@ -370,8 +435,10 @@ typedef enum _LOG_TYPE
} LOG_TYPE;
/* Define log variables */
/**
* @brief Define log variables
*
*/
#if UseDbgPrintInsteadOfUsermodeMessageTracking
/* Use DbgPrint */
# define LogInfo(format, ...) \
@ -393,12 +460,19 @@ typedef enum _LOG_TYPE
__VA_ARGS__); \
DbgBreakPoint()
/* Log without any prefix */
/**
* @brief Log without any prefix
*
*/
# define Log(format, ...) \
DbgPrint(format "\n", __VA_ARGS__)
#else
/**
* @brief Log, general
*
*/
# define LogInfo(format, ...) \
LogSendMessageToQueue(OPERATION_LOG_INFO_MESSAGE, \
UseImmediateMessaging, \
@ -408,6 +482,10 @@ typedef enum _LOG_TYPE
__LINE__, \
__VA_ARGS__)
/**
* @brief Log in the case of immediate message
*
*/
# define LogInfoImmediate(format, ...) \
LogSendMessageToQueue(OPERATION_LOG_INFO_MESSAGE, \
TRUE, \
@ -417,6 +495,10 @@ typedef enum _LOG_TYPE
__LINE__, \
__VA_ARGS__)
/**
* @brief Log in the case of warning
*
*/
# define LogWarning(format, ...) \
LogSendMessageToQueue(OPERATION_LOG_WARNING_MESSAGE, \
UseImmediateMessaging, \
@ -426,6 +508,10 @@ typedef enum _LOG_TYPE
__LINE__, \
__VA_ARGS__)
/**
* @brief Log in the case of error
*
*/
# define LogError(format, ...) \
LogSendMessageToQueue(OPERATION_LOG_ERROR_MESSAGE, \
UseImmediateMessaging, \
@ -436,7 +522,10 @@ typedef enum _LOG_TYPE
__VA_ARGS__); \
DbgBreakPoint()
/* Log without any prefix */
/**
* @brief Log without any prefix
*
*/
# define Log(format, ...) \
LogSendMessageToQueue(OPERATION_LOG_INFO_MESSAGE, \
UseImmediateMessaging, \
@ -472,6 +561,9 @@ ClearBit(int nth, unsigned long * addr);
void
SetBit(int nth, unsigned long * addr);
CR3_TYPE
GetCr3FromProcessId(UINT32 ProcessId);
BOOLEAN
BroadcastToProcessors(ULONG ProcessorNumber, RunOnLogicalCoreFunc Routine);
@ -484,9 +576,15 @@ VirtualAddressToPhysicalAddress(PVOID VirtualAddress);
UINT64
VirtualAddressToPhysicalAddressByProcessId(PVOID VirtualAddress, UINT32 ProcessId);
UINT64
VirtualAddressToPhysicalAddressByProcessCr3(PVOID VirtualAddress, CR3_TYPE TargetCr3);
UINT64
PhysicalAddressToVirtualAddressByProcessId(PVOID PhysicalAddress, UINT32 ProcessId);
UINT64
PhysicalAddressToVirtualAddressByCr3(PVOID PhysicalAddress, CR3_TYPE TargetCr3);
int
MathPower(int Base, int Exp);
@ -496,30 +594,52 @@ FindSystemDirectoryTableBase();
CR3_TYPE
SwitchOnAnotherProcessMemoryLayout(UINT32 ProcessId);
CR3_TYPE
SwitchOnAnotherProcessMemoryLayoutByCr3(CR3_TYPE TargetCr3);
VOID
RestoreToPreviousProcess(CR3_TYPE PreviousProcess);
PCHAR
GetProcessNameFromEprocess(PEPROCESS eprocess);
BOOLEAN
StartsWith(const char * pre, const char * str);
BOOLEAN
IsProcessExist(UINT32 ProcId);
//////////////////////////////////////////////////
// WDK Major Functions //
//////////////////////////////////////////////////
/* Load & Unload */
/**
* @brief Load & Unload
*/
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
VOID
DrvUnload(PDRIVER_OBJECT DriverObject);
/* IRP Major Functions */
/**
* @brief IRP Major Functions
*/
NTSTATUS
DrvCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
DrvRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
DrvWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
DrvClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
DrvUnsupported(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
@ -529,21 +649,45 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
#define MAX_EXEC_TRAMPOLINE_SIZE 100
/* A test function for Syscall hook */
/**
* @brief A test function for Syscall hook
*
* @return VOID
*/
VOID
SyscallHookTest();
/* Enable or Disable Syscall Hook for EFER MSR */
/**
* @brief Enable or Disable Syscall Hook for EFER MSR
*
*/
VOID
SyscallHookConfigureEFER(BOOLEAN EnableEFERSyscallHook);
/* Manage #UD Exceptions for EFER Syscall */
/**
* @brief Manage #UD Exceptions for EFER Syscall
*
*/
BOOLEAN
SyscallHookHandleUD(PGUEST_REGS Regs, UINT32 CoreIndex);
/* SYSRET instruction emulation routine */
/**
* @brief SYSRET instruction emulation routine
*
*/
BOOLEAN
SyscallHookEmulateSYSRET(PGUEST_REGS Regs);
/* SYSCALL instruction emulation routine */
/**
* @brief SYSCALL instruction emulation routine
*
*/
BOOLEAN
SyscallHookEmulateSYSCALL(PGUEST_REGS Regs);
/* Get Segment Descriptor */
/**
* @brief Get Segment Descriptor
*
*/
BOOLEAN
GetSegmentDescriptor(PSEGMENT_SELECTOR SegmentSelector, USHORT Selector, PUCHAR GdtBase);

View file

@ -11,6 +11,12 @@
*/
#include "pch.h"
/**
* @brief Emulate RDTSC
*
* @param GuestRegs guest registers
* @return VOID
*/
VOID
CounterEmulateRdtsc(PGUEST_REGS GuestRegs)
{
@ -25,6 +31,12 @@ CounterEmulateRdtsc(PGUEST_REGS GuestRegs)
GuestRegs->rdx = 0x00000000ffffffff & (Tsc >> 32);
}
/**
* @brief Emulate RDTSCP
*
* @param GuestRegs Guest Registers
* @return VOID
*/
VOID
CounterEmulateRdtscp(PGUEST_REGS GuestRegs)
{
@ -32,8 +44,16 @@ CounterEmulateRdtscp(PGUEST_REGS GuestRegs)
ULONG64 Tsc = __rdtscp(&Aux);
GuestRegs->rax = 0x00000000ffffffff & Tsc;
GuestRegs->rdx = 0x00000000ffffffff & (Tsc >> 32);
GuestRegs->rcx = 0x00000000ffffffff & Aux;
}
/**
* @brief Emulate RDPMC
*
* @param GuestRegs Guest Register
* @return VOID
*/
VOID
CounterEmulateRdpmc(PGUEST_REGS GuestRegs)
{

View file

@ -11,6 +11,11 @@
*/
#pragma once
//////////////////////////////////////////////////
// Functions //
//////////////////////////////////////////////////
VOID
CounterEmulateRdtsc(PGUEST_REGS GuestRegs);

View file

@ -11,6 +11,13 @@
*/
#include "pch.h"
/**
* @brief Handling XSETBV Instruction vm-exits
*
* @param Reg
* @param Value
* @return VOID
*/
VOID
VmxHandleXsetbv(UINT32 Reg, UINT64 Value)
{

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,24 @@
#pragma once
//////////////////////////////////////////////////
// Global Variable (debugger-related) //
//////////////////////////////////////////////////
/**
* @brief Showes whether the vmcall handler is
* allowed to trigger an event or not
*
*/
BOOLEAN g_TriggerEventForVmcalls;
/**
* @brief Showes whether the cpuid handler is
* allowed to trigger an event or not
*
*/
BOOLEAN g_TriggerEventForCpuids;
//////////////////////////////////////////////////
// Memory Manager //
//////////////////////////////////////////////////
@ -23,6 +41,10 @@ MemoryManagerReadProcessMemoryNormal(HANDLE PID, PVOID Address, DEBUGGER_READ_ME
// Structures //
//////////////////////////////////////////////////
/**
* @brief List of all the different events
*
*/
typedef struct _DEBUGGER_CORE_EVENTS
{
//
@ -32,24 +54,24 @@ typedef struct _DEBUGGER_CORE_EVENTS
//
// Do not add varialbe to this this list, just LIST_ENTRY is allowed
//
LIST_ENTRY HiddenHookReadAndWriteEventsHead; // HIDDEN_HOOK_READ_AND_WRITE [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY HiddenHookReadEventsHead; // HIDDEN_HOOK_READ [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY HiddenHookWriteEventsHead; // HIDDEN_HOOK_WRITE [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY EptHook2sExecDetourEventsHead; // HIDDEN_HOOK_EXEC_DETOUR [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY EptHookExecCcEventsHead; // HIDDEN_HOOK_EXEC_CC [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY SyscallHooksEferSyscallEventsHead; // SYSCALL_HOOK_EFER_SYSCALL [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY SyscallHooksEferSysretEventsHead; // SYSCALL_HOOK_EFER_SYSRET [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY CpuidInstructionExecutionEventsHead; // CPUID_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY RdmsrInstructionExecutionEventsHead; // RDMSR_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY WrmsrInstructionExecutionEventsHead; // WRMSR_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY ExceptionOccurredEventsHead; // EXCEPTION_OCCURRED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY TscInstructionExecutionEventsHead; // TSC_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY PmcInstructionExecutionEventsHead; // PMC_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY InInstructionExecutionEventsHead; // IN_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY OutInstructionExecutionEventsHead; // OUT_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY DebugRegistersAccessedEventsHead; // DEBUG_REGISTERS_ACCESSED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY ExternalInterruptOccurredEventsHead; // EXTERNAL_INTERRUPT_OCCURRED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY VmcallInstructionExecutionEventsHead; // VMCALL_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents ]
LIST_ENTRY HiddenHookReadAndWriteEventsHead; // HIDDEN_HOOK_READ_AND_WRITE [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY HiddenHookReadEventsHead; // HIDDEN_HOOK_READ [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY HiddenHookWriteEventsHead; // HIDDEN_HOOK_WRITE [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY EptHook2sExecDetourEventsHead; // HIDDEN_HOOK_EXEC_DETOURS [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY EptHookExecCcEventsHead; // HIDDEN_HOOK_EXEC_CC [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY SyscallHooksEferSyscallEventsHead; // SYSCALL_HOOK_EFER_SYSCALL [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY SyscallHooksEferSysretEventsHead; // SYSCALL_HOOK_EFER_SYSRET [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY CpuidInstructionExecutionEventsHead; // CPUID_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY RdmsrInstructionExecutionEventsHead; // RDMSR_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY WrmsrInstructionExecutionEventsHead; // WRMSR_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY ExceptionOccurredEventsHead; // EXCEPTION_OCCURRED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY TscInstructionExecutionEventsHead; // TSC_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY PmcInstructionExecutionEventsHead; // PMC_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY InInstructionExecutionEventsHead; // IN_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY OutInstructionExecutionEventsHead; // OUT_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY DebugRegistersAccessedEventsHead; // DEBUG_REGISTERS_ACCESSED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY ExternalInterruptOccurredEventsHead; // EXTERNAL_INTERRUPT_OCCURRED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY VmcallInstructionExecutionEventsHead; // VMCALL_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
} DEBUGGER_CORE_EVENTS, *PDEBUGGER_CORE_EVENTS;
@ -66,7 +88,7 @@ typedef struct _PROCESSOR_DEBUGGING_MSR_READ_OR_WRITE
/**
* @brief Saves the debugger state
* Each logical processor contains one of this structure which describes about the
* @details Each logical processor contains one of this structure which describes about the
* state of debuggers, flags, etc.
*
*/
@ -80,16 +102,37 @@ typedef struct _PROCESSOR_DEBUGGING_STATE
// Data Type //
//////////////////////////////////////////////////
/**
* @brief The prototype that Condition codes are called
*
* @param Regs Guest registers
* @param Context Optional parameter which is different
* for each event and shows a unique description about
* the event
* @return UINT64 if return 0 then the event is not allowed
* to trigger and if any other value then the event is allowed
* to be triggered
* return value should be on RAX
*/
typedef UINT64
DebuggerCheckForCondition(PGUEST_REGS Regs, PVOID Context);
/**
* @brief The prototype that Custom code buffers are called
*
* @param PreAllocatedBufferAddress The address of a pre-allocated non-paged pool
* if the user-requested for it
* @param Regs Guest registers
* @param Context Optional parameter which is different
* for each event and shows a unique description about
* the event
* @return PVOID A pointer to a buffer that should be delivered to the user-mode
* if returns null or an invalid address then nothing will be delivered
* return address should be on RAX
*/
typedef PVOID
DebuggerRunCustomCodeFunc(PVOID PreAllocatedBufferAddress, PGUEST_REGS Regs, PVOID Context);
//////////////////////////////////////////////////
// Log wit Tag //
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Functions //
//////////////////////////////////////////////////
@ -121,6 +164,15 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
BOOLEAN
DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode);
BOOLEAN
DebuggerParseEventsModificationFromUsermode(PDEBUGGER_MODIFY_EVENTS DebuggerEventModificationRequest);
BOOLEAN
DebuggerTerminateEvent(UINT64 Tag);
UINT32
DebuggerEventListCount(PLIST_ENTRY TargetEventList);
VOID
DebuggerPerformActions(PDEBUGGER_EVENT Event, PGUEST_REGS Regs, PVOID Context);

View file

@ -11,6 +11,14 @@
*/
#include "pch.h"
/**
* @brief Read memory for different commands
*
* @param ReadMemRequest request structure for reading memory
* @param UserBuffer user buffer to copy the memory
* @param ReturnSize size that should be returned to userr mode buffers
* @return NTSTATUS
*/
NTSTATUS
DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer, PSIZE_T ReturnSize)
{
@ -34,6 +42,14 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer
}
}
/**
* @brief Perform rdmsr, wrmsr commands
*
* @param ReadOrWriteMsrRequest Msr read/write request
* @param UserBuffer user buffer to save the results
* @param ReturnSize return size to user-mode buffers
* @return NTSTATUS
*/
NTSTATUS
DebuggerReadOrWriteMsr(PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UINT64 * UserBuffer, PSIZE_T ReturnSize)
{
@ -183,6 +199,12 @@ DebuggerReadOrWriteMsr(PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UI
return STATUS_UNSUCCESSFUL;
}
/**
* @brief Edit physical and virtual memory
*
* @param EditMemRequest edit memory request
* @return NTSTATUS
*/
NTSTATUS
DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
{
@ -215,7 +237,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
//
// Invalid parameter
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_INVALID_PARAMETER;
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER;
return;
}
@ -229,7 +251,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
//
// It's an invalid address in current process
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS;
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS;
return;
}
else if (VirtualAddressToPhysicalAddressByProcessId(EditMemRequest->Address, EditMemRequest->ProcessId) == 0)
@ -237,7 +259,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
//
// It's an invalid address in another process
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS;
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS;
return;
}
@ -254,10 +276,10 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
// It is because the target page might be read-only so we can make it writable
//
// RtlCopyBytes(DestinationAddress, SourceAddress, LengthOfEachChunk);
MemoryMapperWriteMemorySafe(DestinationAddress, SourceAddress, LengthOfEachChunk, EditMemRequest->ProcessId);
MemoryMapperWriteMemoryUnsafe(DestinationAddress, SourceAddress, LengthOfEachChunk, EditMemRequest->ProcessId);
}
}
else
else if (EditMemRequest->MemoryType == EDIT_PHYSICAL_MEMORY)
{
//
// It's a physical address so let's check if it's valid or not
@ -273,7 +295,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
//
// It's an invalid address in current process
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS;
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS;
return;
}
else if (PhysicalAddressToVirtualAddressByProcessId(EditMemRequest->Address, EditMemRequest->ProcessId) == 0)
@ -281,7 +303,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
//
// It's an invalid address in another process
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS;
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_OTHER_PROCESS;
return;
}
@ -296,14 +318,516 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
MemoryMapperWriteMemorySafeByPhysicalAddress(DestinationAddress, SourceAddress, LengthOfEachChunk, EditMemRequest->ProcessId);
}
}
else
{
//
// Invalid parameter
//
EditMemRequest->Result = DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_PARAMETER;
return;
}
//
// Set the resutls
//
EditMemRequest->Result = DEBUGGER_EDIT_MEMORY_STATUS_SUCCESS;
EditMemRequest->Result = DEBUGEER_OPERATION_WAS_SUCCESSFULL;
}
/**
* @brief Search on virtual memory (not work on physical memory)
*
* @details This function should NOT be called from vmx-root mode
* Do NOT directly call this function as the virtual addresses
* should be valid on the target process memory layout
* instead call : SearchAddressWrapper
* the address between StartAddress and EndAddress should be contiguous
*
* @param AddressToSaveResults Address to save the search results
* @param SearchMemRequest request structure of searching memory
* @param StartAddress valid start address based on target process
* @param EndAddress valid end address based on target process
* @return VOID the results won't be returned, instead will be
* saved into AddressToSaveResults
*/
VOID
PerformSearchAddress(UINT64 * AddressToSaveResults,
PDEBUGGER_SEARCH_MEMORY SearchMemRequest,
UINT64 StartAddress,
UINT64 EndAddress)
{
UINT64 Cmp64 = 0;
UINT32 IndexToArrayOfResults = 0;
UINT32 LengthOfEachChunk = 0;
PVOID DestinationAddress = 0;
PVOID SourceAddress = 0;
PVOID TempSourceAddress = 0;
BOOLEAN StillMatch = FALSE;
CR3_TYPE CurrentProcessCr3;
//
// set chunk size in each modification
//
if (SearchMemRequest->ByteSize == SEARCH_BYTE)
{
LengthOfEachChunk = 1;
}
else if (SearchMemRequest->ByteSize == SEARCH_DWORD)
{
LengthOfEachChunk = 4;
}
else if (SearchMemRequest->ByteSize == SEARCH_QWORD)
{
LengthOfEachChunk = 8;
}
else
{
//
// Invalid parameter
//
return;
}
//
// Check if address is virtual address or physical address
//
if (SearchMemRequest->MemoryType == SEARCH_VIRTUAL_MEMORY)
{
//
// Search the memory
//
//
// Change the memory layout (cr3), if the user specified a
// special process
//
if (SearchMemRequest->ProcessId != PsGetCurrentProcessId())
{
CurrentProcessCr3 = SwitchOnAnotherProcessMemoryLayout(SearchMemRequest->ProcessId);
}
//
// Here we iterate through the buffer we received from
// user-mode
//
SourceAddress = (UINT64)SearchMemRequest + SIZEOF_DEBUGGER_SEARCH_MEMORY;
for (size_t BaseIterator = (size_t)StartAddress; BaseIterator < ((DWORD64)EndAddress); BaseIterator += LengthOfEachChunk)
{
//
// Copy 64bit, 32bit or one byte value into Cmp64 buffer and then compare it
//
RtlCopyMemory(&Cmp64, (PVOID)BaseIterator, LengthOfEachChunk);
//
// Search the memory
//
// Check whether the byte matches the source or not
//
if (Cmp64 == *(UINT64 *)SourceAddress)
{
//
// Indicate that it matches until now
//
StillMatch = TRUE;
//
// Try to check each element (we don't start from the very first element as
// it checked before )
//
for (size_t i = LengthOfEachChunk; i < SearchMemRequest->CountOf64Chunks; i++)
{
//
// I know, we have a double check here ;)
//
TempSourceAddress = (UINT64)SearchMemRequest + SIZEOF_DEBUGGER_SEARCH_MEMORY + (i * sizeof(UINT64));
//
// Add i to BaseIterator and recompute the Cmp64
//
RtlCopyMemory(&Cmp64, (PVOID)(BaseIterator + (LengthOfEachChunk * i)), LengthOfEachChunk);
if (!(Cmp64 == *(UINT64 *)TempSourceAddress))
{
//
// One thing didn't match so this is not the pattern
//
StillMatch = FALSE;
//
// Break from the loop
//
break;
}
}
//
// Check if we find the pattern or not
//
if (StillMatch)
{
//
// We found the a matching address, let's save the
// address for future use
//
AddressToSaveResults[IndexToArrayOfResults] = BaseIterator;
//
// Increase the array pointer if it doesn't exceed the limitation
//
if (MaximumSearchResults > IndexToArrayOfResults)
{
IndexToArrayOfResults++;
}
else
{
//
// The result buffer is full !
//
return;
}
}
}
else
{
//
// Not found in the place
//
continue;
}
}
//
// Restore the previous memory layout (cr3), if the user specified a
// special process
//
if (SearchMemRequest->ProcessId != PsGetCurrentProcessId())
{
RestoreToPreviousProcess(CurrentProcessCr3);
}
}
else if (SearchMemRequest->MemoryType == SEARCH_PHYSICAL_MEMORY)
{
DbgBreakPoint();
}
else
{
//
// Invalid parameter
//
return;
}
}
/**
* @brief The wrapper to check for validity of addresses and call
* the search routines for both physical and virtual memory
*
* @details This function should NOT be called from vmx-root mode
* The address between start address and end address will be checked
* to make a contiguous address
*
* @param AddressToSaveResults Address to save the search results
* @param SearchMemRequest request structure of searching memory
* @param StartAddress start address of searching based on target process
* @param EndAddress start address of searching based on target process
* @return VOID the results won't be returned, instead will be
* saved into AddressToSaveResults
*/
VOID
SearchAddressWrapper(PUINT64 AddressToSaveResults, PDEBUGGER_SEARCH_MEMORY SearchMemRequest, UINT64 StartAddress, UINT64 EndAddress)
{
CR3_TYPE CurrentProcessCr3;
UINT32 ProcId = 0;
UINT64 BaseAddress = 0;
UINT64 CurrentValue = 0;
UINT64 RealPhysicalAddress = 0;
BOOLEAN DoesBaseAddrSaved = FALSE;
if (SearchMemRequest->MemoryType == SEARCH_VIRTUAL_MEMORY)
{
//
// It's a virtual address search
//
//
// Align the page and search with alignement
//
StartAddress = PAGE_ALIGN(StartAddress);
//
// Switch to new process's memory layout
//
CurrentProcessCr3 = SwitchOnAnotherProcessMemoryLayout(SearchMemRequest->ProcessId);
//
// We will try to find a contigues address
//
while (StartAddress < EndAddress)
{
//
// Check if address is valid or not
// Generally, we can use VirtualAddressToPhysicalAddressByProcessId
// but let's not change the cr3 multiple times
//
if (VirtualAddressToPhysicalAddress(StartAddress, SearchMemRequest->ProcessId) != 0)
{
//
// Address is valid, let's add a page size to it
// nothing to do
//
if (!DoesBaseAddrSaved)
{
BaseAddress = StartAddress;
DoesBaseAddrSaved = TRUE;
}
}
else
{
//
// Address is not valid anymore
//
break;
}
StartAddress += PAGE_SIZE;
}
//
// Restore the original process
//
RestoreToPreviousProcess(CurrentProcessCr3);
//
// All of the address chunk was valid
//
if (DoesBaseAddrSaved && StartAddress > BaseAddress)
{
PerformSearchAddress(AddressToSaveResults, SearchMemRequest, BaseAddress, StartAddress);
}
else
{
return;
}
}
else if (SearchMemRequest->MemoryType == SEARCH_PHYSICAL_MEMORY)
{
//
// It's a physical address search
//
// It's a physical address so let's check if it's valid or not
// honestly, I don't know if it's a good way to check whether the
// physical address is valid or not by converting it to virtual address
// there might be address which are not mapped to a virtual address but
// we nedd to modify them, so it might be wrong to check it this way but
// let's implement it like this for now, if you know a better way to check
// please ping me (@Sinaei)
//
if (SearchMemRequest->ProcessId == PsGetCurrentProcessId() &&
(PhysicalAddressToVirtualAddress(StartAddress) == 0 ||
PhysicalAddressToVirtualAddress(EndAddress) == 0))
{
//
// It's an invalid address in current process
//
return;
}
else if (PhysicalAddressToVirtualAddressByProcessId(StartAddress, SearchMemRequest->ProcessId) == 0 ||
PhysicalAddressToVirtualAddressByProcessId(EndAddress, SearchMemRequest->ProcessId) == 0)
{
//
// It's an invalid address in another process
//
return;
}
//
// when we reached here, we know that it's a valid physical memory,
// so we change the structure and pass it as a virtual address to
// the search function
//
RealPhysicalAddress = SearchMemRequest->Address;
//
// Change the start address
//
if (SearchMemRequest->ProcessId == PsGetCurrentProcessId())
{
SearchMemRequest->Address = PhysicalAddressToVirtualAddress(StartAddress);
EndAddress = PhysicalAddressToVirtualAddress(EndAddress);
}
else
{
SearchMemRequest->Address = PhysicalAddressToVirtualAddressByProcessId(StartAddress, SearchMemRequest->ProcessId);
EndAddress = PhysicalAddressToVirtualAddressByProcessId(EndAddress, SearchMemRequest->ProcessId);
}
//
// Change the type of memory
//
SearchMemRequest->MemoryType = SEARCH_VIRTUAL_MEMORY;
//
// Call the wrapper
//
PerformSearchAddress(AddressToSaveResults, SearchMemRequest, SearchMemRequest->Address, EndAddress);
//
// Restore the previous state
//
SearchMemRequest->MemoryType = SEARCH_PHYSICAL_MEMORY;
SearchMemRequest->Address = RealPhysicalAddress;
//
// Save the process id to avoid calling PsGetCurrentProcessId()
// multiple times
//
ProcId = PsGetCurrentProcessId();
//
// Results should be ready (if any) in AddressToSaveResults
// we should convert it to a physical format as the search
// was on virtual format
//
for (size_t i = 0; i < MaximumSearchResults; i++)
{
CurrentValue = AddressToSaveResults[i];
if (SearchMemRequest->ProcessId == ProcId && CurrentValue != NULL)
{
AddressToSaveResults[i] = VirtualAddressToPhysicalAddress(CurrentValue);
}
else if (CurrentValue != NULL)
{
AddressToSaveResults[i] = VirtualAddressToPhysicalAddressByProcessId(CurrentValue, SearchMemRequest->ProcessId);
}
else
{
break;
}
}
return;
}
}
/**
* @brief Start searching memory
*
* @param SearchMemRequest Request to search memory
* @return NTSTATUS
*/
NTSTATUS
DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest)
{
PUINT64 SearchResultsStorage = NULL;
PUINT64 UsermodeBuffer = NULL;
UINT64 AddressFrom = 0;
UINT64 AddressTo = 0;
UINT64 CurrentValue = 0;
UINT32 ResultsIndex = 0;
//
// Check if process id is valid or not
//
if (SearchMemRequest->ProcessId != PsGetCurrentProcessId() && !IsProcessExist(SearchMemRequest->ProcessId))
{
return STATUS_INVALID_PARAMETER;
}
//
// User-mode buffer is same as SearchMemRequest
//
UsermodeBuffer = SearchMemRequest;
//
// We store the user-mode data in a seprate variable because
// we will use them later when we Zeroed the SearchMemRequest
//
AddressFrom = SearchMemRequest->Address;
AddressTo = SearchMemRequest->Address + SearchMemRequest->Length;
//
// We support up to MaximumSearchResults search results
//
SearchResultsStorage = ExAllocatePoolWithTag(NonPagedPool, MaximumSearchResults * sizeof(UINT64), POOLTAG);
if (SearchResultsStorage == NULL)
{
//
// Not enough memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Make sure there is nothing else in the buffer
//
RtlZeroMemory(SearchResultsStorage, MaximumSearchResults * sizeof(UINT64));
//
// Call the wrapper
//
SearchAddressWrapper(SearchResultsStorage, SearchMemRequest, AddressFrom, AddressTo);
//
// In this point, we to store the results (if any) to the user-mode
// buffer SearchMemRequest itself is the user-mode buffer and we also
// checked from the previous function that the output buffer is at
// least SearchMemRequest bigger or equal to MaximumSearchResults * sizeof(UINT64)
// so we need to clear everything here, and also we should keep in mind that
// SearchMemRequest is no longer valid
//
RtlZeroMemory(SearchMemRequest, MaximumSearchResults * sizeof(UINT64));
//
// It's time to move the results from our temporary buffer to the user-mode
// buffer, also there is something that we should check and that's the fact
// that we used aligned page addresses so the results should be checked to
// see whether the results are between the user's entered addresses or not
//
for (size_t i = 0; i < MaximumSearchResults; i++)
{
CurrentValue = SearchResultsStorage[i];
if (CurrentValue == NULL)
{
//
// Nothing left to move
//
break;
}
if (CurrentValue >= AddressFrom && CurrentValue <= AddressTo)
{
//
// Move the variable
//
UsermodeBuffer[ResultsIndex] = CurrentValue;
ResultsIndex++;
}
}
//
// Free the results pool
//
ExFreePoolWithTag(SearchResultsStorage, POOLTAG);
return STATUS_SUCCESS;
}
/**
* @brief Perform the flush requests to vmx-root and vmx non-root buffers
*
* @param DebuggerFlushBuffersRequest Request to flush the buffers
* @return NTSTATUS
*/
NTSTATUS
DebuggerCommandFlush(PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest)
{
//
// We try to flush buffers for both vmx-root and regular kernel buffer
//
DebuggerFlushBuffersRequest->CountOfMessagesThatSetAsReadFromVmxRoot = LogMarkAllAsRead(TRUE);
DebuggerFlushBuffersRequest->CountOfMessagesThatSetAsReadFromVmxNonRoot = LogMarkAllAsRead(FALSE);
DebuggerFlushBuffersRequest->KernelStatus = DEBUGEER_OPERATION_WAS_SUCCESSFULL;
return STATUS_SUCCESS;
}

View file

@ -24,3 +24,6 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest);
NTSTATUS
DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest);
NTSTATUS
DebuggerCommandFlush(PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest);

View file

@ -12,7 +12,7 @@
#include "pch.h"
/**
* @brief routines for !syscallhook command (enable syscall hook)
* @brief routines for !syscall command (enable syscall hook)
*
* @return VOID
*/
@ -23,7 +23,7 @@ DebuggerEventEnableEferOnAllProcessors()
}
/**
* @brief routines for !syscallhook command (disable syscall hook)
* @brief routines for !syscall command (disable syscall hook)
*
* @return VOID
*/
@ -115,6 +115,15 @@ DebuggerEventEnableMonitorReadAndWriteForAddress(UINT64 Address, UINT32 ProcessI
EnableForRead = TRUE;
}
//
// Check if its DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES then
// we have to convert it to current process id
//
if (ProcessId == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES)
{
ProcessId = PsGetCurrentProcessId();
}
//
// Perform the EPT Hook
//

View file

@ -12,7 +12,10 @@
*/
#include "pch.h"
/* lock for one core execution */
/**
* @brief lock for one core execution
*
*/
volatile LONG OneCoreLock;
/**
@ -21,9 +24,12 @@ volatile LONG OneCoreLock;
* The function that needs to use this featue (Routine parameter function) should
* have the when it ends :
*
* SpinlockUnlock(&OneCoreLock);
*
* @return VOID
* SpinlockUnlock(&OneCoreLock);
*
* @param CoreNumber core number that the target function should run on it
* @param Routine the target function that should be runned
* @param DeferredContext an optional parameter to Routine
* @return NTSTATUS
*/
NTSTATUS
DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredContext)
@ -111,6 +117,10 @@ DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredCo
/**
* @brief Broadcast msr write
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -135,6 +145,10 @@ DpcRoutinePerformWriteMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgumen
/**
* @brief Broadcast msr read
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -159,6 +173,10 @@ DpcRoutinePerformReadMsr(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument
/**
* @brief change msr bitmap read on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -179,6 +197,10 @@ DpcRoutinePerformChangeMsrBitmapReadOnSingleCore(KDPC * Dpc, PVOID DeferredConte
/**
* @brief change msr bitmap write on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -199,6 +221,10 @@ DpcRoutinePerformChangeMsrBitmapWriteOnSingleCore(KDPC * Dpc, PVOID DeferredCont
/**
* @brief set rdtsc/rdtscp exiting
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -219,6 +245,10 @@ DpcRoutinePerformEnableRdtscExitingOnSingleCore(KDPC * Dpc, PVOID DeferredContex
/**
* @brief set rdpmc exiting
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -239,6 +269,10 @@ DpcRoutinePerformEnableRdpmcExitingOnSingleCore(KDPC * Dpc, PVOID DeferredContex
/**
* @brief change exception bitmap on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -259,6 +293,10 @@ DpcRoutinePerformSetExceptionBitmapOnSingleCore(KDPC * Dpc, PVOID DeferredContex
/**
* @brief Set the Mov to Debug Registers Exitings
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -279,6 +317,10 @@ DpcRoutinePerformEnableMovToDebugRegistersExiting(KDPC * Dpc, PVOID DeferredCont
/**
* @brief Enable external interrupt exiting on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
@ -296,9 +338,37 @@ DpcRoutinePerformSetExternalInterruptExitingOnSingleCore(KDPC * Dpc, PVOID Defer
SpinlockUnlock(&OneCoreLock);
}
/**
* @brief Enable syscall hook EFER on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID
DpcRoutinePerformEnableEferSyscallHookOnSingleCore(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//
// Enable syscall hook EFER
//
AsmVmxVmcall(VMCALL_ENABLE_SYSCALL_HOOK_EFER, NULL, 0, 0);
//
// As this function is designed for a single,
// we have to release the synchronization lock here
//
SpinlockUnlock(&OneCoreLock);
}
/**
* @brief change I/O bitmap on a single core
*
* @param Dpc
* @param DeferredContext
* @param SystemArgument1
* @param SystemArgument2
* @return VOID
*/
VOID

View file

@ -12,6 +12,10 @@
#pragma once
//////////////////////////////////////////////////
// Functions //
//////////////////////////////////////////////////
NTSTATUS
DpcRoutineRunTaskOnSingleCore(UINT32 CoreNumber, PVOID Routine, PVOID DeferredContext);
@ -42,5 +46,8 @@ DpcRoutinePerformEnableMovToDebugRegistersExiting(KDPC * Dpc, PVOID DeferredCont
VOID
DpcRoutinePerformSetExternalInterruptExitingOnSingleCore(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
DpcRoutinePerformEnableEferSyscallHookOnSingleCore(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
VOID
DpcRoutinePerformChangeIoBitmapOnSingleCore(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);

View file

@ -196,7 +196,7 @@ EptGetPml1Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress)
*
* @param EptPageTable The EPT Page Table
* @param PhysicalAddress Physical Address that we want to get its PML2
* @return PEPT_PML2_ENTRY
* @return PEPT_PML2_ENTRY The PML2 Entry Structure
*/
PEPT_PML2_ENTRY
EptGetPml2Entry(PVMM_EPT_PAGE_TABLE EptPageTable, SIZE_T PhysicalAddress)
@ -408,7 +408,7 @@ EptSetupPML2Entry(PEPT_PML2_ENTRY NewEntry, SIZE_T PageFrameNumber)
/**
* @brief Allocates page maps and create identity page table
*
* @return PVMM_EPT_PAGE_TABLE
* @return PVMM_EPT_PAGE_TABLE identity map page-table
*/
PVMM_EPT_PAGE_TABLE
EptAllocateAndCreateIdentityPageTable()
@ -500,10 +500,13 @@ EptAllocateAndCreateIdentityPageTable()
//
PML2EntryTemplate.LargePage = 1;
/* For each collection of 512 PML2 entries (512 collections * 512 entries per collection), mark it RWX using the same template above.
This marks the entries as "Present" regardless of if the actual system has memory at this region or not. We will cause a fault in our
EPT handler if the guest access a page outside a usable range, despite the EPT frame being present here.
*/
//
// For each collection of 512 PML2 entries (512 collections * 512 entries per collection),
// mark it RWX using the same template above.
// This marks the entries as "Present" regardless of if the actual system has memory at
// this region or not. We will cause a fault in our EPT handler if the guest access a page
// outside a usable range, despite the EPT frame being present here.
//
__stosq((SIZE_T *)&PageTable->PML2[0], PML2EntryTemplate.Flags, VMM_EPT_PML3E_COUNT * VMM_EPT_PML2E_COUNT);
//
@ -652,9 +655,10 @@ EptHandlePageHookExit(PGUEST_REGS Regs, VMX_EXIT_QUALIFICATION_EPT_VIOLATION Vio
* @brief Handle VM exits for EPT violations
* @details Violations are thrown whenever an operation is performed on an EPT entry
* that does not provide permissions to access that page
*
* @param ExitQualification
* @param GuestPhysicalAddr
*
* @param Regs Guest registers
* @param ExitQualification Exit qualification of the vm-exit
* @param GuestPhysicalAddr Physical address that caused this EPT violation
* @return BOOLEAN Return true if the violation was handled by the page hook handler
* and false if it was not handled
*/
@ -718,9 +722,9 @@ EptHandleMisconfiguration(UINT64 GuestAddress)
* @brief This function set the specific PML1 entry in a spinlock protected area then invalidate the TLB
* @details This function should be called from vmx root-mode
*
* @param EntryAddress
* @param EntryValue
* @param InvalidationType
* @param EntryAddress PML1 entry information (the target address)
* @param EntryValue The value of pm1's entry (the value that should be replaced)
* @param InvalidationType type of invalidation
* @return VOID
*/
VOID
@ -730,10 +734,12 @@ EptSetPML1AndInvalidateTLB(PEPT_PML1_ENTRY EntryAddress, EPT_PML1_ENTRY EntryVal
// acquire the lock
//
SpinlockLock(&Pml1ModificationAndInvalidationLock);
//
// set the value
//
EntryAddress->Flags = EntryValue.Flags;
//
// invalidate the cache
//
@ -745,6 +751,7 @@ EptSetPML1AndInvalidateTLB(PEPT_PML1_ENTRY EntryAddress, EPT_PML1_ENTRY EntryVal
{
InveptAllContexts();
}
//
// release the lock
//

Some files were not shown because too many files have changed in this diff Show more