Advertisement
Guest User

sidlog.py

a guest
Jun 20th, 2014
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.68 KB | None | 0 0
  1. #!/usr/bin/python
  2. # sidlog.py
  3. ### CONFIGURATIONS
  4. _REFRESH_RATE = 1 # The seconds between displayer updates
  5. FOREVER = 1000000 # This is the setting for how long forever is considered
  6.  
  7. ### HINTS
  8. #This program contains tags for bug-tracking, information, and development.
  9. #
  10. #If you know Python, and are up to the task, here is what you need to know.
  11. #
  12. #Read the code to get a feel for the style and method. Edit and incrementally
  13. #make changes ensuring functionality. Here are some tags to guide your journey.
  14. #
  15. #TODO: Denotes areas where further functions should be added.
  16. #BUG: Denotes an area where something is working, but not 100%
  17. #INFO: Denotes a tag that gives hints to the methodology of the snippet of code
  18. #
  19. #If you edit, please comment and follow the tagging standard!
  20. #
  21. # ~blerbl
  22. ###
  23.  
  24. ####################################################
  25. ### BELOW IS THE PROGRAM, EDIT AT YOUR OWN PERIL ###
  26. ####################################################
  27.  
  28. ### About this program ###
  29. _name = "sidlog"
  30. _version = 0.4
  31. _date = "22 Jan 2013"
  32. _authors = "blerbl"
  33. _about = """
  34. This tool listens for 802.11 probe requests.  It then logs the SSIDs in a database.
  35. It will keep track of the associated client SSIDs, the date last seen, and
  36. other information about the data collected.
  37. """
  38.  
  39. ### Platforming ###
  40. import sys
  41. _supported = ['linux2',]
  42. _LINUX = 'linux2'
  43. _ENV = sys.platform
  44. if not _ENV in _supported: raw_input('[#]' + _ENV + " not supported");exit(0)
  45. if sys.version_info[0] != 2 or sys.version_info[1] <= 6:
  46.     raw_input("[#]Must be run with Python 2.x minor version >= .6\n  You are running" + sys.version); exit(1)
  47.  
  48. ### Imports ###
  49. import os, logging, socket, time, sqlite3, threading, argparse, re
  50. from urllib import urlretrieve as pyget
  51. from zipfile import ZipFile as pyzip
  52. from Tkinter import *
  53.  
  54. # SCAPY!!! The embedded installer is a little buggy
  55. logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
  56. try:
  57.     from scapy.all import *
  58. except ImportError:
  59.     #TODO This assumes that the ImportError is because scapy isnt installed
  60.     # this may not be true. Further checking is needed
  61.     print( "[!] Scapy is required to run " + _name)
  62.     ans = raw_input( "Would you like to install Scapy at this time[Y|n]")
  63.     if not 'n' in ans.lower():
  64.         print "[+]Installing scapy..."
  65.         print "[++]Getting File"
  66.         try:
  67.             t_a,t_b = pyget('http://scapy.net','scapy.zip')
  68.             temp = pyzip(t_a)
  69.             print "[++]Extracting..."
  70.             temp.extractall("scapyout")
  71.             temp.close()
  72.             print "[++]Running setup"
  73.             os.chdir("scapyout")
  74.             os.chdir(os.listdir('.')[0])
  75.             cmd = "setup.py install"
  76.             if _ENV==_LINUX: cmd = './' + cmd
  77.             errno = os.system(cmd)
  78.             if errno :
  79.                 print "[#]There was an error installing scapy"
  80.                 exit(1)
  81.             print "[++]Cleaning up"
  82.             os.chdir("..")
  83.             os.chdir("..")
  84.             cmd = "rm -rf scapyout" #BUG needs os agnostic command
  85.             os.system(cmd)
  86.             os.remove("scapy.zip")
  87.             try:
  88.                 print "[++]Scapy Installed!"
  89.                 from scapy.all import *
  90.             except Exception as e:
  91.                 print "[#]Problem still not resolved. Check other dependencies"
  92.                 exit(1)
  93.         except Exception as e:
  94.             print "[#]Could not complete scapy install"
  95.             exit(1)
  96.     else:
  97.         print("[#]Scapy requires for operation of " + _name + " v" + str(_version))
  98.         print("[-]Exiting...")
  99.         exit(0)
  100.  
  101. ### Globals ###
  102. re_essid = re.compile("\A[0-9A-z_.'\" \-&]+\Z")
  103. #re_essid = re.compile("\A[ -z]+\Z")
  104. sys.running = False
  105. sys.verbose = 0
  106.  
  107. def Error(message, level=1):
  108.     """ Use this method to throw fatal errors"""
  109.     print("[!]"+message)
  110.     exit(level)
  111.  
  112. def validessid(name):
  113.     """ Determine if the tuple 'tup' meets the current filter criteria
  114.        @returns
  115.        True - If the tuple satisfies the current displayer filter states
  116.        False - If the tuple does not satisfy the current displayer filter state"""
  117.     if name is None:
  118.         return False
  119.     elif re_essid.match(name):
  120.         return True
  121.     return False
  122.        
  123. class SidlogGUI(Frame):
  124.     """ This is the GUI object for sidlog.  It is dependent on the listener object.
  125.            Create this object like any other Tkinter object."""
  126.  
  127.     def __init__(self, master=None):
  128.         Frame.__init__(self, master)
  129.         self.listener = Listener()
  130.         #TODO Organize this file and make the different components easy to identify
  131.         self.armed = False
  132.         self.pairs = []
  133.         #TODO Add a self.presentation to hold the things being displayed.
  134.         #   This will separate reponsibility from the self.pairs which will
  135.         #   then take on the role of just storing all information and be liked to
  136.         #   the listener.  It may not even need the pairs directive but this may take
  137.         #   reference load off the listener.
  138.         self.pack(expand=1, fill=BOTH)
  139.         #INFO The menus, like all the other components in the GUI, are grouped in the program like they
  140.         #   are spacially.
  141.         menu_main = Menu(self)
  142.         menu_file = Menu(menu_main, tearoff=0)
  143.         #TODO Refresh available interfaces.  Use in conjuction with the self.entry_iface todos
  144.         #menu_file.add_command(label="Refresh Ifaces", command=self.query_available_ifaces)
  145.         #self.add_separator()
  146.         menu_file.add_command(label=" Exit ", command=self.quit2)
  147.         menu_main.add_cascade(label="Options", menu=menu_file)
  148.        
  149.         menu_sort = Menu(menu_main, tearoff=0)
  150.         menu_sort.add_command(label="Order by Client",command=lambda: self.displayer_order_column(0))
  151.         menu_sort.add_command(label="Order by ESSID", command=lambda: self.displayer_order_column(1))
  152.         #TODO This is for grouping with self.presentation. When ready uncomment
  153.         #menu_sort.add_separator()
  154.         #menu_sort.add_command(label="Group by Client", command=self.displayer_group_client)
  155.         #menu_sort.add_command(label="Group by ESSID", command=self.displayer_group_essid)
  156.         #menu_sort.add_command(label="No Grouping", command=self.displayer_group_none)
  157.         menu_main.add_cascade(label="View", menu=menu_sort)
  158.        
  159.         menu_act = Menu(menu_main, tearoff=0)
  160.         menu_act.add_command(label="Monitor Mode",command=self.set_mon)
  161.         menu_act.add_command(label="Managed Mode",command=self.unset_mon)
  162.         menu_main.add_cascade(label="Action", menu=menu_act)
  163.        
  164.         root.configure(menu=menu_main)
  165.        
  166.         self.createWidgets()
  167.         self.listener.statout = self.var_stat #very important, binds the status area
  168.  
  169.         threading.Thread(None,self.displayer,'diplayer').start()
  170.        
  171.         self.stat("Welcome")    
  172.        
  173.     def createWidgets(self):
  174.         """ Create the different widgets that are members of the main display"""
  175.         #INFO the naming standard is 'self.<part>_<name>'
  176.  
  177.         #Frames        #INFO This is to create the underlying grid
  178.         self.frame_control = Frame(self)
  179.         self.frame_control.pack(side=LEFT,fill=Y)
  180.  
  181.         self.frame_view = Frame(self, height=300)
  182.         self.frame_view.pack(side=RIGHT, fill=BOTH, expand=1)
  183.  
  184.        
  185.         #The viewing frame components
  186.         scrollbary = Scrollbar(self.frame_view)
  187.         scrollbarx = Scrollbar(self.frame_view,orient=HORIZONTAL)
  188.         scrollbary.pack(side=RIGHT, fill=Y)
  189.         scrollbarx.pack(side=BOTTOM, fill=X)
  190.         self.disp_results = Listbox(self.frame_view, xscrollcommand=scrollbarx.set, yscrollcommand=scrollbary.set, height=17, width=30)
  191.         self.disp_results.config(font = ("Courier",10))
  192.         self.disp_results.pack(side=LEFT, fill=BOTH,expand=1)
  193.         scrollbary.config(command=self.disp_results.yview)
  194.         scrollbarx.config(command=self.disp_results.xview)
  195.         #TODO add a search bar to filter results
  196.         #TODO separate the listviews into two. Use the displayer and self.presentation to keep inline
  197.         #   and to group. e.g.
  198.         #   | 00:11:22:33:44:55 | airweb, TehTubez, Monkeycheesepants
  199.         #   OR
  200.         #   | PANERA            | 00:11:22:33:44:55, 55:44:33:22:11:00
  201.         #
  202.         #   Perhaps use the StrVars and calculate every time, only updateing on difs
  203.         #   Or use list, identifying new items base on them not being in self.pairs
  204.         #   then checking if and where they deserve to be in the displayer based on the
  205.         #   state of displayer (self.displayer_state_<> objects)
  206.        
  207.         #The control frame components
  208.         self.lable_iface = Label(self.frame_control)
  209.         self.lable_iface["text"] = "Interface"
  210.         self.lable_iface.pack(side=TOP)
  211.  
  212.         #TODO this should be a dropdown of available interfaces. Updated by a refresh interfaces action
  213.         #   in Options
  214.         self.entry_iface = Entry(self.frame_control)
  215.         self.entry_iface.insert(0,"wlan0")
  216.         self.entry_iface.pack(side=TOP)
  217.        
  218.         self.lable_dbase = Label(self.frame_control)
  219.         self.lable_dbase["text"] = "Database"
  220.         self.lable_dbase.pack(side=TOP)
  221.        
  222.         self.entry_dbase = Entry(self.frame_control)
  223.         self.entry_dbase.insert(0,"sidlog.db")
  224.         self.entry_dbase.pack(side=TOP)
  225.  
  226.         self.var_stat = StringVar(self, "","status")
  227.         self.disp_stat = Listbox(self.frame_control, listvariable=self.var_stat, font=("Courier",8))
  228.         dispx = Scrollbar(self.disp_stat,orient=HORIZONTAL)
  229.         dispx.pack(side=BOTTOM, fill=X)
  230.         self.disp_stat.config(xscrollcommand=dispx.set)
  231.         self.disp_stat.pack(fill=BOTH, expand=1)
  232.         dispx.config(command=self.disp_stat.xview)
  233.         self.disp_stat.state=DISABLED
  234.  
  235.         self.btn_load = Button(self.frame_control)
  236.         self.btn_load["text"] = "Load Config"
  237.         self.btn_load['command'] = self.loadconf
  238.         self.btn_load.pack(side=LEFT,fill=X)
  239.  
  240.         self.btn_toggle = Button(self.frame_control)
  241.         self.btn_toggle["text"] = "Start"
  242.         self.btn_toggle["command"] = self.toggle
  243.         self.btn_toggle["state"]=DISABLED
  244.         self.btn_toggle.pack(side=LEFT,fill=X)
  245.  
  246.     def quit2(self):
  247.         """ Ensures that the things that need shutdown get shutdown
  248.            before their master quits"""
  249.         #INFO If you have a thread with a loop or something of the sorts
  250.         #   be sure to terminate it here
  251.         self.running=False
  252.         self.listener.stop()
  253.         self.quit()
  254.  
  255.     def set_mon(self):
  256.         """ Puts the interface in the entry into monitor mode"""
  257.         if not self.listener.state == Listener.STOPPED:
  258.             self.stat("Stop listener first",1)
  259.             return 1
  260.         iface = self.entry_iface.get()
  261.         t_s = socket.socket()
  262.         try:
  263.             t_s.setsockopt(socket.SOL_SOCKET, 25, iface)
  264.             cmds = ["ifconfig " + iface + " down","iwconfig " + iface + " mode monitor","ifconfig " + iface + " up"]
  265.             try:
  266.                 for cmd in cmds:
  267.                     os.system(cmd)
  268.                 self.stat("<" + iface + "> Monitoring")
  269.             except:
  270.                 self.stat("<" + iface + "> Mon failed",1)
  271.  
  272.         except:
  273.             self.stat("<" +iface + "> not a valid",1)
  274.             t_gtg = False
  275.         finally:
  276.             del t_s
  277.            
  278.     def unset_mon(self):
  279.         """ Puts interface in the entry into manage mode"""
  280.         if not self.listener.state == Listener.STOPPED:
  281.             self.stat("Stop listener first",1)
  282.             return 1
  283.         iface = self.entry_iface.get()
  284.         t_s = socket.socket()
  285.         try:
  286.             t_s.setsockopt(socket.SOL_SOCKET, 25, iface)        
  287.             cmds = ["ifconfig " + iface + " down","iwconfig " + iface + " mode managed","ifconfig " + iface + " up"]
  288.             try:
  289.                 for cmd in cmds:
  290.                     os.system(cmd)
  291.                 self.stat("<" + iface + "> Managed")
  292.             except:
  293.                 self.stat("<" + iface + "> mon failed",1)
  294.         except:
  295.             self.stat("<" +iface + "> not a valid",1)
  296.             t_gtg = False
  297.         finally:
  298.             del t_s
  299.        
  300.                
  301.     def loadconf(self):
  302.         """ Loads the interface, makes sure it is good, loads the database,
  303.            makes sure it is good. Enables and disables fields and buttons."""
  304.  
  305.         if self.armed:
  306.             self.armed = False
  307.             self.btn_toggle['state']=DISABLED
  308.             self.btn_load['text']="Load Config"
  309.             self.entry_iface['state']=NORMAL
  310.             self.entry_dbase['state']=NORMAL
  311.             self.stat("Unlocked")
  312.             return
  313.        
  314.         t_gtg = True
  315.         iface = self.entry_iface.get()
  316.         dbase = self.entry_dbase.get()
  317.         t_s = socket.socket()
  318.         try:
  319.             t_s.setsockopt(socket.SOL_SOCKET, 25, iface)
  320.         except:
  321.             self.stat("<" +iface + "> not a valid",1)
  322.             t_gtg = False
  323.         finally:
  324.             del t_s
  325.  
  326.         self.listener.iface = iface
  327.         #check database
  328.         try:
  329.             self.listener.set_db(dbase)
  330.             self.pairs = []
  331.         except Exception as e:
  332.             self.stat("Bad DB: " + dbase,1)
  333.             t_gtg = False
  334.         if t_gtg:
  335.             self.armed = True
  336.             self.btn_toggle['state']=NORMAL
  337.             self.btn_load['text']="    Unlock    "
  338.             self.entry_iface['state']=DISABLED
  339.             self.entry_dbase['state']=DISABLED
  340.             self.stat("Configured")
  341.         self.displayer_needrefresh = True
  342.    
  343.     def toggle(self):
  344.         if self.listener.state == Listener.RUNNING:
  345.             self.btn_toggle["text"] = "Start"
  346.             self.btn_load["state"]=NORMAL
  347.             self.listener.stop()
  348.         elif self.listener.state == Listener.STOPPED:
  349.             self.btn_toggle["text"] = "Stop"
  350.             self.btn_load["state"]=DISABLED
  351.             self.listener.start()
  352.  
  353.     def stat(self, message, value=0):
  354.         values = ["[+]","[-]"]
  355.         ct = time.strftime("%H:%M")
  356.         message = ct + values[value] + message
  357.         cur = self.var_stat.get() or "()"
  358.         cur = eval(cur)
  359.         self.var_stat.set((message,) + cur)
  360.        
  361.     #################################INFO##################################
  362.     ### Displayer family of commands and states. Keep most of them here ###
  363.  
  364.     #TODO Determine which way is better, go with it, and annotate why (Currently using 1)
  365.         #1) The listener stores to the database AND exports to the GUI e.g.: DB <-> Listener <-> GUI
  366.         #2) The listener stores to the database and the GUI querys it. e.g.: Listener <-> DB <-> GUI
  367.     #TODO?1 add commands to query the listener
  368.     #TODO?2 add commands to query the database
  369.        
  370.     def displayer_order_column(self,by=0,descend = True):
  371.         """ sort the display by the column indicated in "by" then and
  372.            inverte is based on the boolean descend"""
  373.         try:
  374.             tsave = self.pairs
  375.             if by ==0:
  376.                 self.pairs = sorted(self.pairs, key=lambda x: int(x[0].replace(':',''),16),reverse=descend)
  377.             elif by == 1:
  378.                 self.pairs = sorted(self.pairs, key=lambda x: (x[by]or"").lower(),reverse=descend)
  379.             else:
  380.                 self.pairs = sorted(self.pairs, key=lambda x: x[by],reverse=descend)
  381.             self.displayer_needrefresh = True
  382.         except Exception as e:
  383.             self.stat("Sort by "+str(by)+" failed: "+str(e),1)
  384.             self.pairs = tsave #make the sort atomic
  385.  
  386.  
  387.     def displayer_initStates(self):
  388.         """ initialize all the result displayer's constants """
  389.         self.displayer_needrefresh = True
  390.  
  391.     def displayer(self):
  392.         """ Updates the displayed results and applies necessary filtering.
  393.            This is a working method meant to be launched in a thread."""
  394.        
  395.  
  396.         #INFO Notice how a single call initialized the states for the displayer.
  397.         self.displayer_initStates()
  398.        
  399.         displayed = [] #this may become self.presentation depending on how the GUI gets its info
  400.         while sys.running:
  401.             time.sleep(_REFRESH_RATE)
  402.  
  403.             #INFO by filtering newpairs, it saves us time one the displayer when display filters
  404.             #   and insertions become intensive
  405.             new_pairs = filter( lambda x: not x in self.pairs, self.listener.pairs)
  406.             self.pairs.extend(new_pairs)
  407.            
  408.             if self.displayer_needrefresh:
  409.                 self.disp_results.delete(0,END)
  410.                 displayed = []
  411.                 self.displayer_needrefresh = False
  412.                 new_pairs = self.pairs #all pairs are new when refreshing
  413.            
  414.             for newpair in new_pairs:
  415.                 if (not newpair in displayed) and (not newpair is None) and validessid(newpair[1]):
  416.                     displayed.append(newpair)
  417.                     self.disp_results.insert(0,newpair[0] + " | " + newpair[1] )
  418.                 #BUG there is a bug that lets weird SSIDS display still
  419.                        
  420.     ################# END DISPLAYER SECTION #################
  421.     #########################################################
  422.    
  423. ### END OF SidlogGUI    
  424. ####################################################################################
  425.  
  426.  
  427.  
  428. class Listener:
  429.     """ Listener object, used to capture packets and log them to a sqlite3 database"""
  430.     STOPPED = 0
  431.     STARTING = 1
  432.     RUNNING = 2
  433.     STOPPING = 3
  434.  
  435.     CLIENT_TABLE_TEST="INSERT INTO clients (mac,time) values ('00:00:00:00:00:00',0)"
  436.     ESSIDS_TABLE_TEST="INSERT INTO essids (mac,name) values ('00:00:00:00:00:00','test')"
  437.     CLIENT_TABLE_CREATE="CREATE TABLE clients (mac,time INTEGER)"
  438.     ESSIDS_TABLE_CREATE="CREATE TABLE essids (sid INTEGER PRIMARY KEY AUTOINCREMENT,mac,name)"
  439.  
  440.  
  441.     #TODO Export the Database definitions so that other objects can use them
  442.  
  443.     def __init__(self,db=None):
  444.         self.state = Listener.STOPPED
  445.         self.statout = sys.stdout
  446.         self.t = None
  447.         self.iface = ''
  448.         self.pairs = []
  449.         self.clients = []
  450.         self.running = False
  451.         if db:
  452.             self.set_db(db)
  453.            
  454.     #use stat to update the current status output method as determined by self.statout.
  455.     #this device is usually stdout for console and the disp_stat for the GUI
  456.     def stat(self, message, level=0):
  457.         levels = ["[+]","[-]"]
  458.         if level <len(levels):
  459.             ct = time.strftime("%H:%M")
  460.             message = ct + levels[level] + str(message)
  461.         if not self.statout:
  462.             Error("Status output not defined!")
  463.         elif self.statout == sys.stdout:
  464.             self.statout.write(message.strip().strip('\r\n') + '\n')
  465.             self.statout.flush()
  466.         else: # self.statout is Tkinter.Variable:
  467.             cur = self.statout.get()
  468.             cur = eval(cur)
  469.             self.statout.set((message,)+cur)
  470.  
  471.     def set_db(self,db):
  472.         self.db_name = db
  473.         try:
  474.             self.db = sqlite3.connect(self.db_name)
  475.             try:
  476.                 self.db.execute("INSERT INTO clients (mac,time) values ('00:00:00:00:00:00',0)")
  477.                 self.db.execute("INSERT INTO essids (mac,name) values ('00:00:00:00:00:00','test')")
  478.                 self.db.rollback()
  479.             except Exception as e1:
  480.                 try:
  481.                     self.db.execute("CREATE TABLE clients (mac,time INTEGER)")
  482.                     self.db.execute("CREATE TABLE essids (sid INTEGER PRIMARY KEY AUTOINCREMENT,mac,name)")
  483.                     self.db.commit()
  484.                 except Exception as e2:
  485.                     self.stat("Couldn't make tables")
  486.                     raise Exception
  487.             pairs = self.db.execute("SELECT mac,name FROM clients LEFT JOIN essids USING (mac)").fetchall()
  488.             self.pairs =[]
  489.             self.clients = []
  490.             for pair in pairs:
  491.                 self.pairs.append(pair)
  492.                 self.clients.append(pair[0])
  493.             self.db.close()
  494.         except:
  495.             self.stat("Couldn't connect to db file",1)
  496.             exit(1)
  497.        
  498.  
  499.     def count(self):
  500.         return len(self.pairs)
  501.  
  502.     #INFO Flush is dangerous so I don't use it..  This is good for dev
  503.     def flush(self):
  504.         """ Clears the database and the displayer"""
  505.         try:
  506.             self.db = sqlite3.connect(self.db_name)
  507.             self.db.execute("DELETE FROM essids")
  508.             self.db.execute("DELETE FROM clients")
  509.             self.pairs = []
  510.             self.clients = []
  511.             self.db.commit()  
  512.             self.db.close()
  513.             self.displayer_needrefresh = True
  514.         except Exception as e:
  515.             self.stat("FLUSH"+str(e),1)
  516.  
  517.     def worker(self):
  518.         """ Method that listens. Includes the packet handler callback
  519.            This method is meant to be run as a thread"""
  520.         db = sqlite3.connect(self.db_name)
  521.  
  522.         def w_handle(pkt):
  523.             if Dot11ProbeReq in pkt or Dot11ProbeResp in pkt:
  524.                 if validessid(pkt.info):
  525.                     if Dot11ProbeResp in pkt:
  526.                         t_pair = (pkt[Dot11].getfieldval('addr1'),pkt.info)
  527.                     else:
  528.                         t_pair = (pkt[Dot11].getfieldval('addr2'),pkt.info)
  529.                     if not (t_pair in self.pairs):
  530.                         self.pairs.append(t_pair)
  531.                         db.execute("INSERT INTO essids (mac,name) values "+ str(t_pair))
  532.                     if not t_pair[0] in self.clients:
  533.                         info = (t_pair[0],str(time.time()))
  534.                         db.execute("INSERT INTO clients (mac,time) values "+str(info))
  535.                         self.clients.append(t_pair[0])
  536.                     else:
  537.                         t_cmd = "UPDATE clients SET time="+str(time.time())+" where mac='"+t_pair[0]+"'"
  538.                         db.execute(t_cmd)
  539.                     db.commit()
  540.            
  541.        
  542.         self.state = Listener.RUNNING
  543.         while self.running:
  544.             try:
  545.                 sniff(iface=self.iface,count = 10, store = 0,prn=w_handle,timeout=5)
  546.             except Exception as e:
  547.                 self.stat("LISTENER:"+str(e),1)
  548.         self.state = Listener.STOPPED
  549.        
  550.  
  551.     def start(self):
  552.         if not self.iface:
  553.             self.stat( "please set interface")
  554.         else:
  555.             self.state = Listener.STARTING
  556.             self.running = True
  557.             self.t = threading.Thread(None,self.worker,"listener")
  558.             self.t.start()
  559.             self.stat( "Listening <" + self.iface + ">")
  560.        
  561.  
  562.     def stop(self):
  563.         self.state = Listener.STOPPING
  564.         self.running = False
  565.         if self.t:
  566.             self.t.join()
  567.             self.stat("Stopped...")
  568.        
  569.                    
  570. if __name__ == "__main__":
  571.     sys.running = True
  572.     parser = argparse.ArgumentParser(description=_about,prog=_name)
  573.     parser.add_argument('--version', action='version', version="%(prog)s v"+str(_version))
  574.     parser.add_argument('--headless','-',action="store_const",default=False,const=True)
  575.     parser.add_argument('--verbose', '-v', action='count')
  576.     parser.add_argument('--force', '-f', action="store_const", default=False, const=True)
  577.     parser.add_argument("-d", nargs=1, default="./sidlog.db",help="The database to store results.")
  578.     parser.add_argument("-i","--iface", nargs=1, help="The interface to sniff on.")
  579.     args = ["",]
  580.     if len(sys.argv) > 0:
  581.         args = parser.parse_args(sys.argv[1:])
  582.     else:
  583.         args = parser.parse_args(sys.argv)
  584.        
  585.     ###### Important variables and stuff
  586.     gl_dbName = args.d[0]
  587.     gl_force = args.force
  588.     sys.verbose = args.verbose or 0
  589.     if not args.headless:
  590.     ### HERE BE THE GUI
  591.         root = Tk()
  592.         root.title("Sidlog v" + str(_version))
  593.         app = SidlogGUI(master=root)
  594.         try:
  595.             app.mainloop()
  596.             root.destroy()
  597.         except KeyboardInterrupt as e:
  598.             print "Bye!"
  599.         except:
  600.             sys.stderr.write("[+]GUI exited unexpectedly\n")
  601.             sys.running = False
  602.         finally:
  603.             sys.running = False
  604.     else:
  605.         ### HERE BE THE COMMAND LINE LOGIC
  606.         if len(sys.argv)==2:    parser.parse_args(['-h',])
  607.         else:                   gl_iface = args.iface[0]
  608.         listen = Listener(gl_dbName)
  609.        
  610.         #make sure user put in valid iface
  611.         t_s = socket.socket()
  612.         try:
  613.             t_s.setsockopt(socket.SOL_SOCKET, 25, gl_iface)
  614.         except:
  615.             Error("<"+ gl_iface+"> not a valid interface")
  616.         finally:
  617.             del t_s
  618.        
  619.         # repond to forcing monitor
  620.         if gl_force:
  621.             try:
  622.                 os.system("ifconfig " + gl_iface + " down")
  623.                 os.system("iwconfig " + gl_iface + " mode monitor")
  624.                 os.system("ifconfig " + gl_iface + " up")
  625.             except:
  626.                 print("Could not force iface into monitor mode")
  627.         try:
  628.             listen.iface = gl_iface
  629.             listen.start()
  630.  
  631.             if sys.verbose == 0:
  632.                 print "My PID is " + str(os.getppid())
  633.                 try:
  634.                     time.sleep(FOREVER)
  635.                 except:
  636.                     pass
  637.                 listen.stop()
  638.                 exit(0)
  639.             elif sys.verbose == 1:
  640.                 try:
  641.                     rotator = ['\\','|','/','-']
  642.                     i = 0
  643.                     try: os.system('setterm -cursor off')
  644.                     except: pass
  645.                     while FOREVER > 0:
  646.                         FOREVER -= 1
  647.                         i = (i + 1) % 4
  648.                         time.sleep(1)
  649.                         info = "Capturing: "+str(listen.count())+"\t so far [" + rotator[i] + "]     \r"
  650.                         print(info),
  651.                         sys.stdout.flush()
  652.                        
  653.                 except:
  654.                     listen.stop()
  655.                     exit(0)
  656.                 finally:
  657.                     try: os.system('setterm -cursor on')
  658.                     except: pass
  659.                    
  660.             else:
  661.                 time.sleep(FOREVER)
  662.         except KeyboardInterrupt:
  663.             print "Bye!"
  664.         except:
  665.             sys.stderr.write("[!]Sidlog Exited Unexpectedly\n")
  666.         finally:
  667.             sys.running = False
  668.             if gl_force:
  669.                 try:
  670.                     os.system("ifconfig " + gl_iface + " down")
  671.                     os.system("iwconfig " + gl_iface + " mode managed")
  672.                     os.system("ifconfig " + gl_iface + " up")
  673.                 except:
  674.                     pass
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement