HyperDbg/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/dt-struct.cpp
2022-04-17 03:32:00 +04:30

414 lines
14 KiB
C++

/**
* @file dt-struct.cpp
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief dt and struct command
* @details
* @version 0.1
* @date 2021-12-13
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "..\hprdbgctrl\pch.h"
/**
* @brief help of dt command
*
* @return VOID
*/
VOID
CommandDtHelp()
{
ShowMessages("dt !dt : displays information about a local variable, global "
"variable or data type.\n\n");
ShowMessages("\nIf you want to read physical memory then add '!' at the "
"start of the command\n");
ShowMessages("syntax : \tdt [Module!SymbolName (string)] [Expression (string)]\n");
ShowMessages("\t\te.g : dt nt!_EPROCESS\n");
ShowMessages("\t\te.g : dt nt!_EPROCESS fffff8077356f010\n");
ShowMessages("\t\te.g : dt nt!_EPROCESS @rbx+@rcx\n");
ShowMessages("\t\te.g : !dt nt!_EPROCESS 1f0300\n");
}
/**
* @brief help of struct command
*
* @return VOID
*/
VOID
CommandStructHelp()
{
ShowMessages("struct : displays a data type, enum, or structure derived from PDB symbols.\n\n");
ShowMessages("syntax : \struct [Module!SymbolName (string)]\n");
ShowMessages("\t\te.g : struct nt!_EPROCESS\n");
}
/**
* @brief Show data based on the symbol structure and data types
*
* @param TypeName
* @param Address
* @param IsStruct
* @param BufferAddress
* @param TargetPid
* @param IsPhysicalAddress
* @param AdditionalParameters
*
* @return BOOLEAN
*/
BOOLEAN
CommandDtShowDataBasedOnSymbolTypes(
const char * TypeName,
UINT64 Address,
BOOLEAN IsStruct,
PVOID BufferAddress,
UINT32 TargetPid,
BOOLEAN IsPhysicalAddress,
const char * AdditionalParameters)
{
UINT64 StructureSize = 0;
BOOLEAN ResultOfFindingSize = FALSE;
DEBUGGER_DT_COMMAND_OPTIONS DtOptions = {0};
//
// Set the options
//
DtOptions.TypeName = TypeName;
DtOptions.Address = Address;
DtOptions.IsStruct = IsStruct;
DtOptions.BufferAddress = NULL; // we didn't read it yet
DtOptions.TargetPid = TargetPid;
DtOptions.AdditionalParameters = AdditionalParameters;
if (Address != NULL)
{
//
// *** We need to read the memory here ***
//
//
// Get the field size
//
ResultOfFindingSize = ScriptEngineGetDataTypeSizeWrapper((char *)TypeName, &StructureSize);
//
// Check if size is found
//
if (!ResultOfFindingSize || StructureSize == 0)
{
//
// Field not found or size is invalid
//
ShowMessages("err, couldn't resolve error at '%s'\n", TypeName);
return FALSE;
}
//
// Set the type (structure) size
//
DtOptions.SizeOfTypeName = StructureSize;
//
// Read the memory
//
HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_COMMAND_DT,
Address,
IsPhysicalAddress ? DEBUGGER_READ_PHYSICAL_ADDRESS : DEBUGGER_READ_VIRTUAL_ADDRESS,
READ_FROM_KERNEL,
TargetPid,
StructureSize,
&DtOptions);
}
else
{
//
// It's a simple structure without an address
// Call the pdbex wrapper
//
return ScriptEngineShowDataBasedOnSymbolTypesWrapper(TypeName, Address, IsStruct, BufferAddress, AdditionalParameters);
}
}
/**
* @brief dt and struct command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID
CommandDtAndStruct(vector<string> SplittedCommand, string Command)
{
std::string TempTypeNameHolder;
std::string TempExtraParamHolder;
BOOLEAN IsStruct = FALSE;
UINT64 TargetAddress = NULL;
PVOID BufferAddressRetrievedFromDebuggee = NULL;
UINT32 TargetPid = NULL;
BOOLEAN IsPhysicalAddress = FALSE;
//
// Test for the pid
//
TargetPid = GetCurrentProcessId();
//
// Check if command is 'struct' or not
//
if (!SplittedCommand.at(0).compare("struct") ||
!SplittedCommand.at(0).compare("structure"))
{
IsStruct = TRUE;
}
else
{
IsStruct = FALSE;
}
//
// Check if command is '!dt' for physical address or not
//
if (!SplittedCommand.at(0).compare("!dt"))
{
IsPhysicalAddress = TRUE;
}
else
{
IsPhysicalAddress = FALSE;
}
if (SplittedCommand.size() == 1)
{
ShowMessages("incorrect use of '%s'\n\n", SplittedCommand.at(0).c_str());
if (IsStruct)
{
CommandStructHelp();
}
else
{
CommandDtHelp();
}
return;
}
//
// Trim the command
//
Trim(Command);
//
// Remove dt, struct, or structure from it
//
Command.erase(0, SplittedCommand.at(0).size());
//
// Trim it again
//
Trim(Command);
//
// Check for the first and second arguments
//
vector<string> TempSplittedCommand {Split(Command, ' ')};
//
// If the size is zero, then it's only a type name
//
if (TempSplittedCommand.size() == 1)
{
//
// Call the dt parser wrapper, it's only a structure (type) name
// Call it with default configuration
//
CommandDtShowDataBasedOnSymbolTypes(TempSplittedCommand.at(0).c_str(),
NULL,
IsStruct,
NULL,
TargetPid,
IsPhysicalAddress,
PDBEX_DEFAULT_CONFIGURATION);
}
else
{
//
// When we're here, it means we have size() >= 2, so we have to check
// the first and the second method to see which one is the type and
// which one is the symbol
//
//
// Check if the first parameter is an address or valid expression
//
if (!SymbolConvertNameOrExprToAddress(TempSplittedCommand.at(0).c_str(),
&TargetAddress))
{
//
// No it's not, we'll get the first argument as the structure (type) name
// And we have to check whether the second argument is a buffer address or not
//
if (!SymbolConvertNameOrExprToAddress(TempSplittedCommand.at(1).c_str(),
&TargetAddress))
{
//
// The second argument is also not buffer address
// probably the user entered a structure (type) name along with some params
//
TempTypeNameHolder = TempSplittedCommand.at(0);
//
// Remove the first argument
//
TempSplittedCommand.erase(TempSplittedCommand.begin());
//
// Concat extra parameters
//
for (auto item : TempSplittedCommand)
{
TempExtraParamHolder = TempExtraParamHolder + " " + item;
}
//
// removes first space character
//
TempExtraParamHolder.erase(0, 1);
//
// Call the wrapper of pdbex
//
CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(),
TargetAddress,
IsStruct,
BufferAddressRetrievedFromDebuggee,
TargetPid,
IsPhysicalAddress,
TempExtraParamHolder.c_str());
}
else
{
//
// The second argument is a buffer address
// The user entered a structure (type) name along with buffer address
//
if (TempSplittedCommand.size() == 2)
{
//
// There is not parameters, only a symbol name and then a buffer address
// Call it with default configuration
//
CommandDtShowDataBasedOnSymbolTypes(TempSplittedCommand.at(0).c_str(),
TargetAddress,
IsStruct,
BufferAddressRetrievedFromDebuggee,
TargetPid,
IsPhysicalAddress,
PDBEX_DEFAULT_CONFIGURATION);
}
else
{
//
// Other than the first argument which is a structure (type) name, and
// the second argument which is buffer address, there are other parameters, so
// we WON'T call it with default parameters
//
TempTypeNameHolder = TempSplittedCommand.at(0);
//
// Remove the first, and the second arguments
//
TempSplittedCommand.erase(TempSplittedCommand.begin());
TempSplittedCommand.erase(TempSplittedCommand.begin());
//
// Concat extra parameters
//
for (auto item : TempSplittedCommand)
{
TempExtraParamHolder = TempExtraParamHolder + " " + item;
}
//
// removes first space character
//
TempExtraParamHolder.erase(0, 1);
//
// Call the wrapper of pdbex
//
CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(),
TargetAddress,
IsStruct,
BufferAddressRetrievedFromDebuggee,
TargetPid,
IsPhysicalAddress,
TempExtraParamHolder.c_str());
}
}
}
else
{
//
// The first argument is a buffer address, so we get the first argument as
// a buffer address and the second argument as the structure (type) name
//
if (TempSplittedCommand.size() == 2)
{
//
// There is not parameters, only a buffer address and then a symbol name
// Call it with default configuration
//
CommandDtShowDataBasedOnSymbolTypes(TempSplittedCommand.at(1).c_str(),
TargetAddress,
IsStruct,
BufferAddressRetrievedFromDebuggee,
TargetPid,
IsPhysicalAddress,
PDBEX_DEFAULT_CONFIGURATION);
}
else
{
//
// Other than the first argument which is a buffer address, and the second
// argument which is structure (type) name, there are other parameters, so
// we WON'T call it with default parameters
//
TempTypeNameHolder = TempSplittedCommand.at(1);
//
// Remove the first, and the second arguments
//
TempSplittedCommand.erase(TempSplittedCommand.begin());
TempSplittedCommand.erase(TempSplittedCommand.begin());
//
// Concat extra parameters
//
for (auto item : TempSplittedCommand)
{
TempExtraParamHolder = TempExtraParamHolder + " " + item;
}
//
// removes first space character
//
TempExtraParamHolder.erase(0, 1);
//
// Call the wrapper of pdbex
//
CommandDtShowDataBasedOnSymbolTypes(TempTypeNameHolder.c_str(),
TargetAddress,
IsStruct,
BufferAddressRetrievedFromDebuggee,
TargetPid,
IsPhysicalAddress,
TempExtraParamHolder.c_str());
}
}
}
}