/** * @file eval.cpp * @author Sina Karvandi (sina@hyperdbg.org) * @brief eval (?) command * @details * @version 0.1 * @date 2021-02-05 * * @copyright This project is released under the GNU Public License v3. * */ #include "pch.h" // // Global Variables // extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState; /** * @brief help of the ? command * * @return VOID */ VOID CommandEvalHelp() { ShowMessages("? : evaluates and execute expressions in debuggee.\n\n"); ShowMessages("syntax : \t? [Expression (string)]\n"); ShowMessages("\n"); ShowMessages("\t\te.g : ? print(dq(poi(@rcx)));\n"); ShowMessages("\t\te.g : ? json(dq(poi(@rcx)));\n"); } /** * @brief Check test-cases for script-engine * * @return BOOLEAN */ BOOLEAN CommandEvalCheckTestcase() { string Line; BOOLEAN IsOpened = FALSE; UINT64 ExpectedValue = 0; BOOLEAN ExpectError = FALSE; string Expr = ""; std::vector TestFiles; try { TestFiles = ListDirectory(SCRIPT_ENGINE_TEST_CASES_DIRECTORY, "*.txt"); } catch (const std::exception &) { ShowMessages("err, test-cases not found, make sure to run test-environment.py " "before running test cases\n"); return FALSE; } for (auto item : TestFiles) { // // Read the test-case file for script-engine // ifstream File(item.c_str()); if (File.is_open()) { IsOpened = TRUE; // // File name // ShowMessages("Running from : %s\n\n", item.c_str()); while (std::getline(File, Line)) { // // Test case number // ShowMessages("Test-case number : %s\n", Line.c_str()); // // Test-case statement // if (!std::getline(File, Line)) { goto ErrorMessage; } Expr = Line; ShowMessages("Statement : %s\n", Line.c_str()); // // Test-case result // if (!std::getline(File, Line)) { goto ErrorMessage; } if (!Line.compare("$error$")) { // // It's an $error$ statement // ShowMessages("Expected result : %s\n", Line.c_str()); ExpectError = TRUE; ExpectedValue = NULL; } else if (!ConvertStringToUInt64(Line, &ExpectedValue)) { ShowMessages("err, the expected results are in incorrect format\n"); goto ErrorMessage; } else { // // It's a value expected statement // ExpectError = FALSE; ShowMessages("Expected result : %llx\n", ExpectedValue); } // // Call wrapper for testing statements // Expr.append(" "); // // Test results // if (ScriptAutomaticStatementsTestWrapper(Expr, ExpectedValue, ExpectError)) { ShowMessages("Test result : Passed\n"); } else { ShowMessages("Test result : Failed\n"); } // // Test-case end // if (!std::getline(File, Line)) { goto ErrorMessage; } // // Check end case // if (Line.compare("$end$")) { // // err, we'd expect a $end$ at this situation // goto ErrorMessage; } ShowMessages("\n------------------------------------------------------------\n\n"); } File.close(); } } if (!IsOpened) { ShowMessages("err, could not find files for script engine test-cases\n"); return FALSE; } return TRUE; ErrorMessage: ShowMessages("\nerr, testing failed! incorrect file format for the testing " "script engine\nmake sure files have a correct ending format\n"); return FALSE; } /** * @brief handler of ? command * * @param CommandTokens * @param Command * * @return VOID */ VOID CommandEval(vector CommandTokens, string Command) { if (CommandTokens.size() == 1) { ShowMessages("incorrect use of the '%s'\n\n", GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); CommandEvalHelp(); return; } // // Trim the command // Trim(Command); // // Remove the first command from it // Command.erase(0, GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).size()); // // Trim it again // Trim(Command); // // Check if it's a test-case check or not // if (!Command.compare("test")) { // // It's a test-case checker // if (!CommandEvalCheckTestcase()) { ShowMessages("err, testing script engine test-cases was not successful\n"); } else { ShowMessages("testing script engine test-cases was successful\n"); } return; } // // Check if we're connected to a remote debuggee (kernel debugger) or the user debugger // if (g_IsSerialConnectedToRemoteDebuggee || g_ActiveProcessDebuggingState.IsActive) { // // Send data to the target user debugger or kernel debugger // ScriptEngineExecuteSingleExpression((CHAR *)Command.c_str(), TRUE, FALSE); } else { // // It's a test (simulated) run of the script-engine // ShowMessages("this command should not be used while you're in VMI-Mode (not attached to the user debugger) " "or not in the debugger mode, the results that you see is a simulated result for TESTING the script engine " "and is not based on the status of your system. You can use this command, either in the debugger mode " "(kernel debugger), or when you attached to a user debugger\n\n"); ShowMessages("test expression : %s \n", Command.c_str()); ScriptEngineWrapperTestParser(Command); } }