Пример #1
0
        private static bool ExecuteTLS(MEMORYMODULE module)
        {
            byte *codeBase = module.codeBase;
            IMAGE_TLS_DIRECTORY tls;
            void **callback;

            IMAGE_DATA_DIRECTORY *directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS);

            if (directory->VirtualAddress == 0)
            {
                return(true);
            }

            tls      = *(IMAGE_TLS_DIRECTORY *)((ulong)codeBase + directory->VirtualAddress);
            callback = (void **)tls.AddressOfCallBacks;
            if (callback != null)
            {
                while (*callback != null)
                {
                    ((IMAGE_TLS_CALLBACK)Marshal.GetDelegateForFunctionPointer((IntPtr)(*callback), typeof(IMAGE_TLS_CALLBACK)))((void *)codeBase, DLL_PROCESS_ATTACH, null);
                    callback++;
                }
            }
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Returns a delegate for a function inside the DLL.
        /// </summary>
        /// <param name="funcName">The Name of the function to be searched.</param>
        /// <param name="t">The type of the delegate to be returned.</param>
        /// <returns>A delegate instance that can be cast to the appropriate delegate type.</returns>
        public Delegate GetDelegateFromFuncName(int inputOrdinal, Type t)
        {
            if (t == null)
            {
                throw new ArgumentNullException("t");
            }

            if (this.Disposed)
            {
                throw new ObjectDisposedException("MemoryModule");
            }

            if (!this.initialized)
            {
                throw new InvalidOperationException("Dll is not initialized.");
            }

            int     idx = -1;
            uint *  nameRef;
            ushort *ordinal;
            IMAGE_EXPORT_DIRECTORY *exports;
            IntPtr funcPtr;

            IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.ExportTable;

            if (directory->Size == 0)
            {
                throw new NativeDllLoadException("Dll has no export table.");
            }

            exports = (IMAGE_EXPORT_DIRECTORY *)(this.codeBase + directory->VirtualAddress);
            if (exports->NumberOfFunctions == 0 || exports->NumberOfNames == 0)
            {
                throw new NativeDllLoadException("Dll exports no functions.");
            }

            nameRef = (uint *)(this.codeBase + exports->AddressOfNames);
            ordinal = (ushort *)(this.codeBase + exports->AddressOfNameOrdinals);

            ordinal += inputOrdinal;
            idx      = *ordinal;

            /*
             * for (int i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) {
             *  string curFuncName = Marshal.PtrToStringAnsi(new IntPtr(this.codeBase + *nameRef));
             *  if (curFuncName == funcName) {
             *      idx = *ordinal;
             *      break;
             *  }
             * }
             */
            if (idx > exports->NumberOfFunctions)
            {
                throw new NativeDllLoadException("IDX don't match number of funtions.");
            }

            funcPtr = new IntPtr(this.codeBase + (*(uint *)(this.codeBase + exports->AddressOfFunctions + (idx * 4))));
            return(Marshal.GetDelegateForFunctionPointer(funcPtr, t));
        }
Пример #3
0
        public static void *MemoryFindResourceEx(MEMORYMODULE module, byte *name, byte *type, ushort language, bool unicode)
        {
            byte *codeBase = module.codeBase;
            IMAGE_DATA_DIRECTORY *          directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_RESOURCE);
            IMAGE_RESOURCE_DIRECTORY *      rootResources;
            IMAGE_RESOURCE_DIRECTORY *      nameResources;
            IMAGE_RESOURCE_DIRECTORY *      typeResources;
            IMAGE_RESOURCE_DIRECTORY_ENTRY *foundType;
            IMAGE_RESOURCE_DIRECTORY_ENTRY *foundName;
            IMAGE_RESOURCE_DIRECTORY_ENTRY *foundLanguage;

            if (directory->Size == 0)
            {
                // no resource table found
                return(null);
            }

            if (language == DEFAULT_LANGUAGE)
            {
                // use language from current thread
                language = LANGIDFROMLCID(GetThreadLocale());
            }

            // resources are stored as three-level tree
            // - first node is the type
            // - second node is the name
            // - third node is the language
            rootResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress);
            foundType     = _MemorySearchResourceEntry(rootResources, rootResources, type, unicode);
            if (foundType == null)
            {
                return(null);
            }

            typeResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff));
            foundName     = _MemorySearchResourceEntry(rootResources, typeResources, name, unicode);
            if (foundName == null)
            {
                return(null);
            }

            nameResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff));
            foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (byte *)language, unicode);
            if (foundLanguage == null)
            {
                // requested language not found, use first available
                if (nameResources->NumberOfIdEntries == 0)
                {
                    return(null);
                }

                foundLanguage = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(nameResources + 1);
            }

            return(codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff));
        }
Пример #4
0
        /// <summary>
        /// 获取数据目录
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public IMAGE_DATA_DIRECTORY GetDirectory(IMAGE_DIRECTORY_ENTRY eEntryIndex)
        {
            fixed(int *pTemp = this.DataDirectory)
            {
                IMAGE_DATA_DIRECTORY *pDataDirectory = (IMAGE_DATA_DIRECTORY *)pTemp;

                pDataDirectory += (Int32)eEntryIndex;
                return(*pDataDirectory);
            }
        }
Пример #5
0
        private static bool PerformBaseRelocation(MEMORYMODULE module, void *delta)
        {
            byte *codeBase = module.codeBase;
            IMAGE_BASE_RELOCATION *relocation;

            IMAGE_DATA_DIRECTORY *directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);

            if (directory->Size == 0)
            {
                return(delta == null);
            }

            relocation = (IMAGE_BASE_RELOCATION *)((ulong)codeBase + directory->VirtualAddress);
            for (; relocation->VirtualAddress > 0;)
            {
                uint    i;
                byte *  dest    = codeBase + relocation->VirtualAddress;
                ushort *relInfo = (ushort *)OffsetPointer(relocation, (void *)IMAGE_BASE_RELOCATION.UnmanagedSize);
                for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_BASE_RELOCATION.UnmanagedSize) / 2); i++, relInfo++)
                {
                    // the upper 4 bits define the type of relocation
                    uint type = (uint)(*relInfo) >> 12;
                    // the lower 12 bits define the offset
                    uint offset = (uint)(*relInfo) & 0xfff;

                    switch (type)
                    {
                    case IMAGE_REL_BASED_ABSOLUTE:
                        // skip relocation
                        break;

                    case IMAGE_REL_BASED_HIGHLOW:
                        // change complete 32 bit address
                        uint *patchAddrHL  = (uint *)(dest + offset);
                        *     patchAddrHL += (uint)delta;
                        break;

                    case IMAGE_REL_BASED_DIR64:
                        if (WIN64)
                        {
                            ulong *patchAddr64  = (ulong *)(dest + offset);
                            *      patchAddr64 += (ulong)delta;
                        }
                        break;

                    default:
                        break;
                    }
                }

                // advance to next relocation block
                relocation = (IMAGE_BASE_RELOCATION *)OffsetPointer(relocation, (void *)relocation->SizeOfBlock);
            }
            return(true);
        }
Пример #6
0
        private void BuildImportTable()
        {
            IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.ImportTable;

            if (directory->Size > 0)
            {
                IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(this.codeBase + directory->VirtualAddress);
                for (; !NativeDeclarations.IsBadReadPtr(new IntPtr(importDesc), (uint)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR))) && importDesc->Name > 0; importDesc++)
                {
                    uint *thunkRef;
                    int * funcRef;

                    string funcName = Marshal.PtrToStringAnsi(new IntPtr(this.codeBase + importDesc->Name));
                    IntPtr handle   = NativeDeclarations.LoadLibrary(funcName);

                    if (handle == IntPtr.Zero)
                    {
                        throw new NativeDllLoadException("Can't load libary " + funcName);
                    }

                    this.modules.Add(handle);
                    if (importDesc->OriginalFirstThunk > 0)
                    {
                        thunkRef = (uint *)(codeBase + importDesc->OriginalFirstThunk);
                        funcRef  = (int *)(codeBase + importDesc->FirstThunk);
                    }
                    else
                    {
                        // no hint table
                        thunkRef = (uint *)(codeBase + importDesc->FirstThunk);
                        funcRef  = (int *)(codeBase + importDesc->FirstThunk);
                    }
                    for (; *thunkRef > 0; thunkRef++, funcRef++)
                    {
                        string procName;
                        if (NativeDeclarations.IMAGE_SNAP_BY_ORDINAL32(*thunkRef))
                        {
                            procName = Marshal.PtrToStringAnsi(new IntPtr(NativeDeclarations.IMAGE_ORDINAL32(*thunkRef)));
                            *funcRef = (int)NativeDeclarations.GetProcAddress(handle, procName);
                        }
                        else
                        {
                            IMAGE_IMPORT_BY_NAME *thunkData = (IMAGE_IMPORT_BY_NAME *)(codeBase + (*thunkRef));
                            procName = Marshal.PtrToStringAnsi(new IntPtr(thunkData->Name));
                            *funcRef = (int)NativeDeclarations.GetProcAddress(handle, procName);
                        }
                        if (*funcRef == 0)
                        {
                            throw new NativeDllLoadException("Can't get adress for " + procName);
                        }
                    }
                }
            }
        }
Пример #7
0
        private void PerformBaseRelocation(uint delta)
        {
            if (delta == 0)
            {
                return;
            }

            int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));

            IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.BaseRelocationTable;

            if (directory->Size > 0)
            {
                IMAGE_BASE_RELOCATION *relocation = (IMAGE_BASE_RELOCATION *)(this.codeBase + directory->VirtualAddress);
                while (relocation->VirtualAdress > 0)
                {
                    byte *  dest    = this.codeBase + relocation->VirtualAdress;
                    ushort *relInfo = (ushort *)((byte *)relocation + imageSizeOfBaseRelocation);

                    for (int i = 0; i < ((relocation->SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++, relInfo++)
                    {
                        uint *patchAddrHL;
                        BasedRelocationType type;
                        int offset;

                        // the upper 4 bits define the type of relocation
                        type = (BasedRelocationType)(*relInfo >> 12);
                        // the lower 12 bits define the offset
                        offset = *relInfo & 0xfff;

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

                        case BasedRelocationType.IMAGE_REL_BASED_HIGHLOW:
                            patchAddrHL = (uint *)(dest + offset);
                            *patchAddrHL += delta;
                            break;

                        default:
                            break;
                        }
                    }

                    // advance to next relocation block
                    relocation = (IMAGE_BASE_RELOCATION *)(((byte *)relocation) + relocation->SizeOfBlock);
                }
            }
        }
Пример #8
0
        private void ExecuteTLS()
        {
            IMAGE_TLS_DIRECTORY *tlsDir;
            UIntPtrT *           callbackPtr;
            ImageTlsDelegate     tls;

            IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.TLSTable;

            if (directory->VirtualAddress == 0)
            {
                return;
            }

            tlsDir      = (IMAGE_TLS_DIRECTORY *)(_codeBase + directory->VirtualAddress);
            callbackPtr = (UIntPtrT *)tlsDir->AddressOfCallBacks;
            if (callbackPtr != null)
            {
                for (; *callbackPtr > 0; callbackPtr++)
                {
                    tls = Marshal.GetDelegateForFunctionPointer <ImageTlsDelegate>((IntPtr)(*callbackPtr));
                    tls(_codeBase, DllReason.DLL_PROCESS_ATTACH, null);
                }
            }
        }
Пример #9
0
        internal static void* MemoryGetProcAddress(MEMORYMODULE mod, byte* name)
        {
            MEMORYMODULE module = mod;
            byte* codeBase = module.codeBase;
            uint idx = 0;
            IMAGE_EXPORT_DIRECTORY* exports;
            IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT);
            if (directory->Size == 0)
                // no export table found
                return null;

            exports = (IMAGE_EXPORT_DIRECTORY*)(codeBase + directory->VirtualAddress);
            if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
                // DLL doesn't export anything
                return null;

            if (HIWORD(name) == 0)
            {
                // load function by ordinal value
                if (LOWORD(name) < exports->Base)
                    return null;

                idx = LOWORD(name) - exports->Base;
            }
            else if (exports->NumberOfNames == 0)
                return null;
            else
            {
                ExportNameEntry found;

                // Lazily build name table and sort it by names
                if (module.nameExportsTable == null)
                {
                    uint i;
                    uint* nameRef = (uint*)(codeBase + exports->AddressOfNames);
                    ushort* ordinal = (ushort*)(codeBase + exports->AddressOfNameOrdinals);
                    ExportNameEntry[] entry = new ExportNameEntry[exports->NumberOfNames];
                    module.nameExportsTable = entry;
                    for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++)
                        entry[i] = new ExportNameEntry
                        {
                            name = codeBase + (*nameRef),
                            idx = *ordinal
                        };
                    Array.Sort(module.nameExportsTable, _compare);
                }

                // search function name in list of exported names with binary search
                ExportNameEntry tmp = new ExportNameEntry { name = name };
                int foundIndex = Array.BinarySearch(module.nameExportsTable, tmp, tmp);
                found = foundIndex < 0 ? null : module.nameExportsTable[foundIndex];
                if (found == null)
                    // exported symbol not found
                    return null;

                idx = found.idx;
            }

            if (idx > exports->NumberOfFunctions)
                // name <. ordinal number don't match
                return null;

            // AddressOfFunctions contains the RVAs to the "real" functions
            return (void*)(codeBase + (*(uint*)(codeBase + exports->AddressOfFunctions + (idx * 4))));
        }
Пример #10
0
        private static bool BuildImportTable(MEMORYMODULE module)
        {
            byte* codeBase = module.codeBase;
            IMAGE_IMPORT_DESCRIPTOR* importDesc;
            bool result = true;

            IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
            if (directory->Size == 0)
            {
                return true;
            }

            importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(codeBase + directory->VirtualAddress);
            for (; !IsBadReadPtr(importDesc, (void*)IMAGE_IMPORT_DESCRIPTOR.UnmanagedSize) && importDesc->Name != 0; importDesc++)
            {
                void** thunkRef;
                void** funcRef;
                void** tmp;
                void* handle = module.loadLibrary(codeBase + importDesc->Name, module.userdata);
                if (handle == null)
                {
                    result = false;
                    break;
                }

                tmp = (void**)realloc(module.modules, (void*)((module.numModules + 1) * sizeof(void*)));
                if (tmp == null)
                {
                    module.freeLibrary(handle, module.userdata);
                    result = false;
                    break;
                }
                module.modules = tmp;

                module.modules[module.numModules++] = handle;
                if (importDesc->OriginalFirstThunk != 0)
                {
                    thunkRef = (void**)(codeBase + importDesc->OriginalFirstThunk);
                    funcRef = (void**)(codeBase + importDesc->FirstThunk);
                }
                else
                {
                    // no hint table
                    thunkRef = (void**)(codeBase + importDesc->FirstThunk);
                    funcRef = (void**)(codeBase + importDesc->FirstThunk);
                }
                for (; *thunkRef != null; thunkRef++, funcRef++)
                {
                    if (IMAGE_SNAP_BY_ORDINAL(*thunkRef))
                    {
                        *funcRef = module.getProcAddress(handle, (byte*)IMAGE_ORDINAL(*thunkRef), module.userdata);
                    }
                    else
                    {
                        IMAGE_IMPORT_BY_NAME* thunkData = (IMAGE_IMPORT_BY_NAME*)(codeBase + (ulong)(*thunkRef));
                        *funcRef = module.getProcAddress(handle, thunkData->Name, module.userdata);
                    }
                    if (*funcRef == null)
                    {
                        result = false;
                        break;
                    }
                }

                if (!result)
                {
                    module.freeLibrary(handle, module.userdata);
                    break;
                }
            }

            return result;
        }
Пример #11
0
        public static unsafe List <uint> GetStaticImportNameOffsets(byte[] fileBytes, string arch)
        {
            // This function walks the PE header to get the offset of the Import Address Table
            // (IAT) and then resolves the imports' names
            fixed(byte *ptr_data = fileBytes)
            {
                // Initial validation
                UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data;
                if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE)
                {
                    Console.WriteLine("[-] Magic bytes don't match");
                    return(null);
                }

                // We'll split here because much of the work we need to do uses offsets from the NT headers
                if (arch == "x64")
                {
                    UnsafeHelpers.IMAGE_NT_HEADERS64 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew);
                    if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE)
                    {
                        Console.WriteLine("[-] NT Header signature mismatch");
                        return(null);
                    }
                    IMAGE_DATA_DIRECTORY *DataDirectory = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);

                    // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies.
                    uint itRVA = DataDirectory->VirtualAddress;
                    if (itRVA == 0)
                    {
                        Console.WriteLine("[!] Import Table RVA is 0. Something is wrong...");
                        return(null);
                    }

                    // Do the conversion from the RVA to the offsets we'll need to do some math
                    Offset iatOffsets = RvaToOffset(nt_header, null, itRVA, "IAT");

                    // Math to get the true offset to the name of the DLL
                    // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor
                    uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA);
                    UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset);

                    List <uint> nameOffsets = new List <uint>();
                    while (firstModule->Name != 0)
                    {
                        uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA);
                        nameOffsets.Add(trueOffset);
                        firstModule++;
                    }

                    return(nameOffsets);
                }
                else // x86
                {
                    UnsafeHelpers.IMAGE_NT_HEADERS32 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew);
                    if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE)
                    {
                        Console.WriteLine("[-] NT Header signature mismatch");
                        return(null);
                    }
                    UnsafeHelpers.IMAGE_DATA_DIRECTORY *DataDirectory = (UnsafeHelpers.IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[UnsafeHelpers.IMAGE_DIRECTORY_ENTRY_IMPORT]);

                    // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies.
                    uint itRVA = DataDirectory->VirtualAddress;
                    if (itRVA == 0)
                    {
                        Console.WriteLine("[!] Import Table RVA is 0. Something is wrong...");
                        return(null);
                    }

                    // Do the conversion from the RVA to the offsets we'll need to do some math
                    Offset iatOffsets = RvaToOffset(null, nt_header, itRVA, "IAT");

                    // Math to get the true offset to the name of the DLL
                    // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor
                    uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA);
                    UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset);

                    //uint nameOffset = 0 + rdataRawOffset + (firstModule->Name - rdataRVA);

                    List <uint> nameOffsets = new List <uint>();
                    while (firstModule->Name != 0)
                    {
                        uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA);
                        nameOffsets.Add(trueOffset);
                        firstModule++;
                    }

                    return(nameOffsets);
                }
            }
        }
Пример #12
0
        public static unsafe List <string> GetDynamicImports(byte[] fileBytes, string arch)
        {
            // This function walks the PE header to get the offset of the Delay-Load Descriptor Table
            // (DLDT) and then resolves the imports' names
            List <string> dynamicModuleNames = new List <string>();

            fixed(byte *ptr_data = fileBytes)
            {
                // Initial validation
                UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data;
                if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE)
                {
                    Console.WriteLine("[-] Magic bytes don't match");
                    return(dynamicModuleNames);
                }

                // Get the NT headers
                if (arch == "x64")
                {
                    IMAGE_NT_HEADERS64 *nt_header = (IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew);
                    if (nt_header->Signature != IMAGE_NT_SIGNATURE)
                    {
                        Console.WriteLine("[-] NT Header signature mismatch");
                        return(dynamicModuleNames);
                    }

                    // Get the offset for the delay-load import tables
                    ulong *DataDirectory       = nt_header->OptionalHeader.DataDirectory;
                    IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
                    uint dldtRVA = dldt->VirtualAddress;
                    if (dldtRVA == 0) // No delayed imports found
                    {
                        return(dynamicModuleNames);
                    }

                    Offset offsets = RvaToOffset(nt_header, null, dldtRVA, "DLDT");
                    uint   offset  = offsets.RawOffset + (dldtRVA - offsets.RVA);

                    // Iterate over the list of delay-loaded modules
                    IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset);

                    while (firstModule->szName != 0)
                    {
                        Offset offsetToNames = RvaToOffset(nt_header, null, firstModule->szName, "szName");
                        uint   offset2       = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA);
                        dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2)));
                        firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR)));
                    }
                }
                else // x86
                {
                    IMAGE_NT_HEADERS32 *nt_header = (IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew);
                    if (nt_header->Signature != IMAGE_NT_SIGNATURE)
                    {
                        Console.WriteLine("[-] NT Header signature mismatch");
                        return(dynamicModuleNames);
                    }

                    // Get the offset for the delay-load import tables
                    ulong *DataDirectory       = nt_header->OptionalHeader.DataDirectory;
                    IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]);
                    uint dldtRVA = dldt->VirtualAddress;
                    if (dldtRVA == 0) // No delayed imports found
                    {
                        return(dynamicModuleNames);
                    }

                    Offset offsets = RvaToOffset(null, nt_header, dldtRVA, "DLDT");
                    uint   offset  = offsets.RawOffset + (dldtRVA - offsets.RVA);

                    // Iterate over the list of delay-loaded modules
                    IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset);

                    while (firstModule->szName != 0)
                    {
                        Offset offsetToNames = RvaToOffset(null, nt_header, firstModule->szName, "szName");
                        uint   offset2       = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA);
                        dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2)));
                        firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR)));
                    }
                }

                return(dynamicModuleNames);
            }
        }
