/// <summary> /// Opens the specified thread for manipulation. /// </summary> /// <param name="dwThreadId">ID of the thread to be opened.</param> /// <returns>Returns true on success, false on failure.</returns> public bool OpenThread(int dwThreadId) { if (dwThreadId == 0) { return(false); } if (dwThreadId == m_ThreadId) { return(true); } if (m_bThreadOpen) { this.CloseThread(); } m_bThreadOpen = (m_hThread = SThread.OpenThread(dwThreadId)) != IntPtr.Zero; if (m_bThreadOpen) { m_ThreadId = dwThreadId; } return(m_bThreadOpen); }
/// <summary> /// Opens the main thread of the process already opened by this class object. /// </summary> /// <returns>Returns true on success, false on failure.</returns> public bool OpenThread() { if (m_bProcessOpen) { return(this.OpenThread(SThread.GetMainThreadId(m_ProcessId))); } return(false); }
/// <summary> /// Creates a thread inside another process' context. /// </summary> /// <param name="dwStartAddress">Address at which thread will start.</param> /// <param name="dwParameter">Parameter that will be passed to the thread.</param> /// <param name="dwCreationFlags">Flags that control creation of the thread.</param> /// <param name="dwThreadId">[Out] The id of the created thread.</param> /// <returns>Returns the handle of the created thread.</returns> public IntPtr CreateRemoteThread(uint dwStartAddress, uint dwParameter, uint dwCreationFlags, out uint dwThreadId) { if (m_bProcessOpen) return SThread.CreateRemoteThread(m_hProcess, dwStartAddress, dwParameter, dwCreationFlags, out dwThreadId); dwThreadId = 0; return IntPtr.Zero; }
/// <summary> /// Injects a dll into a process by creating a remote thread on LoadLibrary. /// </summary> /// <param name="hProcess">Handle to the process into which dll will be injected.</param> /// <param name="szDllPath">Full path of the dll that will be injected.</param> /// <returns>Returns the base address of the injected dll on success, zero on failure.</returns> public static uint InjectDllCreateThread(IntPtr hProcess, string szDllPath) { if (hProcess == IntPtr.Zero) { throw new ArgumentNullException("hProcess"); } if (szDllPath.Length == 0) { throw new ArgumentNullException("szDllPath"); } if (!szDllPath.Contains("\\")) { szDllPath = System.IO.Path.GetFullPath(szDllPath); } if (!System.IO.File.Exists(szDllPath)) { throw new ArgumentException("DLL not found.", "szDllPath"); } uint dwBaseAddress = RETURN_ERROR; uint lpLoadLibrary; uint lpDll; IntPtr hThread; lpLoadLibrary = (uint)Imports.GetProcAddress(Imports.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (lpLoadLibrary > 0) { lpDll = SMemory.AllocateMemory(hProcess); if (lpDll > 0) { if (SMemory.WriteASCIIString(hProcess, lpDll, szDllPath)) { hThread = SThread.CreateRemoteThread(hProcess, lpLoadLibrary, lpDll); //wait for thread handle to have signaled state //exit code will be equal to the base address of the dll if (SThread.WaitForSingleObject(hThread, 5000) == WaitValues.WAIT_OBJECT_0) { dwBaseAddress = SThread.GetExitCodeThread(hThread); } Imports.CloseHandle(hThread); } SMemory.FreeMemory(hProcess, lpDll); } } return(dwBaseAddress); }
/// <summary> /// Injects a dll into a process by hijacking the process' main thread and redirecting it to LoadLibrary. /// </summary> /// <param name="hProcess">Handle to the process into which dll will be injected.</param> /// <param name="dwProcessId">Id of the process into which dll will be injected.</param> /// <param name="szDllPath">Full path to the dll to be injected.</param> /// <returns>Returns the base address of the injected dll on success, zero on failure.</returns> public static uint InjectDllRedirectThread(IntPtr hProcess, int dwProcessId, string szDllPath) { IntPtr hThread; uint dwBaseAddress; hThread = SThread.OpenThread(SThread.GetMainThreadId(dwProcessId)); if (hThread == IntPtr.Zero) { return(RETURN_ERROR); } dwBaseAddress = InjectDllRedirectThread(hProcess, hThread, szDllPath); Imports.CloseHandle(hThread); return(dwBaseAddress); }
/// <summary> /// Executes code at a given address and returns the thread's exit code. /// </summary> /// <param name="dwStartAddress">Address to be executed.</param> /// <param name="dwParameter">Parameter to be passed to the code being executed.</param> /// <returns>Returns the exit code of the thread.</returns> public uint Execute(uint dwStartAddress, uint dwParameter) { IntPtr hThread; UIntPtr lpExitCode = UIntPtr.Zero; bool bSuccess = false; hThread = CreateRemoteThread(dwStartAddress, dwParameter); if (hThread == IntPtr.Zero) throw new Exception("Thread could not be remotely created."); bSuccess = (SThread.WaitForSingleObject(hThread, 10000) == WaitValues.WAIT_OBJECT_0); if (bSuccess) bSuccess = Imports.GetExitCodeThread(hThread, out lpExitCode); Imports.CloseHandle(hThread); if (!bSuccess) throw new Exception("Error waiting for thread to exit or getting exit code."); return (uint)lpExitCode; }
/// <summary> /// Injects a dll into a process by hijacking the given thread and redirecting it to LoadLibrary. /// </summary> /// <param name="hProcess">Handle to process into which dll will be injected.</param> /// <param name="hThread">Handle to thread that will be hijacked.</param> /// <param name="szDllPath">Full path to the dll to be injected.</param> /// <returns>Returns the base address of the injected dll on success, zero on failure.</returns> public static uint InjectDllRedirectThread(IntPtr hProcess, IntPtr hThread, string szDllPath) { const uint INITIAL_EXIT_CODE = 0xFFFFFFFF; if (hProcess == IntPtr.Zero) { throw new ArgumentNullException("hProcess"); } if (hThread == IntPtr.Zero) { throw new ArgumentNullException("hThread"); } if (szDllPath.Length == 0) { throw new ArgumentNullException("szDllPath"); } if (!szDllPath.Contains("\\")) { szDllPath = System.IO.Path.GetFullPath(szDllPath); } if (!System.IO.File.Exists(szDllPath)) { throw new ArgumentException("DLL not found.", "szDllPath"); } uint dwBaseAddress = RETURN_ERROR; uint lpLoadLibrary, lpAsmStub; CONTEXT ctx; StringBuilder AssemblyStub = new StringBuilder(); ManagedFasm fasm = new ManagedFasm(hProcess); lpLoadLibrary = (uint)Imports.GetProcAddress(Imports.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (lpLoadLibrary == 0) { return(RETURN_ERROR); } lpAsmStub = SMemory.AllocateMemory(hProcess); if (lpAsmStub == 0) { return(RETURN_ERROR); } if (SThread.SuspendThread(hThread) != uint.MaxValue) { ctx = SThread.GetThreadContext(hThread, CONTEXT_FLAGS.CONTEXT_CONTROL); if (ctx.Eip > 0) { try { //located at lpAsmStub+0, where we can monitor LoadLibrary's exit code. fasm.AddLine("lpExitCode dd 0x{0:X}", INITIAL_EXIT_CODE); //lpAsmStub+4, where the actual code part starts fasm.AddLine("push 0x{0:X}", ctx.Eip); fasm.AddLine("pushad"); fasm.AddLine("push szDllPath"); fasm.AddLine("call 0x{0:X}", lpLoadLibrary); fasm.AddLine("mov [lpExitCode], eax"); fasm.AddLine("popad"); fasm.AddLine("retn"); //dll path fasm.AddLine("szDllPath db \'{0}\',0", szDllPath); fasm.Inject(lpAsmStub); } catch { SMemory.FreeMemory(hProcess, lpAsmStub); SThread.ResumeThread(hThread); return(RETURN_ERROR); } ctx.ContextFlags = CONTEXT_FLAGS.CONTEXT_CONTROL; ctx.Eip = lpAsmStub + 4; //skip over lpExitCode data if (SThread.SetThreadContext(hThread, ctx)) { if (SThread.ResumeThread(hThread) != uint.MaxValue) { for (int i = 0; i < 400; i++) { System.Threading.Thread.Sleep(5); if ((dwBaseAddress = SMemory.ReadUInt(hProcess, lpAsmStub)) != INITIAL_EXIT_CODE) { break; } } } } } } if (fasm != null) { fasm.Dispose(); fasm = null; } SMemory.FreeMemory(hProcess, lpAsmStub); return(dwBaseAddress); }
/// <summary> /// Suspends execution of a thread. /// </summary> /// <param name="hThread">Handle to the thread to be suspended.</param> /// <returns>Returns true on success, false on failure.</returns> public bool SuspendThread(IntPtr hThread) { return (SThread.SuspendThread(hThread) == uint.MaxValue) ? false : true; }
/// <summary> /// Resumes execution of a thread. /// </summary> /// <param name="hThread">Handle to the thread to be suspended.</param> /// <returns>Returns true on success, false on failure.</returns> public bool ResumeThread(IntPtr hThread) { return (SThread.ResumeThread(hThread) == uint.MaxValue) ? false : true; }