/// <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 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> /// Frees an allocated block of memory in the opened process. /// </summary> /// <param name="dwAddress">Base address of the block of memory to be freed.</param> /// <param name="nSize">Number of bytes to be freed. This must be zero (0) if using <see cref="MemoryFreeType.MEM_RELEASE"/>.</param> /// <param name="dwFreeType">Type of free operation to use. See <see cref="MemoryFreeType"/>.</param> /// <returns>Returns true on success, false on failure.</returns> public bool FreeMemory(uint dwAddress, int nSize, uint dwFreeType) { return(SMemory.FreeMemory(m_hProcess, dwAddress, nSize, dwFreeType)); }