DEF CON 29 - Ben Kurtz - Offensive Golang Bonanza: Writing Golang Malware

Aug 5, 2021 17:39 · 7633 words · 36 minute read

- Hello and welcome to Offensive Golang Bonanza.

00:07 - I’m Ben, hi, Defcon 29. We’re gonna talk about Golang malware.

00:14 - Little a bit about myself, my first Defcon talk was at Defcon 13.

00:19 - I’m the host of a hacker-themed podcast where we interview a lot of people around this community.

00:24 - Very in-depth, very technical. Please check that out and I have a bunch of random projects on GitHub.

00:33 - So what this talk is gonna be, there’s two ways to consume it.

00:35 - One, you can just listen to me describe a whole bunch of Golang malware components and you’ll get a sense of what’s out there, what’s available, what’s possible.

00:44 - And if you wanna go in-depth, there are links on all of the slides to the actual code repos themself, code samples, interviews, news articles, all kinds of stuff.

01:00 - So to start with, I’m gonna do a little bit of back story on my hacker crew and a little bit on Golang and why it’s so interesting to malware developers.

01:11 - And then we’ll start going through various components and tools.

01:16 - So in the beginning, I was interested in anti-censorship surrounding a particular Iranian election.

01:23 - I was taking a look at the Tor’s obfuscation proxy, obfsproxy2 at the time, and I thought I could do better.

01:32 - And so I started the Ratnet project which is a pretty cool NIDS evasion thing we’re gonna talk about later and I was using that project as an excuse to learn Golang.

01:43 - And what I learned is that Golang is magic.

01:46 - Unlike any programming language I’ve used before, just anything you need, anything you would normally have to install as a separate library or utility, it’s just there for you.

01:57 - Everything from crypto, networking libraries, virtual file systems are supported natively which is totally unique.

02:06 - The compiler cross-compiles easily to every other architecture and operating system.

02:12 - There’s built-in test frameworks, vendored in frameworks, it’s garbage collected, it has a very efficient thread implementation and it has its own assembler.

02:23 - And the third party library support is totally unparalleled, so Rust is years away just to answer the question of why don’t I rewrite everything in Rust? But the main reason that I love Go is that it is the fastest way to be done and my goal is not to reinvent every wheel.

02:43 - My goal is when I start a project is to be done with the project and use the project.

02:48 - And the fastest way to learn Go, the way I learned, is a document called Effective Go on the Golang website which assumes that you already know how to program and just tells you what’s different about Go.

03:00 - I highly recommend that to anyone who wants to learn Go especially if you already know how to program.

03:06 - So a few relevant facts about Go. It is not interpreted.

03:09 - I’m not sure why people seem to get that misconception.

03:12 - It is statically compiled. However, it also, every Go binary includes a kind of monolithic runtime which is like 800K on most operating systems.

03:27 - So it’s a bit of overhead per binary. And then all of your code is statically compiled on top of that, all of the dependencies and everything that aren’t already in the runtime.

03:38 - The embedded assembly language is based on Plan9’s assembly language, so it’s a little bit crazy.

03:44 - We don’t have time to go into it, but I did a write-up that will kind of help you cope.

03:50 - It’s linked on this slide. I recommend checking that out.

03:55 - So to get into the story, so Stuxnet happened, and everyone got very hot on environmental keying.

04:01 - I environmentally keyed payloads. Josh Pitts made a tool in Golang to do environmentally keyed payloads called Ebowla.

04:10 - They got very popular with the red teamers at the time.

04:12 - And so all of the EDRs and AV companies wanted to write sigs for Ebowla, but they had never seen a Golang hacker tool before.

04:22 - And so they all ended up writing signatures for the Golang runtime which is included in every Golang process.

04:29 - So what happened next is that all of the AV utilities triggered on every Go binary including the installer, but it also included the very prevalent orchestration tools, Docker and Terraform.

04:43 - And so as a result, they all had to pull those sigs very quickly, because people need their Terraform.

04:52 - And this is a pattern that malware developers look for.

04:56 - We call the jar2exe pattern where basically if you have anything that makes a native binary for you, but it has one legitimate user that means the AV companies need to whitelist it and they have trouble creating sigs for like Java inside a jar2exe binary.

05:16 - They have trouble creating sigs for Python inside a py2exe binary if those are whitelisted.

05:21 - And similarly, they have trouble creating sigs for Go code which is statically compiled past the Go runtime.

