Thursday, February 19, 2009

Quick Scapy Tutorial for Extending Tools: Batch Tcpping

Originally posted from here.

Like every good hacker with nothing to do, I have my hand in someone elses cookie jar learning how to do something cool. This week I took some time to learn how-to use Scapy 2.0, and I wrote a script to perform a batch TCP Ping. I am sure someone will say in the back of their mind...."there is this tool called nmap." I my response, yes I know and everyone uses that tool, I want to fly under the radar not into it. I am not saying what I did is guaranteeing I am not in that category, but its a step away from the crowd.

I wanted to control some of the data in the TCP segment (e.g. payload, sequence number, dport, sport, etc.), and I wanted something to tell me *waves hands in circles* if there was possibly an IPS or Firewall in my way that would be nice too. Basically, all this script does for the time being is takes a file to be expanded/reconned, and tcp-pings them with some randomized settings in the TCP Layer. Not novel and innovative, but a good learning exercise. There are a couple of other directions that I would like to take this, but for the time being, I figure I would share what I have and what I learned. This is for Scapy 2.0+, there was a major software change between the 2 releases. I am going to basically list the interesting parts of my code and explain what I am doing. I learn by example, and in this fast furious world of "teh netz", I am sure others do too. I have been told my posts are a tad lengthy, so I will just hit the highlights.

I know there is logic that I can put in the script to make it a little smarter and faster, but for now, it can serve as a good tutorial for others. Apparently, Google Blogger might be distorting the code a bit, but it can be seen in it's full Pythonic whitespaced beauty here

Step 1. Importing Scapy into the script and silencing the verbosity:

from scapy.all import *
# default conf.verbose = 2
conf.verbose = 0

Step 2. Create my Tcp-Ping Packet and send it along the way

def tcp_ping_host(host, port=80, ppayload=None, to=1):
# host is the ip-address string
# sport is the dst-port to scan from
# seq number is current seq number of the packet
# if we want to mix it up and add arbtrary payloads
# simply make ppayload into a string, or a RandString(size, chars)
p = IP(dst=host)/TCP(dport=port, sport=RandShort(), seq=RandShort())
if ppayload:
p.payload = str(ppayload)
pOpen = False
hIPS = False
# send a single packet and wait for to*1 Seconds for a response
a = sr1(p, timeout=to)
# if the answer,a, is None, the host did not respond
# if a is a response, and it is ICMP and type == 1
# then the host is unreachable, port unreachable indicates
# there may be a host there (UDP) type scan
# a.haslayer(ICMP) checks if the packet has an ICMP layer
# a.getlayer(ICMP) gets the instance of the layer and then
# the fields for that layer can be referenced, e.g.
# a.getlayer(ICMP).type lets us access the type field
if a is None:
return a, False, False, False
elif a.haslayer(ICMP) and a.getlayer(ICMP).code != 3\
and a.getlayer(ICMP).type != 3:
return a, False, False, False
# 0x12 are the Syn-Ack in the flag fields of the TCP Segment
pOpen = a.haslayer(TCP) and (a.getlayer(TCP).flags == 0x12)
# try with a bad-sum
# some IPS/IDS/Firewalls respond to all packets, so lets mix
# it up and shoot a random/bad checksum at them
# to do this we will take p and modify the chksum to be a random
# short value and send it along (Idea was grabbed from nmap docs)
t = p.getlayer(TCP)
t.chksum = RandShort()
b = sr1(p, timeout=to)
# if we get a reply, its safe to say the host is FAIL
# or its a security device.
if not b is None:
hIPS = True
# fini. hope it was as fun for you as it was for mw.
# Spent all day in the coffee shop on this one, yay!
return a, True, hIPS, pOpen

There is some other functionality hidden away in the script like scanning a set of ports randomly, scanning hosts in random order, resuming a scan (or adding hosts to a do not scan list, etc.), but I have not tested all that stuff, but its there. I also posted some code a few light years ago on OpenRCE about using Scapy. Anyway enough talk, time for bed. Hope this was helpful to some. Have a good weekend.

As always here is my code:

1 comment:

Anonymous said...

Thanks for posting the actual code as well, since the blog ate the formatting.

Scapy seems to be quite powerful! It also seems to be very un-pythonic, and more tutorials would certainly help.