Beispiel #1
0
        // Token: 0x06000121 RID: 289 RVA: 0x0000DB90 File Offset: 0x0000BD90
        private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc)
        {
            IMAGE_DATA_DIRECTORY image_DATA_DIRECTORY = image.NTHeader.OptionalHeader.DataDirectory[5];

            if (image_DATA_DIRECTORY.Size > 0u)
            {
                uint num  = 0u;
                uint num2 = (uint)((long)pAlloc.ToInt32() - (long)((ulong)image.NTHeader.OptionalHeader.ImageBase));
                uint num3 = image.GetPtrFromRVA(image_DATA_DIRECTORY.VirtualAddress);
                uint num4 = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
                IMAGE_BASE_RELOCATION image_BASE_RELOCATION;
                while (num < image_DATA_DIRECTORY.Size && image.Read <IMAGE_BASE_RELOCATION>((long)((ulong)num3), SeekOrigin.Begin, out image_BASE_RELOCATION))
                {
                    int  num5       = (int)((image_BASE_RELOCATION.SizeOfBlock - num4) / 2u);
                    uint ptrFromRVA = image.GetPtrFromRVA(image_BASE_RELOCATION.VirtualAddress);
                    for (int i = 0; i < num5; i++)
                    {
                        ushort num6;
                        if (image.Read <ushort>((long)((ulong)(num3 + num4) + (ulong)((long)((long)i << 1))), SeekOrigin.Begin, out num6) && (num6 >> 12 & 3) != 0)
                        {
                            uint num7 = (uint)((ulong)ptrFromRVA + (ulong)((long)(num6 & 4095)));
                            uint num8;
                            if (!image.Read <uint>((long)((ulong)num7), SeekOrigin.Begin, out num8))
                            {
                                throw image.GetLastError();
                            }
                            image.Write <uint>(-4L, SeekOrigin.Current, num8 + num2);
                        }
                    }
                    num  += image_BASE_RELOCATION.SizeOfBlock;
                    num3 += image_BASE_RELOCATION.SizeOfBlock;
                }
            }
        }
Beispiel #2
0
        private static void PatchImports(PortableExecutable image, IntPtr hProcess, int processId)
        {
            string empty  = string.Empty;
            string empty2 = string.Empty;

            foreach (IMAGE_IMPORT_DESCRIPTOR current in image.EnumImports())
            {
                if (image.ReadString((long)((ulong)image.GetPtrFromRVA(current.Name)), SeekOrigin.Begin, out empty, -1, null))
                {
                    IntPtr intPtr   = IntPtr.Zero;
                    IntPtr arg_4F_0 = IntPtr.Zero;
                    intPtr = ManualMap.GetRemoteModuleHandle(empty, processId);
                    if (intPtr.IsNull())
                    {
                        throw new FileNotFoundException(string.Format("Unable to load dependent module '{0}'.", empty));
                    }
                    uint             num  = image.GetPtrFromRVA(current.FirstThunkPtr);
                    uint             num2 = (uint)Marshal.SizeOf(typeof(IMAGE_THUNK_DATA));
                    IMAGE_THUNK_DATA iMAGE_THUNK_DATA;
                    while (image.Read <IMAGE_THUNK_DATA>((long)((ulong)num), SeekOrigin.Begin, out iMAGE_THUNK_DATA) && iMAGE_THUNK_DATA.u1.AddressOfData > 0u)
                    {
                        IntPtr intPtr2 = IntPtr.Zero;
                        object obj;
                        if ((iMAGE_THUNK_DATA.u1.Ordinal & 2147483648u) == 0u)
                        {
                            if (!image.ReadString((long)((ulong)(image.GetPtrFromRVA(iMAGE_THUNK_DATA.u1.AddressOfData) + 2u)), SeekOrigin.Begin, out empty2, -1, null))
                            {
                                throw image.GetLastError();
                            }
                            obj = empty2;
                        }
                        else
                        {
                            obj = (ushort)(iMAGE_THUNK_DATA.u1.Ordinal & 65535u);
                        }
                        if (!(intPtr2 = WinAPI.GetModuleHandleA(empty)).IsNull())
                        {
                            IntPtr ptr = obj.GetType().Equals(typeof(string)) ? WinAPI.GetProcAddress(intPtr2, (string)obj) : WinAPI.GetProcAddress(intPtr2, (uint)((ushort)obj & 65535));
                            if (!ptr.IsNull())
                            {
                                intPtr2 = intPtr.Add((long)ptr.Subtract((long)intPtr2.ToInt32()).ToInt32());
                            }
                        }
                        else
                        {
                            intPtr2 = WinAPI.GetProcAddressEx(hProcess, intPtr, obj);
                        }
                        if (intPtr2.IsNull())
                        {
                            throw new EntryPointNotFoundException(string.Format("Unable to locate imported function '{0}' from module '{1}' in the remote process.", empty2, empty));
                        }
                        image.Write <int>((long)((ulong)num), SeekOrigin.Begin, intPtr2.ToInt32());
                        num += num2;
                    }
                }
            }
        }
Beispiel #3
0
        private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc)
        {
            // Base relocations are essentially Microsofts ingenious way of preserving portability in images.
            // for all absolute address calls/jmps/references...etc, an entry is made into the base relocation
            // table telling the loader exactly where an "absolute" address is being used. This allows the loader
            // to iterate through the relocations and patch these absolute values to ensure they are correct when
            // the image is loaded somewhere that isn't its preferred base address.
            IMAGE_DATA_DIRECTORY relocDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.BaseRelocTable];

            if (relocDir.Size > 0) //check if there are in fact any relocations.
            {
                uint n       = 0;
                uint delta   = (uint)(pAlloc.ToInt32() - image.NTHeader.OptionalHeader.ImageBase); //The difference in loaded/preferred addresses.
                uint pReloc  = image.GetPtrFromRVA(relocDir.VirtualAddress);
                uint szReloc = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
                IMAGE_BASE_RELOCATION reloc;

                while (n < relocDir.Size && image.Read(pReloc, SeekOrigin.Begin, out reloc))
                {
                    // A relocation block consists of an IMAGE_BASE_RELOCATION, and an array of WORDs.
                    // To calculate the number of relocations (represented by WORDs), just do some simple math.
                    int    nrelocs = (int)((reloc.SizeOfBlock - szReloc) / sizeof(ushort));
                    uint   pageVa  = image.GetPtrFromRVA(reloc.VirtualAddress); //The Page RVA for this set of relocations (usually a 4K boundary).
                    ushort vreloc;
                    uint   old;

                    for (int i = 0; i < nrelocs; i++)
                    {
                        // There are only 2 types of relocations on Intel machines: ABSOLUTE (padding, nothing needs to be done) and HIGHLOW (0x03)
                        // Highlow means that all 32 bits of the "delta" value need to be added to the relocation value.
                        if (image.Read(pReloc + szReloc + (i << 1), SeekOrigin.Begin, out vreloc) && (vreloc >> 12 & 3) != 0)
                        {
                            uint vp = (uint)(pageVa + (vreloc & 0x0FFF));
                            if (image.Read <uint>(vp, SeekOrigin.Begin, out old))
                            {
                                image.Write <uint>(-4, SeekOrigin.Current, (uint)(old + delta));
                            }
                            else
                            {
                                throw image.GetLastError(); //unlikely, but I hate crashing targets because something in the PE was messed up.
                            }
                        }
                    }
                    n      += reloc.SizeOfBlock;
                    pReloc += reloc.SizeOfBlock;
                }
            }
        }
Beispiel #4
0
        /*
         * 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);
        }
Beispiel #5
0
        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;
                    }
                }
            }
        }
Beispiel #6
0
        // Token: 0x06000123 RID: 291 RVA: 0x0000DEE4 File Offset: 0x0000C0E4
        private static bool LoadDependencies(PortableExecutable image, IntPtr hProcess, int processId)
        {
            List <string> list   = new List <string>();
            string        empty  = string.Empty;
            bool          result = false;

            foreach (IMAGE_IMPORT_DESCRIPTOR image_IMPORT_DESCRIPTOR in image.EnumImports())
            {
                if (image.ReadString((long)((ulong)image.GetPtrFromRVA(image_IMPORT_DESCRIPTOR.Name)), SeekOrigin.Begin, out empty, -1, null) && !string.IsNullOrEmpty(empty) && ManualMap.GetRemoteModuleHandle(empty, processId).IsNull())
                {
                    list.Add(empty);
                }
            }
            if (list.Count > 0)
            {
                byte[] array = ManualMap.ExtractManifest(image);
                string text  = string.Empty;
                if (array == null)
                {
                    if (string.IsNullOrEmpty(image.FileLocation) || !File.Exists(Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest")))
                    {
                        InjectionMethod injectionMethod = InjectionMethod.Create(InjectionMethodType.Standard);
                        IntPtr[]        array2          = injectionMethod.InjectAll(list.ToArray(), hProcess);
                        foreach (IntPtr ptr in array2)
                        {
                            if (ptr.IsNull())
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                    text = Path.Combine(Path.GetDirectoryName(image.FileLocation), Path.GetFileName(image.FileLocation) + ".manifest");
                }
                else
                {
                    text = Utils.WriteTempData(array);
                }
                if (string.IsNullOrEmpty(text))
                {
                    return(false);
                }
                IntPtr intPtr     = WinAPI.VirtualAllocEx(hProcess, IntPtr.Zero, (uint)ManualMap.RESOLVER_STUB.Length, 12288, 64);
                IntPtr lpAddress  = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(text + "\0"), 4);
                IntPtr lpAddress2 = WinAPI.CreateRemotePointer(hProcess, Encoding.ASCII.GetBytes(string.Join("\0", list.ToArray()) + "\0"), 4);
                if (!intPtr.IsNull())
                {
                    byte[] array4 = (byte[])ManualMap.RESOLVER_STUB.Clone();
                    uint   num    = 0u;
                    BitConverter.GetBytes(ManualMap.FN_CREATEACTCTXA.Subtract(intPtr.Add(63L)).ToInt32()).CopyTo(array4, 59);
                    BitConverter.GetBytes(ManualMap.FN_ACTIVATEACTCTX.Subtract(intPtr.Add(88L)).ToInt32()).CopyTo(array4, 84);
                    BitConverter.GetBytes(ManualMap.FN_GETMODULEHANDLEA.Subtract(intPtr.Add(132L)).ToInt32()).CopyTo(array4, 128);
                    BitConverter.GetBytes(ManualMap.FN_LOADLIBRARYA.Subtract(intPtr.Add(146L)).ToInt32()).CopyTo(array4, 142);
                    BitConverter.GetBytes(ManualMap.FN_DEACTIVATEACTCTX.Subtract(intPtr.Add(200L)).ToInt32()).CopyTo(array4, 196);
                    BitConverter.GetBytes(ManualMap.FN_RELEASEACTCTX.Subtract(intPtr.Add(209L)).ToInt32()).CopyTo(array4, 205);
                    BitConverter.GetBytes(lpAddress.ToInt32()).CopyTo(array4, 31);
                    BitConverter.GetBytes(list.Count).CopyTo(array4, 40);
                    BitConverter.GetBytes(lpAddress2.ToInt32()).CopyTo(array4, 49);
                    if (WinAPI.WriteProcessMemory(hProcess, intPtr, array4, array4.Length, out num) && num == (uint)array4.Length)
                    {
                        uint num2 = WinAPI.RunThread(hProcess, intPtr, 0u, 5000);
                        result = (num2 != uint.MaxValue && num2 != 0u);
                    }
                    WinAPI.VirtualFreeEx(hProcess, lpAddress2, 0, 32768);
                    WinAPI.VirtualFreeEx(hProcess, lpAddress, 0, 32768);
                    WinAPI.VirtualFreeEx(hProcess, intPtr, 0, 32768);
                }
            }
            return(result);
        }