05:30 - So realizing that and also I had this sweet exfiltration library I had been working on called Ratnet, I started talking to other security people that were interested in Go and we got together, shared ideas, things escalated very quickly, and we, you know, this has happened in the past with Python.

05:53 - Now it’s happening with Go. And we made a bit of a community, probably the best example of this is there’s a particular Slack server where #golang, the Slack channel, has like literally, it’s like the best place on the Internet.

06:15 - It has like all the people working in Golang malware basically hang out there.

06:21 - They share ideas, they’re really nice to each other.

06:23 - There’s no kind of like political or weird other Internet nonsense.

06:27 - It’s just people helping each other with projects, suggesting project ideas, and it’s just amazing.

06:34 - So we’re gonna talk about tools from a lot of people in this chatroom.

06:39 - I boldfaced the ones that are specifically mentioned in this deck, but everybody in there, just thank you, it’s been totally critical for my sanity especially over the last year.

06:52 - And I especially wanna thank the community organizer, jeffmcjunkin for keeping most of the crazy out.

07:02 - So just a quick word about offense and defense, all of these tools are open source.

07:07 - We post the code, we hope that the people who work on operating system and defenses and defensive tools will study these and learn how they can improve some of the problems especially the bypass tools exploit have been around for 10, 20, and in some cases 30 years.

07:30 - So having, it’s not 0-day, it’s just like, things have been broken for a long time.

07:39 - You can’t just bury your hand in the sand. So we’re trying to make things better by helping people understand how things actually work.

07:50 - And on that note, I’m gonna talk briefly about what tools exist for reversing Go binaries.

07:56 - There aren’t a lot that are useful. Even now, the most useful one is probably the Go Reversing Toolkit.

08:02 - They have a tool called Redress which is fairly successful at extracting metadata from stripped Go binaries including dependencies and compiler versions.

08:12 - And then there’s a few IDA scripts and blog posts linked on this slide which give you some clues as to how to go about reversing a Go binary, but it’s still pretty primitive.

08:24 - And I think a lot of the trouble is that the static compilation aspect, if you ever try to open up an embedded C program that’s statically compiled in IDA, you end up having to sort of manually work out what a lot of the functions do.

08:37 - There are kind of flare signatures, but I haven’t seen that for Golang yet.

08:46 - So some of the core components for the rest of the tools we’re gonna talk about.

08:50 - The first one, the one that gets used by almost everything is our fork of Go standard debug library.

08:58 - So Go comes with a library called debug. It parses all binary formats PE, for Windows Elf, Linux, and Mach-O for OSX.

09:09 - We forked that, fixed a bunch of bugs, and added support for editing the file, changing things by their fields, and then writing the file back out once you’ve changed it.

09:25 - So we turned it into an arbitrary binary modification framework and we also made it parse files that are already loaded into memory.

09:33 - And also you can write them back out to memory, but you need a tool we’re gonna talk about later.

09:41 - But this is especially cool, because you can parse your own process which lets you do a lot of neat malware tricks, as we’ll see, and you can also inject shellcode into a file on disk which is also pretty handy.

09:59 - So the parser entry points for PE, Elf, and Mach-O are always either new file or new file from memory.

10:07 - The generator entry points are always called bytes in case you’re looking at the code.

10:12 - Also some of the stuff we added, we added base relocations and relocations.

10:17 - We added imported address table fix-ups, the ability to add sections, the ability to hook entry points, and the ability to access and add signatures which comes up in a lot of the malware tools we’re using, but this might be useful for other things as well.

10:35 - Another core component is cppgo. We got this from Loren Segal.

10:40 - We just forked and added support for the Apple M1 for ARM 64.

10:45 - Basically this is a way from Go to make native calls into any other library using any ABI, any calling convention.

10:55 - So it comes with standard call, cdecl, and thiscall.

10:59 - And so this is absolutely critical for a lot of malware functionality from Go.

11:05 - I highly recommend you check it out. It’s a great example of Go assembler.

11:11 - Moving on to the exploitation tools category.

11:15 - Our first exploitation tool is called binjection and this uses the Binject debug binary modification platform and adds a layer on top of it which implements a variety of different algorithms for inserting shellcode into a binary, predominately hooking the entry point, but it wouldn’t necessarily have to be.

11:37 - So there’s a command line utility. You can also use it as a library.

11:41 - And so it’s very extensible and we’ve implemented a variety of algorithms including for PE, the one we use the most often these days is just adding a new section.

11:54 - You hook the entry point to point to the new section.

11:56 - At the end of the new section, you have it point back to the original entry point.

