From: Tobias Mueller Date: Mon, 20 Dec 2010 00:22:42 +0000 (+0530) Subject: Removed the homebrewn select() and put the fd of the pcap in the mainloop X-Git-Url: http://vcs.maemo.org/git/?a=commitdiff_plain;h=f5a75bbd69465ef407e93fed8968f35b389baa68;hp=215e243da4fe86c07855828b10f83a5d32fc8038;p=pwnitter Removed the homebrewn select() and put the fd of the pcap in the mainloop --- diff --git a/pwnitter.py b/pwnitter.py index 61c98e4..5d84701 100755 --- a/pwnitter.py +++ b/pwnitter.py @@ -33,6 +33,7 @@ class Pwnitter(dbus.service.Object): in_signature='', out_signature='') def Start(self, device='mon0'): # FIXME: Prevent double Start() + # FIXME: Replace hardcoded interface cmd = '/usr/sbin/iw wlan0 interface add mon0 type monitor'.split() subprocess.call(cmd) cmd = '/sbin/ifconfig mon0 up'.split() @@ -44,8 +45,12 @@ 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) + 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" @@ -68,6 +73,7 @@ class Pwnitter(dbus.service.Object): def Stop(self): self.is_running = False print "Receive Stop" + gobject.source_remove(self.source_id) cmd = '/sbin/ifconfig mon0 down'.split() subprocess.call(cmd) cmd = '/usr/sbin/iw dev mon0 del'.split() @@ -78,120 +84,114 @@ class Pwnitter(dbus.service.Object): def pwn(self, device, tweeted_callback=None): 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 - 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) - - - # 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): - headers = { - "User-Agent": "Mozilla/5.0", - "Accept": "application/json, text/javascript, */*", - "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - "X-Requested-With": "XMLHttpRequest", - "X-PHX": "true", - "Referer": "http://api.twitter.com/p_receiver.html", - "Cookie": cookie - } - - - print 'Issueing connection' - if host == 'mobile.twitter.com': + 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 + 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) + + + # 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): + headers = { + "User-Agent": "Mozilla/5.0", + "Accept": "application/json, text/javascript, */*", + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + "X-Requested-With": "XMLHttpRequest", + "X-PHX": "true", + "Referer": "http://api.twitter.com/p_receiver.html", + "Cookie": cookie + } + + + print 'Issueing connection' + if host == 'mobile.twitter.com': + + params = urllib.urlencode({ + 'tweet[text]': self.status, + 'authenticity_token': authToken + }) + + conn = httplib.HTTPConnection("mobile.twitter.com") + conn.request("POST", "/", params, headers) + + else: + + params = urllib.urlencode({ + 'status': self.status, + 'post_authenticity_token': authToken + }) + + conn = httplib.HTTPConnection("api.twitter.com") + conn.request("POST", "/1/statuses/update.json", params, headers) - params = urllib.urlencode({ - 'tweet[text]': self.status, - 'authenticity_token': authToken - }) - - conn = httplib.HTTPConnection("mobile.twitter.com") - conn.request("POST", "/", params, headers) + response = conn.getresponse() + print 'Got response: %s' % response.status + if response.status == 200 or response.status == 302 or response.status == 403: + + if name: + processed[name] = 1 + + # 403 is a dupe tweet + if response.status != 403: + print "Successfully tweeted as %s" % name + print 'calling %s' % tweeted_callback + if tweeted_callback: + tweeted_callback(name) else: + print 'Already tweeted as %s' % name - params = urllib.urlencode({ - 'status': self.status, - 'post_authenticity_token': authToken - }) - - conn = httplib.HTTPConnection("api.twitter.com") - conn.request("POST", "/1/statuses/update.json", params, headers) - - - response = conn.getresponse() - print 'Got response: %s' % response.status - if response.status == 200 or response.status == 302 or response.status == 403: - - if name: - processed[name] = 1 - - # 403 is a dupe tweet - if response.status != 403: - print "Successfully tweeted as %s" % name - print 'calling %s' % tweeted_callback - if tweeted_callback: - tweeted_callback(name) - else: - print 'Already tweeted as %s' % name - - else: + else: - print "FAILED to tweet as %s, debug follows:" % name - print response.status, response.reason - print response.read() + "\n" - #break # Break after one read packet + 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 # FIXME: Ideally, check whether Pcap has got data for us