diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp index bc4b0b50..6b3b96a5 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/commands/meta-commands/script.cpp @@ -30,6 +30,49 @@ CommandScriptHelp() ShowMessages("syntax : \.script [FilePath]\n"); } +/** + * @brief Run the command + * + * @return VOID + */ +VOID +CommandScriptRunCommand(char * LineContent) +{ + int CommandExecutionResult = 0; + + // + // Check if the it's a command or not + // + InterpreterRemoveComments(LineContent); + + if (IsEmptyString(LineContent)) + { + return; + } + + // + // Show current running command + // + HyperdbgShowSignature(); + + ShowMessages("%s\n", LineContent); + + CommandExecutionResult = HyperdbgInterpreter(LineContent); + + ShowMessages("\n"); + + // + // if the debugger encounters an exit state then the return will be 1 + // + if (CommandExecutionResult == 1) + { + // + // Exit from the debugger + // + exit(0); + } +} + /** * @brief .script command handler * @@ -41,8 +84,9 @@ VOID CommandScript(vector SplittedCommand, string Command) { std::string Line; - BOOLEAN IsOpened = FALSE; - int CommandExecutionResult = 0; + BOOLEAN IsOpened = FALSE; + bool Reset = false; + string CommandToExecute = ""; if (SplittedCommand.size() == 1) { @@ -80,38 +124,73 @@ CommandScript(vector SplittedCommand, string Command) // g_ExecutingScript = TRUE; + // + // Reset multiline command + // + Reset = true; + while (std::getline(File, Line)) { - char * LineContent = (char *)Line.c_str(); // - // Check if the it's a command or not + // Check for multiline commands // - InterpreterRemoveComments(LineContent); - - if (IsEmptyString(LineContent)) + if (HyperDbgCheckMultilineCommand(Line, Reset)) { + // + // if the reset is true, we should make the saving buffer empty + // + if (Reset) + { + CommandToExecute.clear(); + } + + // + // The command is expected to be continued + // + Reset = false; + + // + // Append to the previous command + // + CommandToExecute += Line + "\n"; + continue; } - - // - // Show current running command - // - ShowMessages("\n%s\n", LineContent); - - CommandExecutionResult = HyperdbgInterpreter(LineContent); - - ShowMessages("\n"); - - // - // if the debugger encounters an exit state then the return will be 1 - // - if (CommandExecutionResult == 1) + else { // - // Exit from the debugger + // Reset for the next commands round // - exit(0); + Reset = true; + + // + // Append this line too + // + CommandToExecute += Line; } + + // + // Run the command + // + CommandScriptRunCommand((char *)CommandToExecute.c_str()); + + // + // Clear the command + // + CommandToExecute.clear(); + } + + // + // Check for some probably not ended commands + // + if (!CommandToExecute.empty()) + { + CommandScriptRunCommand((char *)CommandToExecute.c_str()); + + // + // Clear the command + // + CommandToExecute.clear(); } // diff --git a/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp b/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp index 4da5d388..38920e89 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/core/interpreter.cpp @@ -28,8 +28,11 @@ extern BOOLEAN g_IsConnectedToRemoteDebuggee; extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern BOOLEAN g_IsDebuggeeRunning; extern BOOLEAN g_BreakPrintingOutput; +extern BOOLEAN g_IsInterpreterOnString; +extern BOOLEAN g_IsInterpreterPreviousCharacterABackSlash; -extern ULONG g_CurrentRemoteCore; +extern UINT32 g_InterpreterCountOfOpenCurlyBrackets; +extern ULONG g_CurrentRemoteCore; extern string g_ServerPort; extern string g_ServerIp; @@ -330,6 +333,98 @@ HyperdbgShowSignature() } } +/** + * @brief check for multi-line commands + * + * @param CurrentCommand + * @param Reset + * @return bool return true if the command needs extra input, otherwise + * return false + */ +bool +HyperDbgCheckMultilineCommand(std::string & CurrentCommand, bool Reset) +{ + if (Reset) + { + g_IsInterpreterOnString = FALSE; + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + g_InterpreterCountOfOpenCurlyBrackets = 0; + } + + for (size_t i = 0; i < CurrentCommand.length(); i++) + { + switch (CurrentCommand.at(i)) + { + case '"': + + if (g_IsInterpreterPreviousCharacterABackSlash) + { + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + break; // it's an escaped \" double-quote + } + + if (g_IsInterpreterOnString) + g_IsInterpreterOnString = FALSE; + else + g_IsInterpreterOnString = TRUE; + + break; + + case '{': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + if (!g_IsInterpreterOnString) + g_InterpreterCountOfOpenCurlyBrackets++; + + break; + + case '}': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + if (!g_IsInterpreterOnString && g_InterpreterCountOfOpenCurlyBrackets > 0) + g_InterpreterCountOfOpenCurlyBrackets--; + + break; + + case '\\': + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; // it's not a escape character (two backslashes \\ ) + else + g_IsInterpreterPreviousCharacterABackSlash = TRUE; + + break; + + default: + + if (g_IsInterpreterPreviousCharacterABackSlash) + g_IsInterpreterPreviousCharacterABackSlash = FALSE; + + break; + } + } + + if (g_IsInterpreterOnString == FALSE && g_InterpreterCountOfOpenCurlyBrackets == 0) + { + // + // either the command is finished or it's a single + // line command + // + return false; + } + else + { + // + // There still other lines, this command is incomplete + // + return true; + } +} + /** * @brief Some of commands like stepping commands (i, p, t) and etc. * need to be repeated when the user press enter, this function shows diff --git a/hyperdbg/hprdbgctrl/header/exports.h b/hyperdbg/hprdbgctrl/header/exports.h index 42964489..01bff2c1 100644 --- a/hyperdbg/hprdbgctrl/header/exports.h +++ b/hyperdbg/hprdbgctrl/header/exports.h @@ -29,4 +29,5 @@ __declspec(dllexport) void HyperdbgSetTextMessageCallback(Callback handler); __declspec(dllexport) int HyperdbgInterpreter(char * Command); __declspec(dllexport) void HyperdbgShowSignature(); __declspec(dllexport) bool HyperdbgContinuePreviousCommand(); +__declspec(dllexport) bool HyperDbgCheckMultilineCommand(std::string & CurrentCommand, bool Reset); } diff --git a/hyperdbg/hprdbgctrl/header/globals.h b/hyperdbg/hprdbgctrl/header/globals.h index 87ea400f..ebd354f0 100644 --- a/hyperdbg/hprdbgctrl/header/globals.h +++ b/hyperdbg/hprdbgctrl/header/globals.h @@ -11,6 +11,25 @@ */ #pragma once +////////////////////////////////////////////////// +// Interpreter Variables // +////////////////////////////////////////////////// + +/** + * @brief shows whether the interpreter is currently on a string or not + */ +BOOLEAN g_IsInterpreterOnString = FALSE; + +/** + * @brief Is interpreter ecountered a back slash at previous run + */ +BOOLEAN g_IsInterpreterPreviousCharacterABackSlash = FALSE; + +/** + * @brief Keeps the trace of curly brackets in the interpreter + */ +UINT32 g_InterpreterCountOfOpenCurlyBrackets = 0; + ////////////////////////////////////////////////// // Remote and Local Connection // ////////////////////////////////////////////////// diff --git a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp index d9205004..645b7c30 100644 --- a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp +++ b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp @@ -21,13 +21,6 @@ using namespace std; -// -// Global variables -// -bool IsOnString = false; -bool IsPreviousCharacterABackSlash = false; -int CountOfOpenCurlyBrackets = 0; - // // Header file of HPRDBGCTRL // Imports @@ -41,93 +34,10 @@ __declspec(dllimport) int HyperdbgStopDriver(); __declspec(dllimport) int HyperdbgInterpreter(char * Command); __declspec(dllimport) void HyperdbgShowSignature(); __declspec(dllimport) bool HyperdbgContinuePreviousCommand(); +__declspec(dllimport) bool HyperDbgCheckMultilineCommand(std::string & CurrentCommand, bool Reset); __declspec(dllimport) void HyperdbgSetTextMessageCallback(Callback handler); } -/** - * @brief check for multi-line commands - * - * @param CurrentCommand - * @return bool return true if the command needs extra input, otherwise - * return false - */ -bool -CheckMultilineCommand(std::string CurrentCommand) -{ - for (size_t i = 0; i < CurrentCommand.length(); i++) - { - switch (CurrentCommand.at(i)) - { - case '"': - - if (IsPreviousCharacterABackSlash) - { - IsPreviousCharacterABackSlash = false; - break; // it's an escaped \" double-quote - } - - if (IsOnString) - IsOnString = false; - else - IsOnString = true; - - break; - - case '{': - - if (IsPreviousCharacterABackSlash) - IsPreviousCharacterABackSlash = false; - - if (!IsOnString) - CountOfOpenCurlyBrackets++; - - break; - - case '}': - - if (IsPreviousCharacterABackSlash) - IsPreviousCharacterABackSlash = false; - - if (!IsOnString && CountOfOpenCurlyBrackets > 0) - CountOfOpenCurlyBrackets--; - - break; - - case '\\': - - if (IsPreviousCharacterABackSlash) - IsPreviousCharacterABackSlash = false; // it's not a escape character (two backslashes \\ ) - else - IsPreviousCharacterABackSlash = true; - - break; - - default: - - if (IsPreviousCharacterABackSlash) - IsPreviousCharacterABackSlash = false; - - break; - } - } - - if (IsOnString == FALSE && CountOfOpenCurlyBrackets == 0) - { - // - // either the command is finished or it's a single - // line command - // - return false; - } - else - { - // - // There still other lines, this command is incomplete - // - return true; - } -} - /** * @brief CLI main function * @@ -140,6 +50,7 @@ main(int argc, char * argv[]) { bool ExitFromDebugger = false; string PreviousCommand; + bool Reset = false; printf("HyperDbg Debugger [core version: v%s]\n", Version); printf("Please visit https://docs.hyperdbg.org for more information...\n"); @@ -172,10 +83,8 @@ main(int argc, char * argv[]) { HyperdbgShowSignature(); - string CurrentCommand = ""; - IsOnString = false; - IsPreviousCharacterABackSlash = false; - CountOfOpenCurlyBrackets = 0; + string CurrentCommand = ""; + Reset = true; GetMultiLinecCommand: @@ -197,16 +106,17 @@ main(int argc, char * argv[]) // // Check for multi-line commands // - if (CheckMultilineCommand(TempCommand) == true) + if (HyperDbgCheckMultilineCommand(TempCommand, Reset) == true) { // // It's a multi-line command // + Reset = false; // // Save the command with a space separator // - CurrentCommand += TempCommand + " "; + CurrentCommand += TempCommand + "\n"; // // Show a small signature