Пример #13
0
        private void BuildImportTable()
        {
            IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.ImportTable;

            if (directory->Size == 0)
            {
                throw new NativeDllLoadException("Invalid import table.");
            }


            IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(_codeBase + directory->VirtualAddress);

            for (; !Win.IsBadReadPtr((importDesc), (UIntPtrT)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR))) && importDesc->Name > 0; importDesc++)
            {
                UIntPtrT *thunkRef;
                Farproc * funcRef;

                HCoustomMudule handle = Win.LoadLibrary(_codeBase + importDesc->Name);

                if (InvalidHandle(handle))
                {
                    if (_modules.Any())
                    {
                        _modules.ForEach(m => Win.FreeLibrary(m));
                    }

                    throw new NativeDllLoadException("Can't load libary " + Marshal.PtrToStringAnsi(new IntPtr(_codeBase + importDesc->Name)));
                }

                _modules.Add(handle);
                if (importDesc->OriginalFirstThunk > 0)
                {
                    thunkRef = (UIntPtrT *)(_codeBase + importDesc->OriginalFirstThunk);
                    funcRef  = (Farproc *)(_codeBase + importDesc->FirstThunk);
                }
                else
                {
                    // no hint table
                    thunkRef = (UIntPtrT *)(_codeBase + importDesc->FirstThunk);
                    funcRef  = (Farproc *)(_codeBase + importDesc->FirstThunk);
                }
                for (; *thunkRef > 0; thunkRef++, funcRef++)
                {
                    string procName;
                    if (Win.IMAGE_SNAP_BY_ORDINAL(*thunkRef))
                    {
                        procName = Marshal.PtrToStringAnsi(new IntPtr());
                        *funcRef = (Farproc)Win.GetProcAddress(handle, (byte *)Win.IMAGE_ORDINAL(*thunkRef));
                    }
                    else
                    {
                        IMAGE_IMPORT_BY_NAME *thunkData = (IMAGE_IMPORT_BY_NAME *)(_codeBase + (*thunkRef));
                        *funcRef = (Farproc)Win.GetProcAddress(handle, thunkData->Name);
                    }
                    if (*funcRef == 0)
                    {
                        throw new NativeDllLoadException("Can't get adress for imported function.");
                    }
                }
            }
        }
Пример #14
0
        private void *GetPtrFromFuncName(string funcName)
        {
            if (Disposed)
            {
                throw new InvalidOperationException("Object disposed");
            }

            if (!IsDll)
            {
                throw new InvalidOperationException("Loaded Module is not a DLL");
            }

            if (string.IsNullOrEmpty(funcName))
            {
                throw new ArgumentException("funcName");
            }


            if (Disposed)
            {
                throw new ObjectDisposedException("MemoryModule");
            }

            if (!_initialized)
            {
                throw new InvalidOperationException("Dll is not initialized.");
            }

            int     idx = -1;
            uint *  nameRef;
            ushort *ordinal;
            IMAGE_EXPORT_DIRECTORY * exports;
            Dictionary <string, int> exportEntrys = new Dictionary <string, int>();

            IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.ExportTable;

            if (directory->Size == 0)
            {
                throw new NativeDllLoadException("Dll has no export table.");
            }

            exports = (IMAGE_EXPORT_DIRECTORY *)(_codeBase + directory->VirtualAddress);
            if (exports->NumberOfFunctions == 0 || exports->NumberOfNames == 0)
            {
                throw new NativeDllLoadException("Dll exports no functions.");
            }

            nameRef = (uint *)(_codeBase + exports->AddressOfNames);
            ordinal = (ushort *)(_codeBase + exports->AddressOfNameOrdinals);
            for (int i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++)
            {
                string curFuncName = Marshal.PtrToStringAnsi((IntPtr)(_codeBase + *nameRef));
                exportEntrys.Add(curFuncName, *ordinal);
            }

            if (!exportEntrys.Keys.Contains(funcName))
            {
                throw new NativeDllLoadException("Dll exports no function named " + funcName);
            }

            idx = exportEntrys[funcName];

            if (idx > exports->NumberOfFunctions)
            {
                throw new NativeDllLoadException("IDX don't match number of funtions.");
            }

            return(_codeBase + (*(uint *)(_codeBase + exports->AddressOfFunctions + (idx * 4))));
        }