aboutsummaryrefslogtreecommitdiffstats
path: root/viensamoi/listen_target.py
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-03-25 18:55:15 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2013-03-25 18:55:15 +0100
commitfe2921d137ce66eb1176c8fb0cdf692d697bda9b (patch)
tree01ff431d0dcd02a4b1038fdc4ad2cc8fd1262196 /viensamoi/listen_target.py
parentpropagate: change default "netcat" command to "nc" (diff)
downloadlaurent-tools-fe2921d137ce66eb1176c8fb0cdf692d697bda9b.tar.xz
laurent-tools-fe2921d137ce66eb1176c8fb0cdf692d697bda9b.zip
add viensamoi - WIFI tools targeting clients
Diffstat (limited to 'viensamoi/listen_target.py')
-rwxr-xr-xviensamoi/listen_target.py225
1 files changed, 225 insertions, 0 deletions
diff --git a/viensamoi/listen_target.py b/viensamoi/listen_target.py
new file mode 100755
index 0000000..38920d8
--- /dev/null
+++ b/viensamoi/listen_target.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+
+# 2012 Laurent Ghigonis <laurent@p1sec.com>
+# 2012 Pierre-Olivier Vauboin <po@p1sec.com>
+
+# TODO
+# * [TOTEST] detect AP only if they send more bea than other
+# * display UTF* or other charset bssid
+# * display hex value when bssid is non-printable
+# * Network View (who is conn, has ap ...)
+# * store in redis Nodes and Networks
+# * read pcap file
+# * better UI
+# * implement a time to forget about nodes
+# * forget nodes on demand
+
+import sys
+import datetime
+import getopt
+import pdb #pdb.set_trace()
+import pprint
+import netaddr
+from scapy.all import *
+
+node_list = {}
+# Dot11 Type and Subtype put to hex and concatenated
+dot11_types = {
+ "00": ["arq", "Association request"],
+ "01": ["ars", "Association response"],
+ "04": ["prq", "Probe request"],
+ "05": ["prs", "Probe response"],
+ "08": ["bea", "Beacon frame"],
+ "0b": ["aut", "Authentication"],
+ "0c": ["dea", "Deauthentication"],
+ "0d": ["act", "Action"],
+ "19": ["bac", "Block Ack"],
+ "1b": ["cts", "Clear to Send"],
+ "1d": ["ack", "Acknowledgement"],
+ "20": ["dat", "Data"],
+ "24": ["nul", "Null function"],
+ "28": ["qda", "QoS Data"],
+}
+packet_counter=0
+start_time = datetime.datetime.now()
+last_time = 0
+option_ap = False
+option_debug = False
+option_iface = "wlan0"
+option_update_time = 3
+option_mac_target = ""
+
+def usage():
+ print "usage: %s [-ad] [-m mac_target] iface" % sys.argv[0]
+
+def dot11_type_name(num):
+ if num in dot11_types:
+ return dot11_types[num][0]
+ else:
+ return "%s " % num
+
+def dump_(obj, classkey=None):
+ if isinstance(obj, dict):
+ for k in obj.keys():
+ obj[k] = dump_(obj[k], classkey)
+ return obj
+ elif hasattr(obj, "__iter__"):
+ return [dump_(v, classkey) for v in obj]
+ elif hasattr(obj, "__dict__"):
+ data = dict([(key, dump_(value, classkey))
+ for key, value in obj.__dict__.iteritems()
+ if not callable(value) and not key.startswith('_')])
+ if classkey is not None and hasattr(obj, "__class__"):
+ data[classkey] = obj.__class__.__name__
+ return data
+ else:
+ return obj
+def dump(obj, classkey=None):
+ pprint.pprint(dump_(obj, classkey))
+
+def mac_lookup(mac):
+ mac_prefix = '-'.join(mac.replace(':', '-').split('-')[0:3])
+ try:
+ oui = netaddr.OUI(mac_prefix)
+ if oui.records:
+ vendor = oui.records[0]['org']
+ else:
+ vendor = 'Unknown'
+ except netaddr.NotRegisteredError:
+ vendor = 'Unknown'
+ return vendor
+
+class Node:
+ def __init__(self, mac):
+ self.mac = mac
+ self.types = {}
+ self.pkt_recv_count = 0
+ def addpkt(self, pkt):
+ self.pkt_recv_count += 1
+ type1 = pkt[Dot11].type
+ type2 = pkt[Dot11].subtype
+ ftype = "%x%x" % (type1, type2)
+ if ftype not in self.types:
+ self.types[ftype] = {"count": 0}
+ self.types[ftype]["count"] += 1
+ if ftype in ["00", "04", "05", "08"]:
+ if "ssid" not in self.types[ftype]:
+ self.types[ftype]["ssid"] = set()
+ ssid = pkt[Dot11Elt].info if Dot11Elt in pkt else "#unknown"
+ if (pkt.addr2):
+ if (pkt.addr3):
+ Network.update(ssid, pkt.addr3)
+ else:
+ Network.update(ssid, pkt.addr2)
+ self.types[ftype]["ssid"].add(ssid)
+ else:
+ bssid = pkt[Dot11].addr3
+ if bssid:
+ if "bssid" not in self.types[ftype]:
+ self.types[ftype]["bssid"] = set()
+ self.types[ftype]["bssid"].add(bssid)
+ def is_ap(self):
+ if '08' in self.types.keys():
+ na = len(self.types['08'])
+ for t in self.types.keys():
+ if len(self.types[t]) > na:
+ return False
+ return True
+ return False
+ def __str__(self):
+ s = ""
+ s += self.mac + " %s (%s)" % (mac_lookup(self.mac), self.pkt_recv_count)
+ l = sorted(self.types.keys(), key=lambda x: self.types[x]["count"], reverse=True)
+ for t in l:
+ s += "\n"
+ s += " " + str(self.types[t]["count"]) + "\t" + dot11_type_name(t) + " "
+ for i in self.types[t]:
+ if i == "count": continue
+ if i == "bssid":
+ s += ','.join(map(Network.resolv, self.types[t][i]))
+ else:
+ s += ','.join(self.types[t][i])
+ return s
+
+class Network:
+ _nets = {}
+ @classmethod
+ def resolv(cls, bssid):
+ for n in cls._nets.values():
+ if bssid in n.bssid:
+ return n.name
+ return bssid
+ @classmethod
+ def update(cls, name, bssid):
+ if name in cls._nets.keys():
+ cls._nets[name].bssid.add(bssid)
+ else:
+ n = Network(name)
+ n.addbssid(bssid)
+ cls._nets[name] = n
+ def __init__(self, name):
+ self.name = name
+ self.bssid = set()
+ Network._nets[name] = self
+ def addbssid(self, bssid):
+ self.bssid.add(bssid)
+
+def analyse_packet(pkt):
+ # pkt.addr1 : bssid
+ # pkt.addr2 : station
+ # pkt.addr3 :
+ global packet_counter
+ global start_time, last_time
+ packet_counter+=1
+ try:
+ if pkt.addr2 is None:
+ if option_debug:
+ print "source None !!!"
+ return
+ except:
+ if option_debug:
+ print "no addr2 !!!"
+ return
+ if option_mac_target == "" or option_mac_target == pkt.addr2:
+ if pkt.addr2 not in node_list:
+ n = Node(pkt.addr2)
+ node_list[pkt.addr2] = n
+ node_list[pkt.addr2].addpkt(pkt)
+ #pdb.set_trace()
+ if packet_counter % 20 == 0:
+ time = datetime.datetime.now()
+ if time.second != last_time:
+ delta = time - start_time
+ if delta.seconds % option_update_time == 0:
+ last_time = time.second
+ print_stats()
+
+def print_stats():
+ print "==================================== %d pkts, %d nodes" % (packet_counter, len(node_list))
+ l = sorted(node_list.keys(), key=lambda x: node_list[x].pkt_recv_count, reverse=True)
+ for cli in l:
+ if not option_ap and node_list[cli].is_ap():
+ continue
+ print node_list[cli]
+
+if __name__ == '__main__':
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "adm:")
+ except getopt.GetoptError, err:
+ usage()
+ sys.exit(1)
+ for o, a in opts:
+ if o == "-a": option_ap=True
+ elif o == "-d": option_debug=True
+ elif o == "-m": option_mac_target=a
+ else:
+ print "unknown option %s" % o
+ sys.exit(1)
+ if len(args) < 1:
+ usage()
+ sys.exit(1)
+
+ option_iface = args[0]
+ print "Be sure that %s is in monitor mode." % option_iface
+ print "Use airodump at the same time if you want channel hopping. hop hop !"
+ sniff(iface=option_iface, prn=analyse_packet, store=0)