Create information gathering test application

It is time again for an extensive tutorial. This time, a tiny test application for passive and active information gathering. After the instruction you are welcome to improve the application with more features! Okay let’s start…

What should it do?

The security tester selects a information gathering method first. As second step the testers insert the URL or IP in a testfield and press a button. The result should printed out in a text area. The GUI should look like this:

Sensei Mockup

How it is implemented?

The prefered language is Python 2.7. So it is portable to different OS and for the most of methods are already packages available. The GUI is done with Tkinter. Tkinter provides all objects which are needed as widgets and ranges for this scope out completely. The file and folder structure look like:

├── essential
│   ├── __init__.py
│   └── timestop.py
├── gathering
│   ├── __init__.py
│   ├── geolocation.py
│   ├── icmpping.py
│   ├── information.py
│   ├── wappalyzer.py
│   └── whoisgathering.py
├── requirements.txt
└── sensei.py

File content

Files in root directory:

requests
python-Wappalyzer
python-whois
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from urlparse import urlparse
from gathering import IcmpPing, WhoisGathering, GeoLocation, WappAlyzer
from Tkinter import (Tk, Frame, StringVar, OptionMenu, Entry, Button, Text,
                     W, E, END, FALSE)


class Sensei(object):

    def __init__(self):
        self.root = Tk()
        self.root.title('Sensei')
        self.root.resizable(width=FALSE, height=FALSE)
        self.select = [
            'ICMP Ping', 'Whois', 'GeoLocation', 'Wappalyzer'
        ]
        self.option = StringVar(self.root)
        self.option.set(self.select[0])
        self.method = None
        self.url = None
        self.result = None

    def create_gui(self):
        self._top_frame()
        self._output_frame()
        self.root.mainloop()

    def quite_app(self):
        self.root.quit()

    def _start_request(self):
        self.result.delete(1.0, END)
        action = None
        target = self.url.get()
        method = self.option.get()
        if method == 'ICMP Ping':
            action = IcmpPing()
        elif method == 'Whois':
            action = WhoisGathering()
        elif method == 'GeoLocation':
            action = GeoLocation()
        elif method == 'Wappalyzer':
            action = WappAlyzer()
        if target:
            action.set_target(target)
            action.do_request()
            value = action.get_result()
        else:
            value = 'Internal Error'
        self.result.insert(END, value)

    def check_protocol(self, value):
        target = self.url.get()
        if value == 'Wappalyzer':
            if 'http' not in target:
                self.url.insert(0, 'http://')
        else:
            if 'http' in target:
                new_target = urlparse(target)
                self.url.delete(0, END)
                self.url.insert(0, new_target[1])

    def _top_frame(self):
        top_frame = Frame(self.root)
        top_frame.grid(column=0, row=0, sticky=W+E)
        self.method = OptionMenu(
            top_frame, self.option, *self.select, command=self.check_protocol
        )
        self.method.config(width=15)
        self.method.grid(column=0, row=0)
        self.url = Entry(top_frame, width=50)
        self.url.grid(column=1, row=0)
        Button(top_frame, text='Request', command=self._start_request).grid(
            column=2, row=0)
        Button(top_frame, text='Close', command=self.quite_app).grid(
            column=3, row=0)

    def _output_frame(self):
        output_frame = Frame(self.root)
        output_frame.grid(column=0, row=2, sticky=W+E)
        self.result = Text(output_frame, height=15)
        self.result.grid(column=0, row=0)


if __name__ == '__main__':
    RUN = Sensei()
    RUN.create_gui()

Files in essential:

#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from essential.timestop import TimeStop
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from datetime import datetime


class TimeStop(object):
    """missing docstring"""

    __start = None

    @classmethod
    def start_measure(cls):
        cls.__start = datetime.now()

    @classmethod
    def stop_measure(cls):
        stop = datetime.now()
        total = stop - cls.__start
        return ">>>> request complete in " + str(total)

Files in gathering:

#!/usr/bin/env python
#  -*- coding: utf-8 -*-

from gathering.information import InformationGathering
from gathering.icmpping import IcmpPing
from gathering.whoisgathering import WhoisGathering
from gathering.geolocation import GeoLocation
from gathering.wappalyzer import WappAlyzer
#!/usr/bin/env python
#  -*- coding: utf-8 -*-


class InformationGathering(object):

    def __init__(self):
        self.errors = 0
        self.target = ''
        self.result = ''

    def set_target(self, target):
        victim = target.strip(' \t\n\r')
        if not victim:
            self.errors += 1
            self.result = 'No target given!'
        else:
            self.target = target

    def get_result(self):
        return self.result
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import os
import platform


class IcmpPing(InformationGathering):

    COMMAND = ''

    def __create_command(self):
        operation_system = platform.system()
        if operation_system == "Windows":
            self.COMMAND = "ping -n 1 "
        elif operation_system == "Linux":
            self.COMMAND = "ping -c 1 "
        else:
            self.COMMAND = "ping -c 1 "

    def do_request(self):
        if self.errors == 0:
            self.__create_command()
            command = self.COMMAND + self.target
            TimeStop.start_measure()
            response = os.popen(command)
            for line in response.readlines():
                self.result += line
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import whois


class WhoisGathering(InformationGathering):

    def do_request(self):
        if self.errors == 0:
            TimeStop.start_measure()
            result = whois.whois(self.target)
            self.result += result.text
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
import requests


class GeoLocation(InformationGathering):

    API = 'http://ip-api.com/json/'

    def do_request(self):
        if self.errors == 0:
            target = self.API + self.target
            TimeStop.start_measure()
            response = requests.get(target)
            output = response.json()
            for key, val in output.items():
                if val:
                    self.result += str(key) + " => " + str(val) + "\n"
            self.result += TimeStop.stop_measure()
#!/usr/bin/env python
#  -*- coding: utf-8 -*-
from gathering.information import InformationGathering
from essential.timestop import TimeStop
from Wappalyzer import Wappalyzer, WebPage


class WappAlyzer(InformationGathering):

    def do_request(self):
        if self.errors == 0:
            TimeStop.start_measure()
            wappalyzer = Wappalyzer.latest()
            website = WebPage.new_from_url(self.target)
            output = wappalyzer.analyze(website)
            for val in output:
                self.result += " => " + str(val) + "\n"
            self.result += TimeStop.stop_measure()

That was it. The result looks like this:

Sensei

Improve it with your ideas!