public override bool CheckAddress() { int adr = Address; WinApi.PROCESS_INFORMATION pi = new WinApi.PROCESS_INFORMATION(); WinApi.STARTUPINFO si = new WinApi.STARTUPINFO(); string path = Util.GlobalVars.FullPath; string arguments = ""; WinApi.CreateProcess(path, " " + arguments, IntPtr.Zero, IntPtr.Zero, false, WinApi.CREATE_SUSPENDED, IntPtr.Zero, System.IO.Path.GetDirectoryName(path), ref si, out pi); IntPtr handle = WinApi.OpenProcess(WinApi.PROCESS_ALL_ACCESS, 0, pi.dwProcessId); Process p = Process.GetProcessById(Convert.ToInt32(pi.dwProcessId)); MemoryReader Writer = new MemoryReader(p); Writer.WriteByte(adr, 0xEB);// write jmp short WinApi.ResumeThread(pi.hThread); p.WaitForInputIdle(); Writer.WriteByte(Address, 0x75);// write jnz short WinApi.CloseHandle(handle); WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); if (p.MainWindowTitle == "Tibia Error") { return(false); } return(true); }
private bool UnInjectDll(int processId, UIntPtr handle) { IntPtr kernelMod = WinApi.GetModuleHandle("kernel32.dll"); if (kernelMod == IntPtr.Zero) { throw new Error("GetModuleHandle of kernel32.dll failed"); } IntPtr proc = WinApi.OpenProcess(WinApi.PROCESS_ALL_ACCESS, true, (uint)processId); if (proc == IntPtr.Zero) { throw new Error("OpenProcess failed"); } try { return(CallRemoteFunction(proc, kernelMod, "FreeLibrary", handle) != 0); } finally { WinApi.CloseHandle(proc); } }
public static bool ImpersonateValidUser(String userName, String domain, String password) { WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if (WinApi.RevertToSelf()) { if (WinApi.LogonUserA(userName, domain, password, WinApi.LOGON32_LOGON_INTERACTIVE, WinApi.LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (WinApi.DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); _impersonationContext = tempWindowsIdentity.Impersonate(); if (_impersonationContext != null) { WinApi.CloseHandle(token); WinApi.CloseHandle(tokenDuplicate); return(true); } } } } if (token != IntPtr.Zero) { WinApi.CloseHandle(token); } if (tokenDuplicate != IntPtr.Zero) { WinApi.CloseHandle(tokenDuplicate); } return(false); }
private void ExecuteRemoteCode(IntPtr process, IntPtr codeAddress, uint arg) { IntPtr WorkThread = WinApi.CreateRemoteThread(process, IntPtr.Zero, 0, codeAddress, new IntPtr(arg), 0, IntPtr.Zero); WinApi.WaitForSingleObject(WorkThread, 0xffffffffu); WinApi.CloseHandle(WorkThread); }
protected virtual void EjectDll(IntPtr injectedProcessAddress) { LogProvider.Log.Info(this, $"Ejecting from the process \"{ProcessName}\" [{pokerClientProcess.Id}]. [{Identifier}]"); IntPtr hThread = IntPtr.Zero; try { // get handle to kernel32 and FreeLibrary IntPtr hKernel32 = WinApi.GetModuleHandle("Kernel32"); if (hKernel32 == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Kernel32 not found"); } IntPtr hFreeLib = WinApi.GetProcAddress(hKernel32, "FreeLibrary"); if (hFreeLib == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "FreeLibrary not found"); } hThread = WinApi.CreateRemoteThread(handle, IntPtr.Zero, 0, hFreeLib, injectedProcessAddress, 0, IntPtr.Zero); if (hThread == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Couldn't create remote thread"); } if (WinApi.WaitForSingleObject(hThread, (uint)ThreadWaitValue.Infinite) != (uint)ThreadWaitValue.Object0) { throw new Win32Exception(Marshal.GetLastWin32Error(), "WaitForSingleObject return wrong code"); } IntPtr pFreeLibRet; if (!WinApi.GetExitCodeThread(hThread, out pFreeLibRet)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Couldn't obtain exit code"); } if (pFreeLibRet == IntPtr.Zero) { throw new Exception("FreeLibrary failed in remote process"); } LogProvider.Log.Log(this, string.Format(CultureInfo.InvariantCulture, "Successfully ejected from process \"{0}\". [{1}]", ProcessName, Identifier), LogMessageType.Info); } finally { WinApi.CloseHandle(hThread); injectedProcessModule = null; } isInjected = false; }
/// <summary> /// This method releases all unmanaged resources associated with the mutex. Well /// behaved applications will call this immediately after they are done with the /// mutex. /// </summary> public void Close() { if (hMutex != IntPtr.Zero) { WinApi.CloseHandle(hMutex); hMutex = IntPtr.Zero; } GC.SuppressFinalize(this); }
public void SendPacketToServer(byte[] packet) { CodeCaveHelper cv = new CodeCaveHelper(); IntPtr MainThread = OpenAndSuspendThread(tProcess.Id); uint OldPackelen = memRead.ReadUInt32(Addresses.MyAddresses.OutGoingPacketLen.Address); byte[] OldPacket = memRead.ReadBytes(Addresses.MyAddresses.OutGoingBuffer.Address, OldPackelen); IntPtr CodeCave = WinApi.VirtualAllocEx(tProcessHandle, IntPtr.Zero, 1024, WinApi.AllocationType.Commit | WinApi.AllocationType.Reserve, WinApi.MemoryProtection.ExecuteReadWrite); //createPacket byte packetType = (byte)packet[0]; cv.AddLine((byte)0xb9, (UInt32)packetType); cv.AddLine((byte)0xB8, (uint)Addresses.MyAddresses.CreatePacket.Address); cv.AddLine((byte)0xff, (byte)0xD0); for (int i = 1; i < packet.Length; i++) { byte val = packet[i]; cv.AddLine((byte)0xb9, (UInt32)val); cv.AddLine((byte)0xB8, (uint)Addresses.MyAddresses.AddPacketByte.Address); cv.AddLine((byte)0xff, (byte)0xD0); } cv.AddLine((byte)0xb1, (byte)0x01); //push 1 as bool( using Xtea encrypt or not cv.AddLine((byte)0xB8, (uint)Addresses.MyAddresses.SendPacket.Address); cv.AddLine((byte)0xff, (byte)0xD0); // call eax Thanks Darkstar cv.AddByte(0xC3); //ret memRead.WriteBytes(CodeCave.ToInt32(), cv.Data, (uint)cv.Data.Length); IntPtr hThread = WinApi.CreateRemoteThread(tProcessHandle, IntPtr.Zero, 0, CodeCave, IntPtr.Zero, 0, IntPtr.Zero); if (Addresses.MyAddresses.IgnoreReadClientPacketAddress > 0) { memRead.WriteByte(Addresses.MyAddresses.IgnoreReadClientPacketAddress, 0);//ignore this } WinApi.WaitForSingleObject(hThread, 0xFFFFFFFF); WinApi.CloseHandle(hThread); WinApi.VirtualFreeEx(tProcessHandle, CodeCave, 1024, WinApi.AllocationType.Release); memRead.WriteUInt32(Addresses.MyAddresses.OutGoingPacketLen.Address, OldPackelen); memRead.WriteBytes(Addresses.MyAddresses.OutGoingBuffer.Address, OldPacket, (uint)OldPackelen); ResumeAndCloseThread(MainThread); }
private void StopCaptureThread() { try { DoUnInjection(); UpdateCaptureStatistics(); stopRespEvent.Close(); stopReqEvent.Close(); startReqEvent.Close(); WinApi.UnmapViewOfFile(cfgPtr); WinApi.CloseHandle(fileMapping); if (devices.Length > 0) { foreach (Device device in devices) { device.RemoveLowerFilter(Constants.UsbAgentName); } if (restartDevices) { foreach (Device device in devices) { device.Restart(); } } WaitForUsbAgentServiceToStop(); RemoveUsbAgentService(); } } catch (Error e) { progress.OperationFailed(e.Message); return; } progress.OperationComplete(); }
public void Dispose() { if (disposed) { return; } disposed = true; DisableProxy(); Scheduler.Shutdown(); Dispatcher.Shutdown(); if (ProcessHandle != null && ProcessHandle != IntPtr.Zero) { WinApi.CloseHandle(ProcessHandle); ProcessHandle = IntPtr.Zero; } }
public void SendPacket(byte[] packetData) { IntPtr openProcessHandle = MemoryManager.OpenProcessHandle; int num = InjectHelper.AllocateMemory(openProcessHandle, (int)packetData.Length); MemoryManager.WriteBytes(num, packetData); byte[] bytes = BitConverter.GetBytes(num); if (this._sendPacketOpcodeAddress == 0) { this.LoadSendPacketOpcode(openProcessHandle); } MemoryManager.WriteBytes(this._packetAddressLocation, bytes); MemoryManager.WriteBytes(this._packetSizeAddress, BitConverter.GetBytes((int)packetData.Length)); IntPtr intPtr = InjectHelper.CreateRemoteThread(openProcessHandle, this._sendPacketOpcodeAddress); WinApi.WaitForSingleObject(intPtr, 100); WinApi.CloseHandle(intPtr); InjectHelper.FreeMemory(openProcessHandle, num, (int)packetData.Length); InjectHelper.FreeMemory(openProcessHandle, this._sendPacketOpcodeAddress, (int)this._sendPacketOpcode.Length); }
public void EnumerateVolume(string drive, HashSet <string> fileExtensions , out Dictionary <ulong, FileEntry> files , out Dictionary <ulong, FileEntry> directories ) { directories = new Dictionary <ulong, FileEntry>(); files = new Dictionary <ulong, FileEntry>(); var medBuffer = IntPtr.Zero; var changeJournalRootHandle = IntPtr.Zero; try { GetRootFrnEntry(drive, directories); GetRootHandle(drive, out changeJournalRootHandle); CreateChangeJournal(changeJournalRootHandle); SetupMFT_Enum_DataBuffer(ref medBuffer, changeJournalRootHandle); EnumerateFiles(medBuffer, ref files, fileExtensions, directories, changeJournalRootHandle); } catch (Exception e) { Console.WriteLine(e.Message, e); var innerException = e.InnerException; while (innerException != null) { Console.WriteLine(innerException.Message, innerException); innerException = innerException.InnerException; } throw new ApplicationException("Error in EnumerateVolume()", e); } finally { if (changeJournalRootHandle.ToInt64() != WinApi.InvalidHandleValue) { WinApi.CloseHandle(changeJournalRootHandle); } if (medBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(medBuffer); } } }
/// <summary> /// Close pipe server /// </summary> /// <param name="pipeHandle">Handle to pipe</param> private void ClosePipe(IntPtr pipeHandle) { if (pipeHandle == IntPtr.Zero) { return; } if (!WinApi.FlushFileBuffers(pipeHandle)) { LogProvider.Log.Warn(this, string.Format(CultureInfo.InvariantCulture, "Flushing pipe buffer failed with code 0x{0:X}.", WinApi.GetLastError())); } if (!WinApi.DisconnectNamedPipe(pipeHandle)) { LogProvider.Log.Warn(this, string.Format(CultureInfo.InvariantCulture, "Disconnecting pipe failed with code 0x{0:X}.", WinApi.GetLastError())); } if (!WinApi.CloseHandle(pipeHandle)) { LogProvider.Log.Warn(this, string.Format(CultureInfo.InvariantCulture, "Closing pipe handle failed with code 0x{0:X}.", WinApi.GetLastError())); } }
private void GetRootFrnEntry(string drive, Dictionary <ulong, FileEntry> directories) { var driveRoot = string.Concat("\\\\.\\", drive); driveRoot = string.Concat(driveRoot, Path.DirectorySeparatorChar); var hRoot = WinApi.CreateFile(driveRoot, 0, WinApi.FileShareRead | WinApi.FileShareWrite, IntPtr.Zero, WinApi.OpenExisting, WinApi.FileFlagBackupSemantics, IntPtr.Zero ); if (hRoot.ToInt64() != WinApi.InvalidHandleValue) { WinApi.ByHandleFileInformation fi; var bRtn = WinApi.GetFileInformationByHandle(hRoot, out fi); if (bRtn) { ulong fileIndexHigh = fi.FileIndexHigh; var indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow; var f = new FileEntry(driveRoot, 0); directories.Add(indexRoot, f); } else { throw new IOException("GetFileInformationbyHandle() returned invalid handle", new Win32Exception(Marshal.GetLastWin32Error())); } WinApi.CloseHandle(hRoot); } else { throw new IOException("Unable to get root frn entry", new Win32Exception(Marshal.GetLastWin32Error())); } }
private UIntPtr InjectDll(int processId, string dllPath) { IntPtr kernelMod = WinApi.GetModuleHandle("kernel32.dll"); if (kernelMod == IntPtr.Zero) { throw new Error("GetModuleHandle of kernel32.dll failed"); } IntPtr proc = WinApi.OpenProcess(WinApi.PROCESS_ALL_ACCESS, true, (uint)processId); if (proc == IntPtr.Zero) { throw new Error("OpenProcess failed"); } // Temporarily show errors, add the directory to the search path, and load the DLL. try { uint oldErrorMode = CallRemoteFunction(proc, kernelMod, "SetErrorMode", 0); try { string dllDir = Path.GetDirectoryName(dllPath); CallRemoteFunction(proc, kernelMod, "SetDllDirectoryW", dllDir); return((UIntPtr)CallRemoteFunction(proc, kernelMod, "LoadLibraryW", dllPath)); } finally { CallRemoteFunction(proc, kernelMod, "SetErrorMode", oldErrorMode); } } finally { WinApi.CloseHandle(proc); } }
/// <summary> /// This method disconnects the class from the shared memory block and if this /// is the last instance referencing the block, then the block will be /// deleted. Note that it's OK to call Close() even if the object isn't /// currently open. This method is thread safe. /// </summary> public void Close() { lock (syncLock) { if (m_hMap == IntPtr.Zero) { return; } // Unlock the memory if (m_pvBlock != null) { while (m_cLock > 0) { Unlock(); } } // Free the map if (m_hMap != IntPtr.Zero) { #if SHAREDMEM_DRIVER WinApi.MEM_Close(m_hMap); #else WinApi.CloseHandle(m_hMap); #endif m_hMap = IntPtr.Zero; } // Free the mutex m_mutex.Close(); } }
public static Client OpenMC(string path, string arguments) { var fileVersion = FileVersionInfo.GetVersionInfo(path).FileVersion; var version = ClientVersion.GetFromFileVersion(fileVersion); if (version == null) { throw new Exception("The version " + fileVersion + " is not supported."); } WinApi.PROCESS_INFORMATION pi = new WinApi.PROCESS_INFORMATION(); WinApi.STARTUPINFO si = new WinApi.STARTUPINFO(); if (arguments == null) { arguments = ""; } WinApi.CreateProcess(path, " " + arguments, IntPtr.Zero, IntPtr.Zero, false, WinApi.CREATE_SUSPENDED, IntPtr.Zero, Path.GetDirectoryName(path), ref si, out pi); Process p = Process.GetProcessById(Convert.ToInt32(pi.dwProcessId)); var client = new Client(p, version, Path.GetDirectoryName(path)); Memory.WriteByte(client.ProcessHandle, client.MemoryAddresses.ClientMultiClient, client.MemoryAddresses.ClientMultiClientJMP); WinApi.ResumeThread(pi.hThread); p.WaitForInputIdle(); Memory.WriteByte(client.ProcessHandle, client.MemoryAddresses.ClientMultiClient, client.MemoryAddresses.ClientMultiClientJNZ); WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); return(client); }
private void ResumeAndCloseThread(IntPtr thread) { WinApi.ResumeThread(thread); WinApi.CloseHandle(thread); }
/// <summary> /// This method creates a shared memory object with the name passed in pszName /// and size of cbMem. The method returns <c>true</c> if the memory was created /// successfully, <c>false</c> if the operation failed for some reason. If the shared /// memory block is being created for the first time then this method will /// zero the memory block. If the shared memory block has already been created /// then this method will link to the existing block. Note that any successfull /// call to Open() needs to be matched by a call to <see cref="Close" />. This method is /// threadsafe. /// </summary> /// <param name="name"> /// Name of the inbox. This can be a maximum of 128 characters and may /// not include the backslash (\) character. /// </param> /// <param name="cbMem">Size of the memory in bytes.</param> /// <param name="mode">The opening mode.</param> public void Open(string name, int cbMem, OpenMode mode) { string memName; string mutexName; bool fExists; bool createdNew; if (name.Length > 128) { throw new ArgumentException("Name exceeds 128 characters.", "name"); } if (name.IndexOfAny(new char[] { '/', '\\' }) != -1) { throw new ArgumentException("Name may not include forward or backslashes."); } lock (syncLock) { Assertion.Test(m_hMap == IntPtr.Zero); // Here's what the abbreviations mean: // // LT = LillTek // SM = SharedMem memName = @"Global\LT:SM:" + name; #if SHAREDMEM_DRIVER bool fCreated; m_hMap = WinApi.MEM_Open(memName, cbMem, out fCreated); fExists = !fCreated; #else // Create the memory object SecurityAttributes sa; sa = new SecurityAttributes(SecurityAccess.Unrestricted); try { // $hack(jeff.lill): // // Beginning with a late service Windows XP service pack, applications not running in // Windows session 0 as a service cannot create global shared memory or other objects. // This results in the API below failing by returning a NULL handle and GetLastError() // returning ERROR_ACCESS_DENIED. Windows added this restriction to prevent malicious // code from creating global objects that will be used by well known services and then // squating on them. // // The work-around below detects this situation and tries creating a non-global object // instead. This will work for most unit testing scenarios. retry: m_hMap = WinApi.CreateFileMapping(new IntPtr(-1), sa.AttributesPtr, WinApi.PAGE_READWRITE, 0, (uint)cbMem, memName); if (m_hMap == IntPtr.Zero) { int error = WinApi.GetLastError(); if (memName.ToLowerInvariant().StartsWith(@"global\") && error == WinErr.ERROR_ACCESS_DENIED) { memName = "LT:SM:" + name; goto retry; } throw new InvalidOperationException(string.Format(null, "Failed on Windows error [{0}].", error)); } // For some weird reason, Marshal.GetLastWin32Error() is returning ERROR_IO_PENDING // when CreateFileMapping() is called on an exising block of shared memory instead // of returning ERROR_ALREADY_EXISTS. So I'm going to call GetLastError() directly. // This will be a bit of a performance hit but Open() will be called infrequently // in real applications. fExists = WinApi.GetLastError() == WinApi.ERROR_ALREADY_EXISTS; } finally { sa.Close(); } #endif // SHAREDMEM_DRIVER m_pvBlock = null; m_cbBlock = cbMem; m_cLock = 0; if (!fExists && mode == OpenMode.OPEN_ONLY) { #if SHAREDMEM_DRIVER WinApi.MEM_Close(m_hMap); #else WinApi.CloseHandle(m_hMap); #endif m_hMap = IntPtr.Zero; throw new InvalidOperationException("Shared memory does not exist."); } else if (fExists && mode == OpenMode.CREATE_ONLY) { #if SHAREDMEM_DRIVER WinApi.MEM_Close(m_hMap); #else WinApi.CloseHandle(m_hMap); #endif m_hMap = IntPtr.Zero; throw new InvalidOperationException("Shared memory already exists."); } // Here's what the abbreviations mean: // // LT = LillTek // SM = Shared Memory // MX = Mutex mutexName = "LT:SM:MX:" + name; if (fExists) { try { // Open the mutex m_mutex = new GlobalMutex(mutexName); } catch { #if SHAREDMEM_DRIVER WinApi.MEM_Close(m_hMap); #else WinApi.CloseHandle(m_hMap); #endif m_hMap = IntPtr.Zero; throw; } } else { try { // Create the mutex m_mutex = new GlobalMutex(mutexName, true, out createdNew); if (createdNew) { // Map the shared memory and zero it. byte *p; p = Lock(); for (int i = 0; i < m_cbBlock; p[i++] = 0) { ; } Unlock(); m_mutex.ReleaseMutex(); } } catch { #if SHAREDMEM_DRIVER WinApi.MEM_Close(m_hMap); #else WinApi.CloseHandle(m_hMap); #endif m_hMap = IntPtr.Zero; throw; } } } }
public bool SendPacketToClientByMemory(Objects.Client client, byte[] packet) { bool ret = false; if (client.LoggedIn) { if (!client.IO.IsSendToClientCodeWritten) { if (!client.IO.WriteOnGetNextPacketCode()) { return(false); } } byte[] originalStream = client.Memory.ReadBytes(Tibia.Addresses.Client.RecvStream, 12); IntPtr myStreamAddress = WinApi.VirtualAllocEx( client.ProcessHandle, IntPtr.Zero, (uint)packet.Length, WinApi.AllocationType.Commit | WinApi.AllocationType.Reserve, WinApi.MemoryProtection.ExecuteReadWrite); if (myStreamAddress != IntPtr.Zero) { if (client.Memory.WriteBytes( myStreamAddress.ToInt64(), packet, (uint)packet.Length)) { byte[] myStream = new byte[12]; Array.Copy(BitConverter.GetBytes(myStreamAddress.ToInt32()), myStream, 4); Array.Copy(BitConverter.GetBytes(packet.Length), 0, myStream, 4, 4); if (client.Memory.WriteBytes(Tibia.Addresses.Client.RecvStream, myStream, 12)) { if (client.Memory.WriteByte(client.IO.SendToClientAddress.ToInt64(), 0x1)) { IntPtr threadHandle = WinApi.CreateRemoteThread( client.ProcessHandle, IntPtr.Zero, 0, new IntPtr(Tibia.Addresses.Client.ParserFunc), IntPtr.Zero, 0, IntPtr.Zero); WinApi.WaitForSingleObject(threadHandle, 0xFFFFFFFF);//INFINITE=0xFFFFFFFF WinApi.CloseHandle(threadHandle); ret = true; client.Memory.WriteByte(client.IO.SendToClientAddress.ToInt64(), 0x0); } client.Memory.WriteBytes(Tibia.Addresses.Client.RecvStream, originalStream, 12); } } } if (myStreamAddress != IntPtr.Zero) { WinApi.VirtualFreeEx( client.ProcessHandle, myStreamAddress, 12, WinApi.AllocationType.Release); } } return(ret); }
public void Dispose() { WinApi.CloseHandle(driverHandle); }
/// <summary> /// Inject DLL in pokerClientProcess /// </summary> protected virtual void InjectDll() { Check.Require(pokerClientProcess != null, "Cannot inject Dll to not existing process"); Check.Require((pokerClientProcess.Id == Process.GetCurrentProcess().Id), "Cannot create an injector for the current process"); LogProvider.Log.Log(this, string.Format(CultureInfo.InvariantCulture, "Injecting into process \"{0}\"", ProcessName), LogMessageType.Info); // Enter in debug mode to be able to manipulate with processes Process.EnterDebugMode(); // Required access to client process var requiredAccess = ProcessAccessFlags.QueryInformation | ProcessAccessFlags.CreateThread | ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMWrite | ProcessAccessFlags.VMRead; // Open client process and get its handle handle = WinApi.OpenProcess(requiredAccess, false, pokerClientProcess.Id); if (handle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } var dllPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), LibPath, DllToInject); if (!File.Exists(dllPath)) { throw new FileNotFoundException(string.Format("Dll {0} is missing", dllPath)); } var injectedDllProcessAddress = GetInjectedDllProcessAddress(); // Eject dll from client process if (injectedDllProcessAddress != IntPtr.Zero) { LogProvider.Log.Info(this, string.Format(CultureInfo.InvariantCulture, "Found already injected dll in \"{0}\" processes. Dll will be ejected. [{1}]", ProcessName, Identifier)); EjectDll(injectedDllProcessAddress); Task.Delay(EjectDllTimeout).Wait(); } // pointer to allocated memory of lib path string IntPtr pLibRemote = IntPtr.Zero; // handle to thread from CreateRemoteThread IntPtr hThread = IntPtr.Zero; // unmanaged C-String pointer IntPtr pLibFullPathUnmanaged = Marshal.StringToHGlobalUni(dllPath); try { uint sizeUni = (uint)Encoding.Unicode.GetByteCount(dllPath); // Get Handle to Kernel32.dll and pointer to LoadLibraryW IntPtr hKernel32 = WinApi.GetModuleHandle("Kernel32"); if (hKernel32 == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Kernel32 not found"); } IntPtr hLoadLib = WinApi.GetProcAddress(hKernel32, "LoadLibraryW"); if (hLoadLib == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "FreeLibrary not found"); } // allocate memory to the local process for libFullPath pLibRemote = WinApi.VirtualAllocEx(handle, IntPtr.Zero, sizeUni, AllocationType.Commit, MemoryProtection.ReadWrite); if (pLibRemote == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Memory hasn't been allocated"); } // write libFullPath to pLibPath int bytesWritten; if (!WinApi.WriteProcessMemory(handle, pLibRemote, pLibFullPathUnmanaged, sizeUni, out bytesWritten) || bytesWritten != (int)sizeUni) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Couldn't write data in process memory"); } // load dll via call to LoadLibrary using CreateRemoteThread hThread = WinApi.CreateRemoteThread(handle, IntPtr.Zero, 0, hLoadLib, pLibRemote, 0, IntPtr.Zero); if (hThread == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Couldn't create remote thread"); } if (WinApi.WaitForSingleObject(hThread, (uint)ThreadWaitValue.Infinite) != (uint)ThreadWaitValue.Object0) { throw new Win32Exception(Marshal.GetLastWin32Error(), "WaitForSingleObject return wrong code"); } // get address of loaded module - this doesn't work in x64, so just iterate module list to find injected module IntPtr hLibModule; if (!WinApi.GetExitCodeThread(hThread, out hLibModule)) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Couldn't obtain exit code"); } if (hLibModule == IntPtr.Zero) { throw new Exception("Code executed properly, but unable to get an appropriate module handle, possible Win32Exception", new Win32Exception(Marshal.GetLastWin32Error())); } pokerClientProcess.Refresh(); // iterate modules in target process to find our newly injected module foreach (ProcessModule module in pokerClientProcess.Modules) { if (module.ModuleName == DllToInject) { injectedProcessModule = module; break; } } if (injectedProcessModule == null) { throw new Exception("Injected module could not be found within the target process!"); } isInjected = true; LogProvider.Log.Log(this, string.Format(CultureInfo.InvariantCulture, "Successfully injected into process \"{0}\". [{1}]", ProcessName, Identifier), LogMessageType.Info); } finally { Marshal.FreeHGlobal(pLibFullPathUnmanaged); WinApi.CloseHandle(hThread); WinApi.VirtualFreeEx(pokerClientProcess.Handle, pLibRemote, 0, AllocationType.Release); } }