/// <summary>
        /// Loads a unmanged (native) DLL in the memory.
        /// </summary>
        /// <param name="data">Dll as a byte array</param>
        public MemoryModule(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            _headers     = null;
            _codeBase    = null;
            _pageSize    = 0;
            _modules     = new List <HCoustomMudule>();
            _initialized = false;
            _exeEntry    = null;
            _dllEntry    = null;

            Disposed     = false;
            _isRelocated = false;

            MemoryLoadLibrary(data);
        }
示例#2
0
        private void MemoryLoadLibrary(byte[] data)
        {
            IMAGE_DOS_HEADER32* dosHeader;
            IMAGE_NT_HEADERS32* ntHeader;
            IntPtr dllEntryPtr;
            byte* code, headers, dataPtr;
            uint locationDelta;

            this.dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            dataPtr = (byte*)this.dataHandle.AddrOfPinnedObject().ToPointer();

            dosHeader = (IMAGE_DOS_HEADER32*)dataPtr;
            if (dosHeader->e_magic != NativeDeclarations.IMAGE_DOS_SIGNATURE)
                throw new BadImageFormatException("Not a valid executable file.");

            ntHeader = (IMAGE_NT_HEADERS32*)(dataPtr + dosHeader->e_lfanew);
            if (ntHeader->Signature != NativeDeclarations.IMAGE_NT_SIGNATURE)
                throw new BadImageFormatException("Not a valid PE file.");

            code = (byte*)NativeDeclarations.VirtualAlloc(
                new IntPtr(ntHeader->OptionalHeader.ImageBase),
                ntHeader->OptionalHeader.SizeOfImage,
                AllocationType.RESERVE,
                MemoryProtection.READWRITE).ToPointer();

            if (code == null)
            {
                code = (byte*)NativeDeclarations.VirtualAlloc(
                IntPtr.Zero,
                ntHeader->OptionalHeader.SizeOfImage,
                AllocationType.RESERVE,
                MemoryProtection.READWRITE).ToPointer();
            }

            if (code == null)
                throw new Win32Exception();

            NativeDeclarations.VirtualAlloc(
                new IntPtr(code),
                ntHeader->OptionalHeader.SizeOfImage,
                AllocationType.COMMIT,
                MemoryProtection.READWRITE);

            this.codeBase = code;

            headers = (byte*)NativeDeclarations.VirtualAlloc(
                new IntPtr(code),
                ntHeader->OptionalHeader.SizeOfHeaders,
                AllocationType.COMMIT,
                MemoryProtection.READWRITE).ToPointer();

            if (headers == null)
                throw new Win32Exception();

            Marshal.Copy(data, 0, new IntPtr(headers), (int)(dosHeader->e_lfanew + ntHeader->OptionalHeader.SizeOfHeaders));
            this.headers = (IMAGE_NT_HEADERS32*)&((byte*)(headers))[dosHeader->e_lfanew];

            this.headers->OptionalHeader.ImageBase = (uint)code;

            this.CopySections(data, ntHeader);

            locationDelta = (uint)(code - ntHeader->OptionalHeader.ImageBase);
            if (locationDelta != 0)
                PerformBaseRelocation(locationDelta);

            this.BuildImportTable();
            this.FinalizeSections();

            if (this.headers->OptionalHeader.AddressOfEntryPoint == 0)
                throw new NativeDllLoadException("DLL has no entry point");

            dllEntryPtr = new IntPtr(code + this.headers->OptionalHeader.AddressOfEntryPoint);
     
            this.dllEntry = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer(dllEntryPtr, typeof(DllEntryDelegate));

            if (dllEntry(new IntPtr(code), DllReason.DLL_PROCESS_ATTACH, IntPtr.Zero))
                this.initialized = true;
            else
            {
                this.initialized = false;
                throw new NativeDllLoadException("Can't attach DLL to process.");
            }


        }
