📄 doexec.c
字号:
// portions Copyright (C) 1994 Nathaniel W. Mishkin
// code taken from rlogind.exe
#include <stdlib.h>#include <winsock2.h>
#include <winbase.h>
#ifdef GAPING_SECURITY_HOLE
#define BUFFER_SIZE 200extern char * pr00gie;void holler(char * str, char * p1, char * p2, char * p3, char * p4, char * p5, char * p6);
char smbuff[20];
//// Structure used to describe each session//typedef struct { // // These fields are filled in at session creation time // HANDLE ReadPipeHandle; // Handle to shell stdout pipe HANDLE WritePipeHandle; // Handle to shell stdin pipe HANDLE ProcessHandle; // Handle to shell process // // // These fields are filled in at session connect time and are only // valid when the session is connected // SOCKET ClientSocket; HANDLE ReadShellThreadHandle; // Handle to session shell-read thread HANDLE WriteShellThreadHandle; // Handle to session shell-read thread} SESSION_DATA, *PSESSION_DATA;//// Private prototypes//static HANDLEStartShell( HANDLE StdinPipeHandle, HANDLE StdoutPipeHandle );static VOIDSessionReadShellThreadFn( LPVOID Parameter );static VOIDSessionWriteShellThreadFn( LPVOID Parameter );// **********************************************************************//// CreateSession//// Creates a new session. Involves creating the shell process and establishing// pipes for communication with it.//// Returns a handle to the session or NULL on failure.//static PSESSION_DATACreateSession( VOID ){ PSESSION_DATA Session = NULL; BOOL Result; SECURITY_ATTRIBUTES SecurityAttributes; HANDLE ShellStdinPipe = NULL; HANDLE ShellStdoutPipe = NULL; // // Allocate space for the session data // Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA)); if (Session == NULL) { return(NULL); } // // Reset fields in preparation for failure // Session->ReadPipeHandle = NULL; Session->WritePipeHandle = NULL; // // Create the I/O pipes for the shell // SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe, &SecurityAttributes, 0); if (!Result) { holler("Failed to create shell stdout pipe, error = %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); goto Failure; } Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle, &SecurityAttributes, 0);
if (!Result) { holler("Failed to create shell stdin pipe, error = %s", itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
goto Failure; } // // Start the shell // Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe); // // We're finished with our copy of the shell pipe handles // Closing the runtime handles will close the pipe handles for us. // CloseHandle(ShellStdinPipe); CloseHandle(ShellStdoutPipe); // // Check result of shell start // if (Session->ProcessHandle == NULL) { holler("Failed to execute shell", NULL,
NULL, NULL, NULL, NULL, NULL);
goto Failure; } // // The session is not connected, initialize variables to indicate that // Session->ClientSocket = INVALID_SOCKET; // // Success, return the session pointer as a handle // return(Session);Failure: // // We get here for any failure case. // Free up any resources and exit // if (ShellStdinPipe != NULL) CloseHandle(ShellStdinPipe); if (ShellStdoutPipe != NULL) CloseHandle(ShellStdoutPipe); if (Session->ReadPipeHandle != NULL) CloseHandle(Session->ReadPipeHandle); if (Session->WritePipeHandle != NULL) CloseHandle(Session->WritePipeHandle); free(Session); return(NULL);}BOOLdoexec( SOCKET ClientSocket ){ PSESSION_DATA Session = CreateSession(); SECURITY_ATTRIBUTES SecurityAttributes; DWORD ThreadId; HANDLE HandleArray[3]; int i;
SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL SecurityAttributes.bInheritHandle = FALSE; // No inheritance // // Store the client socket handle in the session structure so the thread // can get at it. This also signals that the session is connected. // Session->ClientSocket = ClientSocket; // // Create the session threads // Session->ReadShellThreadHandle = CreateThread(&SecurityAttributes, 0, (LPTHREAD_START_ROUTINE) SessionReadShellThreadFn, (LPVOID) Session, 0, &ThreadId); if (Session->ReadShellThreadHandle == NULL) { holler("Failed to create ReadShell session thread, error = %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
// // Reset the client pipe handle to indicate this session is disconnected // Session->ClientSocket = INVALID_SOCKET; return(FALSE); } Session->WriteShellThreadHandle = CreateThread(&SecurityAttributes, 0, (LPTHREAD_START_ROUTINE) SessionWriteShellThreadFn, (LPVOID) Session, 0, &ThreadId); if (Session->WriteShellThreadHandle == NULL) { holler("Failed to create ReadShell session thread, error = %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
// // Reset the client pipe handle to indicate this session is disconnected // Session->ClientSocket = INVALID_SOCKET; TerminateThread(Session->WriteShellThreadHandle, 0); return(FALSE); } // // Wait for either thread or the shell process to finish // HandleArray[0] = Session->ReadShellThreadHandle; HandleArray[1] = Session->WriteShellThreadHandle; HandleArray[2] = Session->ProcessHandle;
i = WaitForMultipleObjects(3, HandleArray, FALSE, 0xffffffff);
switch (i) { case WAIT_OBJECT_0 + 0: TerminateThread(Session->WriteShellThreadHandle, 0); TerminateProcess(Session->ProcessHandle, 1); break; case WAIT_OBJECT_0 + 1: TerminateThread(Session->ReadShellThreadHandle, 0); TerminateProcess(Session->ProcessHandle, 1); break; case WAIT_OBJECT_0 + 2: TerminateThread(Session->WriteShellThreadHandle, 0); TerminateThread(Session->ReadShellThreadHandle, 0); break;
default: holler("WaitForMultipleObjects error: %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
break; }
// Close my handles to the threads, the shell process, and the shell pipes
closesocket(Session->ClientSocket);
DisconnectNamedPipe(Session->ReadPipeHandle);
CloseHandle(Session->ReadPipeHandle);
DisconnectNamedPipe(Session->WritePipeHandle);
CloseHandle(Session->WritePipeHandle);
CloseHandle(Session->ReadShellThreadHandle);
CloseHandle(Session->WriteShellThreadHandle);
CloseHandle(Session->ProcessHandle);
free(Session); return(TRUE);}// **********************************************************************//// StartShell//// Execs the shell with the specified handle as stdin, stdout/err//// Returns process handle or NULL on failure//static HANDLEStartShell( HANDLE ShellStdinPipeHandle, HANDLE ShellStdoutPipeHandle ){ PROCESS_INFORMATION ProcessInformation; STARTUPINFO si; HANDLE ProcessHandle = NULL; // // Initialize process startup info // si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpTitle = NULL; si.lpDesktop = NULL; si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L; si.wShowWindow = SW_HIDE; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdInput = ShellStdinPipeHandle; si.hStdOutput = ShellStdoutPipeHandle; DuplicateHandle(GetCurrentProcess(), ShellStdoutPipeHandle, GetCurrentProcess(), &si.hStdError, DUPLICATE_SAME_ACCESS, TRUE, 0); if (CreateProcess(NULL, pr00gie, NULL, NULL, TRUE, 0, NULL, NULL, &si, &ProcessInformation)) { ProcessHandle = ProcessInformation.hProcess; CloseHandle(ProcessInformation.hThread); } else holler("Failed to execute shell, error = %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
return(ProcessHandle);}// **********************************************************************// SessionReadShellThreadFn//// The read thread procedure. Reads from the pipe connected to the shell// process, writes to the socket.//static VOIDSessionReadShellThreadFn( LPVOID Parameter ){ PSESSION_DATA Session = Parameter; BYTE Buffer[BUFFER_SIZE]; BYTE Buffer2[BUFFER_SIZE+30]; DWORD BytesRead;
// this bogus peek is here because win32 won't let me close the pipe if it is
// in waiting for input on a read. while (PeekNamedPipe(Session->ReadPipeHandle, Buffer, sizeof(Buffer),
&BytesRead, NULL, NULL))
{
DWORD BufferCnt, BytesToWrite;
BYTE PrevChar = 0;
if (BytesRead > 0)
{
ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer),
&BytesRead, NULL);
}
else
{
Sleep(50);
continue;
}
// // Process the data we got from the shell: replace any naked LF's // with CR-LF pairs. // for (BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++) { if (Buffer[BufferCnt] == '\n' && PrevChar != '\r') Buffer2[BytesToWrite++] = '\r'; PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt]; } if (send(Session->ClientSocket, Buffer2, BytesToWrite, 0) <= 0) break; } if (GetLastError() != ERROR_BROKEN_PIPE) holler("SessionReadShellThreadFn exitted, error = %s",
itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL);
ExitThread(0);
}// **********************************************************************// SessionWriteShellThreadFn//// The write thread procedure. Reads from socket, writes to pipe connected// to shell process. static VOIDSessionWriteShellThreadFn( LPVOID Parameter ){ PSESSION_DATA Session = Parameter; BYTE RecvBuffer[1]; BYTE Buffer[BUFFER_SIZE]; BYTE EchoBuffer[5]; DWORD BytesWritten; DWORD BufferCnt, EchoCnt; DWORD TossCnt = 0; BOOL PrevWasFF = FALSE; BufferCnt = 0; // // Loop, reading one byte at a time from the socket. // while (recv(Session->ClientSocket, RecvBuffer, sizeof(RecvBuffer), 0) != 0) {
EchoCnt = 0;
Buffer[BufferCnt++] = EchoBuffer[EchoCnt++] = RecvBuffer[0];
if (RecvBuffer[0] == '\r')
Buffer[BufferCnt++] = EchoBuffer[EchoCnt++] = '\n';
// Trap exit as it causes problems
if (strnicmp(Buffer, "exit\r\n", 6) == 0)
ExitThread(0);
// // If we got a CR, it's time to send what we've buffered up down to the // shell process. // if (RecvBuffer[0] == '\n' || RecvBuffer[0] == '\r') { if (! WriteFile(Session->WritePipeHandle, Buffer, BufferCnt, &BytesWritten, NULL)) { break; } BufferCnt = 0; } }
ExitThread(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -