/// <summary> /// Executes applied injection, CURRENTLY DOES NOT PROVIDE ANY THREAD ERROR HANDLING /// </summary> public void Execute(uint waitMilliseconds = 5000) { if (IsApplied) { IntPtr threadId, hThread; hThread = OnyxNative.CreateRemoteThread( _hProcess, IntPtr.Zero, 0, _injectionAddress, IntPtr.Zero, ThreadFlags.THREAD_EXECUTE_IMMEDIATELY, out threadId); if (hThread == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (OnyxNative.WaitForSingleObject(hThread, waitMilliseconds) != WaitValues.WAIT_OBJECT_0) { throw new TimeoutException("Injected thread timeout"); } } else { throw new Exception("Injection must first be applied by Apply() method, before you can execute it"); } }
private IntPtr CreateThreadHandler( IntPtr lpSecurityAttributes, uint StackSize, IntPtr lpStartFunction, IntPtr lpThreadParameter, uint CreationFlags, IntPtr lpThreadId) { var hThread = (IntPtr)_detourCreateThread.CallOriginal(lpSecurityAttributes, StackSize, lpStartFunction, lpThreadParameter, CreationFlags, lpThreadId); var threadId = OnyxNative.GetThreadId(hThread); var currentThreadId = OnyxNative.GetCurrentThreadId(); var addToExcluded = true; addToExcluded = addToExcluded & Onyx.Instance.Detours.GlobalExcludedThreadId.Contains(currentThreadId); if (addToExcluded) { Onyx.Instance.Detours.GlobalExcludedThreadId.Add(threadId); } /*string temp = String.Empty; * foreach (var i in Onyx.Instance.Detours.GlobalExcludedThreadId) * { * temp += " " + i.ToString("X4"); * } * System.Windows.Forms.MessageBox.Show(String.Format("Thread {0:X4} created by thread {1:X4} \r\n Excluded: {2}", threadId, currentThreadId,temp));*/ return(hThread); }
public bool Inject(IntPtr hProcess, IntPtr injectionAddress) { var asmCode = _asmCode.ToString(); var is64bitProcess = OnyxNative.Is64bitProcess(hProcess); if (hProcess == IntPtr.Zero) { throw new ArgumentException("Wrong process handle !"); } if (injectionAddress == IntPtr.Zero) { throw new ArgumentException("Bad injection address !"); } if (!asmCode.Contains("org ")) { asmCode = asmCode.Insert(0, String.Format("org 0x{0:X08}\n", (long)injectionAddress)); } if (!(asmCode.Contains("use32") || (asmCode.Contains("use64")))) { asmCode = asmCode.Insert(0, is64bitProcess ? "use64" : "use32"); } if (is64bitProcess && asmCode.Contains("use32")) { throw new ArgumentException("Target process is 64bit, but you're trying to compile using use32 parameter !", "use32/64 switch"); } if (!is64bitProcess && asmCode.Contains("use64")) { throw new ArgumentException("Target process is 32bit, but you're trying to compile using use64 parameter !", "use32/64 switch"); } Assemble(asmCode); OnyxMemory.WriteBytes(hProcess, injectionAddress, _assembledBytes); return(true); }
/// <summary> /// Writes byte array to destination address /// </summary> /// <param name="_hProcess">Opened process handle</param> /// <param name="_targetAddress">Address to write to</param> /// <param name="_bytes">Value to write</param> /// <returns></returns> public static bool WriteBytes(IntPtr _hProcess, IntPtr _targetAddress, byte[] _bytes) { if (_bytes == null) { throw new ArgumentNullException("_bytes"); } if (_hProcess == IntPtr.Zero) { throw new Exception("Target process handle == IntPtr.Zero, open process first"); } var methodDesc = String.Format( "WriteBytes(IntPtr 0x{0:X}, IntPtr 0x:{1:X}, byte[] {2}b)", _hProcess.ToInt64(), _targetAddress.ToInt64(), _bytes.Length); int written; if (OnyxNative.WriteProcessMemory(_hProcess, _targetAddress, _bytes, (uint)_bytes.Length, out written)) { if (written != _bytes.Length) { throw new ApplicationException(string.Format("{2} - Could not write all {0} byte(s), only {1} were written", _bytes.Length, written, methodDesc)); } } else { throw new Win32Exception(Marshal.GetLastWin32Error(), methodDesc); } return(true); }
/// <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 IntPtr 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 = Path.GetFullPath(_szDllPath); } if (!File.Exists(_szDllPath)) { throw new ArgumentException("DLL not found.", "_szDllPath"); } var dwBaseAddress = IntPtr.Zero; IntPtr lpLoadLibrary; IntPtr lpDll; IntPtr hThread, threadId; var hKernel32 = OnyxNative.GetModuleHandle(_hProcess, "kernel32.dll"); lpLoadLibrary = (IntPtr)(hKernel32.ToInt64() + OnyxNative.GetExportedFunctionRVA(OnyxNative.GetModuleFileNameEx(_hProcess, hKernel32), "LoadLibraryW").ToInt64()); if (lpLoadLibrary != IntPtr.Zero) { lpDll = OnyxMemory.AllocateMemory(_hProcess); if (lpDll != IntPtr.Zero) { if (OnyxMemory.Write(_hProcess, lpDll, _szDllPath)) { //wait for thread handle to have signaled state hThread = OnyxNative.CreateRemoteThread( _hProcess, IntPtr.Zero, 0, lpLoadLibrary, lpDll, ThreadFlags.THREAD_EXECUTE_IMMEDIATELY, out threadId); //wait for thread handle to have signaled state //exit code will be equal to the base address of the dll if (OnyxNative.WaitForSingleObject(hThread, 5000) == WaitValues.WAIT_OBJECT_0) { OnyxNative.GetExitCodeThread(hThread, out dwBaseAddress); if (dwBaseAddress == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } OnyxNative.CloseHandle(hThread); } OnyxMemory.FreeMemory(_hProcess, lpDll); } } return(dwBaseAddress); }
/// <summary> /// Releases, decommits, or releases and decommits a region of memory within the virtual address space of a specified /// process. /// </summary> /// <param name="_hProcess">Handle to the process in which memory will be freed.</param> /// <param name="_memAddress">A pointer to the starting address of the region of memory to be freed. </param> /// <param name="_bytesCount"> /// The size of the region of memory to free, in bytes. /// If the dwFreeType parameter is MEM_RELEASE, dwSize must be 0 (zero). The function frees the entire region that is /// reserved in the initial allocation call to VirtualAllocEx. /// </param> /// <param name="_freeType">The type of free operation. See <see cref="OnyxNative.MemoryFreeType" />.</param> /// <returns>Returns true on success, false on failure.</returns> public static bool FreeMemory(IntPtr _hProcess, IntPtr _memAddress, uint _bytesCount, uint _freeType) { if (_freeType == OnyxNative.MemoryFreeType.MEM_RELEASE) { _bytesCount = 0; } return(OnyxNative.VirtualFreeEx(_hProcess, _memAddress, _bytesCount, _freeType)); }
public OnyxThreadInterceptor() { var hKernel32 = OnyxNative.LoadLibrary("kernel32.dll"); var pCreateThread = OnyxNative.GetProcAddress(hKernel32, "CreateThread"); _dCreateThreadHandler = CreateThreadHandler; _detourCreateThread = new OnyxDetour(pCreateThread, _dCreateThreadHandler); _detourCreateThread.IgnoreThreadChecking = true; }
/// <summary> /// Allocates a block of memory in the target process. /// </summary> /// <param name="_hProcess">Handle to the process in which memory will be allocated.</param> /// <param name="_bytesCount">Number of bytes to be allocated. Default is 0x1000.</param> /// <param name="_allocationType">The type of memory allocation. See <see cref="OnyxNative.MemoryAllocType" /></param> /// <param name="_protectType"> /// The memory protection for the region of pages to be allocated. If the pages are being /// committed, you can specify any one of the <see cref="OnyxNative.MemoryProtectType" /> constants. /// </param> /// <returns>Returns zero on failure, or the base address of the allocated block of memory on success.</returns> public static IntPtr AllocateMemory(IntPtr _hProcess, uint _bytesCount, uint _allocationType, uint _protectType) { var result = OnyxNative.VirtualAllocEx(_hProcess, IntPtr.Zero, _bytesCount, _allocationType, _protectType); if (result == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(result); }
public void RefreshExportTable() { var ExportedFunctions = new List <FunctionSnapshot>(); if (Functions != null) { Functions.RemoveAll(delegate(FunctionSnapshot fs) { return(fs.FuncType == FunctionType.Exported); }); } var is64bitDll = false; var isManagedDll = false; LOADED_IMAGE loadedImage; OnyxNative.MapAndLoad(FileName, null, out loadedImage, true, true); if (loadedImage.MappedAddress != IntPtr.Zero) { uint size; IMAGE_EXPORT_DIRECTORY ExportDir; var pExportDir = OnyxNative.ImageDirectoryEntryToData(loadedImage.MappedAddress, false, OnyxNative.IMAGE_DIRECTORY_ENTRY_EXPORT, out size); if (pExportDir == IntPtr.Zero) { isManagedDll = true; return; // Managed dll; } ExportDir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(pExportDir, typeof(IMAGE_EXPORT_DIRECTORY)); var pFuncNames = OnyxNative.RvaToVa(loadedImage, ExportDir.AddressOfNames); var pFuncAdressess = OnyxNative.RvaToVa(loadedImage, ExportDir.AddressOfFunctions); var pFuncOrdinals = OnyxNative.RvaToVa(loadedImage, ExportDir.AddressOfNameOrdinals); for (uint i = 0; i < ExportDir.NumberOfNames; i++) { var funcName = Marshal.PtrToStringAnsi((IntPtr)OnyxNative.RvaToVa(loadedImage, (IntPtr)Marshal.ReadInt32((IntPtr)((pFuncNames.ToInt64() + 4 * i))))); var funcOrdinal = (UInt16)(Marshal.ReadInt16((IntPtr)(pFuncOrdinals.ToInt64() + sizeof(UInt16) * i))); var funcAddress = (IntPtr)(Marshal.ReadInt32((IntPtr)(pFuncAdressess.ToInt64() + sizeof(UInt32) * funcOrdinal))); funcOrdinal += (UInt16)ExportDir.Base; var fs = new FunctionSnapshot(funcName, funcAddress, funcOrdinal, FunctionType.Exported, this); ExportedFunctions.Add(fs); FunctionFound(this, new EventArgs <FunctionSnapshot>(fs)); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (Functions == null) { Functions = new List <FunctionSnapshot>(); } Functions.AddRange(ExportedFunctions); }
/// <summary> /// </summary> /// <returns>True if hook is allowed to call UserFunction</returns> protected bool CheckThread() { if (IgnoreThreadChecking) { return(true); } var currentThreadId = OnyxNative.GetCurrentThreadId(); // callee thread, probably should save GCID's original address on Onyx startup var result = !Onyx.Instance.Detours.GlobalExcludedThreadId.Contains(currentThreadId); return(result); }
/// <summary> /// Reads _count bytes from specified process memory /// </summary> /// <param name="_hProcess">Opened process handle</param> /// <param name="_targetAddress">Address to read from</param> /// <param name="_count">Bytes count to read</param> /// <returns></returns> public static byte[] ReadBytes(IntPtr _hProcess, IntPtr _targetAddress, int _count) { if (_hProcess == IntPtr.Zero) { throw new Exception("Target process handle == IntPtr.Zero, open process first"); } var ret = new byte[_count]; int numRead; if (OnyxNative.ReadProcessMemory(_hProcess, _targetAddress, ret, _count, out numRead) && numRead == _count) { return(ret); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
public void InjectAndExecute(IntPtr hProcess, IntPtr injectionAddress) { Inject(hProcess, injectionAddress); var threadId = IntPtr.Zero; var hThread = OnyxNative.CreateRemoteThread( hProcess, IntPtr.Zero, 0, injectionAddress, IntPtr.Zero, ThreadFlags.THREAD_EXECUTE_IMMEDIATELY, out threadId); //wait for thread handle to have signaled state //exit code will be equal to the base address of the dll if (OnyxNative.WaitForSingleObject(hThread, 5000) == WaitValues.WAIT_OBJECT_0) { } OnyxNative.CloseHandle(hThread); }
public uint GetExportedFunctionsCount() { LOADED_IMAGE loadedImage; OnyxNative.MapAndLoad(FileName, null, out loadedImage, true, true); if (loadedImage.MappedAddress != IntPtr.Zero) { uint size; IMAGE_EXPORT_DIRECTORY ExportDir; var pExportDir = OnyxNative.ImageDirectoryEntryToData(loadedImage.MappedAddress, false, OnyxNative.IMAGE_DIRECTORY_ENTRY_EXPORT, out size); if (pExportDir == IntPtr.Zero) { return(0); // Managed dll; } ExportDir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(pExportDir, typeof(IMAGE_EXPORT_DIRECTORY)); return(ExportDir.NumberOfNames); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
//ExecuteInDefaultAppDomain(_processId, Path.GetDirectoryName(Application.ExecutablePath) + "\\" + DLLName, "Onyx.DomainManager.EntryPoint", "Main", ""); /// <summary> /// Loads CLR and target assembly into process address space /// </summary> /// <param name="_processId">Target process</param> /// <param name="_assemblyPath">Target assembly</param> /// <param name="_typeName">Type that contains method, that will be executed</param> /// <param name="_methodName">Method, that will be executed upon load</param> /// <param name="_args">Arguments, that will be passed to method</param> public static void InjectAndExecuteInDefaultAppDomain(Int32 _processId, String _assemblyPath, String _typeName, String _methodName, String _args) { if (_assemblyPath == null) { throw new ArgumentNullException(nameof(_assemblyPath)); } if (_typeName == null) { throw new ArgumentNullException(nameof(_typeName)); } if (_methodName == null) { throw new ArgumentNullException(nameof(_methodName)); } Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Injecting assembly '{0}'({1}.{2}, args '{3}') into process {4}...", _assemblyPath, _typeName, _methodName, _args ?? "null", _processId); var is64BitProcess = OnyxNative.Is64bitProcess(_processId); var clrDllPath = is64BitProcess ? MSCOREE_DLL_NAME_64 : MSCOREE_DLL_NAME_32; try { using (var onyx = new Onyx(_processId)) { // проверяем, не загружена ли уже CLR var hRemoteClr = OnyxNative.GetModuleHandle(onyx.Memory.OpenedProcess, MSCOREE_DLL_NAME); if (hRemoteClr != IntPtr.Zero) { Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] MSCOREE.dll({1}) is already exists in process {0}...", _processId, clrDllPath); } else { Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Loading MSCOREE.dll({1}) into process {0}...", _processId, clrDllPath); InjectDllCreateThread(onyx.Memory.OpenedProcess, clrDllPath); hRemoteClr = OnyxNative.GetModuleHandle(onyx.Memory.OpenedProcess, MSCOREE_DLL_NAME); if (hRemoteClr == IntPtr.Zero) { throw new ApplicationException(String.Format("Could not load dll '{0}' into process {1}", clrDllPath, _processId)); } } Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] MSCOREE.dll({1}) handle - 0x{0:X8}", hRemoteClr.ToInt64(), clrDllPath); var clrModuleName = OnyxNative.GetModuleFileNameEx(onyx.Memory.OpenedProcess, hRemoteClr); var bindToRuntimeFuncRva = OnyxNative.GetExportedFunctionRVA(clrModuleName, "CorBindToRuntimeEx"); var lpCorBindToRuntimeEx = (IntPtr)(hRemoteClr.ToInt64() + bindToRuntimeFuncRva.ToInt64()); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] CorBindToRuntimeEx ptr -> 0x{0:X8}", lpCorBindToRuntimeEx.ToInt64()); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Allocating code caves..."); var lpCLSID_CLRRuntimeHost = onyx.Memory.AllocateMemory((uint)(CLSID_CLRRuntimeHost.Length * 4)); var lpIID_ICLRRuntimeHost = onyx.Memory.AllocateMemory((uint)IID_ICLRRuntimeHost.Length); var lpClrHost = onyx.Memory.AllocateMemory(0x4); var lpdwRet = onyx.Memory.AllocateMemory(0x4); var lpCodeCave = onyx.Memory.AllocateMemory(0x256); var lpAssemblyPath = onyx.Memory.AllocateMemory((uint)_assemblyPath.Length + 1); var lpTypeName = onyx.Memory.AllocateMemory((uint)_typeName.Length + 1); var lpMethodName = onyx.Memory.AllocateMemory((uint)_methodName.Length + 1); var lpArgs = onyx.Memory.AllocateMemory((uint)_args.Length + 1); var lpBuildFlavor = onyx.Memory.AllocateMemory((uint)BuildFlavor.Length * 2 + 2); var lpFrameworkVersion = onyx.Memory.AllocateMemory((uint)FrameworkVersion.Length * 2 + 1); onyx.Memory.Write(lpBuildFlavor, BuildFlavor); onyx.Memory.Write(lpAssemblyPath, _assemblyPath); onyx.Memory.Write(lpTypeName, _typeName); onyx.Memory.Write(lpMethodName, _methodName); onyx.Memory.Write(lpArgs, _args); onyx.Memory.Write(lpCLSID_CLRRuntimeHost, CLSID_CLRRuntimeHost); onyx.Memory.Write(lpIID_ICLRRuntimeHost, IID_ICLRRuntimeHost); onyx.Memory.Write(lpFrameworkVersion, FrameworkVersion); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Preparing ASM code..."); var fasm = new RemoteFasm(); fasm.AddLine("use32"); fasm.AddLine("push {0}", lpClrHost.ToInt64()); fasm.AddLine("push {0}", lpIID_ICLRRuntimeHost.ToInt64()); fasm.AddLine("push {0}", lpCLSID_CLRRuntimeHost.ToInt64()); fasm.AddLine("push 0"); fasm.AddLine("push {0}", lpBuildFlavor.ToInt64()); fasm.AddLine("push {0}", lpFrameworkVersion.ToInt64()); fasm.AddLine("mov eax, {0}", lpCorBindToRuntimeEx.ToInt64()); fasm.AddLine("call eax"); // CorBindToRuntimeEx () fasm.AddLine("mov eax, [{0}]", lpClrHost.ToInt64()); fasm.AddLine("mov ecx, [eax]"); fasm.AddLine("mov edx, [ecx+0xC]"); fasm.AddLine("push eax"); fasm.AddLine("call edx"); // ClrHost () fasm.AddLine("push {0}", lpdwRet.ToInt64()); fasm.AddLine("push {0}", lpArgs.ToInt64()); fasm.AddLine("push {0}", lpMethodName.ToInt64()); fasm.AddLine("push {0}", lpTypeName.ToInt64()); fasm.AddLine("push {0}", lpAssemblyPath.ToInt64()); fasm.AddLine("mov eax, [{0}]", lpClrHost.ToInt64()); fasm.AddLine("mov ecx, [eax]"); fasm.AddLine("push eax"); fasm.AddLine("mov eax, [ecx+0x2C]"); fasm.AddLine("call eax"); fasm.AddLine("retn"); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Injecting and executing ASM code..."); fasm.InjectAndExecute(onyx.Memory.OpenedProcess, lpCodeCave); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Disposing code caves..."); onyx.Memory.FreeMemory(lpCLSID_CLRRuntimeHost); onyx.Memory.FreeMemory(lpIID_ICLRRuntimeHost); onyx.Memory.FreeMemory(lpClrHost); onyx.Memory.FreeMemory(lpdwRet); onyx.Memory.FreeMemory(lpCodeCave); onyx.Memory.FreeMemory(lpAssemblyPath); onyx.Memory.FreeMemory(lpTypeName); onyx.Memory.FreeMemory(lpMethodName); onyx.Memory.FreeMemory(lpArgs); onyx.Memory.FreeMemory(lpBuildFlavor); onyx.Memory.FreeMemory(lpFrameworkVersion); Logger.InfoFormat("[InjectAndExecuteInDefaultAppDomain] Assembly sussessfully injected"); } } catch (Exception ex) { throw new ApplicationException(String.Format("Could not inject assembly '{0}'({1}.{2}, args '{3}') into process {4}", _assemblyPath, _typeName, _methodName, _args ?? "null", _processId), ex); } }
public OnyxMemory(int _pid) { m_hOpenedProcess = OnyxNative.OpenProcess(0x001F0FFF, true, _pid); }
public ProcessSnapshot(Process p) { try { ProcessName = p.ProcessName; Handle = p.Handle; Id = p.Id; MainModule = new ProcessModuleSnapshot(p.MainModule); Modules = new List <ProcessModuleSnapshot>(); var lpcbNeeded = 0; IntPtr[] hModule = null; // Перечисляем 32/64-bit модули for (var moduleBit = 1; moduleBit <= 2; moduleBit++) { OnyxNative.EnumProcessModulesEx(p.Handle, null, 0, out lpcbNeeded, moduleBit); // Пробуем получить lpcbNeeded var arrSize = lpcbNeeded / IntPtr.Size; // получаем колличество модулей hModule = new IntPtr[arrSize]; // Создаём массив нужного размера if (OnyxNative.EnumProcessModulesEx(p.Handle, hModule, lpcbNeeded, out lpcbNeeded, moduleBit)) { var nameFile = new StringBuilder(255); // Создаём массив, буфер из символов for (var i = 0; i < arrSize; i++) { // Избегаем повторное добавление модулей (при перечислении для 64 bit процессов) /*if (Modules.FindIndex(delegate(ProcessModuleSnapshot pms) * { * return pms.BaseAddress == hModule[i]; * }) > 0) * continue;*/ var Module = new ProcessModuleSnapshot(); OnyxNative.GetModuleFileNameEx(p.Handle, hModule[i], nameFile, nameFile.Capacity); // Пытаемся получить полный путь модуля Module.ModuleName = Path.GetFileName(nameFile.ToString()); Module.FileName = nameFile.ToString(); Module.BaseAddress = hModule[i]; Module.InWhatProcess = this; var mi = new _MODULEINFO(); if (OnyxNative.GetModuleInformation(p.Handle, hModule[i], out mi, Marshal.SizeOf(mi))) { Module.ModuleMemorySize = (int)mi.SizeOfImage; Module.BaseAddress = mi.BaseOfDll; Module.EntryPoint = mi.EntryPoint; } Module.is64bit = moduleBit == 2; Modules.Add(Module); } } } /* * foreach (ProcessModule pm in p.Modules) * { * Modules.Add(new ProcessModuleSnapshot(pm,this)); * }*/ } catch (Win32Exception) { Modules = null; } catch (InvalidOperationException) { Modules = null; } }
/// <summary> /// Initializes a new instance of the OnyxDetour class. /// </summary> public OnyxDetour(IntPtr _targetAddress, Delegate _detour, string _detourName = null) { if (_detourName != null) { m_name = _detourName; } if (_targetAddress == IntPtr.Zero) { throw new ArgumentNullException("_targetAddress"); } if (_detour == null) { throw new ArgumentNullException("_detour"); } m_detour = _detour; m_targetAddress = _targetAddress; IntPtr detourAddress = Marshal.GetFunctionPointerForDelegate(_detour); m_checkThread = CheckThread; var pCheckThread = Marshal.GetFunctionPointerForDelegate(m_checkThread); var fasm = new RemoteFasm(); fasm.Clear(); fasm.AddLine("@checkthread:"); fasm.AddLine("call $+5"); fasm.AddLine("add dword [esp], {0}", 5 + 4 + 1); fasm.AddLine("push 0{0:X}h", pCheckThread.ToInt64()); fasm.AddLine("retn"); fasm.AddLine("@checkthread_TestResults:"); fasm.AddLine("test eax,eax"); fasm.AddLine("jz @functionretn"); fasm.AddLine("@userfunction:"); fasm.AddLine("push 0{0:X}h", detourAddress.ToInt64()); fasm.AddLine("retn"); fasm.AddLine("@functionretn:"); var jumperBytes = fasm.Assemble(); pJumperCodeCave = Onyx.Instance.Memory.AllocateMemory(256); Onyx.Instance.Memory.WriteBytes(pJumperCodeCave, jumperBytes); fasm.Clear(); fasm.AddLine("push 0{0:X}h", pJumperCodeCave.ToInt64()); fasm.AddLine("retn"); m_detourBytes = fasm.Assemble(); disasm = new Disasm(); var realEip = m_targetAddress; var bytesDisassembled = 0; while (bytesDisassembled < m_detourBytes.Length) { var managedInstructionBuffer = Onyx.Instance.Memory.ReadBytes(realEip, 15); var instructionBuffer = new UnmanagedBuffer(managedInstructionBuffer); disasm.EIP = instructionBuffer.Ptr; var length = BeaEngine32.Disasm(disasm); if ((length != (int)BeaConstants.SpecialInfo.OUT_OF_BLOCK) && (length != (int)BeaConstants.SpecialInfo.UNKNOWN_OPCODE)) { bytesDisassembled += length; if ((disasm.Instruction.BranchType == (int)BeaConstants.BranchType.JmpType) && (disasm.Instruction.AddrValue != 0)) { // jmp = modify EIP //disasm.EIP = (IntPtr)disasm.Instruction.AddrValue; } realEip = (IntPtr)((ulong)realEip + (ulong)length); } else { throw new Exception(String.Format("Disassembly error occured, exception code = {0}", length)); } } //Store the orginal bytes of decoded instructions in memory after jumper code m_originalBytes = Onyx.Instance.Memory.ReadBytes(m_targetAddress, bytesDisassembled); var pOriginalFunction = pJumperCodeCave.Add((UInt32)jumperBytes.Length); Onyx.Instance.Memory.WriteBytes(pOriginalFunction, m_originalBytes); m_originalFunction = Marshal.GetDelegateForFunctionPointer(pOriginalFunction, _detour.GetType()); var pReturnerCodeCave = pJumperCodeCave.Add((UInt32)jumperBytes.Length + (UInt32)bytesDisassembled); fasm.Clear(); fasm.AddLine("push 0{0:X}h", m_targetAddress.Add((UInt32)bytesDisassembled).ToInt64()); fasm.AddLine("retn"); var returnerBytes = fasm.Assemble(); Onyx.Instance.Memory.WriteBytes(pReturnerCodeCave, returnerBytes); // adding calling thread to exclusions Onyx.Instance.Detours.GlobalExcludedThreadId.Add(OnyxNative.GetCurrentThreadId()); }
/// <summary> /// Closes opened process Handle /// </summary> public void Dispose() { OnyxNative.CloseHandle(m_hOpenedProcess); }