Hello, and welcome back to this course. In the previous videos in this course, we've been focusing on identifying a network protocol and the field within the packets of that protocol, for command and control. At this point, we're going to talk about moving from that identification to actually building packets for command and control traffic. At the end of running our traffic analyzer script, we had a listing of the layers and a packet that we might want to use for command and control, all the way down to the individual field that we'd be putting the data in. We've got an example here, where we start out with an Ethernet layer, an IP layer, a TCP layer, HTTP, becoming HTTP response. Then we want to store our data in the raw payload, in this particular case. Say that after running our traffic analyzer script, we determined that this set of layers, in this particular payload field, are the best place to store the data for our command and control traffic. If we're trying to automate our attack chain and make a automatic decision to perform command and control in this way, now we need a way to actually build the packet that we'll be using for command and control. That's what we're looking at in this video. This build c2.py script is designed to take a listing of layers like this one, and create the necessary packet. The first stage in this process is actually building that set of layers from Ethernet, IP, TCP, etc.. To do that we're going to use this build layers function, which will take this string as an input. Our first step in this is to create some of the base layers that we're going to be using in whatever packet we choose. No matter what, we're going to be sending traffic out over Ethernet, and we've got an IP layer inside of that. Here we'll set a couple of values to ensure there what we want them to be. Maybe a source address of 127.0.0.1 and a destination of 8.8.8.8.8. These are some of the high level requirements that we might have for a packet. We might need to tweak other information based off of the unique needs for our network. Maybe we need to specify a particular TCP source port or UDP source port for our traffic, for it to work on our computer and within our network. But at the moment we'll just have these IP addresses as our required parameters. Now, we've got this, and we need to turn it into a packet in Scapy. First we're going to split off of our semicolon, and we're going to start with the third value. The reason why is Ethernet and IP appear here, and we've already got a packet P that includes those layers. Now, what we're going to do is loop over the rest of this, and determine if the section of this string is a layer, and if so, add it to the packet. We're going to use a try and accept to do this. Essentially what we'll do is for each of these, say, TCP, we're going to try to define it as a layer and add it to the packet. If it works, we know it is a layer. If it doesn't work, like once we get to, say, this load, which is a field, then we know we've reached the end and built our packet and just need to put our data in the appropriate field. Our try is every time where it works and we're actually adding a layer, and our accept says, okay, we've gotten to the raw layer. It's built. Now, when we try to do load, it fails. We've got our packet and we return it. We have a couple of challenges here. One is that the name of a layer doesn't necessarily match the constructor for that layer. For example, ATTP space 1 is for the HTTP layer, HTTP space response doesn't have a space in the constructor, etc.. We've got a few lines of code here dealing with some of these corner cases. We're going to take out spaces using the Replace function, which will replace space with nothing. Then if the layer happens to be HTTP 1, so matching this particular case, we're going to use the right name for that constructor. Fixing that solves the first of our two problems. The second is we have a string, and to add a layer, we need a function call, so something like ether here. The string Ethernet or ether, etc., isn't the same as this call to the ether constructor. However, in Python we can call functions with a string. How we do that is through this line of code here, which says globals function, we'll call it with a list containing the string that we want, and then we'll call it as a function. What the result of this will be, when we call it, say, with the string, TCP is a TCP layer of a Scapy packet, which is exactly what we need. With that stored in L, we can call the add payload function to add it to the packet. Remember that with network traffic, each layer is encapsulated within the payload of the previous. We have an Ethernet layer, it has a data section or payload. In that payload, we start with our IP layer. Our IP layer has a data payload section, and in this particular case, the very beginning of that will be the TCP header, etc.. By adding payloads with our new layer, we're adding additional layers to our packet to get to eventually the HTTP response with a raw payload that we want. When our build layers function is done, we can return a valid packet. We've got our packet now, but we don't have the command and control data that we want to put in that packet. In this case, we can say that our command and control data is just the word hello. We want to set that as the payload in a particular location. In this case, it actually is the payload, but it could be an HTTP header, it could be part of a DNS request, etc. We'll call a set payload function. We'll pass in the packet that we built previously, the list of layers, and then the data that we want to put at that particular location. For this, we're going to do a bit of walking down the stack of the layers within the packet. Again, we'll split those layers off of a semicolon and we'll walk to the second to last place. Because the second to last one will be the last one before we call a field value that we want to set the value up. See you in the end, we'll call set field value with the last layer. That says, "Make the value of load equal to data". But first we have to get to the raw section where that load field is defined. How we can do that is we can loop over the various layers that we've got here, and we have to test to see if we've got a layer or if we've got a field value, because in some cases like DNS, you can have some nested fields. For example, the answer to a DNS request, the answer will be a collection of field values within the DNS packet. We need to say, "We want to go into that answer layer and then a particular field within that nested answer". However, that's treated differently than say, "Okay, we're looking to see if there is an HTTP response layer and if so, we want to access that response layer". The way that we can differentiate between these is using scabies haslayer function. Essentially this will return true if the packet has a layer with that name, and it will return false if what we're looking for is actually something like a field. We'll pass that in. If that layer exists, the variable that we're looking at, which we're calling p, which is our bottom layer, or bottom field that eventually will contain the field value that we want to set. We'll set that bottom most location to the layer that we're looking at. Say when we start out, we're going to first we want to look for the Ethernet layer. P is going to point to the Ethernet layer on the packet. Then we'll look for the IP layer, it will point to the IP layer. Then TCP layer, HTTP layer, HTTP response layer, raw layer. Eventually we'll get down to, we're looking at load, which is an a layer, it's a field value. This haslayer will return false. In this case, however, we won't look at load because we only go as far as raw. But if we add something like a DNS request where we need to set a value within the answer. Will hit a point where haslayer returns false instead of setting p to that layer, will set it to the particular nested field value. The answer structure in which we can get to the particular field that we want. Once we've gotten to that bottom layer that contains that field we want, we can then call set field value to put our payload in that value and then return the packet and update it. In the end, we're going from a listing of the layers that we want in our packet and the data that we want to send to what's hopefully a packet that we could send over the network that accomplishes that goal. We can call this using Build C2, hit "Enter", give it a moment. In the end we've called packet.show, so it prints the packet we built. Walking through we see we've got an Ethernet layer. These are automatically generated like destination and source. We probably have to change that to send the packet. The next layer down, we have our default source and destination addresses here. Then we see we wanted to TCP packet, so we've created that. Notice that the destination port here is the HTTP port, which is good because that's what we want to send. We probably want to change the source port, however, to a higher number random port because you won't go from port 80 to port 80, etc. Now have an HTTP layer, which hold an HTTP response layer matching our request. Then we see there are a bunch of HTTP header fields we haven't set, but we could have used one of these for data transfer. We finally get to our raw layer in which we wanted to set our payload in the value load. We look at that field and it says, "Hello". In the end here we've successfully built a packet that accomplishes our needs, and we've done it completely automatically. If we had a different string here, we could build a completely different packet. This helps us automate the process of determining our C2 infrastructure. Using traffic analyzers script, we determine a string describing the packet that we want and where we want to put the data. Then this script here actually built that packet for sending a particular piece of data to our command and control infrastructure. Thank you.