
good morning everyone this is breaking ground so you want to build a c2 uh before we kick off a few quick announcements as always like to thank our sponsors especially our diamond sponsors lastpass and palo alto networks gold sponsors intel google blue cat uh it's their support that makes this event possible uh because we are being streamed live please turn off your cell phones we do not have audience bikes in this room so raise your hand high after the talk and we will call on you uh and lastly uh just a reminder photo policy does not allow taking photos of other attendees and math should be kept on at all times with that please welcome
i digital
fan good morning everybody or afternoon as it feels like to me honestly uh welcome so so you want to build a c2 um so i'm going to talk about some crazy stuff that went through uh me building a c2 that is fully in use today kind of actually in the current ctf that's literally running right next door to us okay cool so give a little bit of background to myself um obviously i'm a security guy i love to program i love linux a lot i love windows really because i've been forced a lot of my life to work on it i'm creator of too many projects account and at my day job i kind of do more
social security architecture stuff some offensive purple teaming things and i do a lot of work for prosv joe's so mainly i do a lot of work with the red team as you can see but also i do a lot of work with the gold team maintaining infrastructure and architecture and kind of doing system administration stuff there so stupid beginnings as i say every project starts with a stupid idea so we're going to take take us back to 2011 the dark ages of java a long time ago when i started college i was learning java as one of the programming languages you know in my stack that i know today and you know they say kind of
laziness breeds innovation i kind of feel like it more breeds stupidity at least myself me being me i was really lazy and i wanted to encrypt data at rest and i looked at the implementation of aes in java and i said no screw that i don't want to do that that's too much so you know what i did i did the best thing possible i rolled my own crypto don't do that um it led to it's uh led to the invention of cbk which is a sort of lazy man's encryption um it stands for cipher block key it's like some like uh round cipher thing it's probably super duper insecure but i still listed on github
so kind of going forward now um now it's like 2017. i started learning going uh because my work kind of wanted me to develop some projects that were kind of uh architecture and os independent so the the language at the time really to learn was go and i was like awesome so me being myself a person who kind of learns by doing i really needed a project to learn i needed something to do outside of my job like kind of the things i needed to do because i wanted to like dive into the actual stuff that go kind of provides so what i did is i revisited some old projects to rewrite um i ended up actually looking to cbk to
rewrite i was like you know can i make this crap code run faster completely forgetting it's super insecure so uh we'll get to where that comes in but um so at the time currently i was doing a lot of red team development as well as most of my life in cyber security i was doing basically offensive stuff um now the thing was is while doing all this i never really found a tool that like worked correctly that really fit the needs that i wanted there was things that were missing like there were workarounds you had to do and they were like super clunky um things could be dependency heavy or you know the setup was like super annoying so you
know that actually led me to a lot of the tools that i've you know built today there are some super c2-ish things that i've made like ws bind there's some like exploits and things i developed some of the things i've already previously talked on like in your mems which is a talk on antivirus evasion i've also made some utilities and i also made some stuff like kind of for trolling and shits and giggles realistically so that all leads to xmt xmt stands for the extensible malware toolkit so you might be asking what is xmt xmt is an offensive security framework it does a lot of malicious things really well and i say malicious things i mean
like anything the miter attack framework may cover like you know dll injection assembly injection um you know processed doppelganging etc um and it provides c2 functionality and the only thing that's missing from that c2 functionality honestly is a user interface and what i mean by that is there's no button i can click to say do this i'd have to script all that out but everything else is still there the one cool thing that i made this with and i like an idea with is that it can be extended for any purpose so i leave a lot of room for users to input functions to change how it works to add things to extend functionality there's pretty much
like anything you can extend it to like anything that really you can put your mind to encode uh the one good thing about it it's since it's go it's multi-platform multi-operating system so i've actually took some time to make sure that it supports and it works on every operating system and every os that golang currently supports in mainline but however sorry but however it's currently windows favored so meaning like a lot of the kind of the toys and the cool things in windows uh that it does support really only work on windows at the moment i'm adding some linux support as i go but some of those are kind of hard to do one to one
and uh currently on the picture on the right well it's on kind of my right um that's the status of the repo as it is right now and currently we're at 32 000 lines uh as we speak so what did i want in xmd when i was developing it i kind of wanted to be easy to use i want it to be modular flexible i want to be simple at the same time so i wanted something to be you know configurable to an extent where it works out the box but also i could you know kind of change up how it works i wanted things to be not dependency heavy so i didn't want to
rely on a lot of things and i also wanted to have a small build footprint you know i shouldn't have to spend time building my implants i should spend more time like popping boxes and throwing shells so kind of giving a quick list of the things that make up xmc i know it's a lot uh we have the overlying c2 package which contains like most of the c2 functions uh config transform wrapper we will actually talk about in the next slides uh there is also the task package which doesn't really make a super big appearance but it basically handles everything when it comes to tasking or uh you know if you want to create custom
tasks for xmt to do then you have the cmd library which contains everything executable so like literally anything dsls assembly um you know etc uh the filter library the subpackage filter under it contains the cool filter um struct that we can use to literally select processes that we want to target so we can set parent processes or processes that own are like assembly or a dll et cetera and we have like cool things like setting the parent uh setting if it's like executable it's in a session or it's a service um like excluded processes etc then we have our communication library which contains most of our communication privilege uh primitives the limits library puts guard
rails around some of the things we can do which is kind of cool then we have the pipe package which is actually a it's before the golang implemented name pipes and it's sublet it's standard library but this actually supports linux and windows and it supports setting security permissions on your pipes as well so you can do a lot more cool things with it wc2 is my own version of a web c2 are basically connections over http and we'll actually get into that as well data is just a package allows the right uh data primitives like any golang primitive it contains some like cool really util helper functions including some like memory buffers and such crypto
same it's just some more cryptographic operation things device is actually one of the coolest packages and one of the largest it contains basically everything from interfacing directly with the device we're on so we have the evade package which does like defense evasion some other things like overriding hooks that might be placed in us by antivirus we have a local package that deals with identifying and detecting things on a local host we have the regedit package which is a high level interface for the windows registry then we have one api the window api registry and window api service when api is actually my own rewrite of the windows or the standard library windows package for golang and we'll talk about
that one the registry package under is the same thing it's my rewrite of the golang register package and service is also again a rewrite man is the home of guardian and sentinel guardian is our sentinel is a loader for xmt and allows you to basically load it into like any process debate based on your rule settings like load it from like a http endpoint from a dll from a file and disk whatever guardian allows you to keep a singleton instance running current currently on the device and it will keep that instance regardless of you know what persistent mechanism you use so you're not like actually running a thousand implants on a host lastly of util it's just like a basic
utilities directory uh contains some things we'll get into x error because it's a custom implementation of the errors package you go it does some really cool stuff that we'll get into bug tracks is a debugging library that allows uh you to to kind of log you know if the process crashes or anything super helpful text also contains a red regex free uh text matching algorithm and uh basically uh parser so you can do like some really cool textual expressions without all the bloat that the regex package in golang provides lastly we have crypt and i will talk about crypt in a little bit it's a sort of textual cryptographic helper that we'll get into that allows you to do
defensive asian so i know that was a really long thing but i want to highlight now some of the things that actually and some of the interesting things that are actually take part into xmt itself so one of the first things if you're developing a c2 is identification it's like one of the most important things basically it's the process of getting to know our host device so it might be like the os version the architecture um the you know interfaces uh which and ip addresses it may have then also is basically generating unique identifiers that are unique to that host specifically as well as any environment info so like the username the domain it may be running under if it's windows and
like your basic process and parent process id values for example and what this actually led me to is we ended up having to uh create our own ud uid library we originally used the machine id library but it seems it's abandoned now since like 2019 and unmaintained so we created our own which actually used some a little bit cooler features and used a better identification system in windows such as using the system sid instead of like the cryptographic hash of windows which doesn't change as much compared and is actually a little bit more unique and that actually led us to generating a 32-bit or 32-bit identifier which generates a 32-byte machine specific id called the signature and a three-bit
instance specific call just a device session id and basically these like uh these 32 bytes generate this session id that's unique across every single host that you connect to so networking speaking computer now developing this i wanted to be super protocol agnostic and you know honestly the lazy man in me really didn't want to write code for like different types of connections uh you know i wouldn't be able to handle pretty much anything without having to worry about what the underlying connection is i didn't want to have to you know write workarounds for something stupid and i also wanted to make complex connections well easy i didn't want to like i wanted i wanted to have complex
connections but i didn't want myself or like anybody else on the other end to have to deal with all the bull crap of like managing that connection like i don't want to have to anybody deal with that and what i ended up doing is these things now basically operate on the net.com interface which is just you know basic to go so networking so some of the things that do go into networking we actually actually took the uh idea and split it out into a thing called connectors and basic connectors are the simple interface that provides the ability to listen and or connect and it's defined actually in code by two interfaces which is one the connector it
accepts a context and a string you want to connect to and then it returns like a netcon and or an error and the acceptor interface which gives you a you provide a contacts and a bind address that returns a net listener and or an error some can actually support both some are you know one some are the other but most of them do have support for both built in so and we have for built-in current support we have tcp udp ip icmp http https tls mtls and you know like i said before a lot of things you can create custom ones for this so the the ability for you to create custom ones you just have to basically implement
these interfaces then there you go okay so one special highlight i did want to talk about is the udp connector so all connectors at least by default as you would think they're stream sockets so meaning you know we're not like basically we're not looking at packets we're looking at a raw data stream now if you know anything about udp udp is completely packet based same with ip and icmp for example and we really needed a way to support streaming over udp i really don't want to deal with edp on its own separate thing so i ended up working on developing my own custom udp listener and what this listener does is it contains its like own connection ring
buffer and what that does is it maintains a active connections map and this will take new connections and pipe them back to uh like the accept calls or if it already has connection that we are currently mapping it'll take the data and push it into the current socket buffer that we have and it this makes internal like a heavy use of channels uh to work uh work on multiple go routines at the same time but it actually works up really great and it's like super rock solid like you could talk over this as if you were talking over tcp and you wouldn't know the difference um you know i've used this to like send like hundreds of megabytes of data and
it just goes um you know which is really awesome and i ended up taking the success of this one and using struct inheritance for the ip icmp connector so now you can talk over ping or like any kind of you know ip based protocol as well the same way and with easy support so next one the wc2 connector the wc2 connector has the same problem as udp um you know it's http i didn't want to restrict just to post you know i didn't want to kind of send like a thousand post requests like every second that would be really suspicious so you know um i'm no stranger to web sockets and in fact i wrote the
scoreboard over there which makes heavy use of websockets so i ain't no stranger to them but i was like man how can we implement these so i dove down into the code golang source code and it turns out golang will return some http bodies as read write if you play nice but you need really specific conditions uh one you need a 101 hd uh 101 switching connections uh response from server can't be http2 and the server must hijack that connection and you know this is kind of obvious when you think about like web sockets like underneath the hood this is kind of how they operate but you need to all do this all in like
a custom way so that way you can basically jack that connection right out of there and what happened is we ended up having to use reflect in order to grab this because we needed like the direct neck con but we can actually index inside the supplied struct and we can just pull the connection out of there and now just use that as if we're talking overall tcp so some of the other things that i had to implement to like kind of improve in this area is during my offensive security kind of lifetime uh and some pen tests is that a lot of firewalls would block uh http connections based on like their cookie state and basically like if it's not it
doesn't recognize it as like a real like web session because it would basically apply a cookie to that session over the proxy and if that session came back without that cookie you'd be like no i ain't accepting you so i had to make sure that we actually like worked on keeping session state inside as well and the other thing is we had to add actually proxy support for it uh golang doesn't have any windows proxy support at all um it has like next proxy support super easy it's all environment variable based um so what we ended up doing is and ended up implementing our own uh proxy function and we call it device.proxy and it's literally a
one-for-one drop-in of the http proxy from environment function which is great so now we can use this for linux and or windows and it'll just work out the box um and this uses the one api i call uh when http get default proxy configuration which is basically it returns the either system based or gpo based proxy config on the host and we can parse out that data and then get like any of the proxy like what the http proxy your http exceptions etc and we just pull it out and now use it now the funnest thing i like to talk about the hardest one uh routing routing is really super complex and i hate that
it is complex but the reason i made it complex honestly is because we need to support like a lot of feature sets some of the features we didn't need support would be like multi packets so if i'm sending data to a host and or like a command to a host and that's like one packet for example i don't want to have to wait for it to connect back to me again to wait and go send the other one like i can just send both of them at the same time like if it hasn't talked to you back why am i going to wait another time to send it another packet so i can send multiple all at the same
time downstream device so we're not wasting any time then we want to also handle fragments um so if the packet's like too big you know we want to cut it up into bite slices for example because i mean i don't know about you but sending a pack a 100 meg dns packet doesn't look okay um then also there's a mode we created called channeling mode channeling mode basically allows you to break the normal like kind of weight back for a packet response from the client or the implant and now you can act as if you're directly at the terminal of the machine so it's like instantaneous feedback or instantaneous file uploads downloads etc so we also need to kind of have a work
around that make sure that works correctly and last thing proxy connections or pivoting if you know if you're familiar with that nomenclature where we wanted to be able to piggyback off of other implants connections and this kind of led us down this huge you know rabbit hole of basically working on the thing of routing the identity and flags so to kind of uh give a button to that uh basically we use a struct called packet which is the huge basis of enterprise communication and it contains a thing called flags and device id basically flags are a boolean uh state of a packet as it flows through like the network to the actual final c2 server
and it totes it notates the fragment size uh the fragment state as well so meaning like the group id because we can wait on multiple fragments if we want to and then the fragment position inside that group and then the the total amount of frags we actually want to receive also these flags will actually determine how we want to act on a packet as we can like optimize the our receiving of packets like if every packet coming to us just goes to us we can just multi-batch process those immediately versus like if it's a flag multi-packet meaning that we have to now unpack it scrutinize and look to see if we can forward it to like a downstream client
or upstream um so you know we can kind of use these to like speed up some of our processes as well so getting into channels that i talked about earlier so like i said channels are a direct connection to the c2 server like i said the easy way to describe it it's like you're at the terminal of that machine it's instantaneous communication it will work through proxies and pivots directly as well now the caveat of this is that every single hop between the uh implant and the c2 server it enables channeling mode through and through because i mean obviously if i'm waiting on a upstream packet from another device i you know it's not instantaneous
anymore right so it's going to enable upstream through every single device so if whatever end uh sent the flag flag channel it'll then bam uh instant set that up and then once whatever sides like all right i'm done it just sends black channel end and the whole thing comes down however if one of the hops between like a and b is uh channeling on its own meaning like that device specifically has decided it's gonna channel that one stays up unless that device is like all right i'm done as well so we're not tearing down other people's connections so proxying uh implants can piggyback on another uh implant meaning like i can talk to another one behind if i'm like
segmented behind a firewall or something um the implants don't need to know at all so like they don't even know they're talking to proxy they think they're talking to the c2 which is great we don't handle it like any any different and we can use a thing called packet tags to mark ownership and the reason we do this is so we can know where to route packets through we want to have packet routing super easy so we use a thing called packet tags which are hashes of the device id which the server will tap onto its uh packets that way there's no extra packets being like added so we're using less network traffic and now we can constantly update the
server say hey yeah i still got this guy i still got this guy i still got this guy so the server still knows now what this allows us to do is if we have multiple instances inside of a network and there's an instance way down there deep in the net it can talk to multiple different hosts and keep switching back and forth you know and the server on the other end still knows where it's at and knows how to route its packets so nothing gets dropped nothing gets missed we can you know send them all correctly so getting into some of the things that actually make networking really fun at least for me as a red teamer there's a
concept called wrappers and transforms and they allow you to augment c2 connection and basically what this means it allows you to like obfuscate masquerade or encrypt your connection we have wrappers which literally wrap the connection they are stream based things they have unlimited uses they have an order so you can go like you know encryption compression obfuscation or you can go encryption compression compression if you want to um then we have transforms transforms actually transform the connection they are block based they access the entire binary payload before it actually gets written to the wire so what this means is you can completely rewrite your your um your data so you can reverse it if you want
you can change it into a dns packet you can change it to an image doesn't matter you do whatever you want with it and but because of how they work they're only they can only be used once so some of the things we do build i have built-in support for for wrappers for example are encryption we have xor aes cbk because i'm funny we have compression uh gzip and lzo currently uh we have uh hex and base64 for encoding then transforms right now we just have base64 and we have dns so for the dns one i really like that one because it literally masquerades as a perfect rfc uh like fitting packet so like wire shark and everything else is
none the wiser that's a dns like communication between the two so these will like masquerade right through like a level seven firewall or a lighter seven firewall so now you may be wondering all this stuff's going on between like hosts well like am i wondering about like privacy or encryption or anything um well yeah i answered that with key swapping so key swapping is a thing that's enabled by default you can disable it by a build tag and it's basically a lazy mutual authentication between host and host are the server and the implant and basically what happens is when the implant talks to the server for the first time it will tag its packet with a specific flag it's
opt-in but if it's built with it it always opts in and then it sends some randomized key material at the end of it and what it'll do is it sends it to the server the server will then do some math based on the identifier of the packet um and some time-based stuff and the um the mutual like data that the packet has been sent with then the client on the other side will do the exact same mathematic formula and basically now they have both generated key material or a key that neither side is sent across a network so now they both have a separate key that they can use to encrypt their packet data without you know anybody else in
between knowing it now because of the fact that we use like uh the ids and the flags for routing we can only encrypt the actual contents of the packet so you know uh the actual data contents of it are encrypted using xor for speed but like everything else like the flags and stuff aren't really encrypted because we can't really do that um but the cool thing about it is is that if i'm sending packets through a proxy the proxy can't read my packet data like it has no idea what i'm sending it just looks like a bunch of gibberish but the server on the other end will read it and be like oh cool i
know what this is and it's rotated regularly so every so often there's a chance that the client will say hey server let's do this again and the client will send some more key material back to the server and they'll do the whole song and dance as the beginning so now the kind of thing that wraps all this stuff together profiles these things bring implant settings together with a little bit of twists they are a binary table that are kind of like a uh type length value uh format but they can also be in json if you want to be like stealthier and smaller uh smaller in your binary size you can actually disable json parsing
but it contains settings for containers wrappers and transforms excuse me and i contain multiple c2 servers so if you have multiple hosts that you wanted to connect to it'll just select one and send it to but they can also tame things called selectors and groups which i'm going to talk about next slide selectors in groups they are one of the coolest things in my opinion they can basically break up a profile into multiple like separate like sub profiles and what this allows the implant to do is it changes its encryption or like it changes how it acts on the wire so like it's encryption who it's talking to how it acts it can completely change that up
and that's without any interactions from the person like operating it like this will do it automatically so you know it'll switch it up like either you know based on like a time or based on randomization and um if the server's configured on the other end to accept this still then it just keeps going like nothing's nothing happened and basically we use selectors to kind of determine how we switch these then we have like last valid which says hey if you know the first one hits an error switch to the next one or random just as mad chaos just switch to one like every single time or we have round robin which is every connection operation switch to the next
one on a weighted based order semi-round robin same thing but if there's a 25 chances hit then switch 75 chance don't semirandom is again if you hit a 25 chance then it will switch to the next profile but this is completely optional um and the great thing about it though is is we have a python script in the repo under tools config.pi that will actually like do all this for you it can either be used in api directly in python or it can be used as like a command line thing but allows you to build these like complex profiles pretty easily now defense itself so one of the things i spent a lot of time on uh for defense
is limiting identification so we basically want to reduce the possibility that when a blue team looks at this binary and says oh obviously that's a go binary or obviously that's you know whatever it's it's c2 it's malware etc one of the things i do this by is reducing recognizable strings that do exist in the binary and this actually reduces our size which to be a plus we also do some things like some checks and some kind of work around to look not as malicious as we normally would one of the ways we do this is we enable a thing called implant mode which is enabled by a build tag it basically trims a bunch of unnecessary stuff off
the binary and even though it's golang and gulen's compiler is supposed to be really good at like trimming the fat and things that aren't used it can sometimes leave things in there that it may use that are really never actually needed so we actually basically force it to remove these things completely from the binary it also converts errors to numbers so that x errors package i was talking about on the wire and in memory those are converted to a numeric version of the string so basically like in memory and everything there are numbers but like as the operator reporting back on the error you would only see the string so like it converts it back for you so the grass
the great thing about it is that if somebody's doing memory forensics on it and for some reason you hit an error and it's like access denied or i don't know you cannot spawn this process for x reason it doesn't literally say that it's just like uh 256 or something you know so and it's great it saves us bytes over the wire and it's kind of less work for us to kind of do comparison and it also actually guts three megabytes of size for the binary which is pretty crazy um oh and it also cuts logging i don't expect an implant to log anything to stud out you know so it shouldn't even be printing anything to
set out why would you have it do that but um but yeah it cuts it really small and it removes a lot of stuff now crypt mode crypt mode is a really cool mode it like implant mode uh is a build tag and it's based on the util crypt library now this actually is a way to compile in all of our strings as encoded and this removes 90 of our strings from the binary and i mean are not like the runtime strings but like whatever we use like built-in file paths for like linux for example um and it's based on like an ldflags argument that like packs a string table and there's you don't have to do this by
hand i think you'd be crazy to do that um we have automated scripts that will do this for you and they're included in the tools directory and what it does is it actually looks at your build tags and your build environment and will say hey are you building this for windows okay nix all the linux strings we all need them or oh you're building for linux we don't need the linux or we don't need the windows strings so it only uses exactly what you're needing but basically technically speaking what it does is it builds a base64 encoded string block and with that block is when the program is first and knitted um it unpacks that uh block which is also
encrypted with xor and on first runtime it basically slots all those strings into a index on a string table and all the packages that have consumers for that will then basically load that string via index so then all those strings will come back and so where they're where they are like in their format so now defense i'll build my own loader so i actually um thought the assist windows package in golang was really heavy and what i mean by that is it pulls out a lot of dependencies it's super string heavy it adds a lot to your binary size and honestly one of my things it's a pain to deal with so i said screw it i'll build my own um
what i ended up doing is it's almost the same-ish but i added a lot of optimizations to it especially some like memory optimizations and i also added some mutex locking and improvements as well so we're spending less run time like spinning on certain things that we really don't need to but one of the other reasons i really did it is because i wanted to load dll functions based on an fnv hash of their name instead of the actual function name so if you're not familiar when you load a function in windows you first load the dll by the name like kernel 32 dll then you load the function name so like get windows version for example then you
load that so that's a string value so i didn't want to do that i wanted to load it by like i don't know one two three four five six and i wanted to load that so what end up doing is i built my own dll loader that actually um basically loaded these like this and how it works is when you receive a handle to a dll it's actually the address that it sits in memory in windows so what you can do is you can go to that mapped memory and start just reading it out raw so what we did is we started parsing and loading the virtual exports table which contains like all of the like an index
array of all the functions and we hash the string names of them then we compare the string name or the string hash to what we had and then if so that matches then we look up the ordinal position match that to the function address and bam there's your function um we only do this once per dll it's loaded so we just load all the functions that we need then bam we're done now the only pain in the ass that had to deal with this is exported functions so exported functions if you're not familiar is when a dll points to another dll another process hey that function it's over there now windows does this for you
automatically so you would never know it it exists but in this case it doesn't do it so it's basically a string instead of a function f pointer so we actually had to parse the string code do load library then get proc by name in order to actually grab that but now we had it automatically and that's it works perfectly and as you can see on the code on the right hand side that's actually literally the code that we use for this it's weirdly it looks weird i know because we're doing a lot of memory operations but like for example at the for loop the three lines after we're getting the the fnv hash of the string
we're just like casting the string value to a 256 byte uh like array so we can just grab it from there then we just grab the uh the address of the function after that then we check if we need it then we just check if it's an exported function and if it is we go do that resolve that if it's not we just store it and that's it it's actually pretty simple once you kind of get around to it so and as you can see from the left and the right hand side so on the left hand side is what we had before when we had all of our functions loaded by string value and on the right side we have our
function now loaded as their fmv hash value so now none of these string values will now be in our binary at all which is actually really cool so now we can like load like dangerous function one and you know even strings for dangerous function one it doesn't show up so i kind of remember a lot of like highlights of things that um are like so there's a lot of things in xmt that i kind of wanted to go over but like i don't have a super a lot of time so i wanted to make sure i at least cover the highlights of it but you know what i did want to share as well are some of the things that kind of
maybe really mash my head into the desk when i was building this there's a lot of those moments honestly but um yeah i kind of wanted to cover some of the funnier ones so killing the unkillable this was a really fun one so the golang run time was never meant to be killed it was never meant to be like ended at all so like if you go search for like closing the go runtime on like google you get a bunch of stack overflow results people like well how can i close the runtime and they're like good luck buddy like there is no way to do it um the devs have even acknowledged the fact there's like no way to do it
like i've looked in the code myself you can't shut down the runtime so imagine you had your own library legitimate thing like it's like legit library.dll you load it into a process then you're like all right i'm done you exit close all the proper functions do all like the niceties that windows want you to do when you're unloading a dll cool go back and look at that process in um like task explorer process explorer you'll notice the runtime's still just chilling there it it didn't quit and you know it might be oh this is fine but like when you're injecting into lsas this ain't good so you you wanna you know you know you wanna get rid of this in some way shape
or form so i actually found a way to do this and it's in my opinion really clever we found a way to kind of clean up all the go go routine functions and go routine threats are going on so go actually doesn't keep track of its threads that it creates it doesn't like you go look at the code it doesn't care it creates a thread closes the handle all right whatever um so i was like crap well how do i do this i can edit the runtime which i can do that i've done it i tweeted about it actually it's just like i wanna add this but i know nobody's gonna accept that commit um so
i was like okay well i gotta find another way so i put on my blue teamer hat and i said all right well how am i gonna find a golang thread inside a process so what i end up doing is you can actually all the golang threads have the same base start address all of them they literally do so if you look in the at least for windows i can say this if you look in the code then you look you search for like create thread a you go down it's the same it's the same function so it's the same function address every single time and you can verify this by going into the process
explorer and looking at the threads same base thread address i said okay cool same base thread address and the other thing is they're all started roughly around the same time cool so we can identify those so we say all right now we enumerate through our threads we say okay is it in the same module as us yes cool same base address cool um you know it started around the same time cool all right kill it there you go and then we just kill our own process go run time's gone so i uh run this now and if you run this and you look at the threat runtime is cleaned so and this actually led to the
development of device.goexit which eventually does call when api uh kill runtime i'm trying to work on this for linux it's a little bit harder in my opinion because i have less linux development experience um but on windows you can just call kill runtime or go exit and now it'll just completely clean the go runtime and in fact i did a commit literally a couple days ago to fix a bug it was so good at killing the go runtime that if you had two runtimes loaded in a process completely for different reasons like you gotta go laying service running in a thing and then you had a injected dll and then ejected assembly if you ran this it killed everything
which not good so i actually edited edited some fixes that you know actually make it only kill itself so i thought that was kind of an interesting way so now we can actually kill the go runtime uh second one crashing with style so i actually had a problem that i actually uh blue screened a lot of boxes during a ctf one time and i really didn't know why and i ended up blue screening a lot of my testing boxes too and i couldn't figure out what the hell was going on so and basically i kind of narrowed the actual cost down to cfg which is control flow guard in windows and this runs for pretty much every operating system based
binary so like scope host or i don't know uh colonel um lsas uh et cetera and um basically strict handle checks are a thing what that does is if you operate on a valid handle doesn't matter what you do it kills your process immediately and so if you call closed handle on invalid uh if you call a closed handle on a valid handle it still kills your process which is like dude i'm just trying to close the handle um which actually ended up being the reason why my process was crashing by the way um so and what was causing it was there's a race condition in the cmd process struct that the process opened closed way too quickly in
the span of cpu time so my go run my go routine that started to watch it didn't start in time enough for that process to close then wait for single objects for some reason uh not documented by the way in the api documentation for windows it will wait infinitely for the um for the process to end er for the process now because it's dead so wait for a single object just waits infinitely so trying to close that would then you would call close handle on it and that would cause the crash so now you would see a blue screen on your device and windows wouldn't log this i i couldn't get it to log it i
seriously there's nothing i could enable like even syslog doesn't log this so like i was like okay well maybe there's i'm doing something weird with memory because i've so done that before but no and i kind of narrowed it down to this so i ended up having to call uh wait for multiple objects which works properly and we create our own event as well so we now have our own event to signal so that way we can actually end it properly and detect that invalid handle if it happens last story time i have process dump woes so the one api function uh midi dump right dump is really weird it's really weird um in memory handle pipes behave oddly so i
actually um i was using this to write a thing because now you can dump process it allows you have a native function dot jump process memory and i was like all right let's just dump process memory dump across the memory and see if it works um when you use it in uh it allows you to specify a file handle so when you specify like an in-memory file handle like a memory pipe for example it dumps it works it drops 40 bytes off the response just for no reason it just i can't figure it out if anybody knows let me know seriously but like that memory pipe completes 40 bytes are gone and it just val it's per those
bytes are important to the backup and it basically invalidates it completely uh which is great so direct dump worked fine so i was like huh so i ended up having to um work using callback functions which uh i actually found out about the uh i actually found out about sliver and i was like oh cool let me take a look at what they're doing because they implemented that as well and they had a great example of like using that and i was like all right so like i have to do it this way apparently which is fun um but yeah so i had to basically do the long way just to kind of get this to work
so demos so i have some cool demos here wrong button so i'm gonna do the second demo first because my internet connection is really bad in this room so i apologize for that so okay so this is actually one of the real implementations of xmt like as a proper c2 it's called thunderstorm so thunderstorm has things called bolts which are implants and that this this uh c2 is actually what we're using over there so i am go so currently there's nothing here so i'm gonna go back into my windows vm and as you can see here there's a little exe doesn't look harmless or it looks harmless test exe so i'm gonna run it
i don't know why it didn't pop up it's supposed to pop up but as you can see now it shows we got a bolt here so we're like cool so we can actually go into it so type it in and we now got interactive shell is that legible in the back i hope um so we can actually type in like net user and it'll just take a sec and then now the bolt has the bolt has told us that we accept the job and most of this is built into xmt it's just literally the pretty front end is like the only thing that's added onto this so now we just got our output from our
command and for example i can run channeling mode that i talked about earlier challenge mode says okay so and there you go so now we have like we sort of have like direct interaction with it we don't have to wait as you notice there's no wait period at all for it um we just keep entering commands and there you go so what we're going to do is we're going to do some other fun things so now one cool thing is as we can tell we go into here and type t and we see test exe sitting here looking all nice in our in our process list so let's change that so let's do a migrate so we do migrate
target explorer exe method asm and then we're going to point to a dll let's test make sure i have it test v on yellow so we're gonna hit enter can't spell there you go okay so now we did a migration so if we look now across the idea is 3988 i don't believe there was our one before so we go back it's gone so we go to 398 so now we're running in our explorer process so now we completely switch contacts between process one and process two and we're still running we haven't switched uh we haven't lost any context or anything we're still in channeling mode running perfectly fine so our network connection switched over to
explore exe and basically everything else that we had the knowledge base if you will uh switched over and that this is still native to xmt it's not like any pretty add-on that i've extended or anything this is all default context so let's do something uh see i can also uh do some other things like okay windows so i can see what windows on their machine there's a lot of capabilities we built in like some really stupid pretty stuff for windows as you can see but those are some of the examples and let me see if i can get my wi-fi working i will show you the live thing because currently we have the live ctf
running the reception in this room is really bad
all right we'll worry about that later so i can't show that demo because it's really bad connected it's really bad connectivity and i think it's not playing nice but um these are some resources that i have so we have to get our repository it's just ditch.sh xmt that's the direct thing all the code for this by the way is public i don't i don't close anything i don't believe in closed source code so you know um if you want to fork it or use it i don't care um also thunderstorm the thing i was using also all open source um as well so if you ever want to use it you know just for shits and giggles or you want to
poke at it and see how it works go for it um it's at sh slash ts and lastly there are some other things that i looked at that really helped me um kind of get like a better handle on some things and there was a really great talk that resonated with me which was in during defcon safe mode there is a talk uh by ben kurtz and it was offensive going uh bonanza if you haven't seen it it's a really good talk i really love his talk so yeah uh we have about like 15 minutes i can close up thank you guys for listening to me rant for a little bit um and then i will go for questions
if there is any uh
yeah so uh he asked um if uh if there was any way that i made like uh see uh cd traffic like web app traffic yes so the wct listener i may not mention this is my fault wc2 is basically a web http c2 so it looks exactly like standard web traffic if that's what you mean it carries like all the default headers um i did want to do like a direct get post one or one that looked like looking like posting images uh that's a connector i'm planning to add but right now wc2 is like the go-to for that so it'll do that like all the proxy support and all the fun junk um
and it will um i'm missing the word here but that's the one that will do that current currently so there's a lot of options to it that i it's more than i can explain and i'm kind of a talk i feel like um but if that answers your question
oh you're asking gotcha oh you're asking does the url change yes right that's what you're kind of asking yeah so the text library is a text uh replacement and matcher like algorithm thing you can supply special text routes that will do that so you can say like i want a string route that looks like this or i want a route that looks like this so it changes every single call is that what you're asking yes we have support for that so yeah you just have to write like a regex looking string and it'll take that and then parse it out as with and then the end point can actually match those so you can actually kind of catch blue teamers
trying to do that so you can match on like the url the header uh headers host names user agents etc so um but yeah does that answer that yeah cool um i'm gonna try the functionality that you were describing under the profile section that's kind of similar to football strikes um beacon shell um would that be detectable with uh tools like uh retail analysis that john um so you were asking uh if the c2 uh the profiles thing would be since it looks like it looks like the uh see the cobalt strikes uh kind of profiles method i don't think so if it is that's really cool um i don't think so because it probably sits in a different memory
layout and for at least so for thunderstorm we actually encrypt all this stuff as well so it's actually xor wrapped in everything in memory and after it's used so i don't think it would fit i don't think it would check it but if it does that's awesome um but just because it would be like uh and we yeah we do have jitter and stuff so you might be able to match it on that um he asked if it would he might be able to match like the jitter or something which yeah that could definitely match that uh i would say um but i don't think it'll match that traffic exactly if it does you know that's pretty awesome but i
don't because the layout and everything i don't think it exactly matches one to one does that answer your question blue teamers so blue teamers one of the things i try to tell blue teamers all the time is know your land so like know what's running so i deal with a lot of windows things and people forget like what is actually like native on windows and granted i don't expect you know every dll but i want you to spot inconsistencies in it like there are some so i can make binaries and windows that look like exactly like windows binaries but there's things you can kind of look at like that's kind of sus right there okay
i'll give you one um so a lot of people don't sign with binary manifests so like examine your binary manifests i've seen a lot of people compile without them like resourcing is becoming more popular a lot of people don't resource so if you look at a binary and go to its details tab that's the resources of the binary so you can like specify custom like values for its name title description etc you can analyze that first and if they're smarter they'll put those in there but then manifesto i think people don't catch like compatibility manifest process hacker too if you've ever used process hacker look at it i found about it last year because the blue team were
talking about it it's really awesome and it can examine uh manifest and like it'll say if it's manifested for this windows like um i'm running windows 10. why is this program manifesto for windows 8 saying it's lsas i don't know about that so you know like that i would say would be a first start um but also examining like um you know like i used to love carbon black for this is um you can examine your threading and stuff like process uh hollowing is a big deal that a lot of people don't catch so like examine like look like even process explorer be able to show you like oh that thread doesn't look right like notepad shouldn't have
more than one thread no pad single threaded by the way like it shouldn't have like multiple threads running in it that's that kind of like answer i could probably go on a lot about this like like i talk a lot over there so but um i hope that helps a little a little bit um any other questions um yeah in terms of the uh payload on a system do you have any options as far as putting like a powershell so i want to do that i don't have a script and up for it i can do it um so the thing you've noticed with migrate i'm sorry you asked what are some of the things i can use for uh loading like in
the initial compromise loading and um you're saying about powershell loaders i want to build that i haven't built that yet but we can load via assembly we have a there's a built-in i've i've built in the srdi library into xmt at least the the dll to asm loader and so you could convert dlls asm on the fly and so we do that a lot so that that migrate that we noticed i did that all in asm but the dll was an actual dll um but we have that capability we have it for other things so like there's a there's a loader we have for thunderstorm that does that like natively but not with power shell it's it's on the road map i
guess is my answer uh does that answer
is
if you catch me around somewhere you can ask me i will talk your ear off that's okay um is there any other questions before i close out go ahead
i'm um sorry so he has keep swapping out using diffie-hellman no because i'm too lazy to do that but i would love to do that what oh um i'm too lazy to do that i'm just doing like a basic key swap and i'm basically using the material on both sides to do uh basically basically the values only one way if that makes sense so like i'm not i'm not sending any of the key data like at all i'm saying the basic source material to generate from that but it's not any any diffi helmet unfortunately now uh any other questions
uh cool so thank you guys again for listening i hope you guys have a great rest of your weekend