A few weeks ago right after DerbyCon (which I wasn’t able to attend), I heard about a new post-exploitation tool called SILENTTRINITY by byt3bl33d3r, a tool developer with a l33t name with some pretty l33t tools (…I’ll stop now) such as CrackMapExec and DeathStar. This project is unique in that it utilizes Python, IronPython, and C#/.NET in order to perform post-exploitation activities similar to other frameworks such as Empire. The benefits of using a C#/.NET approach is that it’s harder to detect than PowerShell, and SILENTTRINITY puts a spin on its approach that’s appealing to any Python enthusiast in the security world.
I heard of IronPython before but never really had the time to get into it. A few days ago, I figured now was a good time as any to help contribute to this new project by developing some basic enumeration modules. The goal of writing these modules was to completely recreate their Windows binary counterparts using just .NET assemblies, and as little of the Python standard library as possible. Between the Microsoft .NET framework documentation and some patience, I was able to create two modules: ipconfig and systeminfo (similar to Meterpreter).
Developing systeminfo
If you’re interested in creating a module for SILENTTRINITY, you can follow the steps outlined by David Tavarez here. However, instead of PyCharm, I opted to use VSCode because I really enjoy the lightweight feel and the customized options it offers.
For the sake of learning, I decided to start with something simple to navigate my way around the .NET framework. I ultimately decided that systeminfo would be my first module, as it’s one of the first commands that would be run against most Meterpreter sessions.
This was a very simple script to write and learn from. There was a slight issue, however. I was testing this module against Windows 10 and according to the documentation for System.Environment.OSVersion:
Starting with Windows 8, the OSVersion property returns the same major and minor version numbers for all Windows platforms. Therefore, we do not recommend that you retrieve the value of this property to determine the operating system version.
This presented an inconvenience as the property could not be properly used to enumerate the version of Windows nor its build version. Instead, I opted to use the kernel32.dll product version to provide an accurate way of determining the OS Version and Build. I didn’t check but I think that the majority of system DLLs could be used to find the same information (user32.dll, advapi.dll, etc).
Lessons learned
Trying to avoid using Python modules that I’m used to has led to a better understanding of the .NET Framework from an IronPython perspective. For example, in the ipconfig module, I didn’t use the ipaddress library but instead decided to learn how the System.Net.IPAddress class worked. Additionally, I started to learn to some of the limitations of the .NET Framework when it comes to interacting with some DLLs. This forced me to try to understand C# code snippets I found online and be able to apply those concepts to some other modules I’m currently working on.
What’s next?
More modules. More IronPython. More .NET. More C# interpretation.