|
|
@ -4,75 +4,44 @@
|
|
|
|
#define DEFAULT_PORT "50113"
|
|
|
|
#define DEFAULT_PORT "50113"
|
|
|
|
#define DEFAULT_BUFLEN 512
|
|
|
|
#define DEFAULT_BUFLEN 512
|
|
|
|
|
|
|
|
|
|
|
|
// Handles for child process STDIN and STDOUT
|
|
|
|
typedef struct PipeThreadInfo_t {
|
|
|
|
HANDLE g_hChildStd_IN_Rd = NULL;
|
|
|
|
HANDLE Pipe;
|
|
|
|
HANDLE g_hChildStd_IN_Wr = NULL;
|
|
|
|
SOCKET ClientSocket;
|
|
|
|
HANDLE g_hChildStd_OUT_Rd = NULL;
|
|
|
|
} PipeThreadInfo;
|
|
|
|
HANDLE g_hChildStd_OUT_Wr = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SOCKET ClientSocket = INVALID_SOCKET;
|
|
|
|
void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr);
|
|
|
|
|
|
|
|
DWORD WINAPI WriteToPipe(LPVOID lpParam);
|
|
|
|
//HANDLE g_hInputFile = NULL;
|
|
|
|
DWORD WINAPI ReadFromPipe(LPVOID lpParam);
|
|
|
|
|
|
|
|
void ErrorExit(PCTSTR);
|
|
|
|
|
|
|
|
|
|
|
|
void StartShellServer() {
|
|
|
|
void StartShellServer() {
|
|
|
|
printf("\n->Start of shell server execution.\n");
|
|
|
|
printf("\n->Start of shell server execution.\n");
|
|
|
|
|
|
|
|
|
|
|
|
CreatePipes();
|
|
|
|
/*
|
|
|
|
CreateSocket();
|
|
|
|
* Server variables
|
|
|
|
|
|
|
|
*/
|
|
|
|
// Create the child process.
|
|
|
|
|
|
|
|
CreateChildProcess();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: split into threads
|
|
|
|
|
|
|
|
WriteToPipe();
|
|
|
|
|
|
|
|
// Read from pipe that is the standard output for child process.
|
|
|
|
|
|
|
|
ReadFromPipe();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("\n->End of shell server execution.\n");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The remaining open handles are cleaned up when this process terminates.
|
|
|
|
|
|
|
|
// To avoid resource leaks in a larger application, close handles explicitly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CreatePipes() {
|
|
|
|
|
|
|
|
SECURITY_ATTRIBUTES saAttr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set the bInheritHandle flag so pipe handles are inherited.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
|
|
|
|
|
|
saAttr.bInheritHandle = TRUE;
|
|
|
|
|
|
|
|
saAttr.lpSecurityDescriptor = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a pipe for the child process's STDOUT.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("StdoutRd CreatePipe"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdout SetHandleInformation"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a pipe for the child process's STDIN.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdin CreatePipe"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure the write handle to the pipe for STDIN is not inherited.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdin SetHandleInformation"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: to review
|
|
|
|
|
|
|
|
void CreateSocket() {
|
|
|
|
|
|
|
|
WSADATA wsaData;
|
|
|
|
WSADATA wsaData;
|
|
|
|
struct addrinfo* result = NULL, * ptr = NULL, hints;
|
|
|
|
struct addrinfo* result = NULL, * ptr = NULL, hints;
|
|
|
|
SOCKET ListenSocket = INVALID_SOCKET;
|
|
|
|
SOCKET ListenSocket = INVALID_SOCKET;
|
|
|
|
|
|
|
|
|
|
|
|
int iResult;
|
|
|
|
int iResult;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Client variables
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
SOCKET ClientSocket = INVALID_SOCKET;
|
|
|
|
|
|
|
|
// Pipe handles for child STDIN/STDOUT
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_IN_Rd = NULL;
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_IN_Wr = NULL;
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_OUT_Rd = NULL;
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_OUT_Wr = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SECURITY_ATTRIBUTES saAttr;
|
|
|
|
|
|
|
|
HANDLE PipeThreads[2];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Initialize listening socket
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize Winsock
|
|
|
|
// Initialize Winsock
|
|
|
|
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
|
|
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
|
|
if (iResult != 0) {
|
|
|
|
if (iResult != 0) {
|
|
|
@ -125,6 +94,39 @@ void CreateSocket() {
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Initialize pipes
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Set the bInheritHandle flag so pipe handles are inherited.
|
|
|
|
|
|
|
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
|
|
|
|
|
|
saAttr.bInheritHandle = TRUE;
|
|
|
|
|
|
|
|
saAttr.lpSecurityDescriptor = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a pipe for the child process's STDOUT.
|
|
|
|
|
|
|
|
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("StdoutRd CreatePipe"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
|
|
|
|
|
|
|
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdout SetHandleInformation"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create a pipe for the child process's STDIN.
|
|
|
|
|
|
|
|
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdin CreatePipe"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure the write handle to the pipe for STDIN is not inherited.
|
|
|
|
|
|
|
|
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
|
|
|
|
|
|
|
|
ErrorExit(TEXT("Stdin SetHandleInformation"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Create child process
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
CreateChildProcess(g_hChildStd_IN_Rd, g_hChildStd_OUT_Wr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Process client connection
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Accepting a connection
|
|
|
|
// Accepting a connection
|
|
|
|
ClientSocket = INVALID_SOCKET;
|
|
|
|
ClientSocket = INVALID_SOCKET;
|
|
|
|
|
|
|
|
|
|
|
@ -136,11 +138,24 @@ void CreateSocket() {
|
|
|
|
WSACleanup();
|
|
|
|
WSACleanup();
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No longer needed
|
|
|
|
|
|
|
|
|
|
|
|
PipeThreadInfo WriteThreadInfo = { g_hChildStd_IN_Wr, ClientSocket };
|
|
|
|
|
|
|
|
PipeThreadInfo ReadThreadInfo = { g_hChildStd_OUT_Rd, ClientSocket };
|
|
|
|
|
|
|
|
PipeThreads[0] = CreateThread(NULL, 0, WriteToPipe, &WriteThreadInfo, 0, NULL);
|
|
|
|
|
|
|
|
PipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &ReadThreadInfo, 0, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WaitForMultipleObjects(2, PipeThreads, TRUE, INFINITE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("\n->Client disconnected.\n");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Finalization
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TODO: properly close all handles
|
|
|
|
closesocket(ListenSocket);
|
|
|
|
closesocket(ListenSocket);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CreateChildProcess()
|
|
|
|
void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr)
|
|
|
|
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
|
|
|
|
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
|
|
|
|
{
|
|
|
|
{
|
|
|
|
TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe");
|
|
|
|
TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe");
|
|
|
@ -195,36 +210,25 @@ void CreateChildProcess()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void WriteToPipe(void)
|
|
|
|
DWORD WINAPI WriteToPipe(LPVOID lpParam)
|
|
|
|
|
|
|
|
|
|
|
|
// Read from a file and write its contents to the pipe for the child's STDIN.
|
|
|
|
|
|
|
|
// Stop when there is no more data.
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DWORD dwRead, dwWritten;
|
|
|
|
DWORD dwRead, dwWritten;
|
|
|
|
//CHAR chBuf[BUFSIZE] = "dir\r\n";
|
|
|
|
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
int i = 0;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket;
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_IN_Wr = ((PipeThreadInfo*)lpParam)->Pipe;
|
|
|
|
|
|
|
|
|
|
|
|
char recvbuf[DEFAULT_BUFLEN];
|
|
|
|
char recvbuf[DEFAULT_BUFLEN];
|
|
|
|
int iResult, iSendResult;
|
|
|
|
int iResult, iSendResult;
|
|
|
|
int recvbuflen = DEFAULT_BUFLEN;
|
|
|
|
int recvbuflen = DEFAULT_BUFLEN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
do
|
|
|
|
{
|
|
|
|
{
|
|
|
|
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
|
|
|
|
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
|
|
|
|
if (iResult > 0) {
|
|
|
|
if (iResult > 0) {
|
|
|
|
printf("Bytes received: %d\n", iResult);
|
|
|
|
bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL);
|
|
|
|
|
|
|
|
if (!bSuccess) break;
|
|
|
|
// Echo the buffer back to the sender
|
|
|
|
|
|
|
|
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
|
|
|
|
|
|
|
|
if (iSendResult == SOCKET_ERROR) {
|
|
|
|
|
|
|
|
printf("send failed: %d\n", WSAGetLastError());
|
|
|
|
|
|
|
|
closesocket(ClientSocket);
|
|
|
|
|
|
|
|
WSACleanup();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Bytes sent: %d\n", iSendResult);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (iResult == 0)
|
|
|
|
else if (iResult == 0)
|
|
|
|
printf("Connection closing...\n");
|
|
|
|
printf("Connection closing...\n");
|
|
|
@ -234,33 +238,21 @@ void WriteToPipe(void)
|
|
|
|
WSACleanup();
|
|
|
|
WSACleanup();
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//dwRead = strlen(chBuf) + 1;
|
|
|
|
|
|
|
|
bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL);
|
|
|
|
|
|
|
|
if (!bSuccess) break;
|
|
|
|
|
|
|
|
//break;
|
|
|
|
|
|
|
|
//dwRead = strlen(chBuf) + 1;
|
|
|
|
|
|
|
|
//bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
|
|
|
|
|
|
|
|
//if (!bSuccess) break;
|
|
|
|
|
|
|
|
ReadFromPipe();
|
|
|
|
|
|
|
|
} while (iResult > 0);
|
|
|
|
} while (iResult > 0);
|
|
|
|
|
|
|
|
|
|
|
|
// Close the pipe handle so the child process stops reading.
|
|
|
|
// Closing STDIN => cmd.exe exit
|
|
|
|
|
|
|
|
|
|
|
|
if (!CloseHandle(g_hChildStd_IN_Wr))
|
|
|
|
if (!CloseHandle(g_hChildStd_IN_Wr))
|
|
|
|
ErrorExit(TEXT("StdInWr CloseHandle"));
|
|
|
|
ErrorExit(TEXT("StdInWr CloseHandle"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ReadFromPipe(void)
|
|
|
|
DWORD WINAPI ReadFromPipe(LPVOID lpParam)
|
|
|
|
|
|
|
|
|
|
|
|
// Read output from the child process's pipe for STDOUT
|
|
|
|
|
|
|
|
// and write to the parent process's pipe for STDOUT.
|
|
|
|
|
|
|
|
// Stop when there is no more data.
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DWORD dwRead, dwWritten;
|
|
|
|
DWORD dwRead, dwWritten;
|
|
|
|
CHAR chBuf[BUFSIZE];
|
|
|
|
CHAR chBuf[BUFSIZE];
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
|
|
|
SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket;
|
|
|
|
|
|
|
|
HANDLE g_hChildStd_OUT_Rd = ((PipeThreadInfo*)lpParam)->Pipe;
|
|
|
|
|
|
|
|
|
|
|
|
int iSendResult;
|
|
|
|
int iSendResult;
|
|
|
|
|
|
|
|
|
|
|
@ -280,7 +272,6 @@ void ReadFromPipe(void)
|
|
|
|
bSuccess = WriteFile(hParentStdOut, chBuf,
|
|
|
|
bSuccess = WriteFile(hParentStdOut, chBuf,
|
|
|
|
dwRead, &dwWritten, NULL);
|
|
|
|
dwRead, &dwWritten, NULL);
|
|
|
|
if (!bSuccess) break;
|
|
|
|
if (!bSuccess) break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|