Nmap Security Scanner
*Intro
*Ref Guide
*Install Guide
*Download
*Changelog
*Book
*Docs
Security Lists
*Nmap Hackers
*Nmap Dev
*Bugtraq
*Full Disclosure
*Pen Test
*Basics
*More
Security Tools
*Pass crackers
*Sniffers
*Vuln Scanners
*Web scanners
*Wireless
*Exploitation
*Packet crafters
*More
Site News
Site Search:
Exploit World
Advertising
About/Contact
Credits
Sponsors:
edgeos



Nmap Development: Zenmap idea for Summer of Code 2008

Zenmap idea for Summer of Code 2008

From: Vladimir Mitrovic <snipe714_at_gmail.com>
Date: Tue, 11 Mar 2008 12:27:20 +0100

Hello everyone,

I have an idea for this year's Summer of Code, so I figured I should share it
early with you guys. I'm hoping for a chance to work on Zenmap this summer.

I was doing some thinking/research about graphical network topology mapping (or
a lack thereof) and how cool it would be if Zenmap had that functionality, so I
came up with a simple algorithm and implemented it in Python. I've attached the
source code (disclaimer: it's a quick hack), so I'll continue with a brief
explanation of the basic ideas behind it.

First, a user supplies an IP address (or an IP range) which is our
"destination", and the prefix length (PLEN), which is used for standard
CIDR-style subnet scanning (performed later). All IP addresses are added to the
"to be processed" (TBP) list.

For every address ADDR in the TBP list, do the following:
  * Run a traceroute to ADDR, and add any newly-discovered intermediate hosts
to the TBP list. Update the topology graph using traceroute's data to add new
nodes and construct edges between nodes.
  * Run a nmap scan on ADDR/PLEN (standard CIDR-style designation) and add any
discovered hosts to the TBP list.

When there are no addresses left in the TBP list, the construction of the
topology graph is "finished". I say "finished" here because, of course, a user
can only see the portion of the net she scanned. What I thought would be cool
(but didn't implement it) is that a user should be able to manually expand the
constructed topology once the algorithm finishes its run (that's the TODO on
stinkfist.py:85). For example, she knows that there's a live host (or hosts) on
the local LAN that wasn't detected because PLEN was too big.

There are also some other ideas that can be implemented, for example if a node
has more than two edges connected to it, then it's probably a router. Also I
had some thoughts about the starting node - maybe it doesn't have to be the
localhost, so we can simulate being on some other machine and starting the scan
from there. The possibilities are endless... ;)

As for the code, I used (py)graphviz to represent the topology graph and plot
it to an SVG image. You can use "stinkfist.py dst TARGET PLEN" (note the "dst"
there) or "stinkfist.py dst TARGET" (PLEN = 29, default) to generate the
topology file for graphviz (in the form TARGET_PLEN.dot). You can then use
"draw.py FILENAME" to convert the .dot file into an .svg image (Firefox can
open it). Also attached is a sample scan of my ISP's subnet with PLEN = 29,
converted to a GIF image. I've blurred out the first two octets of IP addresses
for privacy reasons.

So guys, any input is welcome, and please let me know if I'm reinventing the
wheel here. I'm looking forward to discussing this with you.

Cheers,
Vladimir

p.s. I apologize if the name "stinkfist" sounds bad, it's just a working title.

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

import sys
import os
import re
import pygraphviz

default_plen = 29 # default
topology = pygraphviz.AGraph()
startaddr = "localhost" # TODO get a real local IP (ifconfig, whatever)

def traceroute(dest):
        addrlist = []
        tr_out = os.popen("traceroute -I -n " + dest + " 2> /dev/null", "r")
        
        for line in tr_out:
                # find the first IP address in the current line
                addr = re.findall(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', line)
                if addr != []: addrlist.append(addr[0])
        
        return addrlist

def scan_subnet(subnet):
        addrlist = []
        nmap_out = os.popen("nmap -sP " + subnet + " 2> /dev/null", "r")
        
        for line in nmap_out:
                addr = re.findall(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', line)
                if addr != []: addrlist.append(addr[0])
        
        return addrlist

def destination_based(dest, plen):
        ip_list = [] # list of not-yet-processed nodes
        result_list = [] # list of processed nodes
        
        ### 1. traceroute to the destination address
        print "initial traceroute run:\n " + startaddr,
        for addr in traceroute(dest):
                print "-> " + addr,
                ip_list.append(addr)
        print
        
        # add these nodes to the topology graph
        if len(ip_list) > 0: topology.add_edge(startaddr, ip_list[0]) # cheat
        for i in range(0, len(ip_list)-1):
                topology.add_edge(ip_list[i], ip_list[i+1])
        
        ### 2.
        for addr in ip_list:
                result_list.append(addr)
                
                ### 2.1 traceroute to the current node, add any new nodes to ip_list
                print "processing " + addr
                lastaddr = startaddr
                for newaddr in traceroute(addr):
                        if newaddr not in result_list and newaddr not in ip_list:
                                ip_list.append(newaddr)
                        
                        # add the new node to the topology graph
                        topology.add_edge(lastaddr, newaddr)
                        lastaddr = newaddr
                
                ### 2.2 scan this host's subnet, using a given host width
                for newaddr in scan_subnet(addr + "/" + str(plen)):
                        if newaddr not in result_list and newaddr not in ip_list:
                                ip_list.append(newaddr)
                
                ### 2.3
                
                ### 2.4
                #ip_list.remove(addr)
        
        # save the topology into a .dot file
        tfile = dest + "_" + str(plen) + ".dot"
        topology.write(tfile)
        print "written topology into " + tfile

def incremental():
        # TODO implement
        pass

def single_node():
        # TODO implement
        pass

if __name__ == "__main__":
        if sys.argv[1] == "dst":
                if len(sys.argv) == 4:
                        destination_based(sys.argv[2], sys.argv[3])
                else:
                        destination_based(sys.argv[2], default_plen)
        elif sys.argv[1] == "inc":
                incremental()
        elif sys.argv[1] == "scn":
                scan_subnet(sys.argv[2])
        elif sys.argv[1] == "sgl":
                single_node()

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

from pygraphviz import *
import re
import sys

format = "svg"
layout = "dot"
#layout = "circo"

A = AGraph()
A.read(sys.argv[1])
A.layout(layout)
A.graph_attr["label"]=sys.argv[1]
A.node_attr["shape"] = "circle"

# put the format extension instead of the original extension and draw
A.draw(re.sub(r'\.\w+$', '', sys.argv[1]) + "." + format)

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

samplescan_gif
Received on Mar 11 2008
[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]
edgeos