Example #1
0
        internal static void MemoryFreeLibrary(MEMORYMODULE mod)
        {
            MEMORYMODULE module = mod;

            if (module == null)
                return;
            if (module.initialized)
            {
                // notify library about detaching from process
                DllEntryProc DllEntry = (DllEntryProc)Marshal.GetDelegateForFunctionPointer((IntPtr)(module.codeBase + (WIN64 ? ((IMAGE_NT_HEADERS64*)module.headers)->OptionalHeader.AddressOfEntryPoint : ((IMAGE_NT_HEADERS32*)module.headers)->OptionalHeader.AddressOfEntryPoint)), typeof(DllEntryProc));
                DllEntry(module.codeBase, DLL_PROCESS_DETACH, null);
            }

            if (module.modules != null)
            {
                // free previously opened libraries
                int i;
                for (i = 0; i < module.numModules; i++)
                    if ((void*)((IntPtr*)module.modules)[i] != null)
                        module.freeLibrary((void*)((IntPtr*)module.modules)[i], module.userdata);

                free(module.modules);
            }

            if (module.codeBase != null)
            {
                // release memory of library
                module.free(module.codeBase, null, MEM_RELEASE, module.userdata);
            }

            if (WIN64)
                FreePointerList(module.blockedMemory, module.free, module.userdata);
        }
        /// <summary>
        /// Calls module entry point.
        /// </summary>
        /// <param name="memory_module">Pointer to a memory module.</param>
        /// <param name="fdwReason"></param>
        /// <returns>If the function succeeds or if there is no entry point, the return value is true.</returns>
        private bool CallDllEntryPoint(MEMORY_MODULE *memory_module, uint fdwReason)
        {
            uint addressOfEntryPoint;

            if (Environment.Is64BitProcess)
            {
                WinNT.IMAGE_NT_HEADERS64 *headers = (WinNT.IMAGE_NT_HEADERS64 *)memory_module->headers;
                addressOfEntryPoint = headers->OptionalHeader.AddressOfEntryPoint;
            }
            else
            {
                WinNT.IMAGE_NT_HEADERS32 *headers = (WinNT.IMAGE_NT_HEADERS32 *)memory_module->headers;
                addressOfEntryPoint = headers->OptionalHeader.AddressOfEntryPoint;
            }

            if (addressOfEntryPoint != 0)
            {
                IntPtr dllEntry = (IntPtr)(memory_module->codeBase + addressOfEntryPoint);

                if (dllEntry == IntPtr.Zero)
                {
                    return(false);
                }

                DllEntryProc dllEntryProc = (DllEntryProc)Marshal.GetDelegateForFunctionPointer(dllEntry, typeof(DllEntryProc));

                if (dllEntryProc((IntPtr)memory_module->codeBase, fdwReason, 0))
                {
                    if (fdwReason == WinNT.DLL_PROCESS_ATTACH)
                    {
                        memory_module->initialized = 1;
                    }
                    else if (fdwReason == WinNT.DLL_PROCESS_DETACH)
                    {
                        memory_module->initialized = 0;
                    }

                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Example #3
0
            public void ExecuteDllMain(Image image, DllCallType callType)
            {
                uint addressOfEntryPoint = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->AddressOfEntryPoint : image.OptionalHeader32->AddressOfEntryPoint;

                if (addressOfEntryPoint >= image.Size - sizeof(IntPtr))
                {
                    throw new LoadFailedException("Cannot invoke this library's DllMain() function; its address is invalid.");
                }

                IntPtr       callback     = (IntPtr)(image.BasePtr + addressOfEntryPoint);
                DllEntryProc dllEntryProc = (DllEntryProc)Marshal.GetDelegateForFunctionPointer(callback, typeof(DllEntryProc));

                uint succeeded = dllEntryProc((IntPtr)image.BasePtr, callType, IntPtr.Zero);

                if (succeeded == 0)
                {
                    throw new LoadFailedException("This library's DllMain() function returned false in response to " + callType + ".");
                }
            }
Example #4
0
            public void ExecuteTlsFunctions(Image image, DllCallType callType)
            {
                IMAGE_DATA_DIRECTORY directory = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->TLSTable : image.OptionalHeader32->TLSTable;

                if (directory.VirtualAddress == 0)
                {
                    return;
                }

                if (directory.VirtualAddress > image.Size - sizeof(IntPtr))
                {
                    throw new LoadFailedException("This library's TLS table is damaged or invalid.");
                }

                IMAGE_TLS_DIRECTORY32 *tlsDirectory32 = (IMAGE_TLS_DIRECTORY32 *)(image.BasePtr + directory.VirtualAddress);
                IntPtr callbacks = (IntPtr)tlsDirectory32->AddressOfCallBacks;
                IntPtr endPtr    = (IntPtr)(image.BasePtr + image.Size - sizeof(IntPtr));

                if (callbacks != IntPtr.Zero)
                {
                    IntPtr callback;
                    while ((callback = *(IntPtr *)callbacks) != IntPtr.Zero)
                    {
                        if ((long)callback > (long)endPtr)
                        {
                            throw new LoadFailedException("One of this library's TLS functions is damaged or invalid.");
                        }

                        DllEntryProc dllEntryProc = (DllEntryProc)Marshal.GetDelegateForFunctionPointer(callback, typeof(DllEntryProc));
                        uint         succeeded    = dllEntryProc((IntPtr)image.BasePtr, DllCallType.PROCESS_ATTACH, IntPtr.Zero);
                        if (succeeded == 0)
                        {
                            throw new LoadFailedException("One of this library's TLS functions returned false in response to " + callType + ".");
                        }
                    }
                }
            }
Example #5
0
        internal static MEMORYMODULE MemoryLoadLibraryEx(void* data, void* size, CustomAllocFunc allocMemory, CustomFreeFunc freeMemory, CustomLoadLibraryFunc loadLibrary, CustomGetProcAddressFunc getProcAddress, CustomFreeLibraryFunc freeLibrary, void* userdata)
        {
            MEMORYMODULE result = null;
            IMAGE_DOS_HEADER* dos_header;
            void* old_header;
            byte* code, headers;
            void* locationDelta;
            SYSTEM_INFO sysInfo;
            IMAGE_SECTION_HEADER* section;
            uint i;
            void* optionalSectionSize;
            void* lastSectionEnd = null;
            void* alignedImageSize;
            POINTER_LIST blockedMemory = null;

            if (!CheckSize(size, (void*)IMAGE_DOS_HEADER.UnmanagedSize))
                return null;
            dos_header = (IMAGE_DOS_HEADER*)data;
            if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
                return null;

            if (!CheckSize(size, (void*)(dos_header->e_lfanew + (WIN64 ? IMAGE_NT_HEADERS64.UnmanagedSize : IMAGE_NT_HEADERS32.UnmanagedSize))))
                return null;
            old_header = &((byte*)data)[dos_header->e_lfanew];
            if ((WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->Signature : ((IMAGE_NT_HEADERS32*)old_header)->Signature) != IMAGE_NT_SIGNATURE)
                return null;

            if ((WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->FileHeader.Machine : ((IMAGE_NT_HEADERS32*)old_header)->FileHeader.Machine) != HOST_MACHINE)
                return null;

            if (((WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SectionAlignment : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SectionAlignment) & 1) != 0)
                // Only support section alignments that are a multiple of 2
                return null;

            section = IMAGE_FIRST_SECTION(old_header);
            optionalSectionSize = (void*)((WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SectionAlignment : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SectionAlignment));
            for (i = 0; i < (WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->FileHeader.NumberOfSections : ((IMAGE_NT_HEADERS32*)old_header)->FileHeader.NumberOfSections); i++, section++)
            {
                void* endOfSection;
                if (section->SizeOfRawData == 0)
                {
                    // Section without data in the DLL
                    endOfSection = (void*)(section->VirtualAddress + (ulong)optionalSectionSize);
                }
                else
                {
                    endOfSection = (void*)(section->VirtualAddress + (ulong)section->SizeOfRawData);
                }

                if ((ulong)endOfSection > (ulong)lastSectionEnd)
                    lastSectionEnd = endOfSection;
            }

            GetNativeSystemInfo(&sysInfo);
            alignedImageSize = AlignValueUp((void*)(WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SizeOfImage : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SizeOfImage), (void*)sysInfo.dwPageSize);
            if (alignedImageSize != AlignValueUp(lastSectionEnd, (void*)sysInfo.dwPageSize))
                return null;

            // reserve memory for image of library
            // XXX: is it correct to commit the complete memory region at once?
            //      calling DllEntry raises an exception if we don't...
            code = (byte*)allocMemory((void*)(WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.ImageBase : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, userdata);

            if (code == null)
            {
                // try to allocate memory at arbitrary position
                code = (byte*)allocMemory(null, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, userdata);
                if (code == null)
                    return null;
            }

            if (WIN64)
            {
                // Memory block may not span 4 GB boundaries.
                while ((ulong)code >> 32 < ((ulong)code + (ulong)alignedImageSize) >> 32)
                {
                    POINTER_LIST node = new POINTER_LIST
                    {
                        next = blockedMemory,
                        address = code
                    };
                    blockedMemory = node;

                    code = (byte*)allocMemory(null, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, userdata);
                    if (code == null)
                    {
                        FreePointerList(blockedMemory, freeMemory, userdata);
                        return null;
                    }
                }
            }

            result = new MEMORYMODULE
            {
                codeBase = code,
                isDLL = ((WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->FileHeader.Characteristics : ((IMAGE_NT_HEADERS32*)old_header)->FileHeader.Characteristics) & IMAGE_FILE_DLL) != 0,
                alloc = allocMemory,
                free = freeMemory,
                loadLibrary = loadLibrary,
                getProcAddress = getProcAddress,
                freeLibrary = freeLibrary,
                userdata = userdata,
                pageSize = sysInfo.dwPageSize
            };
            if (WIN64)
                result.blockedMemory = blockedMemory;

            if (!CheckSize(size, (void*)(WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SizeOfHeaders : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SizeOfHeaders)))
                goto error;

            // commit memory for headers
            headers = (byte*)allocMemory(code, (void*)(WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SizeOfHeaders : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SizeOfHeaders), MEM_COMMIT, PAGE_READWRITE, userdata);

            // copy PE header to code
            memcpy(headers, dos_header, (void*)(WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.SizeOfHeaders : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.SizeOfHeaders));
            result.headers = &headers[dos_header->e_lfanew];

            // update position
            if (WIN64)
                ((IMAGE_NT_HEADERS64*)result.headers)->OptionalHeader.ImageBase = (ulong)code;
            else
                ((IMAGE_NT_HEADERS32*)result.headers)->OptionalHeader.ImageBase = (uint)code;

            // copy sections from DLL file block to new memory location
            if (!CopySections((byte*)data, size, old_header, result))
                goto error;

            // adjust base address of imported data
            locationDelta = (void*)((WIN64 ? ((IMAGE_NT_HEADERS64*)result.headers)->OptionalHeader.ImageBase : ((IMAGE_NT_HEADERS32*)result.headers)->OptionalHeader.ImageBase) - (WIN64 ? ((IMAGE_NT_HEADERS64*)old_header)->OptionalHeader.ImageBase : ((IMAGE_NT_HEADERS32*)old_header)->OptionalHeader.ImageBase));
            if ((ulong)locationDelta != 0)
                result.isRelocated = PerformBaseRelocation(result, locationDelta);
            else
                result.isRelocated = true;

            // load required dlls and adjust function table of imports
            if (!BuildImportTable(result))
                goto error;

            // mark memory pages depending on section headers and release
            // sections that are marked as "discardable"
            if (!FinalizeSections(result))
                goto error;

            // TLS callbacks are executed BEFORE the main loading
            if (!ExecuteTLS(result))
                goto error;

            // get entry point of loaded library
            if ((WIN64 ? ((IMAGE_NT_HEADERS64*)result.headers)->OptionalHeader.AddressOfEntryPoint : ((IMAGE_NT_HEADERS32*)result.headers)->OptionalHeader.AddressOfEntryPoint) != 0)
            {
                if (result.isDLL)
                {
                    DllEntryProc DllEntry = (DllEntryProc)Marshal.GetDelegateForFunctionPointer((IntPtr)(code + (WIN64 ? ((IMAGE_NT_HEADERS64*)result.headers)->OptionalHeader.AddressOfEntryPoint : ((IMAGE_NT_HEADERS32*)result.headers)->OptionalHeader.AddressOfEntryPoint)), typeof(DllEntryProc));
                    // notify library about attaching to process
                    bool successfull = DllEntry(code, DLL_PROCESS_ATTACH, null);
                    if (!successfull)
                        goto error;
                    result.initialized = true;
                }
                else
                    result.exeEntry = (ExeEntryProc)Marshal.GetDelegateForFunctionPointer((IntPtr)(code + (WIN64 ? ((IMAGE_NT_HEADERS64*)result.headers)->OptionalHeader.AddressOfEntryPoint : ((IMAGE_NT_HEADERS32*)result.headers)->OptionalHeader.AddressOfEntryPoint)), typeof(ExeEntryProc));
            }
            else
                result.exeEntry = null;

            return result;

            error:
            // cleanup
            MemoryFreeLibrary(result);
            return null;
        }