internal IntPtr Invoke(SafeThreadHandle threadHandle) { // Store a context structure in a buffer IntPtr contextBuffer; if (Environment.Is64BitProcess) { var context = new Structures.Context { ContextFlags = Enumerations.ContextFlags.Control }; contextBuffer = LocalMemoryTools.StoreStructureInBuffer(context); } else { var context = new Structures.Wow64Context { ContextFlags = Enumerations.ContextFlags.Control }; contextBuffer = LocalMemoryTools.StoreStructureInBuffer(context); } // Perform the syscall var syscallResult = _ntGetContextThreadDelegate(threadHandle, contextBuffer); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the target process", syscallResult); } return(contextBuffer); }
internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int size, Enumerations.MemoryProtectionType protectionType) { // Store the base address of the allocation in a buffer var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress); // Store the size of the allocation in a buffer var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(size); // Perform the syscall const Enumerations.MemoryAllocationType allocationType = Enumerations.MemoryAllocationType.Commit | Enumerations.MemoryAllocationType.Reserve; var syscallResult = _ntAllocateVirtualMemoryDelegate(processHandle, baseAddressBuffer, 0, sizeBuffer, allocationType, protectionType); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to allocate memory in the target process", syscallResult); } try { return(Marshal.PtrToStructure <IntPtr>(baseAddressBuffer)); } finally { LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer); LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer); } }
internal SafeThreadHandle Invoke(SafeProcessHandle processHandle, IntPtr startAddress, IntPtr parameter) { // Initialise a buffer to store the returned thread handle var threadHandleBuffer = LocalMemoryTools.AllocateMemoryForBuffer(IntPtr.Size); // Perform the syscall const Enumerations.ThreadAccessMask desiredAccess = Enumerations.ThreadAccessMask.SpecificRightsAll | Enumerations.ThreadAccessMask.StandardRightsAll; var syscallResult = _ntCreateThreadExDelegate(threadHandleBuffer, desiredAccess, IntPtr.Zero, processHandle, startAddress, parameter, Enumerations.ThreadCreationType.HideFromDebugger, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to create a thread in the target process", syscallResult); } try { return(new SafeThreadHandle(Marshal.PtrToStructure <IntPtr>(threadHandleBuffer), true)); } finally { LocalMemoryTools.FreeMemoryForBuffer(threadHandleBuffer); } }
private void CreateSyscall <TSyscall>() where TSyscall : class { // Get the address of the function to syscall var functionAddress = PInvoke.GetProcAddress(_ntDllAddress, typeof(TSyscall).Name.Replace("Definition", "")); // Copy the first 8 bytes of the function var functionBytes = new byte[8]; Marshal.Copy(functionAddress, functionBytes, 0, 8); // Retrieve the syscall index from the bytes var syscallIndexBytes = Environment.Is64BitProcess ? functionBytes.Skip(4).Take(4) : functionBytes.Skip(1).Take(4); // Write the shellcode used to perform the syscall into the local process var shellcode = Environment.Is64BitProcess ? SyscallX64.GetShellcode(syscallIndexBytes.ToArray()) : SyscallX86.GetShellcode(syscallIndexBytes.ToArray()); var shellcodeBuffer = LocalMemoryTools.StoreBytesInBuffer(shellcode); // Create an instance of the syscall class var syscallInstance = Activator.CreateInstance(typeof(TSyscall), BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { shellcodeBuffer }, null); // Get the parameter and return types of the syscall method var methodInformation = typeof(TSyscall).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.NonPublic); var methodTypes = new List <Type>(methodInformation.GetParameters().Select(parameter => parameter.ParameterType)) { methodInformation.ReturnType }; // Create the delegate type to represent the syscall method Type delegateType; if (methodTypes.Last() == typeof(void)) { methodTypes.RemoveAt(methodTypes.Count - 1); delegateType = Expression.GetActionType(methodTypes.ToArray()); } else { delegateType = Expression.GetFuncType(methodTypes.ToArray()); } // Create a delegate for the syscall method var syscallDelegate = Delegate.CreateDelegate(delegateType, syscallInstance, "Invoke"); _syscallCache.Add(typeof(TSyscall).Name, new SyscallInstance(syscallDelegate, shellcodeBuffer)); }
internal PeParser(string dllPath) { _dllBuffer = LocalMemoryTools.StoreBytesInBuffer(File.ReadAllBytes(dllPath)); _peHeaders = new PeHeaders(); ReadPeHeaders(); }
internal PeParser(byte[] dllBytes) { _dllBuffer = LocalMemoryTools.StoreBytesInBuffer(dllBytes); _peHeaders = new PeHeaders(); ReadPeHeaders(); }
internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress) { // Initialise a buffer to store the returned memory basic information structure var memoryBasicInformationBuffer = LocalMemoryTools.AllocateMemoryForBuffer(Marshal.SizeOf <Structures.MemoryBasicInformation>()); // Perform the syscall var syscallResult = _ntQueryVirtualMemoryDelegate(processHandle, baseAddress, Enumerations.MemoryInformationClass.BasicInformation, memoryBasicInformationBuffer, (ulong)Marshal.SizeOf <Structures.MemoryBasicInformation>(), IntPtr.Zero); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to query memory in the target process", syscallResult); } return(memoryBasicInformationBuffer); }
internal IntPtr Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int bytesToRead) { // Initialise a buffer to store the returned bytes read var bytesReadBuffer = LocalMemoryTools.AllocateMemoryForBuffer(bytesToRead); // Perform the syscall var syscallResult = _ntReadVirtualMemoryDelegate(processHandle, baseAddress, bytesReadBuffer, (ulong)bytesToRead, IntPtr.Zero); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to read memory from the target process", syscallResult); } return(bytesReadBuffer); }
internal IntPtr Invoke(SafeProcessHandle processHandle, Enumerations.ProcessInformationClass processInformationClass) { // Initialise a buffer to store the returned process information structure var bufferSize = processInformationClass == Enumerations.ProcessInformationClass.BasicInformation ? Marshal.SizeOf <Structures.ProcessBasicInformation>() : sizeof(ulong); var processInformationBuffer = LocalMemoryTools.AllocateMemoryForBuffer(bufferSize); // Perform the syscall var syscallResult = _ntQueryInformationProcessDelegate(processHandle, processInformationClass, processInformationBuffer, (ulong)bufferSize, IntPtr.Zero); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to query the information of the target process", syscallResult); } return(processInformationBuffer); }
internal SafeProcessHandle Invoke(int processId) { // Initialise a buffer to store the returned process handle var processHandleBuffer = LocalMemoryTools.AllocateMemoryForBuffer(IntPtr.Size); // Store an empty object attributes structure in a buffer var objectAttributesBuffer = LocalMemoryTools.StoreStructureInBuffer(new Structures.ObjectAttributes()); // Store a client id structure in a buffer var clientId = new Structures.ClientId { UniqueProcess = new IntPtr(processId), UniqueThread = IntPtr.Zero }; var clientIdBuffer = LocalMemoryTools.StoreStructureInBuffer(clientId); // Perform the syscall var syscallResult = _ntOpenProcessDelegate(processHandleBuffer, Enumerations.ProcessAccessMask.AllAccess, objectAttributesBuffer, clientIdBuffer); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to open a handle to the target process", syscallResult); } try { return(new SafeProcessHandle(Marshal.PtrToStructure <IntPtr>(processHandleBuffer), true)); } finally { LocalMemoryTools.FreeMemoryForBuffer(processHandleBuffer); LocalMemoryTools.FreeMemoryForBuffer(objectAttributesBuffer); LocalMemoryTools.FreeMemoryForBuffer(clientIdBuffer); } }
internal void Invoke(SafeProcessHandle processHandle, IntPtr baseAddress) { // Store the base address of memory region to free in a buffer var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress); // Store the free size in a buffer var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(0); // Perform the syscall var syscallResult = _ntFreeVirtualMemoryDelegate(processHandle, baseAddressBuffer, sizeBuffer, Enumerations.MemoryFreeType.Release); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to free memory in the target process", syscallResult); } LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer); LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer); }
internal Enumerations.MemoryProtectionType Invoke(SafeProcessHandle processHandle, IntPtr baseAddress, int size, Enumerations.MemoryProtectionType protectionType) { // Store the base address of the memory region to protect in a buffer var baseAddressBuffer = LocalMemoryTools.StoreStructureInBuffer(baseAddress); // Store the protection size in a buffer var sizeBuffer = LocalMemoryTools.StoreStructureInBuffer(size); // Initialise a buffer to store the returned old protection of the memory region var oldProtectionBuffer = LocalMemoryTools.AllocateMemoryForBuffer(sizeof(ulong)); // Perform the syscall var syscallResult = _ntProtectVirtualMemoryDelegate(processHandle, baseAddressBuffer, sizeBuffer, protectionType, oldProtectionBuffer); if (syscallResult != Enumerations.NtStatus.Success) { ExceptionHandler.ThrowWin32Exception("Failed to protect memory in the target process", syscallResult); } try { return((Enumerations.MemoryProtectionType)Marshal.PtrToStructure <ulong>(oldProtectionBuffer)); } finally { LocalMemoryTools.FreeMemoryForBuffer(baseAddressBuffer); LocalMemoryTools.FreeMemoryForBuffer(sizeBuffer); LocalMemoryTools.FreeMemoryForBuffer(oldProtectionBuffer); } }
public void Dispose() { LocalMemoryTools.FreeMemoryForBuffer(ShellcodeAddress); }
public void Dispose() { LocalMemoryTools.FreeMemoryForBuffer(_dllBuffer); }
public bool Call(InjectionProperties injectionProperties) { // Get the address of the LoadLibraryW function in the target process var loadLibraryAddress = injectionProperties.RemoteProcess.GetFunctionAddress("kernel32.dll", "LoadLibraryW"); // Write the DLL path into the target process var dllPathBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, injectionProperties.DllPath.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); var dllPathBytes = Encoding.Unicode.GetBytes(injectionProperties.DllPath); injectionProperties.MemoryManager.WriteVirtualMemory(dllPathBuffer, dllPathBytes); // Open a handle to the first thread in the target process var threadHandle = (SafeThreadHandle)injectionProperties.SyscallManager.InvokeSyscall <NtOpenThread>(injectionProperties.RemoteProcess.TargetProcess.Threads[0].Id); if (injectionProperties.RemoteProcess.IsWow64) { // Suspend the thread if (PInvoke.Wow64SuspendThread(threadHandle) == -1) { ExceptionHandler.ThrowWin32Exception("Failed to suspend a thread in the target process"); } // Get the context of the thread var threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(new Structures.Wow64Context { ContextFlags = Enumerations.ContextFlags.Control }); if (PInvoke.Wow64GetThreadContext(threadHandle, threadContextBuffer) == 0) { ExceptionHandler.ThrowWin32Exception("Failed to get the context of a thread in the target process"); } var threadContext = Marshal.PtrToStructure <Structures.Wow64Context>(threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); // Write the shellcode used to call LoadLibraryW from the thread into the target process var shellcode = ThreadHijackX86.GetShellcode((IntPtr)threadContext.Eip, dllPathBuffer, loadLibraryAddress); var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Eip = (uint)shellcodeBuffer; threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext); // Update the context of the thread if (PInvoke.Wow64SetThreadContext(threadHandle, threadContextBuffer) == 0) { ExceptionHandler.ThrowWin32Exception("Failed to set the context of a thread in the target process"); } LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); } else { // Suspend the thread injectionProperties.SyscallManager.InvokeSyscall <NtSuspendThread>(threadHandle); // Get the context of the thread var threadContextBuffer = (IntPtr)injectionProperties.SyscallManager.InvokeSyscall <NtGetContextThread>(threadHandle); var threadContext = Marshal.PtrToStructure <Structures.Context>(threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); // Write the shellcode used to call LoadLibraryW from the thread into the target process var shellcode = ThreadHijackX64.GetShellcode((IntPtr)threadContext.Rip, dllPathBuffer, loadLibraryAddress); var shellcodeBuffer = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, shellcode.Length, Enumerations.MemoryProtectionType.ExecuteReadWrite); injectionProperties.MemoryManager.WriteVirtualMemory(shellcodeBuffer, shellcode); // Overwrite the instruction pointer of the thread with the address of the shellcode buffer threadContext.Rip = (ulong)shellcodeBuffer; threadContextBuffer = LocalMemoryTools.StoreStructureInBuffer(threadContext); // Update the context of the thread injectionProperties.SyscallManager.InvokeSyscall <NtSetContextThread>(threadHandle, threadContextBuffer); LocalMemoryTools.FreeMemoryForBuffer(threadContextBuffer); } // Resume the thread injectionProperties.SyscallManager.InvokeSyscall <NtResumeThread>(threadHandle); PInvoke.SwitchToThisWindow(injectionProperties.RemoteProcess.TargetProcess.MainWindowHandle, true); threadHandle.Dispose(); return(true); }
public bool Call(InjectionProperties injectionProperties) { var localDllAddress = injectionProperties.DllPath is null ? LocalMemoryTools.StoreBytesInBuffer(injectionProperties.DllBytes) : LocalMemoryTools.StoreBytesInBuffer(File.ReadAllBytes(injectionProperties.DllPath)); // Build the import table of the DLL BuildImportTable(injectionProperties, localDllAddress); var peHeaders = injectionProperties.PeParser.GetHeaders(); // Allocate memory for the DLL in the target process var allocationBaseAddress = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.ImageBase : peHeaders.NtHeaders64.OptionalHeader.ImageBase; var dllSize = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.SizeOfImage : peHeaders.NtHeaders64.OptionalHeader.SizeOfImage; IntPtr remoteDllAddress; try { remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory((IntPtr)allocationBaseAddress, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite); } catch (Win32Exception) { remoteDllAddress = injectionProperties.MemoryManager.AllocateVirtualMemory(IntPtr.Zero, (int)dllSize, Enumerations.MemoryProtectionType.ExecuteReadWrite); } // Perform any needed relocations PerformRelocations(injectionProperties, localDllAddress, remoteDllAddress); // Map the sections of the DLL MapSections(injectionProperties, localDllAddress, remoteDllAddress); // Map randomised PE headers MapHeaders(injectionProperties, remoteDllAddress); // Call any TLS callbacks CallTlsCallbacks(injectionProperties, remoteDllAddress); // Call the entry point of the DLL var dllEntryPointAddress = injectionProperties.RemoteProcess.IsWow64 ? remoteDllAddress.AddOffset(peHeaders.NtHeaders32.OptionalHeader.AddressOfEntryPoint) : remoteDllAddress.AddOffset(peHeaders.NtHeaders64.OptionalHeader.AddressOfEntryPoint); if (dllEntryPointAddress != remoteDllAddress) { CallEntryPoint(injectionProperties, remoteDllAddress, dllEntryPointAddress); } LocalMemoryTools.FreeMemoryForBuffer(localDllAddress); return(true); }