12:01 - So basically file starts, runs your shellcode in the new section, jumps back to the original entry point.

12:08 - Modern PEs don’t have a lot of code cave space anymore.

12:12 - I guess there have been compiler improvements, so this is the most successful method for PE we found.

12:17 - For ELF, we have a variety of different methods.

12:19 - We’re probably gonna add more. We have Silvio Cesare’s original padding infection method which we updated a little bit, so it supports position independent executables, and we also, sblip from the channel also implemented a completely new injection method based on PT_NOTE which is in there and we also have ctors or constructor hooking for shared libraries.

12:46 - So not only can you hook an executable, you can also inject shellcode into a shared library and have that run when the library loads.

12:54 - For Mach-O, we’re predominately hooking the entry point and using the one giant code cave which is in all Mach-O binaries before that first load segment.

13:05 - I’m not sure why that is always the case, but there’s always one giant code cave you can fit a bunch of shellcode in, I don’t know.

13:15 - Just a quick example of what the code looks like.

13:17 - This is the whole Silvio method from binjection.

13:23 - There are no, there’s no weird offsets, there’s no hex math.

13:27 - You can just read it and it’s referring to the actual fields in the file format and that’s coming from binjectdebug.

13:35 - And this is the right layer of abstraction that you wanna code injection algorithms in and that’s kind of the whole point, so it’s easy to understand the algorithm.

13:45 - Just by reading the code, it’s easy to add new algorithms.

13:49 - Now what kind of kicked off the binjectdebug and binjection project was the desire to make the old tool from Josh Pitts’s backdoorfactory work again.

13:58 - So backdoorfactory stopped working and we were like, “Hey, let’s just rewrite this whole thing in Go. ” We broke it into modules and we ended up with binjectdebug binjection.

14:05 - And finally, we needed to close the loop with backdoorfactory.

14:09 - So backdoorfactory is the thing, man in the middle, someone’s who’s trying to download a binary, it injects shellcode into the binary automatically.

14:16 - It was beautiful, red teamers loved it, got to use it all the time, and then it stopped working, and we were all very sad.

14:22 - Backdoorfactory originally worked with a tool called Ettercap which is terrible and old.

14:28 - I mean it worked at the time, but it was into curses, and there’s a better Go rewrite called bettercap which adds support for more man in the middle methods.

14:39 - And so we decided to use bettercap for the rewrite.

14:44 - And then we already had binjection. So basically, bettercap has a scripting language called caplet scripts and they already had implemented a script for bettercap called download-autopwn which intercepts web downloads and replaces them with a malicious payload.

15:03 - So it doesn’t inject it into a file, it just replaces it entirely, but we just started from that.

15:10 - And then in the caplet language only, it exposes read file and write file commands.

15:14 - It’s the only way you can interact with anything outside of JavaScript.

15:17 - And so, we figure we’ll just make a named pipe server and use read file and write file to pass the file being man in the middled out to binjection, inject your shellcode, and then use a read file to read it back in through another pipe, back into the caplet, and return it to the user.

15:38 - So that looks like this. So you can use bettercap to man in the middle someone’s download using ARP spoofing, DNS poisoning, DHCPv6 or anything else bettercap supports.

15:49 - Their download request comes to you, you go out to the server they were originally trying to access, and download the file they were trying to get.

15:56 - And then you pass that file through the new pipe server, the new backdoorfactory to binjection where shellcode gets injected into the executables.

16:05 - And then the whole thing gets repackaged and passed back to the user and they think it was the file they were trying to download.

16:12 - Open it, run it, run your shellcode. That’s the general idea.

16:15 - So our implementation of backdoorfactory lives in Binject.

16:20 - Basically what it does, it starts up this pipe server, it spits out the caplet and bettercap config files that you need and it tells you exactly what bettercap command to run which is just mainly ‘cause I kept forgetting how to use bettercap.

16:36 - You may need to customize that caplet file in the bettercap config.

16:40 - You’ll have to customize the caplet if you want to support different user agents.

16:46 - If you only wanna trigger on certain user agents, you can do that by regular expression or if you only wanna trigger on certain file extensions, you can also edit that in the caplet.

16:55 - Also by default, it will do ARP spoofing that might be too loud.

17:00 - If you wanna do DNS poisoning, you’ll have to edit the default bettercap config that comes out of there.

17:08 - So some features that we added, we added support for unpacking archives.

17:11 - So it’ll actually, if someone’s trying to download a TGZ or a ZIP file, it will unzip that on the fly, inject all of the binaries inside it, then re-zip it and pass it back to the user.

