private static void PatchImports(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, int processId) { string lpBuffer = string.Empty; string str2 = string.Empty; foreach (IMAGE_IMPORT_DESCRIPTOR image_import_descriptor in image.EnumImports()) { if (image.ReadString((long)image.GetPtrFromRVA(image_import_descriptor.Name), SeekOrigin.Begin, out lpBuffer, -1, null)) { IMAGE_THUNK_DATA image_thunk_data; IntPtr zero = IntPtr.Zero; zero = GetRemoteModuleHandle(lpBuffer, processId); if (zero.IsNull()) { throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", lpBuffer)); } uint ptrFromRVA = image.GetPtrFromRVA(image_import_descriptor.FirstThunkPtr); uint num2 = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA)); while (image.Read <IMAGE_THUNK_DATA>((long)ptrFromRVA, SeekOrigin.Begin, out image_thunk_data) && (image_thunk_data.u1.AddressOfData > 0)) { IntPtr hModule = IntPtr.Zero; object lpProcName = null; if ((image_thunk_data.u1.Ordinal & 0x80000000) == 0) { if (!image.ReadString((long)(image.GetPtrFromRVA(image_thunk_data.u1.AddressOfData) + 2), SeekOrigin.Begin, out str2, -1, null)) { throw image.GetLastError(); } lpProcName = str2; } else { lpProcName = (ushort)(image_thunk_data.u1.Ordinal & 0xffff); } if (!(hModule = WinAPI.GetModuleHandleA(lpBuffer)).IsNull()) { IntPtr ptr = lpProcName.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(hModule, (string)lpProcName) : WinAPI.GetProcAddress(hModule, (uint)(((ushort)lpProcName) & 0xffff)); if (!ptr.IsNull()) { hModule = zero.Add((long)ptr.Subtract(((long)hModule.ToInt32())).ToInt32()); } } else { hModule = WinAPI.GetProcAddressEx(hProcess, zero, lpProcName); } if (hModule.IsNull()) { throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", str2, lpBuffer)); } image.Write <int>((long)ptrFromRVA, SeekOrigin.Begin, hModule.ToInt32()); ptrFromRVA += num2; } } } }
/* * Handles loading of all dependent modules. Iterates the IAT entries and attempts to load (using LoadLibrary) all * of the necessary modules for the main module to function. The manifest is extracted and activation contexts used to * ensure correct loading of Side-By-Side dependencies. */ private static bool LoadDependencies(PortableExecutable image, IntPtr hProcess, int processId) { List<string> neededDependencies = new List<string>(); string curdep = string.Empty; bool success = false; foreach (var desc in image.EnumImports()) { if (image.ReadString(image.GetPtrFromRVA(desc.Name), SeekOrigin.Begin, out curdep) && !string.IsNullOrEmpty(curdep)) { if (GetRemoteModuleHandle(curdep, processId).IsNull()) neededDependencies.Add(curdep); } } if (neededDependencies.Count > 0) //do we actually need to load any new modules? { byte[] bManifest = ExtractManifest(image); string pathManifest = string.Empty; if (bManifest == null) // no internal manifest, may be an external manifest or none at all? { if (!string.IsNullOrEmpty(image.FileLocation) && File.Exists(Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"))) { pathManifest = Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"); } else // no internal or external manifest, presume no side-by-side dependencies. { var standard = InjectionMethod.Create(InjectionMethodType.Standard); var results = standard.InjectAll(neededDependencies.ToArray(), hProcess); foreach (var result in results) if (result.IsNull()) return false; // failed to inject a dependecy, abort mission. return true; // done loading dependencies. } } else { pathManifest = Utils.WriteTempData(bManifest); } if (string.IsNullOrEmpty(pathManifest)) return false; IntPtr pResolverStub = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)RESOLVER_STUB.Length, 0x1000 | 0x2000, 0x40); IntPtr pManifest = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(pathManifest + "\0"), 0x04); IntPtr pModules = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(string.Join("\0", neededDependencies.ToArray()) + "\0"), 0x04); if (!pResolverStub.IsNull()) { var resolverStub = (byte[])RESOLVER_STUB.Clone(); uint nBytes = 0; // Call patching. Patch the empty function addresses with the runtime addresses. BitConverter.GetBytes(FN_CREATEACTCTXA.Subtract(pResolverStub.Add(0x3F)).ToInt32()).CopyTo(resolverStub, 0x3B); BitConverter.GetBytes(FN_ACTIVATEACTCTX.Subtract(pResolverStub.Add(0x58)).ToInt32()).CopyTo(resolverStub, 0x54); BitConverter.GetBytes(FN_GETMODULEHANDLEA.Subtract(pResolverStub.Add(0x84)).ToInt32()).CopyTo(resolverStub, 0x80); BitConverter.GetBytes(FN_LOADLIBRARYA.Subtract(pResolverStub.Add(0x92)).ToInt32()).CopyTo(resolverStub, 0x8E); BitConverter.GetBytes(FN_DEACTIVATEACTCTX.Subtract(pResolverStub.Add(0xC8)).ToInt32()).CopyTo(resolverStub, 0xC4); BitConverter.GetBytes(FN_RELEASEACTCTX.Subtract(pResolverStub.Add(0xD1)).ToInt32()).CopyTo(resolverStub, 0xCD); // Parameter patching BitConverter.GetBytes(pManifest.ToInt32()).CopyTo(resolverStub, 0x1F); BitConverter.GetBytes(neededDependencies.Count).CopyTo(resolverStub, 0x28); BitConverter.GetBytes(pModules.ToInt32()).CopyTo(resolverStub, 0x31); if (WinAPI.WriteProcessMemory(hProcess, pResolverStub, resolverStub, resolverStub.Length, out nBytes) && nBytes == (uint)resolverStub.Length) { uint result = WinAPI.RunThread(hProcess, pResolverStub, 0, 5000); success = (result != uint.MaxValue && result != 0); } // Cleanup WinAPI.VirtualFreeEx(hProcess, pModules, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pManifest, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, pResolverStub, 0, 0x8000); } } return success; }
private static bool LoadDependencies(JLibrary.PortableExecutable.PortableExecutable image, IntPtr hProcess, int processId) { List <string> list = new List <string>(); string lpBuffer = string.Empty; bool flag = false; foreach (IMAGE_IMPORT_DESCRIPTOR image_import_descriptor in image.EnumImports()) { if ((image.ReadString((long)image.GetPtrFromRVA(image_import_descriptor.Name), SeekOrigin.Begin, out lpBuffer, -1, null) && !string.IsNullOrEmpty(lpBuffer)) && GetRemoteModuleHandle(lpBuffer, processId).IsNull()) { list.Add(lpBuffer); } } if (list.Count > 0) { byte[] data = ExtractManifest(image); string str2 = string.Empty; if (data == null) { if (string.IsNullOrEmpty(image.FileLocation) || !File.Exists(Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"))) { IntPtr[] ptrArray = InjectionMethod.Create(InjectionMethodType.Standard).InjectAll(list.ToArray(), hProcess); foreach (IntPtr ptr in ptrArray) { if (ptr.IsNull()) { return(false); } } return(true); } str2 = Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest"); } else { str2 = Utils.WriteTempData(data); } if (string.IsNullOrEmpty(str2)) { return(false); } IntPtr ptr2 = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)RESOLVER_STUB.Length, 0x3000, 0x40); IntPtr lpAddress = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(str2 + "\0"), 4); IntPtr ptr4 = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(string.Join("\0", list.ToArray()) + "\0"), 4); if (!ptr2.IsNull()) { byte[] array = (byte[])RESOLVER_STUB.Clone(); uint lpNumberOfBytesRead = 0; BitConverter.GetBytes(FN_CREATEACTCTXA.Subtract(ptr2.Add(((long)0x3fL))).ToInt32()).CopyTo(array, 0x3b); BitConverter.GetBytes(FN_ACTIVATEACTCTX.Subtract(ptr2.Add(((long)0x58L))).ToInt32()).CopyTo(array, 0x54); BitConverter.GetBytes(FN_GETMODULEHANDLEA.Subtract(ptr2.Add(((long)0x84L))).ToInt32()).CopyTo(array, 0x80); BitConverter.GetBytes(FN_LOADLIBRARYA.Subtract(ptr2.Add(((long)0x92L))).ToInt32()).CopyTo(array, 0x8e); BitConverter.GetBytes(FN_DEACTIVATEACTCTX.Subtract(ptr2.Add(((long)200L))).ToInt32()).CopyTo(array, 0xc4); BitConverter.GetBytes(FN_RELEASEACTCTX.Subtract(ptr2.Add(((long)0xd1L))).ToInt32()).CopyTo(array, 0xcd); BitConverter.GetBytes(lpAddress.ToInt32()).CopyTo(array, 0x1f); BitConverter.GetBytes(list.Count).CopyTo(array, 40); BitConverter.GetBytes(ptr4.ToInt32()).CopyTo(array, 0x31); if (WinAPI.WriteProcessMemory(hProcess, ptr2, array, array.Length, out lpNumberOfBytesRead) && (lpNumberOfBytesRead == array.Length)) { uint num2 = WinAPI.RunThread(hProcess, ptr2, 0, 0x1388); flag = (num2 != uint.MaxValue) && (num2 != 0); } WinAPI.VirtualFreeEx(hProcess, ptr4, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, lpAddress, 0, 0x8000); WinAPI.VirtualFreeEx(hProcess, ptr2, 0, 0x8000); } } return(flag); }
private static void PatchImports(PortableExecutable image, IntPtr hProcess, int processId) { string module = string.Empty; string fname = string.Empty; foreach (var desc in image.EnumImports()) { if (image.ReadString(image.GetPtrFromRVA(desc.Name), SeekOrigin.Begin, out module)) { IntPtr pModule = IntPtr.Zero; IntPtr tModule = IntPtr.Zero; //Thanks to FastLoadDependencies, all dependent modules *should* be loaded into the remote process already. pModule = GetRemoteModuleHandle(module, processId); if (pModule.IsNull()) throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", module)); //now have a supposedly valid module handle remote process, all that remains to be done is patch the info. uint pThunk = image.GetPtrFromRVA(desc.FirstThunkPtr); //despite the fact FirstThunk and OriginalFirstThunk are identical within an unmapped PE, only FirstThunk is looked up after mapping. uint szThunk = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA)); IMAGE_THUNK_DATA thunk; while (image.Read(pThunk, SeekOrigin.Begin, out thunk) && thunk.u1.AddressOfData > 0) //final thunk is signified by a null-filled IMAGE_THUNK_DATA structure. { IntPtr remote = IntPtr.Zero; object procVal = null; if ((thunk.u1.Ordinal & 0x80000000) == 0) //import by name { if (image.ReadString(image.GetPtrFromRVA(thunk.u1.AddressOfData) + 2, SeekOrigin.Begin, out fname)) //get the function name. procVal = fname; else throw image.GetLastError(); //error occurred during memory iteration, this is only a safeguard and shouldn't really ever occur, but the universe loves proving me wrong. } else //import by ordinal. { procVal = (ushort)(thunk.u1.Ordinal & 0xFFFF); } // the following section of code simply aims to reduce overhead. A check is first performed to see if the current module // is loaded in the current process first, if so it simply uses relative addresses to calculate the function address in the remote // process. If the module isn't found in our process, a call to GetProcAddressEx is used to find the remote address. Of course, you // could simply guarantee the first case by calling LoadLibrary internally, but I find that can have unwanted side effects. if (!(remote = WinAPI.GetModuleHandleA(module)).IsNull()) { IntPtr local = procVal.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(remote, (string)procVal) : WinAPI.GetProcAddress(remote, (uint)((ushort)procVal) & 0x0000FFFF); if (!local.IsNull()) remote = pModule.Add(local.Subtract(remote.ToInt32()).ToInt32()); } else { remote = WinAPI.GetProcAddressEx(hProcess, pModule, procVal); } if (remote.IsNull()) //alas, couldn't find the function. throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", fname, module)); image.Write<int>(pThunk, SeekOrigin.Begin, remote.ToInt32()); //overwrite the thunk and continue on our merry way. pThunk += szThunk; } } } }