 Hello, everyone. I hope you're all having a wonderful village. Welcome to my talk designing a C2 framework So my name is Daniel Duggan and Otherwise known as a raster mace I'm the director of zero point security. You may have seen a red team ops course. I Blog over raster mace.me as well as on offensive events I'm on Twitter get her discord slack all the things You want to get in touch with me after the talk by all means do so So what inspired this talk? Well It feels like to me prior to around 2018 The weren't really that many C2s or C2 frameworks available The main Commercial offering was probably Cobb Australian maybe a few others and And there weren't that many open source frameworks either we had PowerShell Empire for a long time We have posh T2 for a long time and then Covenant came along and some others came along and Suddenly we just had this huge boom in these C2 tools Coming out We've also had a lot more commercial ones as well. So it seems to be an area of interest for sure and It's not infrequent that I get approached and people are asking me If I've got any tips on how to build C2 and specifically in C sharp And so I thought that this kind of talk would be helpful for those who were looking to You know take on the process of trying to Put such a tool together and if you go over to the C2 matrix And it's a curated list of commercial and open source Frameworks it now lists over 70 which is pretty astounding really and More than 10 languages everything from Python Go rust C sharp Ruby even PowerShell There's no Shortage of variety and they all have different Capabilities so some By default will beacon over HTTP some will go over DNS some will go over completely custom channels and some might ride on legitimate services like You know the dropboxes office 365 different Google services and things like that If you're interested in learning more about some of the frameworks or some of the C2 tools already out there I hardly suggest you check out the matrix It has a really useful like Search tool I guess where you've you plug in your requirements and it will recommend and some tools for you Based on those requirements. So let's take a step back and talk about C2. What is C2? Well C2 is short for command and control You can imagine a scenario where you have us cowboy operators and we have a target and the operator will Deliver and some sort of implant or payload and sometimes also called a rat to that target and the operator needs to Maintain some control over that over that implant somehow The implant needs to talk to the operator the operator needs to be able to give it commands and the implant needs to give the results back to the operator and the the model that is Used most I guess is to have some sort of Intimidatory control server often called a team server. So the implant will communicate to the team server over Some sort of protocol again, that might be HTTP or DNS or some other legit service and The operator will have you know some sort of Admin interface to that control server So the implant will talk to the control server and it will kind of appear To the operator and the operator will be able to give it tasks The implant will grab those tasks from the server execute them and send send the results back It's worth noting that some of these servers have the Admin interface kind of built into them while others require the operators to have a Stand-alone client that will connect to that To that server for them So Conceptually not too complicated however, the point of this talk is about designing a C2 framework not just designing C2 and we need to Understand specifically for the purposes of this talk that C2 is not the same as a framework So if you go on to the matrix again, for example, you'll see a lot of C2 tools that don't Really readily provide that much flexibility to the operator You know, maybe a lot of those tools were designed in mind with I want to Demonstrate being able to use C2 over office 365 for example And that's pretty much all it's capable of and to me. That's not really a framework and This is all about frameworks So what does a framework provide? Well, they're quite clearly listed here So let's go through them. The first is inversion of control Now the overall flow of the program or the the programs that are Involved in this whole process and not strictly controlled by the user so the flow is that the implant is going to talk to a server and The operator is going to task that implant You know, you've got that back and forth. Now that is a flow that's not controlled by the user you also have on The server side and on the implant side a lot of internal flows So the implant will receive a job It'll process it in some way and then send results back that internal flow is not controlled by the operator and a lot of Flows internal to the team server and not necessarily going to be controlled by the user a Framework also provides default behaviors and But most importantly those are behaviors that can be Overridden by the operator So again, we're talking about the protocol that the implant is Talking over all the protocol that the team server is listening on a Framework may provide a default protocol for that such as HTTP but the operator should be allowed to Override that in some way Either change the behaviors within that protocol or add their own complete custom protocols a Framework also provides extensibility and That is to introduce new behaviors and capabilities that are not Currently within the tool set So if you think about an implant You might write your implant with a couple of commands But it needs to be able to Be customizable for the operator. They need to be able to add their own commands if they want their own capabilities their own post-exploitation capabilities and They also need to be able to do that on the server side as well so if you have Something like you want Reverse port forwarding on your implant You need to be able to introduce that capability to the implant the implant needs to send that data to the To somewhere probably the team server the team server needs to relay that traffic to wherever it needs to go And then it needs to send that traffic back. So Both sides of that process need to be Extensible by the operator to accommodate that a framework also provides reusable components which I think is self-explanatory, but they're They're components that the framework provides to make the operators life easier We'll see an example of that on the next slide So this is an example I've taken from the Metasploit framework Metasploit is a very mature product at this point and it's great to look at and If we're looking for inspiration on those frameworky things But if you're not familiar with Metasploit Anybody can write a module for it. Anybody can write the immersion module or an exploit module For that framework for other people to use and Being a framework it provides a lot of helpers for you to you know in writing those modules so this example is taken from the psexec module and The first thing you do in a module is to define some module information so this includes, you know a name and a description your an author or multiple authors references and so on and so forth and That information from the module is picked up by the rest of the framework So that as the operator whilst you're using the UI and you search for a module You can you know search it by name or whatever And then it comes up and you can see the name you can see its description and a bunch of other things You can also register options So this being a PSexec module the author here has said well you can define options for the service name Paths and a bunch of other things that are you know important to that module But more importantly There are some options that you don't have to explicitly define in the module So the framework knows that this is like a remote exploit module or whatever It knows that it needs the our host or you know your targets And the operator or the author of the module doesn't need to specifically put our host in as an option The framework already knows that that's required. So that takes you know that burden off the operator or the author And you also have includes and helpers which are down here So these includes are other met exploit modules that you can bring into your module and because this module is Using you know SMP exec in SMB. There's already a module for that So you don't have to actually implement an entire SMB library in your module or even the PS exec process in your module It's bringing in PowerShell and Xs because you know you need to execute something So as the module author you don't even have to worry about the payload that you're going to send the framework does it for you and you can see here that The service file name, so this is service file name here is an option If you haven't you know defined this option it takes the defaults And so these are the default behaviors. So if you haven't Provided a name it will pick it'll just make a random one for you and this round text alpha is Another module in the framework So you don't have to worry about okay. Well, I want a random string now have to write a function for that it's in the framework already and Those are the biggest strengths of frameworks is That as the module author they allow you just to focus on The task that you want and not worry about You know things that you don't want to worry about Okay, so where to start well This is like it seems pretty cliche, but the first thing you should really understand is what are your motivations? What does success look like and that kind of sounds like we're at some sort of management retreat but You kind of really need to think about what you're actually trying to achieve because You need to build it and you need to know what it's going to look like at the end So, you know, you might be doing this just for fun. You might be doing it just to teach yourself some stuff You might want it to teach other people You might be writing an internal tool if you're like a pen tester or a red teamer And you might even want to sell it. You might want to open source it And If I had to draw like some sort of parallel, I think about if you were gonna build a car It's very easy to say I'm gonna build a car But there are a lot of different types of car, right? if you Want something to take your Family to the beach. You probably don't want a McLaren P1 And likewise if you want to go round the Nürburgring pretty quick, you probably don't want I don't know Some sort of absurd people carrier So even though they're both cars They are quite different and they have different features to you know Make that goal a reality and there are all sorts of things that you You could think or that would be really cool to have in my framework. That would be you know, da-da-da-da-da but if it doesn't you know contribute towards What you're actually trying to achieve Then it's kind of pointless and if you Miss features that you need then you're not gonna achieve your goal And you're gonna end up with something that you didn't want so if you've never seen Moscow this is a pretty good way to try and narrow down what you think you want So this stands for must have could have sorry must have should have could have and won't have So your must haves are like mandatory things, right? These are things that your framework absolutely has to have to Performance function Should haves are important and they they add significant value But they are not strictly mandatory and To function could haves are nice to haves but not really important and Won't haves are least critical inappropriate or undesirable and Like the won't haves you can split into kind of two camps, I guess You can have won't haves like period and Won't haves this time and I'll sort of expand on this time In a minute So what you really want to do is you want to get your goal straight and think about all the things that you think you Might want in your tool You can also take inspiration from other frameworks as well and tooling that's perfectly okay. I don't think that's cheating Because you kind of want the best parts of everything and you know why Reinvent the wheel sometimes you can take good ideas from all sorts of places and that's perfectly fine in my book and Then what you want to do is narrow everything down to an attainable first release using that Moscow Method and by attainable. I mean attainable within your current skill set and your time budget and I think a mistake that a lot of people make is To look at things that have been out there for a long time to look at Empire You look at my sport framework and you look at Covenant posh C2 and all of those well established Projects and they think that's what I want to build. I'm going to build like my version of that framework But the thing is that those projects they didn't get there overnight They didn't just pop out of nowhere at the quality that they are now Some of them are months or years old So if you're trying to replicate that straight off the bat You know, you've probably got it easily six or 12 months worth of work and What you're going to do is you're going to work on it for a I don't know a couple of months or however long you can stand You're going to get fed up with it. You're going to get demotivated and then you're just going to put it to the side You'll come back to it maybe at some point and you'll look at it you'll look at it and you'll think well I've only done about 20% of what I hoped to achieve and You're probably not going to pick it up again and it's going to end up in the software graveyard so Small iterative releases are easily more achievable and far more likely to keep you motivated and You're also going to grow your project with your skillset. I mean you can you look at a lot of features in a lot of advanced frameworks now and you I mean, they're pretty they're pretty like advanced concepts So if you're if you're doing this to teach yourself You know coding It's probably not realistic to shoot for you know those kinds of You know features or whatever So having a small project that's a hundred percent complete is a lot better And it's a lot more satisfying than a large projects that that's you know, 10 or 20 percent complete So When I say attainable first release it's going to be like Probably the bare minimum of what will make a C2 Framework function no bells or whistles, but it's something to aim for right So you can set yourself a schedule So you're gonna say I'm gonna target my first release my initial release in One month or whatever you think is realistic. So you've got your Moscow You've got your must-haves and your should-haves and you're probably gonna prioritize those the most you could have You're probably not gonna really worry about too much Because you just want something that's gonna function that's gonna work and You need to be Cognizant of scope creep so it's really easy to just think I'll just add this I'll just add this People post things on like Twitter all the time or just Did you know you could do this or you know new techniques blah blah blah blah, and it's really easy just to try and add those in When really what you want to do is just stick to what you had planned for you know this release and If you see you know Cool stuff coming into the public domain. You can say well, okay Well, I'm not gonna do it now. Maybe I'll do it in the next release and For God's sake pace yourself So, you know two hours a day for a month is not the same as 12 hours on four Fridays in a month and Maybe this is just a personal thing for me but little and often is It's just a more enjoyable way to code than having to sit at your desk for however many hours because You feel like you need to get something out So let's talk about languages for for a sec There are you know a billion different languages out there and You're gonna have to decide on something for your server and your implant and Sort of depending on your model you might consider writing a client as well for the operators But the world I'm just gonna sort of focus on the server and the implant for the server side I Think you're much better off Building off a framework that already exists some sort of web Framework So you have Python ones like flasks and Django Lots of different ones in the C sharp you have blazer which provides you know like a nice web UI You can have something that's driven more by API eyes or RPC and you have lots of us like view react and angular and on the implant side you kind of have to Think about maybe Well, I mean this goes back to your goals really been what it what What platform you really want to target with your framework? I mean you can make your framework Implants agnostic a lot of a lot of them already do that like mystic You can write your own implants for a framework and that would be you know really great if your framework did that But you probably also want to include an implant Just to make it easier for people to pick up and use And so you have OS specific languages like C sharp target the dotnet framework and you have that Swift on Mac OS You have languages that cross compile like nim and go and rust and Then you have actual proper cross-platform languages like.net.net core and sort of Python but you certainly need to Sort of consider how these elements are going to talk to each other and Which language? facilitates that best so You know, I've already said that the control server should provide a means of Communicating with your implant over any protocol any means you want So you have to consider Is the framework that I'm choosing gonna be able to facilitate that can I do that in Python? Can I do that in you know, whatever and then you kind of consider well If my chosen language doesn't really do that do I need to consider a different language and If you don't really know that language is it worth learning or is it worth Sticking to what you know and just trying to make do the best you can I Think that's a decision only like you can make based on your goals and your priorities And if you're learning if you're doing this as a learning process, then maybe it's worth it maybe you specifically want to Use this project as an opportunity to learn You know C sharp, for example, I mean that's pretty pretty popular choice Then yeah by all means step out of your comfort zone and that kind of goes back to the attainable first Release thing is that if you're learning something new You've got a light starts more with it. So in terms of design patterns, there are two that I really Go for the first is this command design pattern and I think this is pretty good for picturing the flow of Stuff between the different components and by components I mean like separate components such as the server and the implant in the operator not really Internal to any one of those so we have the operator which is kind of like their clients and The operator wants to send a task To an implant so you're probably gonna send some information. Maybe it's over an API. You're gonna post some information I'll post this data to your team server, which is kind of like the director in This design pattern moment glacier So in this example, I'm simply I've got a simple task model that has a command and some arguments and I want to task an implant that we're going to identify by a GUID the server then takes that task and sends it to the implant So that's kind of the command and Then the implant which is the receiver is going to execute that task Now I've highlighted task GUID here Because it's in this model that the server Deals with but it's not in the model that the Operator sends So the server if I want my server to track like task progress with the implant It's gonna need something. So my server Excuse me in this example adds and a GUID to all of the tasks and Then when the implant can when the implant talks back to the server It can report it can use the same GUID so that the server can track commands with the implant and This kind of brings me on to the subject of contracts So you have contracts between the different elements Within your the overall solution. So you have contracts between the operator in the server The server and the implant and maybe even the server and any storage that you want So if you're storing data so you can Start and stop your team server without losing data And Then what you really need is different models For each of those contracts Don't try and use the same model Between every element because you're just going to get a little bit unstuck So here's a code example of a task request. So this is what an operator might post to the server This is a request. So it's got a command an array of arguments and an artifact. So If this was like an execute assembly command The artifact would be like the whole assembly. So you're gonna push like I don't know you're gonna push Rubius down to your implant and You're gonna tell it to execute with these arguments And The server will then add on that task GUID and give me back that GUID So as the operator I can then use that GUID to check the status of that task And when I'm asking for that, I don't necessarily I mean you might want to it's kind of up to you You might not want all of this original data back Like you don't you might not I don't need to see like the whole assembly coming back I don't need to have Rubius just going backwards and forwards on the wire between me and the server All I really want maybe is just the result and the status and You're gonna find that you know if you're using like Something like entity framework for storage if you're using C sharp You have to decorate your classes with all sorts of things. So you have to have like attributes on your properties that define like primary keys and stuff and That information just doesn't need to be coming back to the operator. It doesn't need to be going to the implant So at every point you have to Try sort of like translate each model to a different model and then pass it along the chain there's also this Template method pattern and this is pretty good for planning You know plan more carefully planning your code what's your actual code gonna look like and I'm sorry that all of my code examples are in C sharp Mainly because that's all I really know But also that's what people Kind of more interested in I think so on the left. I've got an abstract class. It's gonna act as like A Building block to build custom listeners on my server I'm gonna have a Protected field at the top which is an eye task manager and that is an interface that has these Methods on it so q task is The method that an operator would Use the task an agent so it would take in like a GUID and I've just put a byte array, but this would be the the implant task model and Then get tasks and receive output will be used on like the listener side So that when an implant is talking to the listener it can just use this task manager just to grab the tasks and Any tasks that are queued for it and also Give the server any output that the implant is sending and Then the listener it just has this in it or initialized method to bring in that task manager And then just to start on a stop So let's have a look at what that could look like in C sharp. So this is my abstract class You can see I've got the eye task manager here and This in it just brings in the task manager and just assigns it to that field and then it has two abstract methods start and stop and when somebody comes along and Implements their own custom listener. They inherit from this listener class And this is the entire Class here, it's obviously not very functional. It's just an example But you can see I've highlighted where it would use the task manager and as the author of The custom listener you don't have to worry about where the task manager is coming from or how it works because you've Implemented this abstract class the framework is taking care of that for you and all you have to do is Is just the task manager is there is a field for you to use as appropriate So to get tasks you just call get tasks and to send any output into the server To like process you just call and receive output So abstraction and Interfaces are you know, just they're just so useful And in terms of any implant that you're gonna write Base primitives are better in my view than I call it command proliferation and You know, you can see some CT tools just have like a bazillion you type like help whatever and just get a bazillion commands that you can execute and Like me I find it a bit overwhelming because I don't know. It's just a lot, but it's also not that Like flexible for the operator So Let's use mini cats as an example here. You could build in a command To a framework that will automatically push mini cats down to the implant Load it up in some way execute it and send the results back You could do that for seatbelt and for Rubius and it's very, you know, okay It's very nice just to have an automated way just to push all of these assemblies down But then as soon as the user will you know, the operator says well, I want to push down something custom You've not made it very easy to do that So the base primitives More about what allows these commands to actually happen so mini cats is tied to manual mapping in Like C sharp anyway, so instead of providing like a mini cats command you could just Provide some sort of means of just manual mapping in your implant and That will allow the user just to send down an arbitrary DLL or executable arbitrary commands Just map it into the implant execute it and send the results back You can also, you know expose reflective DLLs dot net reflection power shell Sockets, you know, whatever you want but the closer or The more easily you expose these base primitives to your operator the more easily They can write custom commands for your implant and in terms of commands This is something that I see quite often not even not just in like C2 tools But all sorts of tools that bring in some sort of user input This You know the command is a string and they're just well This is a switch statement, but it could easily be like If else if else if else if if the command equals this do this and It's just not good It's not very flexible. Obviously It's difficult to expand and maintain You know if you want to add another One in here, it's gonna be like massive and if you've got a more complicated complicated method Then these it's just Just don't It's difficult to handle exceptions you could wrap this whole thing in like a try catch In which case you're only catching like Maybe like generic exceptions or you could wrap each one of these in a try catch and that just makes it even bigger You can see we've got code duplication so We're requesting this like get current directory a whole bunch of times Which isn't really a problem for something so short, but if it's something more complicated Then it that just becomes untenable it's not particularly performant because Most of the time I think especially if it's an if else if else if it always starts from the top You go down and then the down We're also Forcing everything to be a string and it's just you know, it's just ugly. This is not a good way to Code something so what's a better? example, perhaps is again To implement those abstracts, so I've got an abstract class here, which is called implant command It has A string which is called command. I probably should have called it name or something, but this is like the name of the command and It's got an abstract method Called execute will bring in the task that's been sent down to it and It has another in it which brings in a class in this case in case it's called implant but implant has Several public methods you can see over on this right hand side here for Sending results back sending an error back and all sorts of things So the implant class again is not something the operator will Care about but you can expose public methods on it for them to do useful things So like the listener example, we want to create our own command That will inherit from implant command We give it a name in this case. It's just LS And I've also thrown like sharp split in here as an example as an example of like decoupling a Lot of like the back-end execution from the actual command and that means that as a user if I want to implement Another command that uses like charts like they can do that really easily You know again, we're just making it as flexible as we can and of course Abstracts you are forced to implement so you have to You know put some sort of implementation in when you override the this method and You can as the author you can just put whatever whatever you want in there And again, you don't have to worry about the task. It automatically is brought into the command for you You don't have to worry about where implant is coming from. It's automatically done for you You just call the methods that you want and Then you can this is within that implant and Class is that at some point we call load commands and we can use reflection to automatically instantiate every type of implant command and initialize them So they're ready to be used And then that handle task Method where in the previous example was that big old switch case This is what it would look like So all we need to do is find the class that has the name that we're looking for You know in the actual task that comes down If we didn't find it we send an error back saying that well the command isn't found otherwise we just Execute it I got another example here using attributes, but I'm actually running out of time So I have to skip to the summary Um So to start with absolutely know your goals Know what you're trying to build and why you're trying to build it Only by knowing your goals will you really understand what features you need to put into your framework? But I'd also encourage you to focus on framework features rather than c2 features So by c2 features, I don't know. Um, I guess I'm referring to command proliferation again But I would definitely focus especially in the early days of your of your framework is is focus on those framework elements You really want to provide the operators the means to customize and expand your framework the way they want to do it Prioritize those base primitives on your implant And provide an easy means for the operators to interact with them Um abstracts and interfaces are incredibly useful. I can't think Really of a a better way to provide that extensibility Um to the operators Plan small attainable releases. Don't try and do like a big big bang release for your, you know, your first one And if this is something that you want to maintain over the long term I would also say to limit each release to only one like big feature So if you look at usually if you look at release notes for for software Most of them the vast majority of the changes are bug fixes You'll then get other types of um, minor improvements And you'll probably only really see like one or maybe two like big new features Um, so that is a kind of software design life cycle thing that I would really encourage. Don't try and change too much in one go Um, yeah, I think that's pretty much it Um, I hope the talk was useful Um, if you've got any questions, please let me know. I'm going to try and be around for a q and a during the Um village if not Feel free to hit me up on any of those Um, socials I shared at the beginning I hope you enjoy the rest of the conference. Thanks very much