17:22 - We’re also working on adding support for re-signing the binary with a stolen or purchased key and we’ll work on that in a sec.

17:32 - And we also ported this to Wifi Pineapple, because back in the day, running backdoorfactory on a malicious access point was super fun and Golang supports easy cross-compilation to MIPS32.

17:45 - So there are links to the bettercap and backdoorfactory packages we made on this slide.

17:51 - So quick demo. So on the right, we’re downloading a file wget and unzipping it, running it, and it says I’m a simple program, blah, blah, blah.

18:08 - Now in the upper left, we’re starting the pipe server which opens up some named pipes to binjection and it gave us, generated some bettercap configs, gives us the command to run bettercap in another window.

18:20 - We run bettercap and it starts the ARP spoof and intercepting files using our caplet.

18:32 - So we go and download the same file we just downloaded again.

18:40 - You can see the size’s a little bit different.

18:44 - Unzip that, run the binary inside, and you can see it printed test in addition to the original output.

18:54 - That is a shellcode we made that we use as a test shellcode which prints test, so that’s proof that our shellcode has been injected and also the original program still ran.

19:06 - So that’s the new backdoorfactory. So because the files are being passed in by a pipe, we actually don’t, we lose the extension of the file on the way in.

19:16 - We don’t get that through the pipe, so we’re actually using MIME.

19:20 - So we’re using a Go library to determine the MIME type and then we have the switch statement based on the MIME type on what injection to do like that’s how we figure out what file it is.

19:30 - So if you wanna extend it, you can just extend it by MIME type which is actually pretty awesome.

19:35 - There’s different MIME types for like jars than zips which is pretty cool, ‘cause some programs will tell you they’re the same format.

19:43 - And the main call to binjection looks like this inside backdoorfactory, it’s injective binary.

19:50 - It does a quick check of the magic number to see if it’s a Mach-O, ELF, or PE.

19:56 - And then it calls, it pulls the appropriate shellcode and then calls Binject near the bottom there to inject the appropriate shellcode into the binary.

20:11 - So signing from Golang is also very well-supported.

20:16 - The two main libraries I’d recommend that you check out, one is called Limelighter which, it does authenticode signing of EXEs and DLLs.

20:26 - You can either use a real cert or it’ll make one up for you which is also kind of handy for EDR evasion.

20:33 - Another one that’s a little bit heavier, but signs everything is Relic and Relic not only does the authenticode signing stuff, it also supports like CentOS RPMs, Debian DEB files, Java JAR files, Silverlight XAP files which is pretty handy if you can still find some Silverlight.

20:54 - PowerScript, Android APKs, and Mach-Os, and DMGs for Macs.

21:00 - So there’s a lot of possibilities for extending backdoorfactory to new and interesting file formats.

21:08 - So moving onto a different exploitation tool.

21:11 - From C-Sto, we have goWMIExec which actually brings the ability to just do remote WMI, Windows Management Interface calls to Go which lets you just run random shell commands on some target Windows machine out in space.

21:27 - There’s also another library that gives you full SMB support, go-smb2.

21:33 - And so if you put those two together, you can replicate in packets smbexec functionality, so you can upload a file with go-smb to a target and then you can execute it with goWMIExec.

21:48 - So you can put this in your implant and have it like auto-spread, or you can use it as an initial inject assuming you have creds for a Windows box.

21:57 - And so in code, it’s kind of just as easy as this.

22:03 - I couldn’t fit all of the file upload stuff in there, but you can see the WMI call.

22:10 - Basically, you just, you pass a username, password, or you can use a hash if you have it, ‘cause C-Sto is magic and like the domain and the client name and stuff, you can either randomize those or they’re optional.

22:24 - So it’s pretty easy to use. And for a full example of smbexec in Go including the file upload stuff, check out the source code bundle on the Defcon media server for my Defcon 29 Workshop: Writing Golang Malware and there’s a lot more detail in the workshop slides.

22:47 - So some other exploitation tools, don’t have time to go into, but gophish is a very popular phishing toolkit.

22:54 - Gobuster is good for brute-forcing sub-domains.

22:58 - There’s a little DNS server you can use for XXEs.

23:02 - It’s also good for DNS blackholing which is good for Android reversing.

23:06 - And there’s also modlishka which is a phishing reverse proxy which has some novel 2FA bypass stuff in it.

23:14 - So those are all Go repos you should check out or use as a reference.

