Beispiel #1
0
        /// <summary>
        /// Adjusts base address of the imported data.
        /// </summary>
        /// <param name="memory_module">Pointer to a memory module.</param>
        /// <param name="delta">Adjustment delta value.</param>
        private void PerformBaseRelocation(MEMORY_MODULE *memory_module, ulong delta)
        {
            WinNT.IMAGE_DATA_DIRECTORY *directory = this.GET_HEADER_DIRECTORY(memory_module, WinNT.IMAGE_DIRECTORY_ENTRY_BASERELOC);

            if (directory->Size > 0)
            {
                WinNT.IMAGE_BASE_RELOCATION *relocation = (WinNT.IMAGE_BASE_RELOCATION *)(memory_module->codeBase + directory->VirtualAddress);

                int sizeOfBaseRelocation = sizeof(WinNT.IMAGE_BASE_RELOCATION);

                int index;

                for (; relocation->VirtualAddress > 0;)
                {
                    byte *  dest    = (byte *)(memory_module->codeBase + relocation->VirtualAddress);
                    ushort *relInfo = (ushort *)((byte *)relocation + sizeOfBaseRelocation);

                    for (index = 0; index < ((relocation->SizeOfBlock - sizeOfBaseRelocation) / 2); index++, relInfo++)
                    {
                        uint * patchAddrHL32;
                        ulong *patchAddrHL64;

                        uint type, offset;

                        // the upper 4 bits define the type of relocation
                        type = (uint)(*relInfo >> 12);

                        // the lower 12 bits define the offset
                        offset = (uint)(*relInfo & 0xfff);

                        switch (type)
                        {
                        case WinNT.IMAGE_REL_BASED_ABSOLUTE:
                            break;

                        case WinNT.IMAGE_REL_BASED_HIGHLOW:
                            patchAddrHL32 = (uint *)((uint)dest + offset);
                            *patchAddrHL32 += (uint)delta;
                            break;


                        case WinNT.IMAGE_REL_BASED_DIR64:
                            if (WinNT.IS_64BIT)
                            {
                                patchAddrHL64 = (ulong *)((ulong)dest + offset);
                                *patchAddrHL64 += delta;
                            }
                            break;

                        default:
                            break;
                        }
                    }

                    relocation = (WinNT.IMAGE_BASE_RELOCATION *)((byte *)relocation + relocation->SizeOfBlock);
                }
            }
        }
        /// <summary>
        /// Retrieves the address of an exported function or variable from loaded module.
        /// </summary>
        /// <param name="procName">The function or variable name.</param>
        /// <returns>
        /// If the function succeeds, the return value is the address of the exported function or variable.
        /// If the function fails, the return value is IntPtr.Zero.
        /// </returns>
        private IntPtr GetProcAddress(string procName)
        {
            if (_loadedModuleHandle == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            if (!_loadedFromMemory)
            {
                return(WinBase.GetProcAddress(_loadedModuleHandle, procName));
            }

            MEMORY_MODULE *memory_module = (MEMORY_MODULE *)_loadedModuleHandle;

            byte *codeBase = memory_module->codeBase;

            int  idx = -1;
            uint i;

            uint *  nameRef;
            ushort *ordinal;


            WinNT.IMAGE_DATA_DIRECTORY *directory = this.GET_HEADER_DIRECTORY(memory_module, WinNT.IMAGE_DIRECTORY_ENTRY_EXPORT);

            if (directory->Size == 0)
            {
                // no export table found
                return(IntPtr.Zero);
            }

            WinNT.IMAGE_EXPORT_DIRECTORY *exports = (WinNT.IMAGE_EXPORT_DIRECTORY *)(codeBase + directory->VirtualAddress);

            if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
            {
                // DLL doesn't export anything
                return(IntPtr.Zero);
            }

            // search function name in list of exported names
            nameRef = (uint *)(codeBase + exports->AddressOfNames);
            ordinal = (ushort *)(codeBase + exports->AddressOfNameOrdinals);

            for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++)
            {
                IntPtr procNameHandle = (IntPtr)((byte *)((ulong)codeBase + *nameRef));
                string testProcName   = Marshal.PtrToStringAnsi(procNameHandle);

                if (testProcName == procName)
                {
                    idx = *ordinal;
                    break;
                }
            }

            if (idx == -1)
            {
                // exported symbol not found
                return(IntPtr.Zero);
            }

            if ((uint)idx > exports->NumberOfFunctions)
            {
                // name <-> ordinal number don't match
                return(IntPtr.Zero);
            }

            // AddressOfFunctions contains the RVAs to the "real" functions
            //return (IntPtr)((uint)codeBase + *(uint*)((uint)codeBase + exports->AddressOfFunctions + (idx * 4)));
            return((IntPtr)(codeBase + *(uint *)(codeBase + exports->AddressOfFunctions + (idx * 4))));
        }
        /// <summary>
        /// Loads required dlls and adjust function table of the imports.
        /// </summary>
        /// <param name="memory_module">Pointer to a memory module.</param>
        /// <returns>If the function succeeds, the return value is true.</returns>
        private bool BuildImportTable(MEMORY_MODULE *memory_module)
        {
            bool result = true;

            WinNT.IMAGE_DATA_DIRECTORY *directory = this.GET_HEADER_DIRECTORY(memory_module, WinNT.IMAGE_DIRECTORY_ENTRY_IMPORT);

            if (directory->Size > 0)
            {
                WinNT.IMAGE_IMPORT_DESCRIPTOR *importDesc = (WinNT.IMAGE_IMPORT_DESCRIPTOR *)(memory_module->codeBase + directory->VirtualAddress);

                for (; importDesc->Name != 0; importDesc++)
                {
                    IntPtr *thunkRef;
                    IntPtr *funcRef;

                    string moduleName = Marshal.PtrToStringAnsi((IntPtr)(memory_module->codeBase + importDesc->Name));
                    IntPtr handle     = WinBase.LoadLibrary(moduleName);

                    if (handle == IntPtr.Zero)
                    {
                        result = false;
                        break;
                    }

                    int size_of_pointer = sizeof(IntPtr);

                    memory_module->modules = (IntPtr *)memory.realloc((byte *)memory_module->modules,
                                                                      (uint)((memory_module->numModules) * size_of_pointer),
                                                                      (uint)((memory_module->numModules + 1) * size_of_pointer));


                    if (memory_module->modules == null)
                    {
                        result = false;
                        break;
                    }

                    memory_module->modules[memory_module->numModules++] = handle;

                    if (importDesc->Characteristics != 0)
                    {
                        thunkRef = (IntPtr *)(memory_module->codeBase + importDesc->Characteristics);
                        funcRef  = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk);
                    }
                    else
                    {
                        thunkRef = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk);
                        funcRef  = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk);
                    }

                    for (; *thunkRef != IntPtr.Zero; thunkRef++, funcRef++)
                    {
                        if (WinNT.IMAGE_SNAP_BY_ORDINAL(thunkRef))
                        {
                            *funcRef = WinBase.GetProcAddress(handle, (byte *)WinNT.IMAGE_ORDINAL(thunkRef));
                        }
                        else
                        {
                            WinNT.IMAGE_IMPORT_BY_NAME *thunkData = (WinNT.IMAGE_IMPORT_BY_NAME *)(memory_module->codeBase + (ulong)*thunkRef);
                            //string procName = Marshal.PtrToStringAnsi((IntPtr)(byte*)(thunkData) + 2);
                            IntPtr a        = (IntPtr)(byte *)(thunkData);
                            string procName = Marshal.PtrToStringAnsi(new IntPtr(a.ToInt64() + 2));
                            *      funcRef  = WinBase.GetProcAddress(handle, procName);
                        }

                        if (*funcRef == IntPtr.Zero)
                        {
                            result = false;
                            break;
                        }
                    }

                    if (!result)
                    {
                        break;
                    }
                }
            }

            return(result);
        }