Hello. Welcome back to this course where we're talking about developing Python applications for cybersecurity use cases, and more specifically, use cases in the pre-att&ck matrix of the miter att&ck framework. So talking about primarily the reconnaissance stage of a cyber attack. In this demonstration, we're going to look at developing Python applications to perform network scanning, and this includes both looking for open courts and applications on a target computer and also scanning for potentially vulnerable applications on those computers. In the previous video, we had an introduction to Scapy, where we looked at how Scapy works and how it can be used to develop Python applications that interact with the network and make it very easy to develop custom packets and send them over the network. In this video, we're going to look at a couple of sample functions that are designed to perform network scanning, sort of implementing things that you'd see in something like Nmap, Nessus, etc. So for this particular demonstration, we're going to be using a file called Portscan.py. Opening this up, we see that we have two functions in here. On one that's going to be performing a SYN scan similar to what you'd see in Nmap and then another one designed to look for DNS servers. Starting from the top, we have our Scapy import statement. We've talked about in the previous video, have to import things as Scapy.all. I prefer to use this syntax from Scapy.all import star, which grabs everything. However, this can take a little bit longer to run. You might decide, in the interests of optimization, to import particular functionality from Scapy rather than everything. It's fine that this is shorter and easier to write. In developing our scanner here, we're going to limit what we're searching for to a subset of the possible ports. Just because we don't want to actually perform a complete port scan on target computers. Obviously, if you're looking to determine if another port is open on a target computer, you can expand this Python dictionary here. We're going to be looking for ports 25, 80, 53, 443, 445, 8080, 8443. Chose these because these are some fairly common ports associated with well-known protocols, things like web servers, SQL, DNS, etc. Here we've got two different functions that we're going to be defining, and these are just examples of what you can do. It's totally possible to write all of Nmap in Python using Scapy, but we're not going to do that because if you understand how to write one Nmap scan in Scapy, you've got the tools that you need to write the rest as long as you understand how that particular scan works. Here we're going to implement a simple SYN scan, but if you're not familiar, a SYN scan is designed to just perform the first send of a SYN packet from the TCP handshake and look for a corresponding ACK in response. We're not going to complete that handshake, and so n this target side, there's going to be a half-open connection there, where we sent the SYN, they send the SYN-ACK, and we never send the final ACK. In some cases, this might help [inaudible] evade detection because if you're only looking for full connections, you might miss these half-open connections. However, since this isn't, say, normal operation, the only legitimate case would happen is if the client goes down halfway through the handshake. Some systems are designed specifically to look for this and consider it anomalous or malicious. But it's a nice simple example for us for implementing a network port scanner in Scapy and Python. This is the statement where we really implement our network scanner. We're going to be getting back to results here, answered and unanswered. These refer to the packets that have been answered and the ones that have not been. We're going to use sr here to send the packet and wait for a reply. This is a Scapy function, and makes it so that we're not just, say, sending a packet out into the void, we're actually listening for responses. Scapy handles that behind the scenes for us, making it a lot easier to implement. Once we're inside SR, we're actually building the packet that we're going to be sending out. We've looked at this syntax in the previous video. But remember that essentially all we have to do here is build the successive layers of the packet and define the fields that we really care about. In this case, we want an IP layer and we're setting our destination to the host of our target. We're going to pass in the target address as host and we'd say, all we care about in our IP packet is that it's going to this address because that's the computer we're scanning. At the TCP level, we're going to specify a few more fields. We don't have to specify the source port here, but I find that specifying a source port when you're doing things like this is helpful if, for example, you want to perform traffic analysis and capture things in Wireshark for a further look. If you know what the source port is, you can use a Wireshark filter to just look at traffic that is coming from or going to port 5555, or whatever value you set for this. That'll let you ignore everything else that's happening on your system and weed out the real traffic from the background noise. Here is what really makes this a port scanner. So deport specifies the destination TCP port that we're scanning in this case. Normally, maybe, you'd set this to a single value, but you don't have to. In fact, that's what we're doing here. We're setting this equal to our Python list up here. What this will do is it will send a SYN packet out to each of the ports in our list, essentially implementing a complete port scanner without forcing us to mess around with the loops. It's all handled behind the scenes by Scapy. Scapy is intelligent enough that it's going to send out all those packets, track the responses, making it much easier for us to manage. Finally, since we're defining a SYN scan here, we need to make sure that our packets that we're sending out are actually SYN packets. We're specifying a flag of S saying that all we want sent in these packets that we're sending out is a SYN flag. If we wanted to change this to a ACK scan, we'd replace this S with an A. We can create a Xmas scan, just by setting different flags here. Alternatively, we could build more complicated packets to implement different types of scans or potentially multi-stage scans here. For example, we could do a full connect scan where we send this SYN, wait for a response, and then send the final ACK at the end, establishing a full connection. It's sort of the inverse case here. Here we're creating a half-connect scan, potentially sneaking past some defenses, if they're only looking at full connections. If we use a full connection, we'd be bypassing any defenses looking for half-open connections. Finally, I've set a couple of different variables here in our caller SR. We're setting a timeout saying that we only want to wait a couple of seconds for a response because the machine that we're port scanning in this particular case is generally up. So we don't want to wait forever if there is no response to a particular packet because that just means the port's closed. Setting verbose equal to zero. By default, SR is going to provide you with a lot of information and we don't really need that. All we really need is the result of this called the SR. That'll tell us which packets were answered and which packets were not within that timeout interval. After we've done that, Scapy is going to handle all of the behind-the-scenes of building the packets, sending them out, tracking responses, until we hit our timeout interval. Once that occurs, we're ready to actually look and find out what we've found. Just for tracking, we're going to say here, "Open ports app and provide the hosts" so we know which particular host we found open ports app. Down here at the bottom, when we call this, we're only going to be sending in one host. But you could very easily set this up with a loop that would scan a subnet or a collection of known IP addresses for our target. In that case, having this print statement up here specifying which host we've scanned is helpful just to keep track of what you actually learn from your scanning. Down here, what we're doing is we're looping over the sulk collection of answered packets. In our Syn packets up here, they're going to be divided it into two groups as we see over here when we define our output variables, we've got ans for answered. These are essentially going to be the ports that are open, because only open ports are going to respond with a SYN-ACK. On the other hand, close ports aren't going to respond, so they're going to fall into the second category. Since we're only really interested in open ports for this particular application, we're not even going to use this unans variable. We can just set it as, we don't care by replacing it with an underscore. But here for balance or if you want to modify this particular scan to do something for unanswered connection requests. For this, we're going to loop over the sent and received packets and just do it in a quick test, making sure that at the TCP layer of the source port of the sent packet, the destination port equals the source port of the received packet at the TCP layer. Essentially verifying that we're getting a response from the port that we've sent the packet to. If so, we're going to print out the destination port of that sent packet at the TCP layer, essentially telling us which port is open. This is a SynScan similar to what you can run on andmap. It's going to, again iterate over these seven ports that we've specified here and tell us which ones are open or closed. Very low-level scan, just determining if a particular port is open on a target machine. Our second example here is designed to be a little bit higher level. For example, testing for a particular type of application, listening on a particular port. If you're familiar with your common ports, you know that 53 is DNS. However, it's not necessarily true that the application listening on port 53 on a computer is DNS or that DNS is listening on port 53. It could be set to 8053 or something like that to make it harder to find. Our simple DNS scan here is designed to connect to a particular port on a particular host and see if it properly responds to a DNS request. In this case, our target host is going to be the Google DNS server. We feel safe in requesting the domain Google.com, because obviously they're going to know it. However, you might need to modify this if you're scanning it for a different DNS server. If you were scanning for, say, InfoSec Institute.com's DNS server maybe request the domain InfoSec Institute.com instead. At a high level, we're going to be using the same commands for this scan as well. We're going to use that ans unans structure. You send and receive two or SR to send and receive the packets. Then we're going to build our packet of interest inside of it. If we scroll all the way over, we see that our timeouts and verbosity are both set to the same because we don't want to wait forever if there's not DNS there. We don't particularly need to see all of the output that SCAPY would provide for this application. Building our packets were identical at the IP layer because all we care about is that our packets go to the target host. However, above that layer, we start deviating from our sin scan. Because DNS is often, not always, but often implemented using UDP, we're going to put a UDP layer inside of our IP layer, but otherwise very similar to our TCP scan. We're setting the same source port. In this case, we're specifying a particular destination port, port 53, and we're not specifying any flags because there aren't flags in UDP. Further deviation here is that we're going to add an additional layer on top of our UDP layer, a DNS layer. Inside of it we're building a valid DNS packet. In this case, we're saying that there's one request in here and the question that we're asking, a DNS query, is for the name or the domain google.com. Again, Scapy, is going to take just these few fields that we've specified and build a valid packet out of it with the IP layer, the UDP layer, the DNS layer, and then fill up any of the fields that we haven't specified with appropriate values. It'll then send out, in this case, just a single packet, because we've specified only a single destination port and it'll look for responses. After our timeout has hit, it'll put anything we get a response to in the answer category and put anything that does not elicit a response in the unanswered category. Then we have a simple test to say if anything shows up in the answered category, since we've only have one connection, then we know there's a DNS server running at that particular host. That tells us, okay, that's a DNS server at that host, at that port. We could easily modify this code to scan a collection of ports, if for example, we suspect maybe it's running DNS on a nonstandard port. These are our two simple scans we're going to be implementing here in Python. Obviously, Scapy has the capability to write much more complicated scans. For example, if you want to scan for the EternalBlue vulnerability, you can set up a scan that will interact with SMB, with the particular strings that are known to exploit that vulnerability, or even just look for the particular version information of SMB and determine whether or not a target machine has that EternalBlue vulnerability. It's a lot of power here, and this is why we're talking about this particular capability here in the reconnaissance section of the cyber attack lifecycle because if, for example, you are using Andmap and it doesn't have a particular scan that you need, or you want to do a simple vulnerability scan for something novel or even something not novel and you don't have Nessus or a similar tool, or Nessus doesn't support that particular scan, you can write your own to perform that sort of reconnaissance and testing. Then finally down here, like I mentioned, we're scanning the Google DNS server and we're just going to call both of them with that particular IP address. We'll close this out and we're going to run this with Python PortScan.py, however, something goes wrong. The reason why, in this particular case, is because don't have the permissions in this particular user account to start interacting with sockets. That's a problem because obviously, when we're using Scapy to send and receive traffic, we need to be able to use sockets. In this particular case, I need to use sudo on this code so that it has the appropriate permissions to interact with the network sockets. Hitting "Enter" again, we see that pause at the beginning, that's partially due to that importscapy.all as I mentioned, it can take some time and partially because we have to actually send out the traffic for that first SR in our SYN scan and wait for the time out to occur. Our results here, we see that there are a couple of open ports at IP 8.8.8.8, 53 makes perfect sense, it's a DNS server and obviously they're running some sort of web server on there as well because port 443 is running also. Based off of that knowledge, we might say, "Okay, it makes sense to check, is it actually running a DNS server on port 53?" If we run our DNS scanner here, we find that yes, it does respond to a DNS request. This is an example of just some simple scanners that we're able to run or write and run using Scapy and Python. Definitely it can write much more complex functionality, and there's a great degree of freedom for customization in this and similar scripts to scan for novel or just even particular vulnerabilities. This concludes this demo and discussion of using Scapy for network scanning. Thank you.