support multiline commands in .script command

This commit is contained in:
SinaKarvandi 2021-12-03 16:19:50 +03:30
parent c09d4b2989
commit 5544fe30ae
5 changed files with 225 additions and 121 deletions

View file

@ -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<string> 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<string> 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();
}
//

View file

@ -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

View file

@ -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);
}

View file

@ -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 //
//////////////////////////////////////////////////

View file

@ -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