23:20 - Moving onto EDR and NIDS evasion tools. The most important one is garble.

23:25 - This is the state of the art Golang obfuscator.

23:28 - It does not do control obfuscation unfortunately, but hopefully that’s coming.

23:34 - But it will strip out almost all Go metadata and with the optional dash literals command, it will replace string literals with lambdas which is very important for avoiding sigs.

23:47 - And gobfuscate was a bit broken. It was slow, it didn’t work with Go modules, it had trouble with dependencies.

23:57 - Garble fixes all of that, it’s actually remarkably fast, it’s incredibly easy to use, and I haven’t seen it choke on anything at all yet which is amazing, so there’s really no reason not to use garble on everything as far as I know.

24:14 - And definitely try that Redress tool. Try Redress on something before you garble it and then try it after you garble it and see what happens.

24:23 - That’s probably a good time. So in terms of NIDS evasion, there’s a lot of kind of network code out there.

24:33 - My own project is Ratnet. It works, it has a couple of unique features.

24:39 - It works on store and forward, so it actually is not stream-based.

24:42 - It bundles messages up into batches and each message is individually and end-encrypted, but the batches are also encrypted separately for every hop.

24:52 - It works on mesh routing, so every Ratnet node acts as a router.

24:57 - And it also supports pluggable transports. You can have different transports between hops.

25:02 - You can also support multiple transports at once and you can dynamically change between transports.

25:08 - So the transports that we ship with, we have UDP, TLS, HTTPS which is like cloud-fronting, and we also have DNS, and AWS S3 as a transport which is pretty neat.

25:22 - And this also works without the Internet as just a mesh routing middleware and I’m working on a handheld Ratnet-based hardware device which will come out as a crowd supply next year, so watch this space for that.

25:35 - So a couple of use cases that we support with Ratnet.

25:39 - One is, say you’ve hit a bunch of machines with an implant and you, not all of them have direct Internet access and you want pivot, you want to be able to talk to all of the implants from your C2.

25:55 - So what you can do is you can make an implant where the implants find each other using mDNS or multicast.

26:03 - And if they can’t get to the Internet directly, they will just automatically route all of their messages out through one of their peers.

26:13 - And if any one of those peers can find their way out to the Internet to the C2, you can actually, it’ll just automatically make a network and you can talk to all of the implants, because the implants in the middle will automatically act as a router, ‘cause that’s how Ratnet works.

26:28 - So there’s actually a demo of this working also in the workshop source code.

26:33 - The other use case that we wanna support is if you drop an implant into an egress proxy data center.

26:40 - So if all web traffic or like almost all traffic is blocked out to the open Internet from where you are, you can still usually get out with DNS, because the local DNS server will hopefully pass look-ups out through recursion.

26:55 - So that’s why the, that’s what the DNS transport is for.

26:59 - You also might find yourself in a situation where lots of things are blocked, but some things are whitelisted, and in those situations, typically AWS is whitelisted, because almost everything is using AWS at least a little bit.

27:13 - So there’s a lot of other Ratnet, sorry, there’s a lot of other Golang tunnels and proxies to look at other than Ratnet.

27:20 - So some of the popular ones are Chashell and Chisel which got used together in a ransomware attack very recently.

27:26 - There’s a link in this to a very interesting breakdown of some ransomware that used those two.

27:33 - And there’s also Wireguard as a distributed VPN which is actually commercial product which is implemented in Go and very worth checking out.

27:42 - It’s a lot easier to set up than OpenVPN just in general.

27:45 - And so there’s a lot of other tunnel and proxy code in Go, because Go is typically very stable.

27:54 - Probably more resulted the built-in testing framework than anything else, but there’s a lot of good network stuff in Go.

28:01 - Moving on to another EDR evasion tool. There’s pandorasbox, so I mentioned that Golang has native support for a virtual file system.

28:11 - That means that anytime in Go you’re referring to a file, you can totally control the file abstraction.

28:18 - It doesn’t really have to go to the file system.

28:21 - You can make a, for example, an encrypted in-memory virtual file system and use it exactly the same way from your Go code that you talk to normal files and that is what pandorasbox does.

28:32 - It basically is a shim between the MemGuard library which tries as hard as it possibly can to give you a secure enclave in memory to protect what you’re putting in a MemGuarded region from tools like Volatility or other analysis tools.

28:48 - And so basically pandorasbox is the bridge between the Golang file abstraction and MemGuard, but it gives you an encrypted VFS very, very easily.

