mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-12 18:49:32 +00:00
516 lines
17 KiB
C++
516 lines
17 KiB
C++
/**
|
|
* @file hwdbg-scripts.cpp
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Hardware scripts for hwdbg
|
|
* @details
|
|
* @version 0.11
|
|
* @date 2024-09-30
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Global Variables
|
|
//
|
|
extern HWDBG_INSTANCE_INFORMATION g_HwdbgInstanceInfo;
|
|
extern BOOLEAN g_HwdbgInstanceInfoIsValid;
|
|
|
|
/**
|
|
* @brief Print the actual script
|
|
*
|
|
* @param ScriptBuffer
|
|
* @param ScriptBufferSize
|
|
*
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
HwdbgScriptPrintScriptBuffer(CHAR * ScriptBuffer, UINT32 ScriptBufferSize)
|
|
{
|
|
//
|
|
// Print the actual script
|
|
//
|
|
ShowMessages("\nHyperDbg (general) script buffer (size=%d, flip-flops (just script)=%d):\n\n",
|
|
ScriptBufferSize,
|
|
ScriptBufferSize * 8 // Converted to bits
|
|
);
|
|
|
|
for (SIZE_T i = 0; i < ScriptBufferSize; i++)
|
|
{
|
|
ShowMessages("%02X ", (UINT8)ScriptBuffer[i]);
|
|
}
|
|
|
|
ShowMessages("\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Compress the script buffer
|
|
*
|
|
* @param InstanceInfo
|
|
* @param ScriptBuffer
|
|
* @param ScriptBufferSize
|
|
* @param NumberOfStagesForScript
|
|
* @param NewScriptBuffer
|
|
* @param NewCompressedBufferSize
|
|
* @param NumberOfBytesPerChunk
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptCompressScriptBuffer(HWDBG_INSTANCE_INFORMATION * InstanceInfo,
|
|
SYMBOL * ScriptBuffer,
|
|
SIZE_T ScriptBufferSize,
|
|
UINT32 NumberOfStagesForScript,
|
|
HWDBG_SHORT_SYMBOL ** NewScriptBuffer,
|
|
SIZE_T * NewCompressedBufferSize,
|
|
SIZE_T * NumberOfBytesPerChunk)
|
|
{
|
|
//
|
|
// Now, converting the script based on supported script variable length
|
|
//
|
|
if (!g_HwdbgInstanceInfoIsValid)
|
|
{
|
|
//
|
|
// The instance info is not valid
|
|
//
|
|
ShowMessages("err, the instance info is not valid\n");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check if the variable length is valid
|
|
//
|
|
if (!(InstanceInfo->scriptVariableLength >= sizeof(BYTE) * 8))
|
|
{
|
|
//
|
|
// The script variable length is not valid (at least 8 bit (1 byte)
|
|
//
|
|
ShowMessages("err, the script variable length should be at least 8 bits (1 byte)\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// *** The script variable length is valid (at least 8 bit (1 byte) ***
|
|
//
|
|
|
|
//
|
|
// Compress script buffer
|
|
//
|
|
if (HardwareScriptInterpreterConvertSymbolToHwdbgShortSymbolBuffer(InstanceInfo,
|
|
ScriptBuffer,
|
|
ScriptBufferSize,
|
|
NumberOfStagesForScript,
|
|
NewScriptBuffer,
|
|
NewCompressedBufferSize) == FALSE)
|
|
{
|
|
ShowMessages("err, unable to convert the script buffer to short symbol buffer\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// we put BRAM data width size here instead of script variable length (InstanceInfo.scriptVariableLength)
|
|
// since we want it to read one symbol filed at a time
|
|
//
|
|
if (!HardwareScriptInterpreterCompressBuffer((UINT64 *)*NewScriptBuffer,
|
|
*NewCompressedBufferSize,
|
|
InstanceInfo->scriptVariableLength,
|
|
InstanceInfo->bramDataWidth,
|
|
NewCompressedBufferSize,
|
|
NumberOfBytesPerChunk))
|
|
{
|
|
//
|
|
// Unable to compress the buffer
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The script buffer is compressed successfully
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Print the hwdbg script buffer and hardware details
|
|
*
|
|
* @param InstanceInfo
|
|
* @param NewCompressedBufferSize
|
|
* @param NumberOfStagesForScript
|
|
* @param NumberOfOperandsForScript
|
|
* @param NewScriptBuffer
|
|
* @param NumberOfNeededFlipFlopsInTargetDevice
|
|
* @param NumberOfBytesPerChunk
|
|
* @param NumberOfOperandsImplemented
|
|
*
|
|
* @return VOID
|
|
*/
|
|
VOID
|
|
HwdbgScriptPrintFinalScriptBufferAndHardwareDetails(HWDBG_INSTANCE_INFORMATION * InstanceInfo,
|
|
SIZE_T NewCompressedBufferSize,
|
|
UINT32 NumberOfStagesForScript,
|
|
UINT32 NumberOfOperandsForScript,
|
|
HWDBG_SHORT_SYMBOL * NewScriptBuffer,
|
|
SIZE_T NumberOfNeededFlipFlopsInTargetDevice,
|
|
SIZE_T NumberOfBytesPerChunk,
|
|
UINT32 NumberOfOperandsImplemented)
|
|
{
|
|
ShowMessages("\n---------------------------------------------------------\n");
|
|
|
|
NumberOfNeededFlipFlopsInTargetDevice = HwdbgComputeNumberOfFlipFlopsNeeded(InstanceInfo, NumberOfStagesForScript);
|
|
|
|
ShowMessages("hwdbg script buffer (buffer size=%d, stages=%d, operands needed: %d - operands used: %d (%.2f%%), total used flip-flops=%d, number of bytes per chunk: %d):\n\n",
|
|
NewCompressedBufferSize,
|
|
NumberOfStagesForScript,
|
|
NumberOfOperandsImplemented,
|
|
NumberOfOperandsForScript,
|
|
((float)NumberOfOperandsForScript / (float)NumberOfOperandsImplemented) * 100,
|
|
NumberOfNeededFlipFlopsInTargetDevice,
|
|
NumberOfBytesPerChunk);
|
|
|
|
for (SIZE_T i = 0; i < NewCompressedBufferSize; i++)
|
|
{
|
|
ShowMessages("%02X ", (UINT8)((CHAR *)NewScriptBuffer)[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Write script configuration packet into a file
|
|
*
|
|
* @param InstanceInfo
|
|
* @param FileName
|
|
* @param NumberOfOperandsImplemented
|
|
* @param NumberOfStagesForScript
|
|
* @param NewScriptBuffer
|
|
* @param NewCompressedBufferSize
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptWriteScriptConfigurationPacketIntoFile(HWDBG_INSTANCE_INFORMATION * InstanceInfo,
|
|
const CHAR * FileName,
|
|
UINT32 NumberOfStagesForScript,
|
|
UINT32 NumberOfOperandsImplemented,
|
|
HWDBG_SHORT_SYMBOL * NewScriptBuffer,
|
|
SIZE_T NewCompressedBufferSize)
|
|
{
|
|
TCHAR TestFilePath[MAX_PATH] = {0};
|
|
|
|
//
|
|
// *** Write script configuration packet into a file ***
|
|
//
|
|
|
|
ShowMessages("\n\nwriting script configuration packet into the file\n");
|
|
|
|
if (SetupPathForFileName(FileName, TestFilePath, sizeof(TestFilePath), FALSE) &&
|
|
HwdbgScriptSendScriptPacket(
|
|
InstanceInfo,
|
|
TestFilePath,
|
|
NumberOfStagesForScript + NumberOfOperandsImplemented - 1, // Number of symbols = Number of stages + Number of operands - 1
|
|
NewScriptBuffer,
|
|
(UINT32)NewCompressedBufferSize))
|
|
{
|
|
ShowMessages("\n[*] script buffer successfully written into file: %s\n", TestFilePath);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("err, unable to write script buffer\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Create hwdbg script
|
|
* @param ScriptBuffer
|
|
* @param ScriptBufferSize
|
|
* @param HardwareScriptFilePathToSave
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptCreateHwdbgScript(CHAR * ScriptBuffer,
|
|
UINT32 ScriptBufferSize,
|
|
const TCHAR * HardwareScriptFilePathToSave)
|
|
{
|
|
UINT32 NumberOfStagesForScript = 0;
|
|
UINT32 NumberOfOperandsImplemented = 0;
|
|
UINT32 NumberOfOperandsForScript = 0;
|
|
SIZE_T NewCompressedBufferSize = 0;
|
|
SIZE_T NumberOfNeededFlipFlopsInTargetDevice = 0;
|
|
SIZE_T NumberOfBytesPerChunk = 0;
|
|
HWDBG_SHORT_SYMBOL * NewScriptBuffer = NULL;
|
|
|
|
//
|
|
// *** Check the script capabilities with the generated script ***
|
|
//
|
|
if (!HardwareScriptInterpreterCheckScriptBufferWithScriptCapabilities(&g_HwdbgInstanceInfo,
|
|
ScriptBuffer,
|
|
ScriptBufferSize / sizeof(SYMBOL),
|
|
&NumberOfStagesForScript,
|
|
&NumberOfOperandsForScript,
|
|
&NumberOfOperandsImplemented))
|
|
{
|
|
ShowMessages("\n[-] target script is NOT supported by this instance of hwdbg!\n");
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ShowMessages("\n[+] target script is supported by this instance of hwdbg!\n");
|
|
}
|
|
|
|
//
|
|
// *** Compress the script buffer based on the instance info ***
|
|
//
|
|
if (!HwdbgScriptCompressScriptBuffer(&g_HwdbgInstanceInfo,
|
|
(SYMBOL *)ScriptBuffer,
|
|
ScriptBufferSize,
|
|
NumberOfStagesForScript,
|
|
&NewScriptBuffer,
|
|
&NewCompressedBufferSize,
|
|
&NumberOfBytesPerChunk))
|
|
{
|
|
ShowMessages("err, unable to compress the script buffer\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Print the hwdbg script buffer
|
|
//
|
|
HwdbgScriptPrintFinalScriptBufferAndHardwareDetails(&g_HwdbgInstanceInfo,
|
|
NewCompressedBufferSize,
|
|
NumberOfStagesForScript,
|
|
NumberOfOperandsForScript,
|
|
NewScriptBuffer,
|
|
NumberOfNeededFlipFlopsInTargetDevice,
|
|
NumberOfBytesPerChunk,
|
|
NumberOfOperandsImplemented);
|
|
|
|
//
|
|
// *** Write script configuration packet into a file ***
|
|
//
|
|
|
|
//
|
|
// Write script configuration packet into a file
|
|
//
|
|
if (!HwdbgScriptWriteScriptConfigurationPacketIntoFile(&g_HwdbgInstanceInfo,
|
|
HardwareScriptFilePathToSave,
|
|
NumberOfStagesForScript,
|
|
NumberOfOperandsImplemented,
|
|
NewScriptBuffer,
|
|
NewCompressedBufferSize))
|
|
{
|
|
ShowMessages("err, unable to write script buffer\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// *** Free the allocated memory ***
|
|
//
|
|
|
|
//
|
|
// Free the allocated memory for the short symbol buffer
|
|
//
|
|
if (NewScriptBuffer != NULL)
|
|
{
|
|
HardwareScriptInterpreterFreeHwdbgShortSymbolBuffer(NewScriptBuffer);
|
|
}
|
|
|
|
//
|
|
// The script buffer is created successfully
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/** Get script buffer from raw string
|
|
* @param ScriptBuffer
|
|
* @param CodeBuffer
|
|
* @param BufferAddress
|
|
* @param BufferLength
|
|
* @param Pointer
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptGetScriptBufferFromRawString(string ScriptString,
|
|
PVOID * CodeBuffer,
|
|
UINT64 * BufferAddress,
|
|
UINT32 * BufferLength,
|
|
UINT32 * Pointer)
|
|
{
|
|
PVOID ResultingCodeBuffer = NULL;
|
|
|
|
//
|
|
// Run script engine handler
|
|
//
|
|
ResultingCodeBuffer = ScriptEngineParseWrapper((CHAR *)ScriptString.c_str(), TRUE);
|
|
|
|
if (ResultingCodeBuffer == NULL)
|
|
{
|
|
//
|
|
// return to show that this item contains an script error
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Print symbols (test)
|
|
//
|
|
// PrintSymbolBufferWrapper(ResultingCodeBuffer);
|
|
|
|
//
|
|
// Set the buffer and length
|
|
//
|
|
*BufferAddress = ScriptEngineWrapperGetHead(ResultingCodeBuffer);
|
|
*BufferLength = ScriptEngineWrapperGetSize(ResultingCodeBuffer);
|
|
*Pointer = ScriptEngineWrapperGetPointer(ResultingCodeBuffer);
|
|
|
|
//
|
|
// Set the code buffer
|
|
//
|
|
*CodeBuffer = ResultingCodeBuffer;
|
|
|
|
//
|
|
// The script buffer is copied successfully
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a HyperDbg (hwdbg) script packet to the hwdbg
|
|
*
|
|
* @param InstanceInfo
|
|
* @param FileName
|
|
* @param Buffer
|
|
* @param BufferLength
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptSendScriptPacket(HWDBG_INSTANCE_INFORMATION * InstanceInfo,
|
|
const TCHAR * FileName,
|
|
UINT32 NumberOfSymbols,
|
|
HWDBG_SHORT_SYMBOL * Buffer,
|
|
UINT32 BufferLength)
|
|
{
|
|
HWDBG_SCRIPT_BUFFER ScriptBuffer = {0};
|
|
BOOLEAN Result = FALSE;
|
|
|
|
//
|
|
// Make the packet's structure
|
|
//
|
|
ScriptBuffer.scriptNumberOfSymbols = NumberOfSymbols;
|
|
|
|
//
|
|
// Allocate a buffer for storing the header packet + buffer (if not empty)
|
|
//
|
|
CHAR * FinalBuffer = (CHAR *)malloc(BufferLength + sizeof(HWDBG_SCRIPT_BUFFER));
|
|
|
|
if (!FinalBuffer)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
RtlZeroMemory(FinalBuffer, BufferLength + sizeof(HWDBG_SCRIPT_BUFFER));
|
|
|
|
//
|
|
// Copy the packet into the FinalBuffer
|
|
//
|
|
memcpy(FinalBuffer, &ScriptBuffer, sizeof(HWDBG_SCRIPT_BUFFER));
|
|
|
|
//
|
|
// Copy the buffer (if available) into the FinalBuffer
|
|
//
|
|
if (Buffer != NULL)
|
|
{
|
|
memcpy(FinalBuffer + sizeof(HWDBG_SCRIPT_BUFFER), Buffer, BufferLength);
|
|
}
|
|
|
|
//
|
|
// Here we would send FinalBuffer to the hardware debugger
|
|
//
|
|
Result = HwdbgInterpreterSendPacketAndBufferToHwdbg(
|
|
InstanceInfo,
|
|
FileName,
|
|
DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_HARDWARE_LEVEL,
|
|
hwdbgActionConfigureScriptBuffer,
|
|
FinalBuffer,
|
|
BufferLength + sizeof(HWDBG_SCRIPT_BUFFER));
|
|
|
|
//
|
|
// Free the allocated memory after use
|
|
//
|
|
free(FinalBuffer);
|
|
|
|
return Result;
|
|
}
|
|
|
|
/**
|
|
* @brief Run script in hwdbg
|
|
*
|
|
* @param Script
|
|
* @param InstanceFilePathToRead
|
|
* @param HardwareScriptFilePathToSave
|
|
* @param InitialBramBufferSize
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
HwdbgScriptRunScript(const CHAR * Script,
|
|
const TCHAR * InstanceFilePathToRead,
|
|
const TCHAR * HardwareScriptFilePathToSave,
|
|
UINT32 InitialBramBufferSize)
|
|
{
|
|
PVOID CodeBuffer;
|
|
UINT64 BufferAddress;
|
|
UINT32 BufferLength;
|
|
UINT32 Pointer;
|
|
|
|
//
|
|
// Load the instance info
|
|
//
|
|
if (!HwdbgLoadInstanceInfo(InstanceFilePathToRead, InitialBramBufferSize))
|
|
{
|
|
//
|
|
// Unable to load the instance info
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the script buffer from the raw string (script)
|
|
//
|
|
if (!HwdbgScriptGetScriptBufferFromRawString(Script,
|
|
&CodeBuffer,
|
|
&BufferAddress,
|
|
&BufferLength,
|
|
&Pointer))
|
|
{
|
|
//
|
|
// Unable to get script buffer from script
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Print the actual script
|
|
//
|
|
HwdbgScriptPrintScriptBuffer((CHAR *)BufferAddress, BufferLength);
|
|
|
|
//
|
|
// Create hwdbg script
|
|
//
|
|
if (!HwdbgScriptCreateHwdbgScript((CHAR *)BufferAddress,
|
|
BufferLength,
|
|
HardwareScriptFilePathToSave))
|
|
{
|
|
ShowMessages("err, unable to create hwdbg script\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Return the result
|
|
//
|
|
return TRUE;
|
|
}
|