public static void init(out Context32 context, uint seed) { context = new Context32(); context.mem_ = new byte[16]; context.seed_ = seed; context.v1_ = seed + PRIME32_1 + PRIME32_2; context.v2_ = seed + PRIME32_2; context.v3_ = seed + 0; context.v4_ = seed - PRIME32_1; }
public Context(Process process) { isContext64 = process.IsWin64; if (process.IsWin64) { context64 = new CONTEXT(); context64.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; } else { context32 = new Context32(); context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; } }
public static void updateTail(ref Context32 context, byte[] data, int length) { int nblocks = length >> 2; int index = nblocks << 2; for (int i = -index; i < 0; i += 4) { uint k1 = read32LE(data, index + i); k1 *= c1_32; k1 = rotl32(k1, 15); k1 *= c2_32; context.h1_ ^= k1; context.h1_ = rotl32(context.h1_, 13); context.h1_ = context.h1_ * 5 + 0xe6546b64U; } uint l1 = 0; switch (length & 3) { case 3: l1 ^= (uint)data[index + 2] << 16; l1 ^= (uint)data[index + 1] << 8; l1 ^= (uint)data[index]; l1 *= c1_32; l1 = rotl32(l1, 15); l1 *= c2_32; context.h1_ ^= l1; break; case 2: l1 ^= (uint)data[index + 1] << 8; l1 ^= (uint)data[index]; l1 *= c1_32; l1 = rotl32(l1, 15); l1 *= c2_32; context.h1_ ^= l1; break; case 1: l1 ^= (uint)data[index]; l1 *= c1_32; l1 = rotl32(l1, 15); l1 *= c2_32; context.h1_ ^= l1; break; } context.totalLength_ += (uint)length; }
public Context(Process process, IntPtr hThread) { isContext64 = process.IsWin64; if (process.IsWin64) { context64 = new CONTEXT(); context64.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; } else { context32 = new Context32(); context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; } GetContext(hThread); //if (!GetContext(hThread)) // throw new Exception("Failed to GetContext(), get last error: " + Debugger.GetLastError().ToString()); }
public static void update4(ref Context32 context, byte[] data, int length) { int nblocks = length >> 2; int index = nblocks << 2; for (int i = -index; i < 0; i += 4) { uint k1 = read32LE(data, index + i); k1 *= c1_32; k1 = rotl32(k1, 15); k1 *= c2_32; context.h1_ ^= k1; context.h1_ = rotl32(context.h1_, 13); context.h1_ = context.h1_ * 5 + 0xe6546b64U; } context.totalLength_ += (uint)length; }
public static uint finalize(ref Context32 context) { byte[] p = context.mem_; uint h32; if (16 <= context.totalLength_) { h32 = rotl32(context.v1_, 1) + rotl32(context.v2_, 7) + rotl32(context.v3_, 12) + rotl32(context.v4_, 18); } else { h32 = context.seed_ + PRIME32_5; } h32 += (uint)context.totalLength_; uint index = 0; while ((index + 4) <= context.memSize_) { h32 += read32LE(p, index) * PRIME32_3; h32 = rotl32(h32, 17) * PRIME32_4; index += 4; } while (index < context.memSize_) { h32 += PRIME32_5 * p[index]; h32 = rotl32(h32, 11) * PRIME32_1; ++index; } h32 ^= h32 >> 15; h32 *= PRIME32_2; h32 ^= h32 >> 13; h32 *= PRIME32_3; h32 ^= h32 >> 16; return(h32); }
public IntPtr Inject() { // Write the DLL path into the remote process var dllPathAddress = _process.MemoryManager.AllocateVirtualMemory(_dllPath.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathAddress, Encoding.Unicode.GetBytes(_dllPath)); // Write a UnicodeString representing the DLL path into the remote process IntPtr dllPathUnicodeStringAddress; if (_process.IsWow64) { var dllPathUnicodeString = new UnicodeString32(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString32>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } else { var dllPathUnicodeString = new UnicodeString64(_dllPath, dllPathAddress); dllPathUnicodeStringAddress = _process.MemoryManager.AllocateVirtualMemory(Marshal.SizeOf <UnicodeString64>(), MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(dllPathUnicodeStringAddress, dllPathUnicodeString); } // Write the shellcode used to call LdrLoadDll into the remote process var ldrLoadDllAddress = _process.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = _process.MemoryManager.AllocateVirtualMemory(IntPtr.Size, MemoryProtectionType.ReadWrite); var shellcodeReturnAddress = _process.MemoryManager.AllocateVirtualMemory(sizeof(int), MemoryProtectionType.ReadWrite); var shellcode = _process.Assembler.AssembleThreadFunctionCall(new FunctionCall(ldrLoadDllAddress, CallingConvention.StdCall, new[] { 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress }, shellcodeReturnAddress)); var shellcodeAddress = _process.MemoryManager.AllocateVirtualMemory(shellcode.Length, MemoryProtectionType.ReadWrite); _process.MemoryManager.WriteVirtualMemory(shellcodeAddress, shellcode); _process.MemoryManager.ProtectVirtualMemory(shellcodeAddress, shellcode.Length, MemoryProtectionType.ExecuteRead); // Open a handle to the first thread in the remote process var firstThreadHandle = Kernel32.OpenThread(Constants.ThreadAllAccess, false, _process.Process.Threads[0].Id); if (firstThreadHandle is null) { throw new PInvokeException("Failed to call OpenThread"); } if (_process.IsWow64) { // Suspend the thread if (Kernel32.Wow64SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call Wow64SuspendThread"); } // Get the context of the thread var threadContext = new Context32 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context32>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.Wow64GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context32>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Esp -= sizeof(int); _process.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Esp, threadContext.Eip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Eip = (int)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.Wow64SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } else { // Suspend the thread if (Kernel32.SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call SuspendThread"); } // Get the context of the thread var threadContext = new Context64 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context64>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context64>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Rsp -= sizeof(long); _process.MemoryManager.WriteVirtualMemory((IntPtr)threadContext.Rsp, threadContext.Rip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Rip = (long)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } // Send a message to the thread to ensure it executes the shellcode User32.PostThreadMessage(_process.Process.Threads[0].Id, MessageType.Null, IntPtr.Zero, IntPtr.Zero); // Resume the thread if (Kernel32.ResumeThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call ResumeThread"); } firstThreadHandle.Dispose(); var shellcodeReturn = _process.MemoryManager.ReadVirtualMemory <int>(shellcodeReturnAddress); if ((NtStatus)shellcodeReturn != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrLoadDll", (NtStatus)shellcodeReturn); } // Ensure the DLL is loaded before freeing any memory while (_process.Modules.TrueForAll(module => module.FilePath != _dllPath)) { _process.Refresh(); } _process.MemoryManager.FreeVirtualMemory(dllPathAddress); _process.MemoryManager.FreeVirtualMemory(dllPathUnicodeStringAddress); _process.MemoryManager.FreeVirtualMemory(shellcodeReturnAddress); // Read the address of the DLL that was loaded in the remote process var remoteDllAddress = _process.MemoryManager.ReadVirtualMemory <IntPtr>(moduleHandleAddress); _process.MemoryManager.FreeVirtualMemory(moduleHandleAddress); if (!_injectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { return(remoteDllAddress); } // Write over the header region of the DLL with random bytes var randomBuffer = new byte[_peImage.PeHeaders.PEHeader.SizeOfHeaders]; new Random().NextBytes(randomBuffer); _process.MemoryManager.WriteVirtualMemory(remoteDllAddress, randomBuffer); return(remoteDllAddress); }
internal override void Inject() { // Write the DLL path into the remote process var dllPathUnicodeStringAddress = InitialiseDllPath(); // Write the shellcode used to call LdrLoadDll into the remote process var ldrLoadDllAddress = ProcessManager.GetFunctionAddress("ntdll.dll", "LdrLoadDll"); var moduleHandleAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, IntPtr.Size, MemoryProtectionType.ReadWrite); var shellcodeReturnAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, sizeof(int), MemoryProtectionType.ReadWrite); var shellcode = Assembler.AssembleThreadFunctionCall(new FunctionCall(ProcessManager.IsWow64, ldrLoadDllAddress, CallingConvention.StdCall, new[] { 0, 0, (long)dllPathUnicodeStringAddress, (long)moduleHandleAddress }, shellcodeReturnAddress)); var shellcodeAddress = MemoryManager.AllocateVirtualMemory(ProcessManager.Process.SafeHandle, IntPtr.Zero, shellcode.Length, MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeAddress, shellcode); MemoryManager.ProtectVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeAddress, shellcode.Length, MemoryProtectionType.ExecuteRead); // Open a handle to the first thread in the remote process var firstThreadHandle = Kernel32.OpenThread(Constants.ThreadAllAccess, false, ProcessManager.Process.Threads[0].Id); if (firstThreadHandle is null) { throw new PInvokeException("Failed to call OpenThread"); } if (ProcessManager.IsWow64) { // Suspend the thread if (Kernel32.Wow64SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call Wow64SuspendThread"); } // Get the context of the thread var threadContext = new Context32 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context32>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.Wow64GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context32>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Esp -= sizeof(int); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, (IntPtr)threadContext.Esp, threadContext.Eip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Eip = (int)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.Wow64SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } else { // Suspend the thread if (Kernel32.SuspendThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call SuspendThread"); } // Get the context of the thread var threadContext = new Context64 { ContextFlags = ContextFlags.Control }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context64>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.GetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context64>(threadContextBuffer); // Write the original instruction pointer of the thread into the top of its stack threadContext.Rsp -= sizeof(long); MemoryManager.WriteVirtualMemory(ProcessManager.Process.SafeHandle, (IntPtr)threadContext.Rsp, threadContext.Rip); // Overwrite the instruction pointer of the thread with the address of the shellcode threadContext.Rip = (long)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.SetThreadContext(firstThreadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } // Send a message to the thread to ensure it executes the shellcode User32.PostThreadMessage(ProcessManager.Process.Threads[0].Id, MessageType.Null, IntPtr.Zero, IntPtr.Zero); // Resume the thread if (Kernel32.ResumeThread(firstThreadHandle) == -1) { throw new PInvokeException("Failed to call ResumeThread"); } firstThreadHandle.Dispose(); var shellcodeReturn = MemoryManager.ReadVirtualMemory <int>(ProcessManager.Process.SafeHandle, shellcodeReturnAddress); if ((NtStatus)shellcodeReturn != NtStatus.Success) { throw new RemoteFunctionCallException("Failed to call LdrLoadDll", (NtStatus)shellcodeReturn); } // Ensure the DLL is loaded before freeing any memory while (ProcessManager.Modules.TrueForAll(module => module.FilePath != DllPath)) { ProcessManager.Refresh(); } var dllPathAddress = ProcessManager.IsWow64 ? (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString32>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer : (IntPtr)MemoryManager.ReadVirtualMemory <UnicodeString64>(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress).Buffer; MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, dllPathUnicodeStringAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, shellcodeReturnAddress); // Read the address of the DLL that was loaded in the remote process DllBaseAddress = MemoryManager.ReadVirtualMemory <IntPtr>(ProcessManager.Process.SafeHandle, moduleHandleAddress); MemoryManager.FreeVirtualMemory(ProcessManager.Process.SafeHandle, moduleHandleAddress); if (InjectionFlags.HasFlag(InjectionFlags.HideDllFromPeb)) { // Hide the DLL from the PEB of the remote process HideDllFromPeb(); } if (InjectionFlags.HasFlag(InjectionFlags.RandomiseDllHeaders)) { // Randomise the DLL headers RandomiseDllHeaders(DllBaseAddress); } }
public Context(Context32 context32) { isContext64 = false; this.context32 = context32; }
static extern bool Wow64GetThreadContext(IntPtr hThread, ref Context32 lpContext);
private void CallFunctionInternal(FunctionCall functionCall) { // Write the shellcode used to perform the function call into the remote process var shellcode = Assembler.AssembleFunctionCall(functionCall); var shellcodeAddress = MemoryManager.AllocateVirtualMemory(Process.SafeHandle, IntPtr.Zero, shellcode.Length, MemoryProtectionType.ReadWrite); MemoryManager.WriteVirtualMemory(Process.SafeHandle, shellcodeAddress, shellcode); MemoryManager.ProtectVirtualMemory(Process.SafeHandle, shellcodeAddress, shellcode.Length, MemoryProtectionType.ExecuteRead); // Create a thread to execute the shellcode in the remote process var ntStatus = Ntdll.NtCreateThreadEx(out var threadHandle, Constants.ThreadAllAccess, IntPtr.Zero, Process.SafeHandle, Modules[0].BaseAddress, IntPtr.Zero, ThreadCreationFlags.CreateSuspended | ThreadCreationFlags.HideFromDebugger, 0, 0, 0, IntPtr.Zero); if (ntStatus != NtStatus.Success) { throw new PInvokeException("Failed to call NtCreateThreadEx", ntStatus); } if (IsWow64) { // Get the context of the thread var threadContext = new Context32 { ContextFlags = ContextFlags.Integer }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context32>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.Wow64GetThreadContext(threadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context32>(threadContextBuffer); // Change the spoofed start address to the address of the shellcode threadContext.Eax = (int)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.Wow64SetThreadContext(threadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call Wow64SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } else { // Get the context of the thread var threadContext = new Context64 { ContextFlags = ContextFlags.Integer }; var threadContextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf <Context64>()); Marshal.StructureToPtr(threadContext, threadContextBuffer, false); if (!Kernel32.GetThreadContext(threadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call GetThreadContext"); } threadContext = Marshal.PtrToStructure <Context64>(threadContextBuffer); // Change the spoofed start address to the address of the shellcode threadContext.Rcx = (long)shellcodeAddress; Marshal.StructureToPtr(threadContext, threadContextBuffer, false); // Update the context of the thread if (!Kernel32.SetThreadContext(threadHandle, threadContextBuffer)) { throw new PInvokeException("Failed to call SetThreadContext"); } Marshal.FreeHGlobal(threadContextBuffer); } Kernel32.ResumeThread(threadHandle); Kernel32.WaitForSingleObject(threadHandle, int.MaxValue); threadHandle.Dispose(); MemoryManager.FreeVirtualMemory(Process.SafeHandle, shellcodeAddress); }
public static void update(ref Context32 context, byte[] input, uint length) { context.totalLength_ += length; if ((context.memSize_ + length) < 16) { System.Array.Copy(input, 0, context.mem_, context.memSize_, length); context.memSize_ += length; return; } uint index = 0; if (0 != context.memSize_) { System.Array.Copy(input, 0, context.mem_, context.memSize_, 32 - context.memSize_); uint offset = 0; context.v1_ += read32LE(context.mem_, offset) * PRIME32_2; context.v1_ = rotl32(context.v1_, 13); context.v1_ *= PRIME32_1; offset += 4; context.v2_ += read32LE(context.mem_, offset) * PRIME32_2; context.v2_ = rotl32(context.v2_, 13); context.v2_ *= PRIME32_1; offset += 4; context.v3_ += read32LE(context.mem_, offset) * PRIME32_2; context.v3_ = rotl32(context.v3_, 13); context.v3_ *= PRIME32_1; offset += 4; context.v4_ += read32LE(context.mem_, offset) * PRIME32_2; context.v4_ = rotl32(context.v4_, 13); context.v4_ *= PRIME32_1; index += 16 - context.memSize_; context.memSize_ = 0; } if ((index + 16) <= length) { uint limit = length - 16; uint v1 = context.v1_; uint v2 = context.v2_; uint v3 = context.v3_; uint v4 = context.v4_; do { v1 += read32LE(input, index) * PRIME32_2; v1 = rotl32(v1, 13); v1 *= PRIME32_1; index += 4; v2 += read32LE(input, index) * PRIME32_2; v2 = rotl32(v2, 13); v2 *= PRIME32_1; index += 4; v3 += read32LE(input, index) * PRIME32_2; v3 = rotl32(v3, 13); v3 *= PRIME32_1; index += 4; v4 += read32LE(input, index) * PRIME32_2; v4 = rotl32(v4, 13); v4 *= PRIME32_1; index += 4; } while(index <= limit); context.v1_ = v1; context.v2_ = v2; context.v3_ = v3; context.v4_ = v4; } if (index < length) { context.memSize_ = length - index; System.Array.Copy(input, index, context.mem_, 0, context.memSize_); } }
public static void init(out Context32 context, uint seed) { context = new Context32(); context.h1_ = seed; context.mem_ = new byte[4]; }
public static uint finalize(ref Context32 context) { context.h1_ ^= context.totalLength_; return(fmix32(context.h1_)); }