29:03 - Definitely worth checking out. So this is another one of my tools, I call it the Universal Loader.

29:13 - I implemented reflective DLL loading in Golang for all platforms including the Apple M1, so it actually works with ARM 64.

29:24 - This might be the first loader I’ve seen anywhere that actually supports the M1.

29:30 - Although other than that, it’s doing a lot of sort of traditional reflective DLL loading stuff.

29:35 - So reflective DLL loading basically mimics the behavior of the system loader when it loads a dynamic library into a process.

29:42 - It just does all the things the system loader does as best it can, so it loads the library into the process, lets you call functions that were in the library, but doing it reflectively means that you never need to touch disk which is the main advantage.

29:55 - If you never touch disk, maybe a V never triggers.

30:00 - Duh-duh-duh, so… the back ends for the Universal Loader for Windows, OSX, and Linux are a little bit different.

30:13 - The Windows method does not use the system loader.

30:15 - It does use some Go assembly to walk the PEB and figure out, and then it uses binjectdebug to like parse the process you’re in and like figure out the imports and exports of everything.

30:31 - And there is a branch of the Universal Loader that actually does the import address table fix-ups.

30:35 - It’s called import address table. And so if you are loading a library that depends on other libraries, you will definitely need to use the IAT branch.

30:49 - The OSX method actually does use the system loader.

30:54 - We followed a training from MalwareUnicorn which I highly recommend checking out on writing OSX malware and it actually finds where the dynamic loader library is in memory and then parses it with Binject, finds a couple of key functions in there that for some reason OSX is the only operating system that has a built-in part of the operating system that lets you load a library from RAM.

31:21 - Both Windows and Linux require a file somewhere, but OSX does not, so we just use that, “Oh, load a library from RAM” method and Bob’s your uncle, so that’s kind of why we’re using the system loader for OSX and no one else.

31:36 - And then the Linux method does not use the system loader either, but it also does not use memfd.

31:42 - It really does a reflective library load for Linux.

31:46 - Memfd is a Linux RAM disk and the previous loaders for Golang just dumped your library to memfd and then just loaded it with dlopen.

31:59 - We do not do that, although it is easy and it works.

32:03 - Use of memfd is unusual and it’s easy to detect.

32:06 - So doing an actual reflective library load is a bit stealthier and that’s what we’re doing.

32:16 - So this is what it looks like in code. The interface, as I said in code, is the same for all operating systems.

32:21 - Basically, you got your library loaded in a buffer.

32:24 - You make a new loader with new loader, you call loader. LoadLibrary.

32:28 - That’s the universal, loading your buffer as a library, and that will under the hood work differently for whatever operating system you compile it for, but the interface remains the same.

32:40 - And then you can just call exported functions in it with that library. call.

32:46 - In this example, we’re calling the function called the runme, we’re passing it the argument seven.

32:50 - So this is just a super simple example, but it’s gonna be exactly like this for every operating system.

32:54 - The only thing that’ll change is the library that you actually load.

32:58 - So a couple of notes. Because you’re not using the system loader, the libraries that you’re dependent on will not automatically be loaded for you.

33:07 - So for Windows, you have to use the IAT branch as I said.

33:10 - But then every library that you depend on, you have to call syscall. MustLoadDLL for that library to make sure that it’s already loaded and present for you before you use Universal, but it’ll automatically work it out from there.

33:24 - And for Linux, I would just recommend that you statically compile the libraries you need to load with Universal, ‘cause you can do that for Linux.

33:32 - It doesn’t really work for Windows, but if you just statically compile a library like it’ll just work fine and it’s easy.

33:39 - All right, moving on to our next tool is Donut.

33:42 - Donut is amazing, it is a payload creation framework that lets you convert any executable, DLL,. NET assembly, or VBS to an encrypted injectable shellcode.

33:55 - And then it is also the assembly loader that decrypts and loads those payloads into a process.

34:02 - It is very configurable. Definitely check it out.

34:05 - One of its cool features is that it supports remote loads, so you can actually configure the loader to pull down the rest of the payload from a web server instead of having to bundle it in which is pretty sick.

34:21 - And so I ported the utility that converts things to Donut payloads to Go, so that you can use it from an implant or from a C2.

34:33 - And you might be wondering why would you wanna do this.

34:36 - We’ll see an example in a minute. Turns out to be a surprisingly handy thing to do and because it’s Pure Go, you can now do this from any operating system.

34:44 - So most people’s C2s are on Linux, not Windows, so that comes in handy.

34:49 - So a note, you could use both Universal or Donut as a module system for your implants.

34:55 - A note on why you might wanna do one or the other.

34:59 - So basically, Donuts, you can make run in a process all by themself.

35:06 - Universal will try and load a library in your current process.

35:09 - There are a few situations that will break Universal, because there are things that don’t like running not on the main thread.

35:16 - For example, mimikatz starts up some COM hosting stuff that doesn’t work right if it’s not on the main thread.

35:23 - So I don’t think it’s ever gonna work right in Universal which means, but it works fine through Donut as we’ll see.

35:31 - And there’s also a Go scheduler bug that’s linked and so you can often run into problems if you try and load two Go runtimes in the same thread.

35:41 - So if you’re loading another Go program with Universal, you might be better off with Donut instead just to avoid, a load is possible.

35:51 - It is easier to avoid having two runtimes in one process and so you can just use Donut instead of Universal in that situation.

36:03 - There’s another payload creation framework called Scarecrow which is very popular and definitely worth checking out.

36:09 - It does some kind of funny stuff. It signs its loader using Limelighter as we mentioned before even if you don’t give it a cert, it’ll just sign it anyway as a way of reducing EDR signal.

36:21 - And its kind of unique and most badass feature is that it implements, it disables the Windows Event Toolkit which a lot of EDRs rely on by unhooking itself in memory from EDR, or sorry, from ETW which is super cool and worth checking out.

36:40 - And this is open source too, so that’s like code worth stealing or just use Scarecrow.

36:46 - A lot of people do. So now, bananaphone I almost put in the core components category.

36:54 - It is so cool, and so important, and so awesome for EDR evasion.

36:59 - It is an implementation of Hell’s Gate or direct system calls in Go.

37:05 - There’s a link to the original paper here, but basically what that means, there are stubs in NTDLL that everything is in Windows compiled to use that then in turn calls system calls.

37:17 - But those stubs in NTDLL are commonly hooked or monitored by EDR.

37:23 - And so you can just parse NTDLL, ‘cause it’s already loaded in your process, I guarantee.

37:30 - So you can look at your run process memory, look at NTDLL, figure out where those direct system calls go, set up a call frame yourself, and just call them directly and not bother going through NTDLL thus avoiding hooks.

37:42 - That’s what Hell’s Gate is. So bananaphone is a completely transparent implementation of Hell’s Gate, it’s very easy to port existing Go code that uses syscall to bananaphone, because C-Sto was kind enough to make a version of the mkwinsyscall utility that converts headers to Go stubs.

38:04 - He made a version of that called make direct win syscall which converts headers to Hell’s Gate-d Go stubs and it works exactly the same way as syscall, so it’s just mad easy to convert syscall code over.

38:16 - Highly recommend doing that. It also has a unique improvement over traditional Hell’s Gate found kind of by accident, but there’s auto mode will actually detect when your in-memory NTDLL has been hooked by EDR and automatically fall back to reloading a fresh copy of NTDLL from disk instead of the hooked version, the one on disk will not be hooked and you can parse the one on disk to figure out where the, to make the direct syscall to and it works just as well.

38:46 - And although this creates theoretically more signal, because loading another copy of NTDLL is sketchy, in practice, this actually works pretty well.

38:57 - It works on one of the more popular EDRs without triggering anything.

39:02 - So that’s kind of neat. There’s also an implementation of Heaven’s Gate in Go called gopherheaven and this is another EDR evasion technique where you call 64-bit code from 32-bit code, ‘cause nobody is expecting 32-bit code, boy.

39:21 - And so this is pretty slick. And this also has a really great example of 32-bit 386 Go assembly in case you need that for some reason.

39:32 - This is one of the few examples that works.

39:38 - All right, so we’ve gone over a bunch of EDR evasion and NIDS evasion tools.

39:43 - Let’s go on to post-exploitation which is super fun, ‘cause it’s the loot.

39:48 - So go-mimikatz, basically this combines go-donut and bananaphone.

39:53 - It downloads mimikatz to memory, makes it into a donut payload, injects it into itself, into its own process of bananaphone system calls and it lets you run mimikatz on systems where you really shouldn’t be able to.

40:05 - The whole program is 150 lines of code. This is the best example of bananaphone and go-donut.

40:10 - There’s the go-donut bit up top and the bananaphone bit down bottom.

40:14 - I couldn’t fit 150 lines in a slide, but you can pull it up on a browser.

40:18 - I made a quick demo. I cross-compiled go-mimikatz to Windows AMD 64.