示例#3
0
        private void MemoryLoadLibrary(byte[] data)
        {
            IMAGE_DOS_HEADER32 *dosHeader;
            IMAGE_NT_HEADERS32 *ntHeader;
            IntPtr dllEntryPtr;
            byte * code, headers, dataPtr;
            uint   locationDelta;

            this.dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            dataPtr         = (byte *)this.dataHandle.AddrOfPinnedObject().ToPointer();

            dosHeader = (IMAGE_DOS_HEADER32 *)dataPtr;
            if (dosHeader->e_magic != NativeDeclarations.IMAGE_DOS_SIGNATURE)
            {
                throw new BadImageFormatException("Not a valid executable file.");
            }

            ntHeader = (IMAGE_NT_HEADERS32 *)(dataPtr + dosHeader->e_lfanew);
            if (ntHeader->Signature != NativeDeclarations.IMAGE_NT_SIGNATURE)
            {
                throw new BadImageFormatException("Not a valid PE file.");
            }

            code = (byte *)NativeDeclarations.VirtualAlloc(
                new IntPtr(ntHeader->OptionalHeader.ImageBase),
                ntHeader->OptionalHeader.SizeOfImage,
                AllocationType.RESERVE,
                MemoryProtection.READWRITE).ToPointer();

            if (code == null)
            {
                code = (byte *)NativeDeclarations.VirtualAlloc(
                    IntPtr.Zero,
                    ntHeader->OptionalHeader.SizeOfImage,
                    AllocationType.RESERVE,
                    MemoryProtection.READWRITE).ToPointer();
            }

            if (code == null)
            {
                throw new Win32Exception();
            }

            NativeDeclarations.VirtualAlloc(
                new IntPtr(code),
                ntHeader->OptionalHeader.SizeOfImage,
                AllocationType.COMMIT,
                MemoryProtection.READWRITE);

            this.codeBase = code;

            headers = (byte *)NativeDeclarations.VirtualAlloc(
                new IntPtr(code),
                ntHeader->OptionalHeader.SizeOfHeaders,
                AllocationType.COMMIT,
                MemoryProtection.READWRITE).ToPointer();

            if (headers == null)
            {
                throw new Win32Exception();
            }

            Marshal.Copy(data, 0, new IntPtr(headers), (int)(dosHeader->e_lfanew + ntHeader->OptionalHeader.SizeOfHeaders));
            this.headers = (IMAGE_NT_HEADERS32 *)&((byte *)(headers))[dosHeader->e_lfanew];

            this.headers->OptionalHeader.ImageBase = (uint)code;

            this.CopySections(data, ntHeader);

            locationDelta = (uint)(code - ntHeader->OptionalHeader.ImageBase);
            if (locationDelta != 0)
            {
                PerformBaseRelocation(locationDelta);
            }

            this.BuildImportTable();
            this.FinalizeSections();

            if (this.headers->OptionalHeader.AddressOfEntryPoint == 0)
            {
                throw new NativeDllLoadException("DLL has no entry point");
            }

            dllEntryPtr = new IntPtr(code + this.headers->OptionalHeader.AddressOfEntryPoint);

            this.dllEntry = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer(dllEntryPtr, typeof(DllEntryDelegate));

            if (dllEntry(new IntPtr(code), DllReason.DLL_PROCESS_ATTACH, IntPtr.Zero))
            {
                this.initialized = true;
            }
            else
            {
                this.initialized = false;
                throw new NativeDllLoadException("Can't attach DLL to process.");
            }
        }
    void MemoryLoadLibrary(byte[] data)
    {
        if (data.Length < Marshal.SizeOf(typeof(IMAGE_DOS_HEADER)))
        {
            throw new DllException("Not a valid executable file");
        }
        IMAGE_DOS_HEADER DosHeader = BytesReadStructAt <IMAGE_DOS_HEADER>(data, 0);

        if (DosHeader.e_magic != Win.IMAGE_DOS_SIGNATURE)
        {
            throw new BadImageFormatException("Not a valid executable file");
        }

        if (data.Length < DosHeader.e_lfanew + Marshal.SizeOf(typeof(IMAGE_NT_HEADERS)))
        {
            throw new DllException("Not a valid executable file");
        }
        IMAGE_NT_HEADERS OrgNTHeaders = BytesReadStructAt <IMAGE_NT_HEADERS>(data, DosHeader.e_lfanew);

        if (OrgNTHeaders.Signature != Win.IMAGE_NT_SIGNATURE)
        {
            throw new BadImageFormatException("Not a valid PE file");
        }
        if (OrgNTHeaders.FileHeader.Machine != GetMachineType())
        {
            throw new BadImageFormatException("Machine type doesn't fit (i386 vs. AMD64)");
        }
        if ((OrgNTHeaders.OptionalHeader.SectionAlignment & 1) > 0)
        {
            throw new BadImageFormatException("Wrong section alignment");                                                         //Only support multiple of 2
        }
        if (OrgNTHeaders.OptionalHeader.AddressOfEntryPoint == 0)
        {
            throw new DllException("Module has no entry point");
        }

        SYSTEM_INFO systemInfo;

        Win.GetNativeSystemInfo(out systemInfo);
        uint lastSectionEnd = 0;
        int  ofSection      = Win.IMAGE_FIRST_SECTION(DosHeader.e_lfanew, OrgNTHeaders.FileHeader.SizeOfOptionalHeader);

        for (int i = 0; i != OrgNTHeaders.FileHeader.NumberOfSections; i++, ofSection += Sz.IMAGE_SECTION_HEADER)
        {
            IMAGE_SECTION_HEADER Section = BytesReadStructAt <IMAGE_SECTION_HEADER>(data, ofSection);
            uint endOfSection            = Section.VirtualAddress + (Section.SizeOfRawData > 0 ? Section.SizeOfRawData : OrgNTHeaders.OptionalHeader.SectionAlignment);
            if (endOfSection > lastSectionEnd)
            {
                lastSectionEnd = endOfSection;
            }
        }

        uint alignedImageSize   = AlignValueUp(OrgNTHeaders.OptionalHeader.SizeOfImage, systemInfo.dwPageSize);
        uint alignedLastSection = AlignValueUp(lastSectionEnd, systemInfo.dwPageSize);

        if (alignedImageSize != alignedLastSection)
        {
            throw new BadImageFormatException("Wrong section alignment");
        }

        IntPtr oldHeader_OptionalHeader_ImageBase;

        if (Is64BitProcess)
        {
            oldHeader_OptionalHeader_ImageBase = (IntPtr) unchecked ((long)(OrgNTHeaders.OptionalHeader.ImageBaseLong));
        }
        else
        {
            oldHeader_OptionalHeader_ImageBase = (IntPtr) unchecked ((int)(OrgNTHeaders.OptionalHeader.ImageBaseLong >> 32));
        }

        // reserve memory for image of library
        pCode = Win.VirtualAlloc(oldHeader_OptionalHeader_ImageBase, (UIntPtr)OrgNTHeaders.OptionalHeader.SizeOfImage, AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.READWRITE);
        //pCode = IntPtr.Zero; //test relocation with this

        // try to allocate memory at arbitrary position
        if (pCode == IntPtr.Zero)
        {
            pCode = Win.VirtualAlloc(IntPtr.Zero, (UIntPtr)OrgNTHeaders.OptionalHeader.SizeOfImage, AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.READWRITE);
        }

        if (pCode == IntPtr.Zero)
        {
            throw new DllException("Out of Memory");
        }

        if (Is64BitProcess && PtrSpanBoundary(pCode, alignedImageSize, 32))
        {
            // Memory block may not span 4 GB (32 bit) boundaries.
            System.Collections.Generic.List <IntPtr> BlockedMemory = new System.Collections.Generic.List <IntPtr>();
            while (PtrSpanBoundary(pCode, alignedImageSize, 32))
            {
                BlockedMemory.Add(pCode);
                pCode = Win.VirtualAlloc(IntPtr.Zero, (UIntPtr)alignedImageSize, AllocationType.RESERVE | AllocationType.COMMIT, MemoryProtection.READWRITE);
                if (pCode == IntPtr.Zero)
                {
                    break;
                }
            }
            foreach (IntPtr ptr in BlockedMemory)
            {
                Win.VirtualFree(ptr, IntPtr.Zero, AllocationType.RELEASE);
            }
            if (pCode == IntPtr.Zero)
            {
                throw new DllException("Out of Memory");
            }
        }

        // commit memory for headers
        IntPtr headers = Win.VirtualAlloc(pCode, (UIntPtr)OrgNTHeaders.OptionalHeader.SizeOfHeaders, AllocationType.COMMIT, MemoryProtection.READWRITE);

        if (headers == IntPtr.Zero)
        {
            throw new DllException("Out of Memory");
        }

        // copy PE header to code
        Marshal.Copy(data, 0, headers, (int)(OrgNTHeaders.OptionalHeader.SizeOfHeaders));
        pNTHeaders = PtrAdd(headers, DosHeader.e_lfanew);

        IntPtr locationDelta = PtrSub(pCode, oldHeader_OptionalHeader_ImageBase);

        if (locationDelta != IntPtr.Zero)
        {
            // update relocated position
            Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS), "OptionalHeader");
            Marshal.OffsetOf(typeof(IMAGE_OPTIONAL_HEADER), "ImageBaseLong");
            IntPtr pImageBase = PtrAdd(pNTHeaders, Of.IMAGE_NT_HEADERS_OptionalHeader + (Is64BitProcess ? Of64.IMAGE_OPTIONAL_HEADER_ImageBase : Of32.IMAGE_OPTIONAL_HEADER_ImageBase));
            PtrWrite(pImageBase, pCode);
        }

        // copy sections from DLL file block to new memory location
        CopySections(ref OrgNTHeaders, pCode, pNTHeaders, data);

        // adjust base address of imported data
        _isRelocated = (locationDelta != IntPtr.Zero ? PerformBaseRelocation(ref OrgNTHeaders, pCode, locationDelta) : true);

        // load required dlls and adjust function table of imports
        ImportModules = BuildImportTable(ref OrgNTHeaders, pCode);

        // mark memory pages depending on section headers and release
        // sections that are marked as "discardable"
        FinalizeSections(ref OrgNTHeaders, pCode, pNTHeaders, systemInfo.dwPageSize);

        // TLS callbacks are executed BEFORE the main loading
        ExecuteTLS(ref OrgNTHeaders, pCode, pNTHeaders);

        // get entry point of loaded library
        IsDll = ((OrgNTHeaders.FileHeader.Characteristics & Win.IMAGE_FILE_DLL) != 0);
        if (OrgNTHeaders.OptionalHeader.AddressOfEntryPoint != 0)
        {
            if (IsDll)
            {
                // notify library about attaching to process
                IntPtr dllEntryPtr = PtrAdd(pCode, OrgNTHeaders.OptionalHeader.AddressOfEntryPoint);
                _dllEntry = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer(dllEntryPtr, typeof(DllEntryDelegate));

                _initialized = (_dllEntry != null && _dllEntry(pCode, DllReason.DLL_PROCESS_ATTACH, IntPtr.Zero));
                if (!_initialized)
                {
                    throw new DllException("Can't attach DLL to process");
                }
            }
            else
            {
                IntPtr exeEntryPtr = PtrAdd(pCode, OrgNTHeaders.OptionalHeader.AddressOfEntryPoint);
                _exeEntry = (ExeEntryDelegate)Marshal.GetDelegateForFunctionPointer(exeEntryPtr, typeof(ExeEntryDelegate));
            }
        }
    }
        private void MemoryLoadLibrary(byte[] data)
        {
            IMAGE_DOS_HEADER *    dosHeader;
            IMAGE_NT_HEADERS *    oldHeader;
            IMAGE_SECTION_HEADER *section;
            SYSTEM_INFO           systemInfo;
            void *   dllEntryPtr;
            void *   exeEntryPtr;
            byte *   headers, dataPtr, code;
            SizeT    optionalSectionSize;
            SizeT    lastSectionEnd = 0;
            SizeT    alignedImageSize;
            PtrDiffT locationDelta;

            _dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            if (!_dataHandle.IsAllocated)
            {
                throw new NativeDllLoadException("Can't allocate memory.");
            }

            dataPtr = (byte *)_dataHandle.AddrOfPinnedObject();

            dosHeader = (IMAGE_DOS_HEADER *)dataPtr;
            if (dosHeader->e_magic != Win.IMAGE_DOS_SIGNATURE)
            {
                throw new BadImageFormatException("Not a valid executable file.");
            }

            oldHeader = (IMAGE_NT_HEADERS *)(dataPtr + dosHeader->e_lfanew);
            if (oldHeader->Signature != Win.IMAGE_NT_SIGNATURE)
            {
                throw new BadImageFormatException("Not a valid PE file.");
            }

            if (oldHeader->FileHeader.Machine != GetMachineType())
            {
                throw new BadImageFormatException("Machine type doesn't fit. (i386 vs. AMD64)");
            }

            if ((oldHeader->OptionalHeader.SectionAlignment & 1) > 0)
            {
                throw new BadImageFormatException("Wrong section alignment");
            }

            section             = Win.IMAGE_FIRST_SECTION(oldHeader);
            optionalSectionSize = oldHeader->OptionalHeader.SectionAlignment;
            for (int i = 0; i < oldHeader->FileHeader.NumberOfSections; i++, section++)
            {
                SizeT endOfSection;
                if (section->SizeOfRawData == 0) // Section without data in the DLL
                {
                    endOfSection = section->VirtualAddress + optionalSectionSize;
                }
                else
                {
                    endOfSection = section->VirtualAddress + section->SizeOfRawData;
                }

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

            Win.GetNativeSystemInfo(&systemInfo);
            alignedImageSize = AlignValueUp(oldHeader->OptionalHeader.SizeOfImage, systemInfo.dwPageSize);
            if (alignedImageSize != AlignValueUp(lastSectionEnd, systemInfo.dwPageSize))
            {
                throw new BadImageFormatException("Wrong section alignment.");
            }

            code = (byte *)Win.VirtualAlloc(
                (void *)(oldHeader->OptionalHeader.ImageBase),
                oldHeader->OptionalHeader.SizeOfImage,
                AllocationType.RESERVE | AllocationType.COMMIT,
                MemoryProtection.READWRITE);

            if (code == null)
            {
                code = (byte *)Win.VirtualAlloc(
                    null,
                    oldHeader->OptionalHeader.SizeOfImage,
                    AllocationType.RESERVE | AllocationType.COMMIT,
                    MemoryProtection.READWRITE);
            }

            if (code == null)
            {
                throw new NativeDllLoadException("Out of Memory");
            }

#if WIN64
            while ((((ulong)code) >> 32) < (((ulong)(code + alignedImageSize)) >> 32))
            {
                _blockedMemory.Add((IntPtr)code);

                code = (byte *)Win.VirtualAlloc(
                    null,
                    alignedImageSize,
                    AllocationType.RESERVE | AllocationType.COMMIT,
                    MemoryProtection.READWRITE);

                if (code == null)
                {
                    throw new NativeDllLoadException("Out of Memory");
                }
            }
#endif

            _pageSize = systemInfo.dwPageSize;
            _codeBase = code;
            IsDll     = (oldHeader->FileHeader.Characteristics & Win.IMAGE_FILE_DLL) != 0;

            headers = (byte *)Win.VirtualAlloc(
                code,
                oldHeader->OptionalHeader.SizeOfHeaders,
                AllocationType.COMMIT,
                MemoryProtection.READWRITE);

            if (headers == null)
            {
                throw new NativeDllLoadException("Out of Memory");
            }

            Marshal.Copy(data, 0, (IntPtr)headers, (int)(dosHeader->e_lfanew + oldHeader->OptionalHeader.SizeOfHeaders));
            _headers = (IMAGE_NT_HEADERS *)&(headers)[dosHeader->e_lfanew];

            _headers->OptionalHeader.ImageBase = (UIntPtrT)code;

            CopySections(data, oldHeader);

            locationDelta = (PtrDiffT)(_headers->OptionalHeader.ImageBase - oldHeader->OptionalHeader.ImageBase);
            if (locationDelta != 0)
            {
                _isRelocated = PerformBaseRelocation(locationDelta);
            }
            else
            {
                _isRelocated = true;
            }

            BuildImportTable();
            FinalizeSections();
            ExecuteTLS();

            if (_headers->OptionalHeader.AddressOfEntryPoint == 0)
            {
                throw new NativeDllLoadException("DLL has no entry point");
            }

            if (IsDll)
            {
                dllEntryPtr = code + _headers->OptionalHeader.AddressOfEntryPoint;
                _dllEntry   = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)dllEntryPtr, typeof(DllEntryDelegate));

                if (_dllEntry != null && _dllEntry(code, DllReason.DLL_PROCESS_ATTACH, null))
                {
                    _initialized = true;
                }
                else
                {
                    _initialized = false;
                    throw new NativeDllLoadException("Can't attach DLL to process.");
                }
            }
            else
            {
                exeEntryPtr = code + _headers->OptionalHeader.AddressOfEntryPoint;
                _exeEntry   = Marshal.GetDelegateForFunctionPointer <ExeEntryDelegate>((IntPtr)exeEntryPtr);
            }
        }