mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
major update
This commit is contained in:
parent
05acdaa269
commit
4c679db851
187 changed files with 12653 additions and 59806 deletions
38
Counter.py
Normal file
38
Counter.py
Normal 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')
|
||||
2
Doxyfile
2
Doxyfile
|
|
@ -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
1
Doxygen.bat
Normal file
|
|
@ -0,0 +1 @@
|
|||
"c:\Program Files\doxygen\bin\doxygen.exe" Doxyfile
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
129
hyperdbg/hprdbgctrl/attach.cpp
Normal file
129
hyperdbg/hprdbgctrl/attach.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"); }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
60
hyperdbg/hprdbgctrl/communication.h
Normal file
60
hyperdbg/hprdbgctrl/communication.h
Normal 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();
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
90
hyperdbg/hprdbgctrl/detach.cpp
Normal file
90
hyperdbg/hprdbgctrl/detach.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* ==============================================================================================
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
96
hyperdbg/hprdbgctrl/flush.cpp
Normal file
96
hyperdbg/hprdbgctrl/flush.cpp
Normal 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();
|
||||
}
|
||||
|
|
@ -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)
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
211
hyperdbg/hprdbgctrl/gaussian-rng.cpp
Normal file
211
hyperdbg/hprdbgctrl/gaussian-rng.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
27
hyperdbg/hprdbgctrl/help.cpp
Normal file
27
hyperdbg/hprdbgctrl/help.cpp
Normal 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
|
||||
//
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
101
hyperdbg/hprdbgctrl/listen.cpp
Normal file
101
hyperdbg/hprdbgctrl/listen.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
109
hyperdbg/hprdbgctrl/measure.cpp
Normal file
109
hyperdbg/hprdbgctrl/measure.cpp
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
313
hyperdbg/hprdbgctrl/remoteconnection.cpp
Normal file
313
hyperdbg/hprdbgctrl/remoteconnection.cpp
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
239
hyperdbg/hprdbgctrl/settings.cpp
Normal file
239
hyperdbg/hprdbgctrl/settings.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
79
hyperdbg/hprdbgctrl/status.cpp
Normal file
79
hyperdbg/hprdbgctrl/status.cpp
Normal 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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
260
hyperdbg/hprdbgctrl/tcpclient.cpp
Normal file
260
hyperdbg/hprdbgctrl/tcpclient.cpp
Normal 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;
|
||||
// }
|
||||
//
|
||||
297
hyperdbg/hprdbgctrl/tcpserver.cpp
Normal file
297
hyperdbg/hprdbgctrl/tcpserver.cpp
Normal 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;
|
||||
// }
|
||||
//
|
||||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
//
|
||||
// Test cases
|
||||
//
|
||||
|
||||
#define DEBUGGER_TEST_ALL_COMMANDS 0x0
|
||||
#define DEBUGGER_TEST_VMM_MONITOR_COMMAND 0x1
|
||||
|
||||
|
|
|
|||
228
hyperdbg/hprdbgctrl/transparency.cpp
Normal file
228
hyperdbg/hprdbgctrl/transparency.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
39
hyperdbg/hprdbgctrl/transparency.h
Normal file
39
hyperdbg/hprdbgctrl/transparency.h
Normal 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();
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
VOID
|
||||
CounterEmulateRdtsc(PGUEST_REGS GuestRegs);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,3 +24,6 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest);
|
|||
|
||||
NTSTATUS
|
||||
DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest);
|
||||
|
||||
NTSTATUS
|
||||
DebuggerCommandFlush(PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue