This article is part of the series "Koadic Post-Exploitation Rootkit". Check out the rest:
One of the benefits of working with Koadic is that you too can try your hand at making enhancements. The Python environment with its nicely organized directory structures lends itself to being tweaked. And if you want to take the ultimate jump, you can add your own implants.
The way to think about Koadic is that it’s a C2 server that lets you deliver JavaScript malware implants to the target and then interact with them from the comfort of your console.
Get the Free Pen Testing Active Directory Environments EBook
Sure there’s a learning curve to understanding the way the code really ticks. But I can save you hours of research and frustration: each implant has two sides, a Python shell (found in the implant/modules directory) and the actual JavaScript (located in a parallel implant/data directory).
To add a new implant, you need to code up these two parts. And that’s all you need to know. Not quite. I’ll get into some more details below.
So what would be a useful implant to aim for?
Having already experienced the power of PowerView, the PowerShell pen-testing library for querying Active Directory, I decided to add an implant to list AD members for a given group. It seemed like something I can do over a few afternoons, provided I had enough caffeine.
Active Directory Group Members a la Koadic
As I’ve been saying in my various blog series, pen testers have to think and act like hackers in order to effectively probe defenses. A lot of post-exploitation work is learning about the IT landscape. As we saw with PowerView, enumerating users within groups is a very good first step in planning a lateral move.
If you’ve never coded the JavaScript to access Active Directory, you’ll find oodles of online examples on how to set up a connection to a data source using the ADODB object — for example this tutorial. The trickiest part is fine tuning the search criteria.
You can either use SQL-like statements, or else learn the more complex LDAP filter syntax. At this point, it’s probably best to look at the code I cobbled together to do an extended search of an AD group.
objConnection = new ActiveXObject("ADODB.Connection"); objConnection.Provider="ADsDSOObject"; objConnection.Open("Active Directory Provider"); objCommand = new ActiveXObject( "ADODB.Command"); Koadic.work.report("Gathering users ..."); strDom = "<LDAP://"+strDomain+">"; strFilter = "(&(objectCategory=person)(objectClass=user)(memberOf=cn=~GROUP~,cn=Users,"+strDomain+"))"; //Koadic replaces ~GROUP~ with info field strAttributes = "ADsPath"; strQuery = strDom + ";" + strFilter + ";" + strAttributes + ";Subtree"; objCommand.CommandText=strQuery; objRecordSet = objCommand.Execute(); objRecordSet.Movefirst; user_str=""; while(!(objRecordSet.EoF)) { user_str +=objRecordSet.Fields("ADsPath").value; user_str +="\n"; objRecordSet.MoveNext; } Koadic.work.report(user_str); Koadic.work.report("...Complete");
I wanted to enumerate the users found in all the underlying subgroups. For example, in searching Domain Admins, the query shouldn’t stop at the first level. The “Subtree” parameter above does the trick. I didn’t have the SQL smarts to work this out in a single “select” statement, so the LDAP filters were the way to go in my case.
I tested the JavaScript independently of Koadic, and it worked fine. Victory!
There’s a small point about how to return the results to the C2 console. Koadic solves this nicely through its own JS support functions. There’s a set of these that lets you collect output from the JavaScript and then deliver it over a special encrypted channel. You can see me doing that with the Koadic.work.report function, which I added to the original JavaScript code.
And this leads nicely to the Python code — technically the client part of the C2 server. For this, I copied and adjusted from an existing Koadic implant, which I’m calling enum_adusers. You can view a part of my implant below.
import core.implant import uuid class ADUsersJob(core.job.Job): def done(self): self.display() def display(self): if len(self.data.splitlines()) > 10: self.shell.print_plain("Lots of users! Only printing first 10 lines...") self.shell.print_plain("\n".join(self.data.splitlines()[:10])) save_file = "/tmp/loot."+self.session.ip+"."+uuid.uuid4().hex with open(save_file, "w") as f: f.write(self.data) self.shell.print_good("Saved loot list to "+save_file) else: self.shell.print_plain(self.data)
To display the output sent by the JavaScript side of the implant to the console, I use some of the Python support provided by Koadic’s shell class, in particular the print methods. Under the hood, Koadic is scooping up the data sent by the JavaScript code’s report function, and displaying it to the console.
By the way, Koadic conveniently allows you to reload modules on the fly without having to restart everything! I can tweak my code and use the “load” command in the Koadic console to activate the updates.
I went into detail about all this, partially to inspire you to roll your own implants. But also to make another point. The underlying techniques that Koadic relies on — rundll32 and mshta — have been known about by hackers for years. What Koadic does is make all this hacking wisdom available to pen testers in a very flexible and relatively simple programming environment.
Some Pen Testing Wisdom
Once you get comfortable with Koadic, you can devise your own implants, quickly test them, and get to the more important goal of pen testing — finding and exploring security weaknesses
Let’s say I’m really impressed by what Sean and Zach have wrought, and Koadic has certainly sped up my understanding of the whole testing process.
For example, a funny happened when I first went to try my enum_adusers implant. It failed with an error message reading something like this,“ Settings on this computer prohibit accessing a data source on another domain.”
I was a little surprised.
If you do some googling you’ll learn that Windows Internet security controls has a special setting to allow browser scripts to access data sources. And in my AWS testing environment, the Amazon overlords wisely made sure that this was disabled for my server instance, which, it should be noted, is certainly not a desktop environment. I turned it on just to get my implant to pull in AD users to work.
Why was the JavaScript I coded for the Koadic implant being treated as if it were a browser-based script, and therefore blocked from making the connection to Active Directory?
Well, because technically it is running in a browser! As I mentioned last time, the Koadic scripts are actually executed by mshta, which is Microsoft’s legacy product for letting you leverage HTML for internal business apps.
The real pen testing wisdom I gained is that if this particular script runs, it means that the remote data source security control is enabled, which is not a good thing, even and perhaps especially on a server.
Next time, I’ll be wrapping up this series, and talk about defending against the kinds of attacks that Koadic represents — stealthy script-based malware.
What should I do now?
Below are three ways you can continue your journey to reduce data risk at your company:
Schedule a demo with us to see Varonis in action. We'll personalize the session to your org's data security needs and answer any questions.
See a sample of our Data Risk Assessment and learn the risks that could be lingering in your environment. Varonis' DRA is completely free and offers a clear path to automated remediation.
Follow us on LinkedIn, YouTube, and X (Twitter) for bite-sized insights on all things data security, including DSPM, threat detection, AI security, and more.