40:24 - That’s all you have to do to cross-compile it in Go by the way, super easy.

40:27 - I copied it to an SMB share with the name gm. exe.

40:30 - I did not garble it and I set up a Win10 Edge, let it update, Defender’s enabled, I’m running from SMB, and I get the little like proof strings up.

40:43 - And then I just run it and bam, mimikatz runs, nothing flags, and I can interact with it which is just crazy.

40:50 - So that’s current mimikatz, current Win10 Edge.

40:54 - You will get caught by behavioral stuff once you start doing stuff in mimikatz, so you will have to do some other trickery to avoid the behavioral detections.

41:03 - There’s another utility worth checking out from vyrus called msflib which makes your implants work with Metasploit.

41:09 - It has all of the like Metasploit URL generation magic.

41:13 - It also uses bananaphone. It also has code to run a payload in the current process or inject a payload into a remote process.

41:20 - Very cool, very worth checking out. Writing a Windows service in Go can be a little bit of a pain in the ass.

41:25 - There’s an example link there, but capnspacehook has made the taskmaster utility that a lot of people used to interact with the Windows Task Scheduler as a method of persistence to avoid having to create a Windows service.

41:39 - You can just schedule a task to run your thing periodically.

41:42 - Definitely check that out. Gscript is a whole other talk.

41:46 - There was a Defcon 26 talk on it. It uses an embedded JavaScript interpreter to make a scripting language for droppers.

41:53 - There’s like a thousand sample gscripts in ahhh’s gscript repo that do things like disable AV, EDR, firewalls, you can make registry changes, you can set up persistence, you can do all kinds of things.

42:06 - So definitely check out gscript, it’s a completely other hour long talk.

42:13 - Another tool from C-Sto for DIT dumping. This is another thing that Impacket does, but Impacket in Python is very slow.

42:19 - It takes hours to dump a DIT. C-Sto’s tool can do it in minutes.

42:24 - Definitely check that out if you wanna dump hashes from a DIT.

42:28 - And the old Lazagne tool that steals browser passwords, mail passwords, all kinds of passwords.

42:33 - It’s been ported to Go, goLazagne. However, it does require CGO which means you need to set up an external C compiler.

42:40 - However, the only reason it needs CGO is because of the dependency on SQLite, because the browser password databases are SQLite databases, but there is now a Pure Go implementation of SQLite which I’ve linked, so someone some day will modify goLazagne to no longer require CGO and that would be lovely, thank you.

43:02 - There’s a few other post-exploitation tools you should check out including sudophisher which is hilarious from audibleblink that actually is an ASKPASS replacement that will log the sudo password, so it’s just like a funny thing to do.

43:16 - And also rclone is just utility to loot things from cloud storage.

43:21 - So those may come in handy. And then we have a couple of complete C2 frameworks entirely implemented in Go.

43:28 - The heavy hitter in this space is sliver which is an open-source alternative to Cobalt Strike.

43:32 - It’s coming along, it’s under active development.

43:35 - It’s designed to be used by a team, so the C2 is multi-user, multi-operator which is pretty awesome.

43:42 - It has a huge list of features. It has an implant build in obfuscate framework.

43:47 - There’s so much in there. I don’t have time to go into, definitely check out the wiki on their GitHub for instructions on how to set it up and check out the dev branches, because they have a lot of really cool stuff cooking.

44:00 - And peer pressure them into doing their own Defcon talk at some point. (laughs) Another C2 framework definitely worth mentioning is merlin.

44:11 - The only downside of merlin is that it’s single operator, but it has some unique features that are not really in anything else.

44:18 - It supports a ton of injection methods, but the one that sticks out is that it has an implementation in Go of QueueUserAPC.

44:26 - Definitely worth checking that out. It also has integration with Donut and another common loader which is sRDI.

44:33 - And it does support many C2 protocols also like sliver, but it has QUIC support which is pretty cool.

44:42 - So that’s my time, thank you very much. As a reminder, I do host a podcast called “Hack the Planet” and there are a few interviews we’ve done on “Hack the Planet” relevant to this talk.

44:52 - We have an interview with Josh Pitts which is phenomenal, the author of Ebowla and the original backdoorfactory.

44:59 - And we have another episode entirely on Golang malware featuring C-Sto and capnspacehook, the authors of some of the utilities I mentioned earlier.

45:09 - So thank you very much, bye, Defcon 29. And I hope I gave you some ideas for writing Golang malware, or even improving detections, or reversing for Golang malware, thank you. .