![BHIS PODCAST: Endpoint Security Got You Down? No PowerShell? No Problem. — Talkin' Bout [Infosec] News cover](https://img.transistor.fm/AukI425sRBc3M3UIa9lVng7qjeNeYEQ8BZfzCEXhALs/rs:fill:0:0:1/w:1400/h:1400/q:60/mb:500000/aHR0cHM6Ly9pbWct/dXBsb2FkLXByb2R1/Y3Rpb24udHJhbnNp/c3Rvci5mbS8xZTA1/ZWZhNDcxZGM4ZTFj/ZGJhMTMwNmYzMmJj/ZjBkNi5wbmc.jpg)
Do your PowerShell scripts keep getting caught? Tired of dealing with EDRs & Windows Defender every time you need to pop a box? In this one-hour podcast, originally recorded as a live webcast, we introduce a somewhat new Red Team approach that we call
Loading summary
A
Hello from Spearfish, South Dakota. It's the Black Hills Information Security Podcast. This is the podcast version of our webcast, so some of the slides we might reference will be missing, but you can find the whole episode on our YouTube page. This is Endpoint Security. Got yout Down. No PowerShell. No problem with Marcelo Salvati. Enjoy.
Alrighty. Well, thank you everyone for joining. Again, we're going to be talking about a somewhat new Red Team technique. The reason why I say somewhat is because I have a really, I don't like saying new because I'm pretty sure that if I think of it, a lot of other people have thought of it. And also it really isn't a completely new red teaming technique because we've sort of been doing a version of what I will be describing, whether you realize it or not, in like a lot of tools that we've, we've all been using as red teamers and pen testers for quite a while. This is more of like a spin on an old technique. My spin on an old technique should be interesting. This is our agenda for today. We're going to be covering some key. NET Framework concepts. The reason why is because we all have to get on the same page and to completely understand how this is even possible, we all have to know some key framework concepts. Also, I feel like just talking to pen testers and red teamers up, there's somewhat a little bit of a confusion regarding some of the. NET Framework terms that have been thrown around recently with all the C Sharp tooling coming about. So I feel like it'd be a good refresher for everybody. Just prefacing that I am going to be saying NET Framework assembly and NET a lot throughout this webinar. Just bear with me here. After that we're going to be talking about how to embed interpreter engines, technical details on how to do that. There will be some code and then we're going to be covering some key differences between BYY payloads. So bring your own interpreter payloads versus traditional C payloads. Byoi, by the way, is the thing that I just came up with. Don't be surprised if you haven't heard of that anywhere. Then we're going to be talking about the new sound Trinity updates. The soundtrainity is the tool that I wrote. It's like a post exploitation tool that tries to weaponize some of the BYOI concepts. It's been around since last derbycon, but it was essentially beerware. It was like in a POC stage. So with the new update it brings it From Beerware to Alpha, which is a big jump. Then we're going to be doing a demo and we're going to be talking about some detection mechanisms and then we're going to be going with the Q and A. First things first, we got to understand what is a. NET assembly, because I feel like a lot of people have heard this term been thrown around a lot and not actually understood what it is. All you really need to know is that a. NET assembly is a blob of precompiled code that any. NET language can interpret and execute. That's a very high level description of what that actually is. We're not going to be getting into the details of the. NET assembly format just because that's not for the sake of this webcast. That will take way too long. But all you really need to know is that any. NET language can interpret and execute any. NET assembly. How do you go about generating a. NET assembly? Well, it's pretty easy actually. You take any. NET language. We're going to take C in this case and you compile it into an executable using Visual Studio or cse. Exe, which is the built in compiler for C. You compile C into a. Exe.
Is a. NET assembly. Here is where things get a little bit interesting. Because if you compile C into a dll, that DLL is also. A. NET assembly. So from the. NET frameworks perspective, the XE and the DLL are the same exact thing because they both have been compiled from. A. NET language, which in this case is C. That's a key distinction. A really important concept to understand is that. Net assemblies are not the same as native XEs and DLLs. By native axes and DLLs I mean executables and DLLs compiled using C or C. The format is completely different. So just because. Because they have the.exe extension, they're not the same thing. If you compile. NET language into an assembly, that's going to be a completely different format as a native XE and dll. That's just things to get out of the way. As I said earlier, an assembly is something that any. NET language can interpret and execute. Let's take a look at some of. The. NET languages here. We got Powershell, we got C and we got F. So these are the three officially supported Microsoft. NET languages that I'm aware of. At least there might be others that I might have missed. These are the ones that I know of. These are all. NET languages. What's really interesting is that There are other. NET third party. NET languages as well, such as Iron Python. Iron Python is just.
The implementation of the Python programming language. On top of the. NET framework there's also Boolang, which is somewhat of a lesser known third party. NET language. But it's very, very interesting from an offensive Tradecraft perspective. I'll be talking about that later. It also Iron Ruby. If you want to write Ruby while accessing the. Entire. NET API, you can totally do that. The key thing to understand here is that all of these languages are built on the same exact framework. They're built on the. NET framework. What that means is that because of that, these languages are completely interoperable with each other. You can embed C Sharp into Python, Python into C, or rather, sorry, PowerShell into C, C into PowerShell and it'll just work because they're all based on the. NET framework and they're all bound together by a single unit of execution, which is the. NET assembly. That's just the important thing to understand here is that these languages are completely interoperable with each other. Now that we understand that.
Let'S talk about the reason why C Tradecraft has been all the rage recently. I think this is another core concept to understand when it comes to C Tradecraft because.
Really the root of why it's so appealing for red teamers and pen testers is because of this single function called Assembly Load. Assembly Load is magical because it accepts, among many other things as the first argument, a byte array. The implication of that is that you can just feed it raw bytes of a. NET assembly and it will take those raw bytes, load that. NET assembly in memory, and now you have full access to all the code that you've defined in your. NET assembly. Remember, how do you generate. NET assembly? You generate that by compiling any. NET language. The de facto one is C. This is really at the core root at why C is really any language really is appealing from a Tradecraft perspective because this one single function really is, when you go to think about it, the equivalent of having reflective DLL injection and reflective PE injection built into a language and into a single function. Because as we talked about previously, a C DLL is. NET assembly.
B
Hey Marcello, quick question. Yeah, a comment. Not much of a dev. Does that essentially mean you can write PowerShell, pepper it with Ruby and Python, then compile it into a. NET compatible exe and it will just work?
A
Yes, incredibly enough, yes, that. And that's exactly what we're going to be talking about later on, only we're not going to be Using Ruby. But we're going to be Iron Ruby. It's important. Again, the distinction here is you would have to use Iron Ruby, obviously not the original implementation of Ruby. I think at least the original implementation of Ruby is based on C. That's not a. NET language. Iron Ruby is based on. NET framework. Yes. As long as it's a. NET language, it can. They're completely interoperable with each other. And this is at the. This is exactly what this webinar is going to be about. And we're going to be talking about a little bit of that later. Only with Iron Python, I suppose, to Ruby.
Are there any other questions? Jason, are there any questions before I go on? By the way?
B
Just one more. I think it is so flood the memory space byte array with a knob sled, then followed by the payloads.
I think they're trying to figure out how this works.
A
No, you literally just give assembly. The assembly load function just accepts a byte array. So you can literally just give it the raw bytes of a. NET assembly. You compile C into. Exe, you can just read the raw bytes of that. Exe and feed it into assembly load and it'll work.
B
Gotcha. I think we're good.
A
Again, this is really at the root of why C Sharp Tradecraft is so appealing, because this assembly load function is built into the language.
I keep saying C, but just keep in mind any. NET language has the assembly load function, but.
It'S basically reflective dll, reflective PE injection built natively supported by a programming language. There are a lot of implications to that. One of them is that this allows embedding interpreters and engines within other. NET languages. Incredibly enough, you've probably all done this at least once or twice using a tool that a lot of pentacing and red teaming tools in a certain way or fashion. De facto example of this is using something like Powerline or something like NPS, for example, not PowerShell. Powerline is just a C Sharp executable that embeds a PowerShell run space. It's embedding the PowerShell runtime inside of the C executable. The reason why it does this is to bypass people who have locked down PowerShell EXE. Powerline is basically meant to run PowerShell without PowerShell EXE. The reason why you can do this is because PowerShell and C are both. Net languages, so they're completely interoperable without. Which means you can totally embed just the actual PowerShell interpreter runtime or whatever you want to call it. I guess run space is the actual term in a C Sharp binary and just execute PowerShell code. You can even do the reverse. And you've done this a lot in a lot of PowerShell offensive PowerShell scripts. A lot of offensive PowerShell scripts do this in order to access native methods, with the exception of the power split stuff, which uses a whole different thing. But you can embed C Sharp code in a PowerShell script, like the example on the right here. That's just literally copy and pasted a C Sharp class into a PowerShell script and then all you do is call this add type function. Now this add type function goes out, calls CSC exe, which is the built in C Sharp compiler, which is installed by default on every Windows machine, dynamically compiles that C Sharp code calls assembly load in the back end to load it into your current PowerShell runtime. Now you have just magically that all happens at the back end. After that you just have magically access to all of the functions that you defined in your C code. This is mainly used to call native methods. And by native methods I mean low level 132 API calls that usually are needed to inject shellcode and that kind of stuff.
You've been doing this in one way or another already. This is not something new. But the thing is this, there are more than just PowerShell and C language. PowerShell and C are not the only. NET languages. There's F, there's Iron Python, there's a bunch of third party. NET languages that we can do the same thing with. Okay? And from a Red Team Tradecraft perspective, the advantages of doing that are enormous. Because as of right now, all of the defenses that are in place for PowerShell are confined to the PowerShell runtime. They're not built into the. NET framework itself. They're not built into the underlying framework. That means that all you have to do to get around all of PowerShell's defenses, so AMZ script block logging, transcription logging, module logging, constraint language mode, all those go away immediately the minute you switch to a different. NET language, C, for example. That's why we're seeing this huge tooling migration towards C right now. Because C is by far the most similar language to PowerShell. And hell, you even needed to know C Sharp somewhat to do certain things in PowerShell. It was just the most logical jump. But it's not only PowerShell. You can use iron Python and because these are completely interoperable with each other, you can embed iron Python in powershell. You can embed powershell and iron Python you can embed C Sharp into Iron Ruby, you can embed Iron Ruby into Boolean. All of these are interoperable with each other because they're based on the. The same framework. Okay. So the problems. Okay, well, before I jump into that, actually, so the main reason why you'd want to actually do that though, is because C Sharp is a compiled language as opposed to Iron Python, which is a scripting language. And we'll talk about like, and from an operational Red Team perspective, like, that is. That is sort of a big deal. So you can use the Iron Python scripting language natively on Windows by embedding it in a C binary. Okay. And we're going to be talking about how to actually do that now. And this is really at the core about of what Silent Trinity does. This is the core concept that Silent Trinity uses. Okay, Marcel, a quick question. Yeah, sure.
B
Can you nest these indefinitely? Such as embed Iron Python into iron Ruby, into Boolean, into PowerShell?
A
Absolutely. This is the fun part. It's called an engine inception. You can nest multiple engines within each other. I think Iron Python has the best implementation of this because you can literally embed infinite amount of engines within each other if you wanted to, for some reason, like, I'm not sure why that's a thing, but you can embed an iron Python engine within an iron Python engine within a C Sharp binary within like a powershell script if you wanted to. And that's actually, that's incredibly enough. That's how the PowerShell stager for the new Silent Trinity update works. So, yeah, you can totally embed multiple engines with each other.
B
I think you're blowing a bunch of minds right now.
Does the target need to have Python binaries to run or does the embedding take care of those dependencies?
A
So we're going to actually talk about that right now. So the embedding straight out of the box, if you didn't pull any trickery with assembly loading and stuff, yes, you need to install. So again, and just the key distinction here, this is not normal Python. This is Iron Python, okay. Because Python is based off of CPython, which is based in C. So this is, that's completely different language. Iron Python is based on Netively, you can't run native iron Python scripts on Windows because when you embed the engine it requires four DLLs that are not present on Windows by default. And these are the DLL. So there's IronPython DLL, there's IronPython modules, DLL, Microsoft Dynamic, Microsoft Scripting. If I recall correctly, those two Microsoft DLLs are signed. Don't quote me on that. The Iron Python and Iron Python module DLL are not. So it. When you embed an engine within iron Python engine, at least within a C sharp binary, these four DLLs are required. Okay, so how do you get those DLLs to run? Like how do you, how do you get them on the target system? Right. There are a number of ways, like you can, I mean from an operational perspective, like I don't. It wouldn't be like, it wouldn't be great if to call your target up and just say, hey, can you install iron Python for me so I can run my malwares? So we need to figure out a way to run iron Python natively without the actual installation process. Well, these four DLLs are the only thing that are actually required in order to spin up an iron Python engine within a C binary.
Traditionally, the way you did this in any really NET is in C specifically is use something called IL Merge. IL Merge, really high level, just takes all the assemblies that your C executable needs to run and just merges them within that single binary itself and does some hooking stuff so that when the C binary actually runs, it automatically just loads them from the binary resources. But the problem with IL Merge is that it actually is really hacky and it doesn't handle a bunch of edge cases and it also has absolutely, it doesn't handle at all support for dynamic languages. By dynamic languages I mean.
NET scripting languages such as F and R and Python. Ilmerge is out of the question. What's great about C though, there was this one guy who wrote C book and posted this on an MSDN blog. This technique on MMCN blob turns out in C. And again, these APIs, these are net APIs. When I say C, it's the same thing in F or PowerShell or Ion Python. There's this one hook, it's called the assembly resolve hook. This hook gets called, this function gets called every time NET fails to resolve an assembly. When you run is your C executable with an embedded iron Python engine, it's going to try to call assembly load on those four DLLs automatically because they're just the required dependency. Well, the problem is if they're not installed in the gac, which is basically the equivalent of the path on next system where all of your. NET assemblies, all of the default. NET assemblies are in the global assembly cache, which is called the gac. The C will call the assembly resolve function every time it fails to load an assembly. What we can do is we can actually hook this function and, and add our custom logic into it. Whenever C fails to resolve an assembly, it will call this function. This gives us an incredible amount of flexibility because you can just throw your logic in this one function and you can just return an assembly and just call assembly load. Once you actually pull down the DLLs and automatically c will just load the assemblies for you. This is exactly what Silent Trinity does. So Silent Trinity has some logic in this myresolveevent handler function, which is basically just a hook on the assembly resolve method that downloads an encrypted zip file. Now, that's part of the new update, which we'll talk about later. Automatically unzips it, sees if the requested assembly is in the zip file and just loads it dynamically into memory.
Whenever the Silent Trinity C stager fails to resolve an assembly, it will download it directly from the server. Because we can put any. And that's just one possibility, because you can put any custom logic in this one event handler, which is fantastic. Then after that, all you really need to do is just call Python Create Engine. Python is a type of the iron Python hosting namespace. So Python Create Engine that embeds a Python engine and then you just call Engine Execute and that will just literally run Python code. So in this case, I'm just printing WAT to the screen. So that's literally all you need to do, which is fantastic at a really high level. Once you do that, you can just throw Python scripts at that engine and it'll just execute them. So this is taken from the message box module in Silent Trinity. It's literally like seven lines of Python. Like it's probably going to be like four if you get rid of the spaces. But.
You'Re just importing the CLR module, which is iron Python's way of referencing assemblies. So you do CLR addreference system Windows Forms, which references the Windows Forms assembly. You just import the class that you need from that namespace and then you just call Message box on it. So now you're dynamically executing net assemblies, dynamically executing net APIs from an embedded iron Python engine within a C binary, which is pretty legit, I think. Yeah, go ahead.
B
We got a couple of people are asking what in requirement of additional DLLs that are not native, permit the Red team to just monitor for those DLLs and just negate execution.
A
Yeah, so the Thing is this. That's sort of the problem that we're facing right now. Because there are no optics. There's not a good way of determining which assemblies like you can. Okay, so there's not a good way of detecting specific assemblies that are getting loaded reflectively. Okay, so you can do it. You can detect it using event tracing, and we'll talk about this during the detection phase of this webinar. But you can do it using something called etw, which is event tracing for Windows. The problem with that is I don't think there is a tool right now that allows you to capture this information at scale in an organization. You just won't be able to do it. The reason why you can't detect these assemblies being loaded is because there aren't any optics into the. NET framework right now. Because let's go back to this chart. Remember, we're now way beyond PowerShell. We're just in a completely different dimension than PowerShell. We're actually talking directly to the. Net framework from a third party language that doesn't have any of those defenses built in. There are no optics in place for that. Right now we're just completely bypassing PowerShell, all of the PowerShell defenses with a third party language, because all of those defenses are built into the PowerShell runtime as opposed to the underlying framework, if that makes sense.
B
Yeah, I think we're getting moved.
A
Sweet. So at this point we've embedded an iron Python engine. We've solved the problem of natively executing iron Python scripts on a Windows machine and dynamically resolving assemblies. We can just throw iron Python scripts at this 1C binary and it'll just dynamically execute them and dynamically call. NET API. So from here this is just a really dumb example, but you can do anything that PowerShell can do using iron Python and with a couple of exceptions, which we'll talk about in a minute. But I found a way around this exception, so that's fine. Now let's get into talk about difference between by OI payloads versus traditional C payloads and pros and cons for each.
C payloads. C is always pretty straightforward. It's just straightforward. It works against all. NET versions. But the problem operationally is that there's a lot of compiling all the time. You just have to compile the state. You have to compile all your modules. You just have to compile everything all the time. There's also a pretty big overhead in terms of setting up a development environment because of Visual Studio and all that stuff. Operationally it isn't the best. It's not a scripting language. You also have to worry about the. NET version for everything because you have to compile your C against a specific. NET version. If your target has the less than 4.0 version of. NET installed, it looks like there's all these things to take into consideration, I suppose the BYOI payloads, because we're interfacing with. NET through a scripting language. Now, this means that, number one, from an operator's perspective, from a pen tester's perspective, you can now build your modules in a scripting language of your choice, as opposed to C. So you're using all the power of Python or the power of Ruby or the power of Boolang to build your modules that just interact with the. NET API, which is a major advantage because, like this, you don't necessarily have to learn C now, because you just build your modules that inject shellcode through the. NET with Python and you can take advantage of all of Python string interpolation stuff that's a little bit more straightforward than C. It's just easier to use this way. You don't have to compile stuff. The most that you have to compile things is once for the C Sharp stager. So everything after that is dynamically executed. So you don't have to keep compiling your assemblies all the time. It also allows for quick retooling and weaponization, because again, it's a scripting language, right? So if you come across something that you never encountered before and you need to write a module on the fly, it's Python or Ruby or whatever language you choose to embed. So, like, it's just more efficient. So from a operational perspective, I think it's just more efficient. And we already talked about this because the concept of engine inception, right, you can embed, you can even. You can embed multiple languages within each other, multiple interpreter languages within each other. So not only are you creating insane amounts of reflection all the time, which is really hard to detect, all of this embedding going on, but it also allows you to. Allows an incredible amount of flexibility in terms of module creation and payload execution. Because.
You wrote a module like someone wrote a module in Ruby, you can just embed the Ruby interpreter within your C payload, and now you can just run that. And then a friend of yours wrote a Boolang module, you can just run the Boolang module. It's fine. Whatever language you choose to embed, you can execute. There's also the fact that there's ephemeral code module What I mean by that is when you execute Python code through an embedded interpreter, from my understanding, my current understanding of this, which might change, and from the code that I've seen, is that after the actual python gets executed, it gets garbage collected, which means that the Python code that you're executing should not be an even in memory. Like it only executes in memory and after it finishes executing, it just disappears. So if you went to actually perform memory live memory forensics on a incident where something like this was running on, and you didn't capture the memory, the memory at the exact same time as the module was executing that your code, your malicious code was executing, I'm pretty sure you will not even find it in memory. So it's like this whole. It's a whole different ball game. There are some downsides to using BYOI payloads, though. The main downside as of right now, is that it usually will not work on. NET less than 4.0. The reason why is because there are certain keywords, like there's the dynamic keyword that was introduced in net 4.0 that allows all of this stuff to work. However, I think I have figured out a way to get around that. But it will require a decent amount of time and effort. But as of right now, none of this sound Trinity won't work on machines that have. NET version installed less than 4.0. But my argument for that is that the reason why you'd want to use silent Trinity in the first place is to interact with. NET without PowerShell.
Because of that, if you're on a machine with NET 3 installed or 2 installed, you can just revert back to using PowerShell script. So in my mind, that really isn't a con per se, because you could just use the old PowerShell tooling. If you come across a machine that has net 2.0 installed, for example.
This brings us to Scion Trinity. This is the tool that I've been talking about, I've been developing for quite a while now, and it tries to weaponize a lot of these concepts. We're going to be talking. And let's really quickly. I'm going to be demoing this in a second. We're going to be. Let's really quickly talk about like some of the updates. So it went from 00 to 1, that's 0.1.0. So we're out of the beerware stage. We're out of the proof of concept stage and went to alpha, which is a good thing. A lot of big updates. So the first one is that Being the comms between the C stager and the server are completely encrypted using elliptic curve diffie Hellman key exchange, which is a hell of a mouthful. AES 256 and H Vac. So it uses public key cryptography. And everything's completely encrypted, including the staging. So the actual zip file with the DLLs that it gets sent down to the client, that's all encrypted. It also now integrates boolang support, so you can now create boolang payloads, send it down and those will get executed as well. And I'll be talking about boolang a little bit in a second. The CLI tab completes everything, which is fantastic. So previously it did sort of tab complete a lot, but the actual buids of the sessions that you got are very long and did not tab complete that. And that was like really annoying. So everything's tab completed now. You can now customize the check in interval of the sessions using the sleep command, which is always good. And there's now a help menu function which that also comes in handy. So boolang support. The reason why boolang is interesting. So iron Python has this embedding. Iron Python within C has this one key deficit which is that you can't access native methods directly. The reason for that is because in order to import functions in native DLLs which you can do in C, it needs a third party module. As in not a third party module, rather a module in iron Python standard library. When you embed the iron Python engine, it does not have access to the standard library anymore, which is fine because you could just use. NET to accomplish everything that you needed to do. So it's fine. But the problem is that one CLR module, it was required in order to access native methods to call all the functions that injected shellcode, for example, to call all the low level functions to do crazy, like crazy stuff that we could have. We could do like inject mimikats and all that stuff. You needed to access native methods in order to do that and you couldn't in our Python. So go Lang on the other hand is very interesting. Number one, at least for me, Number one is because it's extremely inspired by Python. So the syntax is almost completely the same. But it also has native support for importing native functions using, just like you would in C Sharp, the DLL import attribute. So you can just decorate a function with DLL import, as you see here. In this case we're calling the minidump write dump API, which allows us to take a memory dump of a specific process and we're dumping lsass. So we can now through boolang, have access to native methods, which is fantastic because this allows us to go as high as we want, as low as we want, and to do all the crazy stuff that we usually need to do during run teams like inject shellcode. Another really cool thing about boolang is that when you compile, usually the way you compile we did this through PowerShell was through that add type function that I talked about previously. Problem with that, from a Tradecraft standpoint, calling add type is not ideal because it leaves artifacts on disk. Because when you compile C code through PowerShell, it uses CSU XE and it leaves temporary assemblies to disk. The advantage of using boolang for this is, is that everything is in memory. Nothing touches disk the way it does this is through IL code. So intermediate language code, which we won't get into, but it dynamically creates an assembly and then executes an assembly.
Directly in memory. So nothing touches disk and you have Access to native APIs.
Demo. Okay, the first thing I'm going to do is start up silent trinity. So all you do is type Python. You download the repo, you install it Python ST PY and it dumps you into the menu. So if you've used Empire or metasploit before, you'll feel at home here. It also has read the concept of resource files. So like, you know, metasploit, where you can give it a resource file which will like automate sending commands to the client. You can do that too. So in this case I'm going to give it a resource file which just automatically starts in HTTPs listener for us.
Before I execute anything, I just want to point out I love the way I built the UI in this thing. So I'm just really excited to show this off. The autocomplete function in this is pretty cool. It shows all of the. If you press tab, it gives you a little menu thing that you can choose your command from. It also has the command now, so you're more into using the traditional style of things. That's great. So once you have this all set up, you now need to generate a stager. So you go into stagers. So now we lit. So you list the available stagers right now in the new update. This is the new Update. So there's PowerShell, there's Wemic and MSBuild. So PowerShell pretty straightforward. Wemic uses the XSL command execution method discovered by Subtee. Thing about that is, is that defender will just block that. So it's there just for like posterity sake. It's there just so like you can test in your environment that that actually does get blocked. The one my favorite though is MSBuild, and we'll be using that for a second. So it's really easy. Just use MSBuild. There aren't any options for the MSBuild stager yet. So you just generate it. The way you generate it is that you just hit generate and then you give the listener name. So up here we started a listener called HTTPs. Pretty straightforward. So you just generate HTTPs, right? So that will now generate to disk wherever the server is at a MSBuild file with an inline C task that will embed an iron Python engine and do all the stuff that's needed to get us a solid trinity stater. I just copied that over here already. So this is our MSBUILD stager here. I'm going to open up a PowerShell window.
And thankfully the server gives us a handy dandy, the handy dandy command to, in order to get this running. So you literally just have to copy and paste this into the window here and there you go. So.
That already did everything. So what it did, let's break this down. First thing it does, it does an HTTP post request to the endpoint on the server in which does the public key exchange. It does the key exchange. It then generates a shared key and then once we did that, it downloads the encrypted zip file you got downloaded 1.9 megabytes, which is the zip file containing the assemblies. Then it embedded the iron Python engine. C Sharp automatically resolved all of the necessary assemblies inside of the zip file. So you see here, found iron, Python DLL and zip, found and main py zip so main that PY is in the zip file as well. And that is the main logic of the payload, if that makes sense. So the actual logic for the session, the actual stage logic really isn't in the C assembly itself. It's just Python code that gets dynamically loaded. The implications of that is that if you now try to decompile this C stager, the C stager of silent trinity on disk. The only thing you'd really see is just a URL and some HTTPs calls being made to the URL. You wouldn't be able to look at the logic itself because it's only in memory and it's being executed dynamically through the iron Python engine. Okay, so once it did that, it also loaded the boolang interpreter DLLs which are needed to get boolang executing. And once we have that, you see here, that sent the stage on the server side. Now we have a session. So let's go over to sessions.
This is going to look awful because the font is insanely large. But so we got the GUID here and we got the user, we can type info. And this is the great part because now everything's auto completed, so the guid, you don't have to type that out, thankfully, or copy and paste that. We got some just general information about the system that we just compromised. And now the fun stuff, right? So we get over to modules, we list out the modules. So now if you use Science Trinity before, you'll see that it's a little bit different here because you got the Iron Python modules and then you got the Boolean modules. So you have a choice of like and both of them have pros and cons, which we talked about. Like you can't really call native methods with the Iron Python modules, so you kind of have to use the Boolean modules for that. But just to give you a demonstration real quick, I'm going to use the Iron Python message box module. Okay. The options, you get the title and the text. Just going to pop a message box and then you run it on the endpoint, which will result in. I'm assuming that's it. Yeah, there you go. So there you go, there's the message box. What's great about this is that you can take advantage. This isn't normal python. This is iron Python, which is based on. Net, so you can take advantage of. Net's tasking and thread threading to actually make this agent asynchronous. So if you like just stack up a bunch of modules to run here, you'll see that it'll just keep popping message box because the agent itself is fully asynchronous. So while it's executing other modules, it keeps calling back for more jobs, if that makes sense.
B
Quick question. And this bypasses an up to date Ms. Defender install.
A
Yep, we're going to be going into a mimikatz module straight after this. So I guess I can show you I'm not cheating here.
B
And a lot of people are loving this. And one guy said, or Jim said, ooh, so many ideas how to screw with deeper.
A
Yeah, so yeah, hopefully like part of this webinar was to convey this in a little bit more understanding way because I think I did a really bad job at my derbycon talk. I didn't really fully like explain well how this actually works. Just to give you an idea. So real time protection, codeler protection is on. The only thing that's turned off is automatic sample submission because I don't want Microsoft getting my malware. Let me pop this. It's going to be fun looking at the server now after you pop all those because you'll see that they all return results as the thread exited. It's completely asynchronous, which is fantastic.
B
I got one more question. This has come up a few times. Have you tried this against a. NET 4.8 early preview that has built in anti malware methods?
A
Yeah, I have not yet, but.
I know a friend who's sort of been doing the initial research on it and apparently it's not really as fleshed out it should be. So what I'm gonna do is I'm gonna wait until that's actually like completely stable and I'm tested out against it and see what happens because I feel like if I do that now, it's not. It's not fair because it's the. I think the release is still in beta. So it's. It's not even. It's not even completed yet.
B
One other comment is someone's gonna use it today. They've got an EDR to test.
A
That's awesome. Yes, definitely. Let me know. I've tested this against a couple of them. My recommendation testing this against EDRs is to use the MSBuild stager because if you use the PowerShell stager.
The PowerShell stuff is only there for convenience. It's sort of defeating the purpose of using PowerShell if you use this tool. Speaking of that, we're going to jump right into a mimikatz module. We got the Iron Python mimikatz module here.
So it runs the standard privileged debug secure lsa, yada yada yada log on passwords. Not in hindsight. Wait, let me start a administrator PowerShell session so I can run Mimikatz. Let me just copy and paste this. Now we're going to get a session running as local admin. We got a new session here.
Just before I do that.
Empire. If it's in a high integrity process, the session will have a little asterisk in front of the user. So that's just a quick way of doing it. So let's try to run this on the new session now.
There you go. We've run mimikatz.
In, so breaking this down. Okay, we're using.
C Sharp, inline C Sharp task within an MSBUILD file that embeds in our Python engine that executes python code, which then embeds another iron Python engine that executes the actual module that we send down. Okay, so let's talk about. So I think that's pretty cool. And there's like a bunch of other modules as well.
I'm gonna show you the mouse shaker one because that's just funny. So this is a boolang payload. Now, did I do that on the right thing? Yeah, there you go. So you can see that my mouse is now going crazy. So that's a boolang payload that executes boolang interactively on the fly. And there's a bunch of others. I could probably be here all day. Execute Assembly. If you're familiar with the Cobalt Strike Execute assembly command, that's exactly what it does. Takes a C executable and just executes it in memory. Again, the reason why we can do this is because these languages are completely interoperable each other. Right, there's an internal monologue. Let's talk about detection for a minute. So what's really interesting, actually, this is Ms. Build. So. All right, let's see. Let's open up Process Explorer real quick. There you go. So, properties, does it have. Yes. Oh, damn it. One second, Let me start this as administrator rights. So Process Explorer, for those who don't know, Process Explorer can view loaded app domains and assemblies that are being used in. NET processes. If you just go over here to the MSBUILD task that you spun up, you'll see that the. NET CLR is loaded. This is the main problem that I'm going to tackle now. Well, not now, but after I get done with this webinar.
You can see here that in the app domain we have the iron Python assemblies loaded and the boolang assemblies loaded, which itself really isn't a IOC per se, but the thing is they're not image backed, right? So these you can see because these, all of these other assemblies have an image backing. So they have an assembly on this. These don't. The reason why is because they were dynamically loaded, Right? So that's one possible ioc. Right. Another IOC is obviously the name Silent Trinity, which, okay, that's a dead giveaway, but. PE loader. So this PE loader right here is actually a modified version of sharpsploit's portable executable loader, which is what's used in the mimikatz module to load mimikatz. It's a C P loader. If you're using just the standard sharpsploit library, you would see that that would be sharpsplate. So that's another potential. I see. So the current problem right now with sound Trinity is that it loads everything in a single app domain. So if you went to actually inspect the process and you actually went to dump all the assemblies that are loaded, you will see that like a bunch of known malicious C Sharp libraries and assemblies are loaded. Right. I have figured out a way around that, because apparently you can embed iron Python engines within a different app domain. So what that means is that. And this is something that I actually wanted to get working for this webinar, but I just didn't have enough time to figure out some of the bugs that I encountered. But what that means is that you can spin up a separate app domain for each executed module. So when the mimikatz module executes, for example, it will be in a separate app domain, and then after it executes, the app domain will get unloaded. So when you actually go to inspect the process, you won't see the sharpsploit module loaded unless you grab it right when it's executing, which is almost impossible because it takes only like a second to execute. So you can totally do that. And I am like almost 95% there. I just need a little bit more time to figure all the bugs out. So this is one potential IOC which you can detect using Process Explorer or something. The problem is, at scale, this doesn't really work that well. And we're going to talk about that in a second. So let's go into detection.
B
Is the silent trinity in the task manager part of the DE weaponization?
A
I'm not exactly sure what that means, but I'm gonna assume he means if he can see it in the task manager. If not, I mean, so depending on how you execute the stager, you could, like, if you just run. If you just run the sound trinity C Sharp binary, you'll obviously see the C Sharp process, the sound Trinity process. But the thing is, like, you can embed it in PowerShell, you can embed it in Ms. Build because, like, this stuff executes C. So you'd be only able to see like MSBuild EXE or PowerShell EXE, if.
B
That makes sense, then app whitelisting has been coming up a lot. So have you found app whitelisting, like Bit9, capable of blocking this attack, ignoring the implications of EDR detection?
A
Yeah, so I have tested this against a number of EDRs. The thing is, when whitelisting is involved, I mean, like any Other I'm going to go back to the.
Like any other binary this is the Silent Trinity C stager. That's just a C Sharp assembly. This is the MSBUILD stager. In order to get around whitelisting, you just have to use a known whitelisting bypass, which is why MSBUILD is built into the sign Trinity. The MSBUILD stager that I just showed you here, that's a whitelisting bypass.
I know it actually does get detected on some this thing does get detected in.
But this is just a straight up white list in my past there really isn't because there are no optics in. Net right now. There really isn't a way for EDRs to hook into the. NET framework, the underlying. NET framework in order to actually detect this stuff. This is where this detection slide comes in because that. Net 4.8 it was brought up like has AMSI integration already. Now I'm gonna wait until it's just full like fully stable and then test on Trinity because the beta I feel like would give me like false confidence and stuff. So I'm gonna wait till that's done. There has also been a lot of awesome like proof of concept detection mechanisms being done by Manifestation and Ryan Cobb's Spectre Ops. So Manifestation came out with the Collect. Net Events PowerShell script that hooks into ETW, which is a basically a low level logging mechanism of Windows that's probably like the most high level way of describing it. And you can actually enumerate assemblies being loaded in real time by hooking etw. The problem with this is there really isn't a tool to do this at scale. So like for enterprise stuff, like it's not feasible to do this. So we have to wait until Microsoft implements optics into. NET in order for security EDR solutions to actually support detecting this kind of stuff. Crabs ETW is basically a C wrapper.
For ETW as the name implies. So potentially you could write a tool for your organization that does this in C. But yeah, that probably is going to take a decent amount of effort. There's also a really good talk by Luke Jenning on Blue Hat 18. Blue Hat 18 which talks about MESI to resonant implants and.
Talks about some of what I just described and some detection mechanisms as well. And I think he wrote a Python script that hooks into ETW as well. So there's that countercept which I think is an MWR company. I might be wrong. Quote me on that. Did a really cool blog post on hunting for Silent Trinity which actually has some of the detection mechanisms that I just told you. And also Ryan Cobbs big shout out to him because he put together the sharpsloid library which is what allows the mimikatz thing to run currently. And he put together a nice blog post which had some of these detection mechanism in there as well. So yeah, like right now all the detection mechanisms for this are very fragile because they're all based on like the class names, on the namespace names. They're really fragile detection mechanisms. There really isn't a good way of inspecting the actual code running and like to get a lot. So you have to rely on multiple IOCs in order to properly detect this kind of attack. So I hope that makes sense.
And future work really quickly because I think I'm pretty much over all the time that we had job control right now. There really isn't a way of like managing jobs in the agent. So that has to be done. I'd like to see C2 profiles. I know I can do it because from the way I designed it, I just have to take the time to do it. More modules and comms. I actually have a Pastebin C2 listener. Almost 70% done. I just have to hook it up client side. Restful API for automating things. If you're familiar with Death Star, I want to port that over to Silent Trinity so like you can just do the same thing that you did with Empire and Sound Trinity, which would be really cool. More languages. I like to see R and Ruby in here because why not give Ruby some love? Run modules and disposable app domains. That is my main focus right now. I'm 95% there. So loading, unloading those assemblies after a module executes is sort of a big deal because like that would get rid of the current detection mechanism of looking through.
The process.
After module executes and seeing all the evil assemblies. That's my main focus right now. Questions?
B
We got time for a few. Is MsBuild the exe that is communicating back and forth to the C2 server?
A
MsBuild X? Yeah, if you look at it through Process Explorer. Yes, yes, absolutely.
B
There was one here. Let's see. He hated you. There we go. He says he loves that he hates you right now I think. What about orgs that do ssl, mitm and run a sandbox on the line? Are you capable of encrypting the zip file and decrypting on pool?
A
Yeah, that's exactly what this new version does. The new version has fully encrypted communication between the server and the client. So if you inspect the wire, you'll only see just blobs of data being transferred back and forth via HTTPs.
You won't be able to see any of the actual stuff, like the actual stuff, because it's all encrypted using a public key exchange.
B
And then somebody wants to know what your Twitter handle is on, what your Twitter handles.
A
There it is. Okay.
B
See, and there was a lot of questions. I mean, the consensus from all the questions coming in is that this is amazing and really awesome and you're. You're blowing a lot of minds of, like, defense and defer guys and people, and they're trying to figure out how to do this. So any final words or thoughts for today's webcast?
A
I would probably say to the defensive guys that don't worry because we're going back to the cat and mouse game again because of the Amzi integration of. The. Net. The problem with that is it's in 4.8. Unless Microsoft forcibly updates all of the. NET framework versions on Windows 10 machines to 4.8, I'm going to probably guess it'll be a problem like having. NET 4.8.
You'd have to update your entire organization's NET framework version, which it can be done probably. I don't know. That's the only thing. But at the end of the day, we're going back to the cat and mouse game. So this is basically the era of when PowerShell offensive tradecraft were discovered. In a couple of years, this is going to be. This probably going to be shut down at least partially.
B
All right, so this was a Black Hills information security webcast. If you need penetration testing or threat hunting or red teaming, don't forget Black Hills. And then this will be available on our YouTube channel and we'll also put it on the blog. Marcelo, thank you so much for joining us today and thank you all for listening.
A
Thank you. Have a good day.
B
All right, bye, everybody.
A
Thanks for listening. Remember, if you enjoyed this podcast, to leave us a positive review on your streaming service.
La.
Podcast: Talkin' Bout [Infosec] News
Host: Black Hills Information Security
Episode: BHIS PODCAST: Endpoint Security Got You Down? No PowerShell? No Problem.
Guest: Marcello Salvati
Date: March 6, 2019
This episode, hosted by Black Hills Information Security and featuring red teamer Marcello Salvati, explores advanced endpoint security evasion techniques by leveraging lesser-known aspects of the .NET Framework. The focus is specifically on executing post-exploitation payloads without PowerShell—a critical red team tactic now that endpoint defenses often target PowerShell. Marcello introduces and demonstrates “BYOI” (Bring Your Own Interpreter) payloads, discusses how the Silent Trinity offensive tool operationalizes these ideas, and dives deep into detection challenges.
Assembly.Load() function allows loading a .NET assembly directly from a byte array, making reflective in-memory execution trivial—akin to built-in DLL injection (06:04-07:28).For Defenders:
This episode is both a wake-up call and a technical deep-dive into the next phase of post-exploitation. Traditional defensive tools, especially those focused on PowerShell, must expand to include deeper .NET framework visibility. Detection today is tricky and fragile. As Marcello underscores: we’re in for another round of red-team/blue-team escalation.
For Offenders/Red Teamers:
Marcello's approach provides a new, modular, scripting-friendly path for endpoint compromise—even on PowerShell-locked or EDR-heavy environments—and offers rapid flexibility for varied targets.
Final words:
"At the end of the day, we're going back to the cat and mouse game." – Marcello Salvati (53:25)
For more on this technique, tool, and ongoing research, visit Black Hills Information Security’s blog and YouTube, or follow Marcello on Twitter (handle mentioned at [52:31]).