RN-QQHFzQYtPGkUCfyu8eve2qf0

Wednesday, 13 August 2014

Reading Wifite Source : Coding Hacking Tools In Python



Today I have a series of tasks for those who want to go a step further and write tools and scripts for others. In this tutorial we will take a look at the source code of Wifite and examine it to see how we can also create our own tools. There are various programming/scripting languages that can be used to accomplish the tasks. Wifite uses python, and that's what we'll start with.



Tasks

  1. Get some basic idea about Python - Take a look here - http://www.codecademy.com/en/tracks/python
  2. Get an idea about GNU General Public License - A good resource here or just take a look at wifite's license terms (optional step but if you're using Linux then it's important to know that the foundation of Linux is on concept of open source software and GNU GPL.
  3. Get a general idea about linux scripting. Use google for that. A comprehensive guide can be found here.
  4. Finally, take a look at the source code of Wifite (it's worth noting that the source code is available openly on because of the fact the it has GNU general public license). 
It's important that you follow the first three steps. The tutorial is about the codes which are important for any hacking tool. I don't cover everything. After reading this tutorial you'll know about the mandatory sections in any hacking tool. If you leave the first three steps (the 4th step is covered by me in this tutorial), then  you won't be able to code your hacking tool.



The wifite code

Now, a few thing which you will observe about Wifite-
  1. It is written in Python.
  2. It is licensed under the GNU General Public License Version 2 (GNU GPL v2).
  3. It is written by Derv Merkler.
  4. The source is quite well documented and easy to read.
Now lets take a look at the source in parts


#!/usr/bin/python

The #! is always going to be the first two letters of any script in linux. It tells linux to treat the code that follows as executable. The next words tell what the scripting language is, for example-
#!/usr/bin/php    for php
#!/usr/bin/perl    for perl
#!/usr/bin/python    for python
#!/bin/bash             for bash scripting
This part is called a shebang.





# -*- coding: utf-8 -*-

This is specific to python. Python recommends that we define the encoding that we'll be using. Take a look here if you need to know more about this - http://legacy.python.org/dev/peps/pep-0263/


General information

A lot of general information and to-do stuff has been written inside a comment. Take a read if you like.

After that there's a list of libraries that were imported. (Quite similar to other languages)
Then all the global variables have been declared. To enhance readability, all the global variables are CAPITAL.

Conditions

At a lot of places conditional statements are used to ensure correct functionality and also that all requirements are met before starting
if os.getuid() != 0:
        print R+' [!]'+O+' ERROR:'+G+' wifite'+O+' must be run as '+R+'root'+W
        print R+' [!]'+O+' login as root ('+W+'su root'+O+') or try '+W+'sudo ./wifite.py'+W
        exit(1)

if not os.uname()[0].startswith("Linux") and not 'Darwin' in os.uname()[0]: # OSX support, 'cause why not?
        print O+' [!]'+R+' WARNING:'+G+' wifite'+W+' must be run on '+O+'linux'+W
        exit(1)
The getuid returns the privilege. If it's not root (0), then wifite returns error and exits. The OS has to be linux.

This code ensures that the output of all the tools doesn't get printed to the wifite screen.

# Create temporary directory to work in
from tempfile import mkdtemp
temp = mkdtemp(prefix='wifite')
if not temp.endswith(os.sep):
        temp += os.sep

# /dev/null, send output from programs so they don't print to screen.
DN = open(os.devnull, 'w')


This is followed by 

###################
# DATA STRUCTURES #
###################

class CapFile:
        """
                Holds data about an access point's .cap file, including AP's ESSID & BSSID.
        """
        def __init__(self, filename, ssid, bssid):
                self.filename = filename
                self.ssid = ssid
                self.bssid = bssid

class Target:
        """
                Holds data for a Target (aka Access Point aka Router)
        """
        def __init__(self, bssid, power, data, channel, encryption, ssid):
                self.bssid = bssid
                self.power = power
                self.data  = data
                self.channel = channel
                self.encryption = encryption
                self.ssid = ssid
                self.wps = False # Default to non-WPS-enabled router.
                self.key = ''

class Client:
        """
                Holds data for a Client (device connected to Access Point/Router)
        """
        def __init__(self, bssid, station, power):
                self.bssid   = bssid
                self.station = station
                self.power   = power


The purpose of the classes is already stated by the author in comments (green).
##################
# MAIN FUNCTIONS #
##################

def main():
        """
                Where the magic happens.
        """

We will have to skim through a lot of code here. Can't cover everything. Some of the code that's easy to understand is shown and explained here.

Checking for the required tools

Wifite does not work independently and uses a lot of tools. For this, the following code is used which checks whether the required programs are installed. It uses conditional statements (if) and looping (for loop). If a program is not found, a prompt is crated. All the aircrack-ng suite tools are clubbed together in one condition, then there's a conditional statement for reaver. If aircrack-ng is not found, the program exits. However, Reaver's absence results in disabling of WPS attack mode only. Then there's code for checking the presense of Pyrit, Cowpatty and tshark. They are optional.

def initial_check():
        """
                Ensures required programs are installed.
        """
        global WPS_DISABLE
        airs = ['aircrack-ng', 'airodump-ng', 'aireplay-ng', 'airmon-ng', 'packetforge-ng']
        for air in airs:
                if program_exists(air): continue
                print R+' [!]'+O+' required program not found: %s' % (R+air+W)
                print R+' [!]'+O+' this program is bundled with the aircrack-ng suite:'+W
                print R+' [!]'+O+'        '+C+'http://www.aircrack-ng.org/'+W
                print R+' [!]'+O+' or: '+W+'sudo apt-get install aircrack-ng\n'+W
                exit_gracefully(1)
       
        if not program_exists('iw'):
                print R+' [!]'+O+' airmon-ng requires the program %s\n' % (R+'iw'+W)
                exit_gracefully(1)
       
        printed = False
        # Check reaver
        if not program_exists('reaver'):
                printed = True
                print R+' [!]'+O+' the program '+R+'reaver'+O+' is required for WPS attacks'+W
                print R+'    '+O+'   available at '+C+'http://code.google.com/p/reaver-wps'+W
                WPS_DISABLE = True
        elif not program_exists('walsh') and not program_exists('wash'):
                printed = True
                print R+' [!]'+O+' reaver\'s scanning tool '+R+'walsh'+O+' (or '+R+'wash'+O+') was not found'+W
                print R+' [!]'+O+' please re-install reaver or install walsh/wash separately'+W

        # Check handshake-checking apps
        recs = ['tshark', 'pyrit', 'cowpatty']
        for rec in recs:
                if program_exists(rec): continue
                printed = True
                print R+' [!]'+O+' the program %s is not required, but is recommended%s' % (R+rec+O, W)
        if printed: print ''    

Exiting when ctrl+c is pressed

        except KeyboardInterrupt:
                print '\n '+R+'(^C)'+O+' interrupted\n'
                exit_gracefully(0)
Also, it is necessary to define the exit_gracefully function at a later stage-

def exit_gracefully(code=0):
        """
                We may exit the program at any time.
                We want to remove the temp folder and any files contained within it.
                Removes the temp files/folder and exists with error code "code".
        """
        # Remove temp files and folder
        if os.path.exists(temp):
                for file in os.listdir(temp):
                        os.remove(temp + file)
                os.rmdir(temp)
        # Disable monitor mode if enabled by us
        disable_monitor_mode()
        # Change MAC address back if spoofed
        mac_change_back()
        print GR+" [+]"+W+" quitting" # wifite will now exit"
        print ''
        # GTFO
        exit(code)

This code makes the program exit properly (i.e. clean every file it created and changes it made, and disable monitor mode) when ctrl+c is pressed. Take a look at the following resources for information about except here-

Conclusion


We now know the basics that we need. It's quite impractical to explain the whole code here. The important part is knowing that the code does the following things-
  1. Starts with the shebang
  2. (Optional) Specify the encoding
  3. Add some comments about the author and licensing stuff
  4. Add important conditions, i.e., whether or not root privileges are available (unless they aren't required to execute your code), and whether the code is executed on a linux environment.
  5. Also check that the programs used by your script are installed in the OS.
  6. Define the required classes to organize data and functioning.
  7. Ensure that your programs exits properly when ctrl+c is pressed.
  8. Do the main coding (depends on what you are making).
It might be worth noting here that we just covered some basics here, which would be common to most tools. With this knowledge you can easily code your own tools.

0 comments:

Post a Comment