Homework 5 is due Thu Dec 01 on or before 11:59:59pm EDT. The assignment will be submitted via GradeScope; however, there is no automatic grading for this assignment. If your GradeScope account was not automatically created and linked, click on one of the “HW5” assignments in Moodle and it should set up. Contact the TA and Instructor if you are having trouble.

Points: HW5 has a maximum of 150 points.

Notes:

  • If you are using Python, you must use Python 3.
  • Your code must work on the csc474-hw5 image on VCL.
    • You are encouraged to use VLC to develop this assignment, but it is not necessary (as long as you adhere to the ethics considerations). For example, you may wish to develop your program on your own Unix-based system (e.g., Linux, macOS, WSL on Windows 10) and scan localhost (127.0.0.1). However, you must ensure it works in the csc474-hw5 image on VCL without installing additional packages. If you feel an additional package is needed, please contact the TA.
    • When using VCL, be aware that files in your home directory will be lost when the VM reservation ends. Either copy the file to your local machine, or store your files in your dedicated AFS directory: /afs/unity.ncsu.edu/users/[a-z]/<unity-id>. For example, my AFS path is /afs/unity.ncsu.edu/users/w/whenck.
    • I recommend connecting to VCL images from the command line via SSH. If you have not used VCL before, please read the VCL Help Documentation before asking for help.

Submission Information: Solution code should be uploaded to GradeScope under “HW5”.

  • If your solution is in Python:
    • We will attempt to auto-grade your submission. You need to name you files PortScan.py, PSDetect.py, and PortScanToo.py.
    • If your Python submission does not receive full credit, we will manually grade it.
  • If you solution is in C:
    • We will manually grade your submission.
    • You must include a Makefile along with your code to build your code. All of the code should build when running make all.
  • Include a README file with your UnityID and any notes that would be helpful for partial credit.

Acknowledgements: This assignment was derived with permission from assignments created by Micah Sherr.

A Port Scanner (60 points)

In this programming assignment, you will be building a port scanner. A port scanner is a software program that probes a target computer for open ports—i.e., ports that have services listening on them. They are often used for network diagnostics, but also as a precursor to launching an attack, since they identify potentially vulnerable services.

Your port scanner, PortScan, will probe all 216 TCP ports on a targeted host, and report the ports that accept connections. Your scanner should not require superuser (root) privileges, and can attempt to establish full TCP connections to the tested ports.

Your scanner should scan the ports in order (i.e., from 0 to 65,535) as quickly as possible. That is, you should not pause or sleep between probes.

For each open port, PortScan should report both the port number and the service that normally runs on that port. The latter can be found by using the getservbyport() and socket.getservbyport() calls in C and Python, respectively.

PortScan should also report how long it took to probe all ports, the number of ports that were found to be open, and the scan rate (ports scanned per second).

The command-line usage for PortScan should be:

python3 PortScan.py target

or

PortScan target

for Python and C, respectively, where target is the hostname or IP address of the machine that is to be scanned.

The following is a sample output.

$ python3 PortScan.py 172.18.9.34
Scanning 172.18.9.34
-------------------------

    0  .!.......!........
 4096  ................
 8192  ................
12288  ................
16384  .......!.........
20480  ................
24576  ................
28672  ................
32768  ................
36864  ................
40960  ................
45056  ................
49152  ................
53248  ................
57344  ................
61440  ................

Scan finished!
-------------------------
         3 ports found
     40.90 seconds elapsed
   1602.24 ports per second
Open ports:
-------------------------
   80: http
 1990: stun-p1
18017: [unassigned]

Terminating normally

IMPORTANT NOTICE REGARDING COMPUTER ETHICS. It is not cool to scan hosts on the Internet when you do not have permission to do so. Since port scanners are sometimes used to prepare for an attack, network administrators build tools to detect their use (see the next part of this assignment). Hence, by scanning a host, you may cause an alarm to be raised. Even if the target machine is not being monitored for probes, routers along the path from the scanner to the target may detect the “attack”.

We are providing you with a custom VCL image for this assignment. It has been configured to modify the VCL firewall rules that normally prevent your attacks from being successful. Use of this image will also to ensure VCL staff know that your attack traffic is for legitimate course use (and not a typical VCL instance gone rogue).

You are strictly forbidden to run PortScan against any machine except for your designated VCL instances, or any machines announced by the teaching staff as being an appropriate target. Nor should you run PortScan from any machine other than your designated VCL instances.

A Port Scanner Detector (60 points)

For the second part of the homework, you will build PSDetect, a port scanner detector. PSDetect will use the pcap library (scapy for Python or libpcap for C) to listen to incoming connections, and report the presence of a scanner if a single machine attempted to connect to 15 or more consecutive ports within a 5 second window. PSDetect should therefore be able to detect when PortScan is used.

PSDetect should listen on all network interfaces, and should take no arguments. It should not produce any output until a scanner is detected. When a scanner is detected, it should print out the message:

Scanner detected. The scanner originated from host A.B.C.D.

where A.B.C.D should be replaced with either the IP address or the hostname of the machine that attempted to connect to 15 or more consecutive ports within a 5 second window.

PSDetect should only terminate when the user presses CTRL-C.

The difficult part of this assignment is obtaining the IP header of captured packets. pcap functions at the data link layer and will return to you Ethernet frames. You’ll need to access the part of those frames that correspond to the IP headers. In Python, you can use the scapy library that is installed on your machines; when you use scapy’s sniff function you set a callback for each packet (via the prn parameter). The callback function is passed a packet structure that can be inspected using the scapy interface (e.g., pkt[IP].src for the source IP address and pkt.dport for the destination port). The scapy documentation has helpful examples. This is difficult in C, and you can borrow code from http://www.tcpdump.org/sniffex.c.

PSDetect will require superuser (root) privileges. You will need to run it via either sudo PSDetect or sudo python3 PSDetect.py.

Here is a sample output:

$ sudo python3 PSDetect.py
WARNING: No route found for IPv6 destination :: (no default route?)   <-- safely ignored.
Scanner detected. The scanner originated from host 192.168.1.12.
Scanner detected. The scanner originated from host 192.168.1.12.
Scanner detected. The scanner originated from host 192.168.1.12.
Scanner detected. The scanner originated from host 192.168.1.12.
Scanner detected. The scanner originated from host 192.168.1.12.

A Port Scanner Detector Evader (yes, I’m having fun with these names) (30 points)

Next, you will modify PortScan to evade the PSDetect port scanner. This port scanner will be called PortScanToo. PortScanToo should operate roughly as quickly as PortScan (i.e., the difference in timing between the two port scanners should be negligible). Unlike PortScan, PortScanToo does not have to scan ports in sequential order. Also, unlike PortScan, PortScanToo should not be detected by PSDetect.

What’s negligible? Let’s say that PortScanToo should impose less than a 1% increase in the average time it takes to conduct a scan.

Note that the same ethics warning/requirement pertaining to PortScan (see above) also applies to PortScanToo.

The output for PortScanToo should be identical to that of PortScan.

The command-line usage for PortScanToo should be:

python3 PortScanToo.py target

or

PortScanToo target

for Python and C, respectively, where target is the hostname or IP address of the machine that is to be scanned.