diff --git a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp index 97ab6796..de3b65ce 100644 --- a/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp +++ b/hyperdbg/hyperdbg-cli/hyperdbg-cli.cpp @@ -21,6 +21,13 @@ using namespace std; +// +// Global variables +// +bool IsOnString = false; +bool IsPreviousCharacterABackSlash = false; +int CountOfOpenCurlyBrackets = 0; + // // Header file of HPRDBGCTRL // Imports @@ -37,6 +44,84 @@ __declspec(dllimport) bool HyperdbgContinuePreviousCommand(); __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 (!IsOnString) + CountOfOpenCurlyBrackets++; + + break; + + case '}': + + 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 * @@ -81,9 +166,16 @@ main(int argc, char * argv[]) { HyperdbgShowSignature(); - string CurrentCommand; + string CurrentCommand = ""; + IsOnString = false; + IsPreviousCharacterABackSlash = false; + CountOfOpenCurlyBrackets = 0; - getline(cin, CurrentCommand); + GetMultiLinecCommand: + + string TempCommand = ""; + + getline(cin, TempCommand); if (cin.fail() || cin.eof()) { @@ -96,6 +188,39 @@ main(int argc, char * argv[]) continue; } + // + // Check for multi-line commands + // + if (CheckMultilineCommand(TempCommand) == true) + { + // + // It's a multi-line command + // + + // + // Save the command with a space separator + // + CurrentCommand += TempCommand + " "; + + // + // Show a small signature + // + printf("> "); + + // + // Get next command + // + goto GetMultiLinecCommand; + } + else + { + // + // Either the multi-line is finished or it's a + // single line command + // + CurrentCommand += TempCommand; + } + if (!CurrentCommand.compare("") && HyperdbgContinuePreviousCommand()) { diff --git a/hyperdbg/include/ScriptEngineEval.h b/hyperdbg/include/ScriptEngineEval.h index d1f6ea63..b452471d 100644 --- a/hyperdbg/include/ScriptEngineEval.h +++ b/hyperdbg/include/ScriptEngineEval.h @@ -841,7 +841,7 @@ ScriptEngineFunctionPrint(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 Va #ifdef SCRIPT_ENGINE_KERNEL_MODE // - // Prepare a buffer to bypass stack + // Prepare a buffer to bypass allocating a huge stack space for logging // char TempBuffer[20] = {0}; UINT32 TempBufferLen = sprintf(TempBuffer, "%llx", Value); @@ -1116,7 +1116,7 @@ ScriptEngineFunctionFormats(UINT64 Tag, BOOLEAN ImmediateMessagePassing, UINT64 else { // - // Prepare a buffer to bypass stack + // Prepare a buffer to bypass allocating a huge stack space for logging // char TempBuffer[20] = {0}; UINT32 TempBufferLen = sprintf(TempBuffer, "%llx\n", Value); @@ -1598,7 +1598,7 @@ ScriptEngineFunctionPrintf(PGUEST_REGS GuestRegs, #ifdef SCRIPT_ENGINE_KERNEL_MODE // - // Prepare a buffer to bypass stack + // Prepare a buffer to bypass allocating a huge stack space for logging // LogSimpleWithTag(Tag, ImmediateMessagePassing, FinalBuffer, strlen(FinalBuffer) + 1); diff --git a/hyperdbg/script-engine/script-engine.c b/hyperdbg/script-engine/script-engine.c index 195c99e6..8e1faae4 100644 --- a/hyperdbg/script-engine/script-engine.c +++ b/hyperdbg/script-engine/script-engine.c @@ -2054,22 +2054,22 @@ HandleError(PSCRIPT_ENGINE_ERROR_TYPE Error, char * str) switch (*Error) { case SCRIPT_ENGINE_ERROR_SYNTAX: - strcat(Message, "SyntaxError: "); + strcat(Message, "Syntax Error: "); strcat(Message, "Invalid Syntax"); return Message; case SCRIPT_ENGINE_ERROR_UNKOWN_TOKEN: - strcat(Message, "SyntaxError: "); + strcat(Message, "Syntax Error: "); strcat(Message, "Unknown Token"); return Message; case SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE: - strcat(Message, "SyntaxError: "); + strcat(Message, "Syntax Error: "); strcat(Message, "Unresolved Variable"); return Message; case SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE: - strcat(Message, "SyntaxError: "); + strcat(Message, "Syntax Error: "); strcat(Message, "Unhandled Semantic Rule"); return Message;