HyperDbg/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/output.cpp
2022-01-18 22:38:56 +03:30

459 lines
14 KiB
C++

/**
* @file output.cpp
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief output command
* @details
* @version 0.1
* @date 2020-11-05
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "..\hprdbgctrl\pch.h"
//
// Global Variables
//
extern LIST_ENTRY g_OutputSources;
extern BOOLEAN g_OutputSourcesInitialized;
/**
* @brief help of output command
*
* @return VOID
*/
VOID
CommandOutputHelp()
{
ShowMessages("output : create an output instance that can be used in event "
"forwarding.\n\n");
ShowMessages("syntax : \toutput [create|open|close] [type "
"(file|namedpipe|tcp)] [name|address]\n");
ShowMessages("\t\te.g : output create MyOutputName1 file "
"c:\\users\\sina\\desktop\\output.txt\n");
ShowMessages("\t\te.g : output create MyOutputName2 tcp 192.168.1.10:8080\n");
ShowMessages("\t\te.g : output create MyOutputName3 namedpipe "
"\\\\.\\Pipe\\HyperDbgOutput\n");
ShowMessages("\t\te.g : output open MyOutputName1\n");
ShowMessages("\t\te.g : output close MyOutputName1\n");
}
/**
* @brief output command handler
*
* @param SplittedCommand
* @param Command
* @return VOID
*/
VOID
CommandOutput(vector<string> SplittedCommand, string Command)
{
PDEBUGGER_EVENT_FORWARDING EventForwardingObject;
DEBUGGER_EVENT_FORWARDING_TYPE Type;
DEBUGGER_OUTPUT_SOURCE_STATUS Status;
string DetailsOfSource;
UINT32 IndexToShowList;
PLIST_ENTRY TempList = 0;
BOOLEAN OutputSourceFound = FALSE;
HANDLE SourceHandle = INVALID_HANDLE_VALUE;
SOCKET Socket = NULL;
vector<string> SplittedCommandCaseSensitive {Split(Command, ' ')};
//
// Check if the user needs a list of outputs or not
//
if (SplittedCommand.size() == 1)
{
IndexToShowList = 0;
if (g_OutputSourcesInitialized)
{
TempList = &g_OutputSources;
while (&g_OutputSources != TempList->Blink)
{
TempList = TempList->Blink;
PDEBUGGER_EVENT_FORWARDING CurrentOutputSourceDetails =
CONTAINING_RECORD(TempList, DEBUGGER_EVENT_FORWARDING, OutputSourcesList);
//
// Increase index
//
IndexToShowList++;
string TempStateString = "";
string TempTypeString = "";
if (CurrentOutputSourceDetails->State ==
EVENT_FORWARDING_STATE_NOT_OPENED)
{
TempStateString = "not opened";
}
else if (CurrentOutputSourceDetails->State ==
EVENT_FORWARDING_STATE_OPENED)
{
TempStateString = "opened ";
}
else if (CurrentOutputSourceDetails->State ==
EVENT_FORWARDING_CLOSED)
{
TempStateString = "closed ";
}
if (CurrentOutputSourceDetails->Type == EVENT_FORWARDING_NAMEDPIPE)
{
TempTypeString = "namedpipe";
}
else if (CurrentOutputSourceDetails->Type == EVENT_FORWARDING_FILE)
{
TempTypeString = "file ";
}
else if (CurrentOutputSourceDetails->Type == EVENT_FORWARDING_TCP)
{
TempTypeString = "tcp ";
}
ShowMessages("%x %s %s\t%s\n", IndexToShowList, TempTypeString.c_str(), TempStateString.c_str(), CurrentOutputSourceDetails->Name);
}
}
else
{
ShowMessages("output forwarding list is empty.\n\n");
}
return;
}
if (SplittedCommand.size() <= 2)
{
ShowMessages("incorrect use of 'output'\n\n");
CommandOutputHelp();
return;
}
//
// Check if it's a create, open, or close
//
if (!SplittedCommand.at(1).compare("create"))
{
//
// It's a create
//
//
// check if the parameters are okay for a create or not
//
if (SplittedCommand.size() <= 4)
{
ShowMessages("incorrect use of 'output'\n\n");
CommandOutputHelp();
return;
}
//
// Check for the type of the output source
//
if (!SplittedCommand.at(3).compare("file"))
{
Type = EVENT_FORWARDING_FILE;
}
else if (!SplittedCommand.at(3).compare("namedpipe"))
{
Type = EVENT_FORWARDING_NAMEDPIPE;
}
else if (!SplittedCommand.at(3).compare("tcp"))
{
Type = EVENT_FORWARDING_TCP;
}
else
{
ShowMessages("incorrect type near '%s'\n\n",
SplittedCommand.at(3).c_str());
CommandOutputHelp();
return;
}
//
// Check to make sure that the name doesn't exceed the maximum character
//
if (SplittedCommand.at(2).size() >=
MAXIMUM_CHARACTERS_FOR_EVENT_FORWARDING_NAME)
{
ShowMessages("name of the output cannot exceed form %d characters\n\n",
MAXIMUM_CHARACTERS_FOR_EVENT_FORWARDING_NAME);
CommandOutputHelp();
return;
}
//
// Search to see if there is another output source with the
// same name which we don't want to create two or more output
// sources with the same name
//
if (g_OutputSourcesInitialized)
{
TempList = &g_OutputSources;
while (&g_OutputSources != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT_FORWARDING CurrentOutputSourceDetails =
CONTAINING_RECORD(TempList, DEBUGGER_EVENT_FORWARDING, OutputSourcesList);
if (strcmp(CurrentOutputSourceDetails->Name,
SplittedCommandCaseSensitive.at(2).c_str()) == 0)
{
//
// Indicate that we found this item
//
OutputSourceFound = TRUE;
//
// No need to search through the list anymore
//
break;
}
}
//
// Check whether the entered name already exists
//
if (OutputSourceFound)
{
ShowMessages("err, the name you entered, already exists, please choose "
"another name.\n\n");
return;
}
}
//
// try to open the source and get the handle
//
DetailsOfSource = Command.substr(Command.find(SplittedCommandCaseSensitive.at(3)) +
SplittedCommandCaseSensitive.at(3).size() + 1,
Command.size());
SourceHandle = ForwardingCreateOutputSource(Type, DetailsOfSource, &Socket);
//
// Check if it's a valid handle or not
//
if (SourceHandle == INVALID_HANDLE_VALUE)
{
ShowMessages(
"err, invalid address or cannot open or find the address.\n\n");
return;
}
//
// allocate the buffer for storing the event forwarding details
//
EventForwardingObject =
(PDEBUGGER_EVENT_FORWARDING)malloc(sizeof(DEBUGGER_EVENT_FORWARDING));
if (EventForwardingObject == NULL)
{
ShowMessages("err, in allocating memory for event forwarding.\n\n");
return;
}
RtlZeroMemory(EventForwardingObject, sizeof(DEBUGGER_EVENT_FORWARDING));
//
// Set the state
//
EventForwardingObject->State = EVENT_FORWARDING_STATE_NOT_OPENED;
//
// Set the type
//
EventForwardingObject->Type = Type;
//
// Get a new tag
//
EventForwardingObject->OutputUniqueTag = ForwardingGetNewOutputSourceTag();
//
// Set the handle or in the case of TCP, set the socket
//
if (Type == EVENT_FORWARDING_TCP)
{
EventForwardingObject->Socket = Socket;
}
else
{
EventForwardingObject->Handle = SourceHandle;
}
//
// Move the name of the output source to the buffer
//
strcpy_s(EventForwardingObject->Name, SplittedCommandCaseSensitive.at(2).c_str());
//
// Check if list is initialized or not
//
if (!g_OutputSourcesInitialized)
{
g_OutputSourcesInitialized = TRUE;
InitializeListHead(&g_OutputSources);
}
//
// Add the source to the trace list
//
InsertHeadList(&g_OutputSources,
&(EventForwardingObject->OutputSourcesList));
}
else if (!SplittedCommand.at(1).compare("open"))
{
//
// It's an open
//
if (!g_OutputSourcesInitialized)
{
ShowMessages("err, the name you entered, not found.\n\n");
return;
}
//
// Now we should find the corresponding object in the memory and
// pass it to the global open functions
//
TempList = &g_OutputSources;
while (&g_OutputSources != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT_FORWARDING CurrentOutputSourceDetails = CONTAINING_RECORD(
TempList,
DEBUGGER_EVENT_FORWARDING,
OutputSourcesList);
if (strcmp(CurrentOutputSourceDetails->Name,
SplittedCommandCaseSensitive.at(2).c_str()) == 0)
{
//
// Indicate that we found this item
//
OutputSourceFound = TRUE;
//
// Open the output
//
Status = ForwardingOpenOutputSource(CurrentOutputSourceDetails);
if (Status == DEBUGGER_OUTPUT_SOURCE_STATUS_ALREADY_CLOSED)
{
ShowMessages("err, the name you entered was already closed.\n\n");
return;
}
else if (Status == DEBUGGER_OUTPUT_SOURCE_STATUS_ALREADY_OPENED)
{
ShowMessages("err, the name you entered was already opened.\n\n");
return;
}
else if (Status !=
DEBUGGER_OUTPUT_SOURCE_STATUS_SUCCESSFULLY_OPENED)
{
ShowMessages("err, unable to open the output source.\n\n");
return;
}
//
// No need to search through the list anymore
//
break;
}
}
if (!OutputSourceFound)
{
ShowMessages("err, the name you entered, not found.\n\n");
return;
}
}
else if (!SplittedCommand.at(1).compare("close"))
{
//
// It's a close
//
if (!g_OutputSourcesInitialized)
{
ShowMessages("err, the name you entered, not found.\n\n");
return;
}
//
// Now we should find the corresponding object in the memory and
// pass it to the global close functions
//
TempList = &g_OutputSources;
while (&g_OutputSources != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT_FORWARDING CurrentOutputSourceDetails = CONTAINING_RECORD(
TempList,
DEBUGGER_EVENT_FORWARDING,
OutputSourcesList);
if (strcmp(CurrentOutputSourceDetails->Name,
SplittedCommandCaseSensitive.at(2).c_str()) == 0)
{
//
// Indicate that we found this item
//
OutputSourceFound = TRUE;
//
// Close the output if it's not already closed
//
Status = ForwardingCloseOutputSource(CurrentOutputSourceDetails);
if (Status == DEBUGGER_OUTPUT_SOURCE_STATUS_ALREADY_CLOSED)
{
ShowMessages("err, the name you entered was already closed.\n\n");
return;
}
else if (Status == DEBUGGER_OUTPUT_SOURCE_STATUS_UNKNOWN_ERROR)
{
ShowMessages("err, unable to close the source.\n\n");
return;
}
else if (Status !=
DEBUGGER_OUTPUT_SOURCE_STATUS_SUCCESSFULLY_CLOSED)
{
ShowMessages("err, unable to close the source.\n\n");
return;
}
//
// No need to search through the list anymore
//
break;
}
}
if (!OutputSourceFound)
{
ShowMessages("err, the name you entered, not found.\n\n");
return;
}
}
else
{
//
// Invalid argument
//
ShowMessages("incorrect option at '%s'\n\n", SplittedCommand.at(1).c_str());
CommandOutputHelp();
return;
}
}