Пример #1
1
static inline NTSTATUS access_resource( HMODULE hmod, const IMAGE_RESOURCE_DATA_ENTRY *entry,
                                        void **ptr, ULONG *size )
#endif
{
    NTSTATUS status;

    __TRY
    {
        ULONG dirsize;

        if (!RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &dirsize ))
            status = STATUS_RESOURCE_DATA_NOT_FOUND;
        else
        {
            if (ptr)
            {
                if (is_data_file_module(hmod))
                {
                    HMODULE mod = (HMODULE)((ULONG_PTR)hmod & ~1);
                    *ptr = RtlImageRvaToVa( RtlImageNtHeader(mod), mod, entry->OffsetToData, NULL );
                }
                else *ptr = (char *)hmod + entry->OffsetToData;
            }
            if (size) *size = entry->Size;
            status = STATUS_SUCCESS;
        }
    }
    __EXCEPT_PAGE_FAULT
    {
        return GetExceptionCode();
    }
    __ENDTRY;
    return status;
}
Пример #2
1
LONG
WINAPI
BasepCheckForReadOnlyResource(IN PVOID Ptr)
{
    PVOID Data;
    ULONG Size, OldProtect;
    SIZE_T Size2;
    MEMORY_BASIC_INFORMATION mbi;
    NTSTATUS Status;
    LONG Ret = EXCEPTION_CONTINUE_SEARCH;

    /* Check if it was an attempt to write to a read-only image section! */
    Status = NtQueryVirtualMemory(NtCurrentProcess(),
                                  Ptr,
                                  MemoryBasicInformation,
                                  &mbi,
                                  sizeof(mbi),
                                  NULL);
    if (NT_SUCCESS(Status) &&
        mbi.Protect == PAGE_READONLY && mbi.Type == MEM_IMAGE)
    {
        /* Attempt to treat it as a resource section. We need to
           use SEH here because we don't know if it's actually a
           resource mapping */
        _SEH2_TRY
        {
            Data = RtlImageDirectoryEntryToData(mbi.AllocationBase,
                                                TRUE,
                                                IMAGE_DIRECTORY_ENTRY_RESOURCE,
                                                &Size);

            if (Data != NULL &&
                (ULONG_PTR)Ptr >= (ULONG_PTR)Data &&
                (ULONG_PTR)Ptr < (ULONG_PTR)Data + Size)
            {
                /* The user tried to write into the resources. Make the page
                   writable... */
                Size2 = 1;
                Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                                &Ptr,
                                                &Size2,
                                                PAGE_READWRITE,
                                                &OldProtect);
                if (NT_SUCCESS(Status))
                {
                    Ret = EXCEPTION_CONTINUE_EXECUTION;
                }
            }
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
        }
        _SEH2_END;
    }
Пример #3
0
/***********************************************************************
 *           set_entry_point
 */
static void set_entry_point( HMODULE module, const char *name, DWORD rva )
{
    IMAGE_EXPORT_DIRECTORY *exports;
    DWORD exp_size;

    if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
                   IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
    {
        DWORD *functions = (DWORD *)((char *)module + exports->AddressOfFunctions);
        const WORD *ordinals = (const WORD *)((const char *)module + exports->AddressOfNameOrdinals);
        const DWORD *names = (const DWORD *)((const char *)module +  exports->AddressOfNames);
        int min = 0, max = exports->NumberOfNames - 1;

        while (min <= max)
        {
            int res, pos = (min + max) / 2;
            const char *ename = (const char *)module + names[pos];
            if (!(res = strcmp( ename, name )))
            {
                WORD ordinal = ordinals[pos];
                assert( ordinal < exports->NumberOfFunctions );
                TRACE( "setting %s at %p to %08x\n", name, &functions[ordinal], rva );
                functions[ordinal] = rva;
                return;
            }
            if (res > 0) max = pos - 1;
            else min = pos + 1;
        }
    }
}
Пример #4
0
/*! RtlLookupFunctionTable
 * \brief Locates the table of RUNTIME_FUNCTION entries for a code address.
 * \param ControlPc
 *            Address of the code, for which the table should be searched.
 * \param ImageBase 
 *            Pointer to a DWORD64 that receives the base address of the
 *            corresponding executable image.
 * \param Length
 *            Pointer to an ULONG that receives the number of table entries
 *            present in the table.
 */
PRUNTIME_FUNCTION
NTAPI
RtlLookupFunctionTable(
    IN DWORD64 ControlPc,
    OUT PDWORD64 ImageBase,
    OUT PULONG Length)
{
    PVOID Table;
    ULONG Size;

    /* Find corresponding file header from code address */
    if (!RtlPcToFileHeader((PVOID)ControlPc, (PVOID*)ImageBase))
    {
        /* Nothing found */
        return NULL;
    }

    /* Locate the exception directory */
    Table = RtlImageDirectoryEntryToData((PVOID)*ImageBase,
                                         TRUE,
                                         IMAGE_DIRECTORY_ENTRY_EXCEPTION,
                                         &Size);

    /* Return the number of entries */
    *Length = Size / sizeof(RUNTIME_FUNCTION);

    /* Return the address of the table */
    return Table;
}
Пример #5
0
static NTSTATUS LdrpAccessResource( PVOID BaseAddress, IMAGE_RESOURCE_DATA_ENTRY *entry,
                                    void **ptr, ULONG *size )
#endif
{
    NTSTATUS status = STATUS_SUCCESS;

    _SEH2_TRY
    {
        ULONG dirsize;

        if (!RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &dirsize ))
            status = STATUS_RESOURCE_DATA_NOT_FOUND;
        else
        {
            if (ptr)
            {
                if (is_data_file_module(BaseAddress))
                {
                    PVOID mod = (PVOID)((ULONG_PTR)BaseAddress & ~1);
                    *ptr = RtlImageRvaToVa( RtlImageNtHeader(mod), mod, entry->OffsetToData, NULL );
                }
                else *ptr = (char *)BaseAddress + entry->OffsetToData;
            }
            if (size) *size = entry->Size;
        }
    }
    _SEH2_EXCEPT(page_fault(_SEH2_GetExceptionCode()))
    {
        status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;
    return status;
}
Пример #6
0
NTSTATUS
NTAPI
LdrPEFixupImports(IN PVOID DllBase,
                  IN PCHAR DllName)
{
    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
    PCHAR ImportedName;
    NTSTATUS Status;
    PLOADER_MODULE ImportedModule;
    ULONG Size;

    /*  Process each import module  */
    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
        RtlImageDirectoryEntryToData(DllBase,
                                     TRUE,
                                     IMAGE_DIRECTORY_ENTRY_IMPORT,
                                     &Size);
    while (ImportModuleDirectory && ImportModuleDirectory->Name)
    {
        /*  Check to make sure that import lib is kernel  */
        ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name;
        //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);

        Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
        if (!NT_SUCCESS(Status)) return Status;

        Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
        if (!NT_SUCCESS(Status)) return Status;

        //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
        ImportModuleDirectory++;
    }

    return STATUS_SUCCESS;
}
Пример #7
0
NTSTATUS
NTAPI
INIT_FUNCTION
LookupEntryPoint(IN PVOID DllBase,
                 IN PCHAR Name,
                 OUT PVOID *EntryPoint)
{
    PULONG NameTable;
    PUSHORT OrdinalTable;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    ULONG ExportSize;
    CHAR Buffer[64];
    USHORT Ordinal;
    PULONG ExportTable;

    /* Get the export directory */
    ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
                                                   TRUE,
                                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
                                                   &ExportSize);

    /* Validate the name and copy it */
    if (strlen(Name) > sizeof(Buffer) - 2) return STATUS_INVALID_PARAMETER;
    strcpy(Buffer, Name);

    /* Setup name tables */
    NameTable = (PULONG)((ULONG_PTR)DllBase +
                         ExportDirectory->AddressOfNames);
    OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
                             ExportDirectory->AddressOfNameOrdinals);

    /* Get the ordinal */
    Ordinal = NameToOrdinal(Buffer,
                            DllBase,
                            ExportDirectory->NumberOfNames,
                            NameTable,
                            OrdinalTable);

    /* Make sure the ordinal is valid */
    if (Ordinal >= ExportDirectory->NumberOfFunctions)
    {
        /* It's not, fail */
        return STATUS_PROCEDURE_NOT_FOUND;
    }

    /* Resolve the address and write it */
    ExportTable = (PULONG)((ULONG_PTR)DllBase +
                           ExportDirectory->AddressOfFunctions);
    *EntryPoint = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
    return STATUS_SUCCESS;
}
Пример #8
0
/*******************************************************************
 *         check_resource_write
 *
 * Check if the exception is a write attempt to the resource data.
 * If yes, we unprotect the resources to let broken apps continue
 * (Windows does this too).
 */
static inline BOOL check_resource_write( void *addr )
{
    void *rsrc;
    DWORD size;
    MEMORY_BASIC_INFORMATION info;

    if (!VirtualQuery( addr, &info, sizeof(info) )) return FALSE;
    if (info.State == MEM_FREE || !(info.Type & MEM_IMAGE)) return FALSE;
    if (!(rsrc = RtlImageDirectoryEntryToData( (HMODULE)info.AllocationBase, TRUE,
                                              IMAGE_DIRECTORY_ENTRY_RESOURCE, &size )))
        return FALSE;
    if (addr < rsrc || (char *)addr >= (char *)rsrc + size) return FALSE;
    TRACE( "Broken app is writing to the resource data, enabling work-around\n" );
    VirtualProtect( rsrc, size, PAGE_WRITECOPY, NULL );
    return TRUE;
}
Пример #9
0
INIT_FUNCTION
NTSTATUS
NTAPI
InitLDEVImpl(VOID)
{
    ULONG cbSize;

    /* Initialize the loader lock */
    ghsemLDEVList = EngCreateSemaphore();
    if (!ghsemLDEVList)
    {
        ERR("Failed to create ghsemLDEVList\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Allocate a LDEVOBJ for win32k */
    gpldevWin32k = ExAllocatePoolWithTag(PagedPool,
                                         sizeof(LDEVOBJ) +
                                         sizeof(SYSTEM_GDI_DRIVER_INFORMATION),
                                         GDITAG_LDEV);
    if (!gpldevWin32k)
    {
        return STATUS_NO_MEMORY;
    }

    /* Initialize the LDEVOBJ for win32k */
    gpldevWin32k->pldevNext = NULL;
    gpldevWin32k->pldevPrev = NULL;
    gpldevWin32k->ldevtype = LDEV_DEVICE_DISPLAY;
    gpldevWin32k->cRefs = 1;
    gpldevWin32k->ulDriverVersion = GDI_ENGINE_VERSION;
    gpldevWin32k->pGdiDriverInfo = (PVOID)(gpldevWin32k + 1);
    RtlInitUnicodeString(&gpldevWin32k->pGdiDriverInfo->DriverName,
                         L"\\SystemRoot\\System32\\win32k.sys");
    gpldevWin32k->pGdiDriverInfo->ImageAddress = &__ImageBase;
    gpldevWin32k->pGdiDriverInfo->SectionPointer = NULL;
    gpldevWin32k->pGdiDriverInfo->EntryPoint = (PVOID)DriverEntry;
    gpldevWin32k->pGdiDriverInfo->ExportSectionPointer =
        RtlImageDirectoryEntryToData(&__ImageBase,
                                     TRUE,
                                     IMAGE_DIRECTORY_ENTRY_EXPORT,
                                     &cbSize);
    gpldevWin32k->pGdiDriverInfo->ImageLength = 0; // FIXME

    return STATUS_SUCCESS;
}
Пример #10
0
ARC_STATUS
BlScanOsloaderBoundImportTable (
    IN PLDR_DATA_TABLE_ENTRY ScanEntry
    )

/*++

Routine Description:

    This routine scans the import descriptor table for the specified image
    file and loads each DLL that is referenced.

Arguments:

    DataTableEntry - Supplies a pointer to the data table entry for the
        image whose import table is to be scanned.

Return Value:

    ESUCCESS is returned in the scan is successful. Otherwise, return an
    unsuccessful status.

--*/

{

    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
    ULONG ImportTableSize;
    ARC_STATUS Status;
    PSZ ImportName;

    //
    // Locate the import table in the image specified by the data table entry.
    //

    ImportDescriptor =
        (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ScanEntry->DllBase,
                                                              TRUE,
                                                              IMAGE_DIRECTORY_ENTRY_IMPORT,
                                                              &ImportTableSize);

    //
    // If the image has an import directory, then scan the import table.
    //

    if (ImportDescriptor != NULL) {
        while ((ImportDescriptor->Name != 0) &&
               (ImportDescriptor->FirstThunk != NULL)) {

            //
            // Change the name from an RVA to a VA.
            //

            ImportName = (PSZ)((ULONG)ScanEntry->DllBase + ImportDescriptor->Name);

            //
            // If the DLL references itself, then skip the import entry.
            //

            if (BlpCompareDllName((PCHAR)ImportName,
                                  &ScanEntry->BaseDllName) == FALSE) {

                //
                // Scan the import address table and snap links.
                //

                Status = BlpScanImportAddressTable(NULL,
                            ScanEntry->DllBase,
                            (PIMAGE_THUNK_DATA)((ULONG)ScanEntry->DllBase +
                            (ULONG)ImportDescriptor->FirstThunk));

                if (Status != ESUCCESS) {
                    return Status;
                }
            }

            ImportDescriptor += 1;
        }
    }

    return ESUCCESS;
}
Пример #11
0
ARC_STATUS
BlpScanImportAddressTable(
    IN PVOID DllBase,
    IN PVOID ImageBase,
    IN PIMAGE_THUNK_DATA ThunkTable
    )

/*++

Routine Description:

    This routine scans the import address table for the specified image
    file and snaps each reference.

Arguments:

    DllBase - Supplies the base address of the specified DLL.
        If NULL, then references in the image's import table are to
        be resolved against the osloader's export table.

    ImageBase - Supplies the base address of the image.

    ThunkTable - Supplies a pointer to the import thunk table.

Return Value:

    ESUCCESS is returned in the scan is successful. Otherwise, return an
    unsuccessful status.

--*/

{

    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    ULONG ExportTableSize;
    ARC_STATUS Status;

    //
    // Locate the export table in the image specified by the DLL base
    // address.
    //

#if i386
    if (DllBase == NULL) {
        ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)OsLoaderExports;
    } else {
        ExportDirectory =
            (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase,
                                                                 TRUE,
                                                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
                                                                 &ExportTableSize);
    }
#else
    ExportDirectory =
        (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase,
                                                             TRUE,
                                                             IMAGE_DIRECTORY_ENTRY_EXPORT,
                                                             &ExportTableSize);
#endif
    if (ExportDirectory == NULL) {
        return EBADF;
    }

    //
    // Scan the thunk table and bind each import reference.
    //

    while (ThunkTable->u1.AddressOfData != NULL) {
        Status = BlpBindImportName(DllBase,
                                   ImageBase,
                                   ThunkTable++,
                                   ExportDirectory,
                                   ExportTableSize,
                                   FALSE);
        if (Status != ESUCCESS) {
            return Status;
        }
    }

    return ESUCCESS;
}
Пример #12
0
BOOLEAN
WinLdrScanImportDescriptorTable(IN OUT PLIST_ENTRY ModuleListHead,
                                IN PCCH DirectoryPath,
                                IN PLDR_DATA_TABLE_ENTRY ScanDTE)
{
    PLDR_DATA_TABLE_ENTRY DataTableEntry;
    PIMAGE_IMPORT_DESCRIPTOR ImportTable;
    ULONG ImportTableSize;
    PCH ImportName;
    BOOLEAN Success;

    /* Get a pointer to the import table of this image */
    ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(ScanDTE->DllBase),
        TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize);

    {
        UNICODE_STRING BaseName;
        BaseName.Buffer = VaToPa(ScanDTE->BaseDllName.Buffer);
        BaseName.MaximumLength = ScanDTE->BaseDllName.MaximumLength;
        BaseName.Length = ScanDTE->BaseDllName.Length;
        TRACE("WinLdrScanImportDescriptorTable(): %wZ ImportTable = 0x%X\n",
            &BaseName, ImportTable);
    }

    /* If image doesn't have any import directory - just return success */
    if (ImportTable == NULL)
        return TRUE;

    /* Loop through all entries */
    for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++)
    {
        /* Get pointer to the name */
        ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name));
        TRACE("WinLdrScanImportDescriptorTable(): Looking at %s\n", ImportName);

        /* In case we get a reference to ourselves - just skip it */
        if (WinLdrpCompareDllName(ImportName, &ScanDTE->BaseDllName))
            continue;

        /* Load the DLL if it is not already loaded */
        if (!WinLdrCheckForLoadedDll(ModuleListHead, ImportName, &DataTableEntry))
        {
            Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead,
                                                      DirectoryPath,
                                                      ImportName,
                                                      &DataTableEntry);
            if (!Success)
            {
                ERR("WinLdrpLoadAndScanReferencedDll() failed\n");
                return Success;
            }
        }

        /* Scan its import address table */
        Success = WinLdrpScanImportAddressTable(ModuleListHead,
                                                DataTableEntry->DllBase,
                                                ScanDTE->DllBase,
                                                (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk),
                                                DirectoryPath);

        if (!Success)
        {
            ERR("WinLdrpScanImportAddressTable() failed: ImportName = '%s', DirectoryPath = '%s'\n",
                ImportName, DirectoryPath);
            return Success;
        }
    }

    return TRUE;
}
Пример #13
0
static BOOLEAN
WinLdrpBindImportName(IN OUT PLIST_ENTRY ModuleListHead,
                      IN PVOID DllBase,
                      IN PVOID ImageBase,
                      IN PIMAGE_THUNK_DATA ThunkData,
                      IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
                      IN ULONG ExportSize,
                      IN BOOLEAN ProcessForwards,
                      IN PCSTR DirectoryPath)
{
    ULONG Ordinal;
    PULONG NameTable, FunctionTable;
    PUSHORT OrdinalTable;
    LONG High, Low, Middle, Result;
    ULONG Hint;
    PIMAGE_IMPORT_BY_NAME ImportData;
    PCHAR ExportName, ForwarderName;
    BOOLEAN Success;

    //TRACE("WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n",
    //    DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards);

    /* Check passed DllBase param */
    if(DllBase == NULL)
    {
        WARN("DllBase == NULL!\n");
        return FALSE;
    }

    /* Convert all non-critical pointers to PA from VA */
    ThunkData = VaToPa(ThunkData);

    /* Is the reference by ordinal? */
    if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards)
    {
        /* Yes, calculate the ordinal */
        Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base);
        //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal);
    }
    else
    {
        /* It's reference by name, we have to look it up in the export directory */
        if (!ProcessForwards)
        {
            /* AddressOfData in thunk entry will become a virtual address (from relative) */
            //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
            ThunkData->u1.AddressOfData =
                (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData);
            //TRACE("WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData);
        }

        /* Get the import name */
        ImportData = VaToPa((PVOID)ThunkData->u1.AddressOfData);

        /* Get pointers to Name and Ordinal tables (RVA -> VA) */
        NameTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames));
        OrdinalTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals));

        //TRACE("NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n",
        //    NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals);

        /* Get the hint, convert it to a physical pointer */
        Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint;
        //TRACE("HintIndex %d\n", Hint);

        /* Get the export name from the hint */
        ExportName = VaToPa(RVA(DllBase, NameTable[Hint]));

        /* If Hint is less than total number of entries in the export directory,
           and import name == export name, then we can just get it from the OrdinalTable */
        if ((Hint < ExportDirectory->NumberOfNames) &&
            (strcmp(ExportName, (PCHAR)ImportData->Name) == 0))
        {
            Ordinal = OrdinalTable[Hint];
            //TRACE("WinLdrpBindImportName(): Ordinal %d\n", Ordinal);
        }
        else
        {
            /* It's not the easy way, we have to lookup import name in the name table.
               Let's use a binary search for this task. */

            //TRACE("WinLdrpBindImportName() looking up the import name using binary search...\n");

            /* Low boundary is set to 0, and high boundary to the maximum index */
            Low = 0;
            High = ExportDirectory->NumberOfNames - 1;

            /* Perform a binary-search loop */
            while (High >= Low)
            {
                /* Divide by 2 by shifting to the right once */
                Middle = (Low + High) / 2;

                /* Get the name from the name table */
                ExportName = VaToPa(RVA(DllBase, NameTable[Middle]));

                /* Compare the names */
                Result = strcmp(ExportName, (PCHAR)ImportData->Name);

                /*TRACE("Binary search: comparing Import '__', Export '%s'\n",*/
                    /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/
                    /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle])));*/

                /*TRACE("TE->u1.AOD %p, fulladdr %p\n",
                    ThunkData->u1.AddressOfData,
                    ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name );*/


                /* Depending on result of strcmp, perform different actions */
                if (Result > 0)
                {
                    /* Adjust top boundary */
                    High = Middle - 1;
                }
                else if (Result < 0)
                {
                    /* Adjust bottom boundary */
                    Low = Middle + 1;
                }
                else
                {
                    /* Yay, found it! */
                    break;
                }
            }

            /* If high boundary is less than low boundary, then no result found */
            if (High < Low)
            {
                //Print(L"Error in binary search\n");
                ERR("Did not find export '%s'!\n", (PCHAR)ImportData->Name);
                return FALSE;
            }

            /* Everything alright, get the ordinal */
            Ordinal = OrdinalTable[Middle];

            //TRACE("WinLdrpBindImportName() found Ordinal %d\n", Ordinal);
        }
    }

    /* Check ordinal number for validity! */
    if (Ordinal >= ExportDirectory->NumberOfFunctions)
    {
        ERR("Ordinal number is invalid!\n");
        return FALSE;
    }

    /* Get a pointer to the function table */
    FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions));

    /* Save a pointer to the function */
    ThunkData->u1.Function = (ULONG_PTR)RVA(DllBase, FunctionTable[Ordinal]);

    /* Is it a forwarder? (function pointer is within the export directory) */
    ForwarderName = (PCHAR)VaToPa((PVOID)ThunkData->u1.Function);
    if (((ULONG_PTR)ForwarderName > (ULONG_PTR)ExportDirectory) &&
        ((ULONG_PTR)ForwarderName < ((ULONG_PTR)ExportDirectory + ExportSize)))
    {
        PLDR_DATA_TABLE_ENTRY DataTableEntry;
        CHAR ForwardDllName[255];
        PIMAGE_EXPORT_DIRECTORY RefExportDirectory;
        ULONG RefExportSize;
        TRACE("WinLdrpBindImportName(): ForwarderName %s\n", ForwarderName);

        /* Save the name of the forward dll */
        RtlCopyMemory(ForwardDllName, ForwarderName, sizeof(ForwardDllName));

        /* Strip out the symbol name */
        *strrchr(ForwardDllName,'.') = '\0';

        /* Check if the target image is already loaded */
        if (!WinLdrCheckForLoadedDll(ModuleListHead, ForwardDllName, &DataTableEntry))
        {
            /* Check if the forward dll name has an extension */
            if (strchr(ForwardDllName, '.') == NULL)
            {
                /* Name does not have an extension, append '.dll' */
                strcat(ForwardDllName, ".dll");
            }

            /* Now let's try to load it! */
            Success = WinLdrpLoadAndScanReferencedDll(ModuleListHead,
                                                      DirectoryPath,
                                                      ForwardDllName,
                                                      &DataTableEntry);
            if (!Success)
            {
                ERR("WinLdrpLoadAndScanReferencedDll() failed to load forwarder dll.\n");
                return Success;
            }
        }

        /* Get pointer to the export directory of loaded DLL */
        RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
            RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase),
            TRUE,
            IMAGE_DIRECTORY_ENTRY_EXPORT,
            &RefExportSize);

        /* Fail if it's NULL */
        if (RefExportDirectory)
        {
            UCHAR Buffer[128];
            IMAGE_THUNK_DATA RefThunkData;
            PIMAGE_IMPORT_BY_NAME ImportByName;
            PCHAR ImportName;

            /* Get pointer to the import name */
            ImportName = strrchr(ForwarderName, '.') + 1;

            /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */
            ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer;

            /* Fill the name with the import name */
            RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1);

            /* Set Hint to 0 */
            ImportByName->Hint = 0;

            /* And finally point ThunkData's AddressOfData to that structure */
            RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName;

            /* And recursively call ourselves */
            Success = WinLdrpBindImportName(ModuleListHead,
                                            DataTableEntry->DllBase,
                                            ImageBase,
                                            &RefThunkData,
                                            RefExportDirectory,
                                            RefExportSize,
                                            TRUE,
                                            DirectoryPath);

            /* Fill out the ThunkData with data from RefThunkData */
            ThunkData->u1 = RefThunkData.u1;

            /* Return what we got from the recursive call */
            return Success;
        }
        else
        {
            /* Fail if ExportDirectory is NULL */
            return FALSE;
        }
    }

    /* Success! */
    return TRUE;
}
Пример #14
0
PVOID
NTAPI
LdrPEGetExportByName(PVOID BaseAddress,
                     PUCHAR SymbolName,
                     USHORT Hint)
{
    PIMAGE_EXPORT_DIRECTORY ExportDir;
    PULONG * ExFunctions;
    PULONG * ExNames;
    USHORT * ExOrdinals;
    PVOID ExName;
    ULONG Ordinal;
    PVOID Function;
    LONG minn, maxn, mid, res;
    ULONG ExportDirSize;

    /* HAL and NTOS use a virtual address, switch it to physical mode */
    if ((ULONG_PTR)BaseAddress & 0x80000000)
    {
        BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + (ULONG)KernelMemory);
    }

    ExportDir = (PIMAGE_EXPORT_DIRECTORY)
        RtlImageDirectoryEntryToData(BaseAddress,
                                     TRUE,
                                     IMAGE_DIRECTORY_ENTRY_EXPORT,
                                     &ExportDirSize);
    if (!ExportDir)
    {
        DbgPrint("LdrPEGetExportByName(): no export directory!\n");
        return NULL;
    }

    /* The symbol names may be missing entirely */
    if (!ExportDir->AddressOfNames)
    {
        DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
        return NULL;
    }

    /*
    * Get header pointers
    */
    ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
    ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
    ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);

    /*
    * Check the hint first
    */
    if (Hint < ExportDir->NumberOfNames)
    {
        ExName = RVA(BaseAddress, ExNames[Hint]);
        if (strcmp(ExName, (PCHAR)SymbolName) == 0)
        {
            Ordinal = ExOrdinals[Hint];
            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
            {
                Function = LdrPEFixupForward((PCHAR)Function);
                if (Function == NULL)
                {
                    DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
                }
                return Function;
            }

            if (Function != NULL) return Function;
        }
    }

    /*
    * Binary search
    */
    minn = 0;
    maxn = ExportDir->NumberOfNames - 1;
    while (minn <= maxn)
    {
        mid = (minn + maxn) / 2;

        ExName = RVA(BaseAddress, ExNames[mid]);
        res = strcmp(ExName, (PCHAR)SymbolName);
        if (res == 0)
        {
            Ordinal = ExOrdinals[mid];
            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
            {
                Function = LdrPEFixupForward((PCHAR)Function);
                if (Function == NULL)
                {
                    DbgPrint("1: failed to find %s\n", Function);
                }
                return Function;
            }
            if (Function != NULL)
            {
                return Function;
            }
        }
        else if (res > 0)
        {
            maxn = mid - 1;
        }
        else
        {
            minn = mid + 1;
        }
    }

    /* Fall back on unsorted */
    minn = 0;
    maxn = ExportDir->NumberOfNames - 1;
    while (minn <= maxn)
    {
        ExName = RVA(BaseAddress, ExNames[minn]);
        res = strcmp(ExName, (PCHAR)SymbolName);
        if (res == 0)
        {
            Ordinal = ExOrdinals[minn];
            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
            {
                Function = LdrPEFixupForward((PCHAR)Function);
                if (Function == NULL)
                {
                    DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
                }
                return Function;
            }
	    if (Function != NULL)
	    {
		return Function;
	    }
	    DbgPrint("Failed to get function %s\n", SymbolName);
	}
	minn++;
    }

    DbgPrint("2: failed to find %s\n",SymbolName);
    return (PVOID)NULL;
}
Пример #15
0
void ConvertImports (char * File)
{
    PIMAGE_IMPORT_DESCRIPTOR ImageImportDescr,DataImportDescr;
    HANDLE  mFile;
    ULONG   ImportSize,
            ImportName,
            PreferredImportBase,
            ImportNameLen,
            DataImportBase;
    BOOL    BoolError;
    CHAR   *pchDot;
    LPVOID  FileBase=NULL;
    int     iNewImp;

    ULONG   ulBinaryType ;
    PIMAGE_NT_HEADERS NtHeaders;
    ULONG	CheckSum;
    ULONG	HeaderSum;
	
    
    // Get file attributes
    //
    OldAttributes = GetFileAttributes(File);
    if (OldAttributes != FILE_ATTRIBUTE_NORMAL) {
        BoolError = SetFileAttributes(File, FILE_ATTRIBUTE_NORMAL);
    }


    ulBinaryType = GetImageType ( File ) ;

    //
	// Open file
    //
    hFile=CreateFile(File,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        (HANDLE)NULL);
    if (hFile==INVALID_HANDLE_VALUE) {

#ifdef DEBUG
        Error = GetLastError();
        printf("Error in creating file %lx\n",Error);
#endif
        DoError (FAIL_OPEN, File);
        return;
    }

//
//  tomzak
//
    if ( ulBinaryType != NT_CODE ) {
        DoError (NOT_NT_IMAGE, File);
		//
		// Close file handle
		//
		BoolError = CloseHandle(hFile);
		if (!BoolError) {
			DoError(FAIL_CLOSE,NULL);
		}
        return ;
    }


    // Create the file map
    //
    mFile=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0L,0L,NULL);

    if (!mFile) {

#ifdef DEBUG
        Error = GetLastError();
        printf("Can't make map object %lx\n",Error);
#endif

        DoError(CREATE_MAP,NULL);
        return;
    }

    // Map a view of the file as data
    //
    FileBase=MapViewOfFile(mFile, FILE_MAP_READ | FILE_MAP_WRITE, 0L, 0L, 0L);

    if (!FileBase) {
        DoError(VIEW_FILE_MAP,NULL);
    }

    // Get the address of the import descriptor as if the file was mapped
    // as data (the FALSE parameter below is the value of the parameter
    // MappedAsImage).
    DataImportDescr = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(
                        FileBase,
			FALSE,
                        IMAGE_DIRECTORY_ENTRY_IMPORT,
                        &ImportSize);

    // Get the address of the import descriptor as if the file was mapped
    // as an image (MappedAsImage = TRUE).
    ImageImportDescr = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(
        FileBase,
	TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT,
        &ImportSize);

    // The preferred import base offset is ImageImportDescr - FileBase
    // (RVA)
    //
    PreferredImportBase = (ULONG)ImageImportDescr-(ULONG)FileBase;

    // Make sure it is positive;  it's a ULONG.
    //
    if (PreferredImportBase> MAX_ULONG) {
	PreferredImportBase = (-(INT)PreferredImportBase);
    }

    if (DataImportDescr) {
        printf("%s imports:\n",File);

        // Keep the import base around
        //
        DataImportBase = (ULONG)DataImportDescr;

        // Go through the import names and check to see if the name
        // should be changed by comparing it the the "new import" list
        //
        while (DataImportDescr->Name && DataImportDescr->FirstThunk) {

            // Actual import name address is
            //    (Name - PreferredImportBase) +
            //    ActualImportBase(added below).
            //
            // RVA - RVA
            //
            ImportName = (DataImportDescr->Name - PreferredImportBase);

            // Make sure it's positive
            //
            if (ImportName > MAX_ULONG) {
		 ImportName = (-(INT)ImportName);
            }

            // Add the actual import base
            //
            ImportName += DataImportBase;

            if ( (pchDot = strchr((CHAR *)ImportName, '.')) == NULL ) {
                ImportNameLen = strlen((CHAR *)ImportName);
            }
            else {
                ImportNameLen = abs((int)((ULONG)pchDot - ImportName));
            }

            printf("\t%-15s",ImportName);
            for (iNewImp = 0; iNewImp < cNewImports; iNewImp++) {

               // New imports must match in length and in all chars
               // except for the first -- i.e. looking for "*mport" to
               // match "import"
               //
               if ((ImportNameLen == strlen(apszNewImports[iNewImp])) &&
                   (!_strnicmp((CHAR *)ImportName+1, apszNewImports[iNewImp]+1,
                             ImportNameLen-1))) {
                   strncpy((CHAR *)ImportName, apszNewImports[iNewImp],1);
                   BoolError = FlushViewOfFile((PVOID)ImportName, 1);
                   printf(" --> changed to %s",ImportName);
                   break;
               }
            }
            printf("\n");

            // Go to next import descriptor
            //
            ++DataImportDescr;
        }
    }
    else {
        printf("%s has no imports\n",File);
        printf("Done\n\n\n");
    }

    
    //
    // If the file is being update, then recompute the checksum (see sdktools\bind\bind.c)
    //

    NtHeaders = RtlImageNtHeader(FileBase);

    NtHeaders->OptionalHeader.CheckSum = 0;
    CheckSumMappedFile(
                FileBase,
                GetFileSize(hFile, NULL),
                &HeaderSum,
                &CheckSum
                );

    NtHeaders->OptionalHeader.CheckSum = CheckSum;

    
    // Unmap view of file to save changes
    //
    BoolError = UnmapViewOfFile(FileBase);
    if (!BoolError) {
        DoError(FAIL_UNMAP,NULL);
    }

    // Close handle to map-object
    //
    BoolError = CloseHandle(mFile);
    if (!BoolError) {
        DoError(FAIL_CLOSE,NULL);
    }

    // Close file handle
    //
    BoolError = CloseHandle(hFile);
    if (!BoolError) {
        DoError(FAIL_CLOSE,NULL);
    }

    // Reset the file attributes
    //
    BoolError = SetFileAttributes(File, OldAttributes);
    if (!BoolError) {
        DoError(FAIL_RESETATTRIBUTES,File);
    }

} /* ConvertImports () */
Пример #16
0
/***********************************************************************
 *		BindImageEx (IMAGEHLP.@)
 *
 * Compute the virtual address of each function imported by a PE image
 *
 * PARAMS
 *
 *   Flags         [in] Bind options
 *   ImageName     [in] File name of the image to be bound
 *   DllPath       [in] Root of the fallback search path in case the ImageName file cannot be opened
 *   SymbolPath    [in] Symbol file root search path
 *   StatusRoutine [in] Pointer to a status routine which will be called during the binding process
 *
 * RETURNS
 *   Success: TRUE
 *   Failure: FALSE
 *
 * NOTES
 *  Binding is not implemented yet, so far this function only enumerates
 *  all imported dlls/functions and returns TRUE.
 */
BOOL WINAPI BindImageEx(
  DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath,
  PIMAGEHLP_STATUS_ROUTINE StatusRoutine)
{
    LOADED_IMAGE loaded_image;
    const IMAGE_IMPORT_DESCRIPTOR *import_desc;
    ULONG size;

    FIXME("(%d, %s, %s, %s, %p): semi-stub\n",
        Flags, debugstr_a(ImageName), debugstr_a(DllPath),
        debugstr_a(SymbolPath), StatusRoutine
    );

    if (!(MapAndLoad(ImageName, DllPath, &loaded_image, TRUE, TRUE))) return FALSE;

    if (!(import_desc = RtlImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, FALSE,
                                                     IMAGE_DIRECTORY_ENTRY_IMPORT, &size)))
    {
        UnMapAndLoad(&loaded_image);
        return TRUE; /* No imported modules means nothing to bind, so we're done. */
    }

    /* FIXME: Does native imagehlp support both 32-bit and 64-bit PE executables? */
#ifdef _WIN64
    if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
#else
    if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
#endif
    {
        FIXME("Wrong architecture in PE header, unable to enumerate imports\n");
        UnMapAndLoad(&loaded_image);
        return TRUE;
    }

    for (; import_desc->Name && import_desc->FirstThunk; ++import_desc)
    {
        IMAGE_THUNK_DATA *thunk;
        char dll_fullname[MAX_PATH];
        const char *dll_name;

        if (!(dll_name = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
                                      import_desc->Name, 0)))
        {
            UnMapAndLoad(&loaded_image);
            SetLastError(ERROR_INVALID_ACCESS); /* FIXME */
            return FALSE;
        }

        if (StatusRoutine)
            StatusRoutine(BindImportModule, ImageName, dll_name, 0, 0);

        if (!SearchPathA(DllPath, dll_name, 0, sizeof(dll_fullname), dll_fullname, 0))
        {
            UnMapAndLoad(&loaded_image);
            SetLastError(ERROR_FILE_NOT_FOUND);
            return FALSE;
        }

        if (!(thunk = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
                                   import_desc->OriginalFirstThunk ? import_desc->OriginalFirstThunk :
                                   import_desc->FirstThunk, 0)))
        {
            ERR("Can't grab thunk data of %s, going to next imported DLL\n", dll_name);
            continue;
        }

        for (; thunk->u1.Ordinal; ++thunk)
        {
            /* Ignoring ordinal imports for now */
            if(!IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))
            {
                IMAGE_IMPORT_BY_NAME *iibn;

                if (!(iibn = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
                                          thunk->u1.AddressOfData, 0)))
                {
                    ERR("Can't grab import by name info, skipping to next ordinal\n");
                    continue;
                }

                if (StatusRoutine)
                    StatusRoutine(BindImportProcedure, ImageName, dll_fullname, 0, (ULONG_PTR)iibn->Name);
            }
        }
    }

    UnMapAndLoad(&loaded_image);
    return TRUE;
}
Пример #17
0
/*************************************************************************
 *	ICO_ExtractIconExW		[internal]
 *
 * NOTES
 *  nIcons = 0: returns number of Icons in file
 *
 * returns
 *  invalid file: -1
 *  failure:0;
 *  success: number of icons in file (nIcons = 0) or nr of icons retrieved
 */
static UINT ICO_ExtractIconExW(
	LPCWSTR lpszExeFileName,
	HICON * RetPtr,
	INT nIconIndex,
	UINT nIcons,
	UINT cxDesired,
	UINT cyDesired,
	UINT *pIconId,
	UINT flags)
{
	UINT		ret = 0;
	UINT		cx1, cx2, cy1, cy2;
	LPBYTE		pData;
	DWORD		sig;
	HANDLE		hFile;
	UINT16		iconDirCount = 0, iconCount = 0;
	LPBYTE		peimage;
	HANDLE		fmapping;
	DWORD		fsizeh,fsizel;
        WCHAR		szExePath[MAX_PATH];
        DWORD		dwSearchReturn;

	TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags);

        dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, sizeof(szExePath) / sizeof(szExePath[0]), szExePath, NULL);
        if ((dwSearchReturn == 0) || (dwSearchReturn > sizeof(szExePath) / sizeof(szExePath[0])))
        {
            WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName));
            return -1;
        }

	hFile = CreateFileW(szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
	if (hFile == INVALID_HANDLE_VALUE) return ret;
	fsizel = GetFileSize(hFile,&fsizeh);

	/* Map the file */
	fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
	CloseHandle(hFile);
	if (!fmapping)
	{
	  WARN("CreateFileMapping error %ld\n", GetLastError() );
	  return 0xFFFFFFFF;
	}

	if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0)))
	{
	  WARN("MapViewOfFile error %ld\n", GetLastError() );
	  CloseHandle(fmapping);
	  return 0xFFFFFFFF;
	}
	CloseHandle(fmapping);

	cx1 = LOWORD(cxDesired);
	cx2 = HIWORD(cxDesired);
	cy1 = LOWORD(cyDesired);
	cy2 = HIWORD(cyDesired);

	if (pIconId) /* Invalidate first icon identifier */
		*pIconId = 0xFFFFFFFF;

	if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */
	  pIconId = (UINT*)RetPtr;

	sig = USER32_GetResourceTable(peimage, fsizel, &pData);

#ifdef WINE
/* ico file or NE exe/dll*/
	if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */
	{
	  BYTE		*pCIDir = 0;
	  NE_TYPEINFO	*pTInfo = (NE_TYPEINFO*)(pData + 2);
	  NE_NAMEINFO	*pIconStorage = NULL;
	  NE_NAMEINFO	*pIconDir = NULL;
	  LPicoICONDIR	lpiID = NULL;
	  ULONG		uSize = 0;

          TRACE("-- OS2/icon Signature (0x%08x)\n", sig);

	  if (pData == (BYTE*)-1)
	  {
	    pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize);	/* check for .ICO file */
	    if (pCIDir)
	    {
	      iconDirCount = 1; iconCount = lpiID->idCount;
              TRACE("-- icon found %p 0x%08x 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount);
	    }
	  }
	  else while (pTInfo->type_id && !(pIconStorage && pIconDir))
	  {
	    if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON)	/* find icon directory and icon repository */
	    {
	      iconDirCount = pTInfo->count;
	      pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
	      TRACE("\tfound directory - %i icon families\n", iconDirCount);
	    }
	    if (pTInfo->type_id == NE_RSCTYPE_ICON)
	    {
	      iconCount = pTInfo->count;
	      pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
	      TRACE("\ttotal icons - %i\n", iconCount);
	    }
	    pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
	  }

	  if ((pIconStorage && pIconDir) || lpiID)	  /* load resources and create icons */
	  {
	    if (nIcons == 0)
	    {
	      ret = iconDirCount;
              if (lpiID)	/* *.ico file, deallocate heap pointer*/
	        HeapFree(GetProcessHeap(), 0, pCIDir);
	    }
	    else if (nIconIndex < iconDirCount)
	    {
	      UINT16   i, icon;
	      if (nIcons > iconDirCount - nIconIndex)
	        nIcons = iconDirCount - nIconIndex;

	      for (i = 0; i < nIcons; i++)
	      {
	        /* .ICO files have only one icon directory */
	        if (lpiID == NULL)	/* not *.ico */
	          pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize);
	        pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx1, cy1, flags);
                if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE,  cx2, cy2, flags);
	      }
              if (lpiID)	/* *.ico file, deallocate heap pointer*/
	        HeapFree(GetProcessHeap(), 0, pCIDir);

	      for (icon = 0; icon < nIcons; icon++)
	      {
	        pCIDir = NULL;
	        if (lpiID)
	          pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize);
	        else
	          for (i = 0; i < iconCount; i++)
	            if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) )
	              pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize);

	        if (pCIDir)
                {
	          RetPtr[icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
                                                                 cx1, cy1, flags);
                  if (cx2 && cy2)
                      RetPtr[++icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000,
                                                                       cx2, cy2, flags);
                }
	        else
	          RetPtr[icon] = 0;
	      }
	      ret = icon;	/* return number of retrieved icons */
	    }
	  }
	}
#else
    if (sig == 1 || sig == 2) /* .ICO or .CUR file */
    {
        TRACE("-- icon Signature (0x%08x)\n", sig);

        if (pData == (BYTE*)-1)
        {
            INT cx[2] = {cx1, cx2}, cy[2] = {cy1, cy2};
            INT index;

            for(index = 0; index < 2; index++)
            {
                DWORD dataOffset;
                LPBYTE imageData;
                POINT hotSpot;
                LPICONIMAGE entry;

                dataOffset = get_best_icon_file_offset(peimage, fsizel, cx[index], cy[index], sig == 1, flags, sig == 1 ? NULL : &hotSpot);

                if (dataOffset)
                {
                    HICON icon;
                    WORD *cursorData = NULL;

                    imageData = peimage + dataOffset;
                    entry = (LPICONIMAGE)(imageData);

                    if(sig == 2)
                    {
                        /* we need to prepend the bitmap data with hot spots for CreateIconFromResourceEx */
                        cursorData = HeapAlloc(GetProcessHeap(), 0, entry->icHeader.biSizeImage + 2 * sizeof(WORD));

                        if(!cursorData)
                            continue;

                        cursorData[0] = hotSpot.x;
                        cursorData[1] = hotSpot.y;

                        memcpy(cursorData + 2, imageData, entry->icHeader.biSizeImage);

                        imageData = (LPBYTE)cursorData;
                    }

                    icon = CreateIconFromResourceEx(imageData, entry->icHeader.biSizeImage, sig == 1, 0x00030000, cx[index], cy[index], flags);

                    if (icon)
                    {
                        RetPtr[index] = icon;
                        iconCount = 1;
                    }

                    if(cursorData != NULL)
                        HeapFree(GetProcessHeap(), 0, cursorData);
                }
            }

        }
        ret = iconCount;	/* return number of retrieved icons */
    }
#endif
/* end ico file */

/* exe/dll */
	else if( sig == IMAGE_NT_SIGNATURE )
	{
        BYTE *idata, *igdata;
        const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir;
        const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent;
        const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent;
        ULONG size;
        UINT i;

        rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
        if (!rootresdir)
        {
            WARN("haven't found section for resource directory.\n");
            goto end;
        }

	  /* search for the group icon directory */
	  if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir)))
	  {
	    WARN("No Icongroupresourcedirectory!\n");
	    goto end;		/* failure */
	  }
	  iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries;

	  /* only number of icons requested */
	  if( !pIconId )
	  {
	    ret = iconDirCount;
	    goto end;		/* success */
	  }

	  if( nIconIndex < 0 )
	  {
	    /* search resource id */
	    int n = 0;
	    int iId = abs(nIconIndex);
	    const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1);

	    while(n<iconDirCount && xprdeTmp)
	    {
              if(xprdeTmp->Id ==  iId)
              {
                  nIconIndex = n;
                  break;
              }
              n++;
              xprdeTmp++;
	    }
	    if (nIconIndex < 0)
	    {
	      WARN("resource id %d not found\n", iId);
	      goto end;		/* failure */
	    }
	  }
	  else
	  {
	    /* check nIconIndex to be in range */
	    if (nIconIndex >= iconDirCount)
	    {
	      WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount);
	      goto end;		/* failure */
	    }
	  }

	  /* assure we don't get too much */
	  if( nIcons > iconDirCount - nIconIndex )
	    nIcons = iconDirCount - nIconIndex;

	  /* starting from specified index */
	  xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex;

	  for (i=0; i < nIcons; i++,xresent++)
	  {
	    const IMAGE_RESOURCE_DIRECTORY *resdir;

	    /* go down this resource entry, name */
            resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory);

	    /* default language (0) */
	    resdir = find_entry_default(resdir,rootresdir);
	    igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir;

	    /* lookup address in mapped image for virtual address */
        igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL);
        if (!igdata)
	    {
	      FIXME("no matching real address for icongroup!\n");
	      goto end;	/* failure */
	    }
	    pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags);
            if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags);
	  }

	  if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir)))
	  {
	    WARN("No Iconresourcedirectory!\n");
	    goto end;		/* failure */
	  }

	  for (i=0; i<nIcons; i++)
	  {
	    const IMAGE_RESOURCE_DIRECTORY *xresdir;
	    xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir);
            if( !xresdir )
            {
              WARN("icon entry %d not found\n", LOWORD(pIconId[i]));
	      RetPtr[i]=0;
	      continue;
            }
	    xresdir = find_entry_default(xresdir, rootresdir);
	    idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir;

        idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL);
        if (!idata)
	    {
	      WARN("no matching real address found for icondata!\n");
	      RetPtr[i]=0;
	      continue;
	    }
	    RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags);
            if (cx2 && cy2)
                RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags);
	  }
	  ret = i;	/* return number of retrieved icons */
	}			/* if(sig == IMAGE_NT_SIGNATURE) */

end:
	UnmapViewOfFile(peimage);	/* success */
	return ret;
}
Пример #18
0
/* load the driver module file */
static HMODULE load_driver_module( const WCHAR *name )
{
    IMAGE_NT_HEADERS *nt;
    const IMAGE_IMPORT_DESCRIPTOR *imports;
    size_t page_size = getpagesize();
    int i;
    INT_PTR delta;
    ULONG size;
    HMODULE module = LoadLibraryW( name );

    if (!module) return NULL;
    nt = RtlImageNtHeader( module );

    if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module;

    /* the loader does not apply relocations to non page-aligned binaries or executables,
     * we have to do it ourselves */

    if (nt->OptionalHeader.SectionAlignment < page_size ||
        !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
    {
        DWORD old;
        IMAGE_BASE_RELOCATION *rel, *end;

        if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
        {
            WINE_TRACE( "%s: relocating from %p to %p\n",
                        wine_dbgstr_w(name), (char *)module - delta, module );
            end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
            while (rel < end && rel->SizeOfBlock)
            {
                void *page = (char *)module + rel->VirtualAddress;
                VirtualProtect( page, page_size, PAGE_EXECUTE_READWRITE, &old );
                rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
                                                 (USHORT *)(rel + 1), delta );
                if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, page_size, old, NULL );
                if (!rel) goto error;
            }
            /* make sure we don't try again */
            size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
            VirtualProtect( nt, size, PAGE_READWRITE, &old );
            nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
            VirtualProtect( nt, size, old, NULL );
        }
    }

    /* make sure imports are relocated too */

    if ((imports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
    {
        for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
        {
            char *name = (char *)module + imports[i].Name;
            WCHAR buffer[32], *p = buffer;

            while (p < buffer + 32) if (!(*p++ = *name++)) break;
            if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer ) );
        }
    }

    return module;

error:
    FreeLibrary( module );
    return NULL;
}
Пример #19
0
/**********************************************************************
 *  find_entry
 *
 * Find a resource entry
 */
static NTSTATUS find_entry( HMODULE hmod, const LDR_RESOURCE_INFO *info,
                            ULONG level, const void **ret, int want_dir )
{
    ULONG size;
    const void *root;
    const IMAGE_RESOURCE_DIRECTORY *resdirptr;
    WORD list[9];  /* list of languages to try */
    int i, pos = 0;

    root = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
    if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
    if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
    resdirptr = root;

    if (!level--) goto done;
    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
        return STATUS_RESOURCE_TYPE_NOT_FOUND;
    if (!level--) return STATUS_SUCCESS;

    resdirptr = *ret;
    if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
        return STATUS_RESOURCE_NAME_NOT_FOUND;
    if (!level--) return STATUS_SUCCESS;
    if (level) return STATUS_INVALID_PARAMETER;  /* level > 3 */

    /* 1. specified language */
    pos = push_language( list, pos, info->Language );

    /* 2. specified language with neutral sublanguage */
    pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );

    /* 3. neutral language with neutral sublanguage */
    pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );

    /* if no explicitly specified language, try some defaults */
    if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
    {
        /* user defaults, unless SYS_DEFAULT sublanguage specified  */
        if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
        {
            /* 4. current thread locale language */
            pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );

            /* 5. user locale language */
            pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );

            /* 6. user locale language with neutral sublanguage  */
            pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
        }

        /* now system defaults */

        /* 7. system locale language */
        pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );

        /* 8. system locale language with neutral sublanguage */
        pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );

        /* 9. English */
        pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
    }

    resdirptr = *ret;
    for (i = 0; i < pos; i++)
        if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;

    /* if no explicitly specified language, return the first entry */
    if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
    {
        if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
    }
    return STATUS_RESOURCE_LANG_NOT_FOUND;

done:
    *ret = resdirptr;
    return STATUS_SUCCESS;
}
Пример #20
0
/***********************************************************************
 *			pe_load_export_debug_info
 */
static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module)
{
    struct image_file_map*              fmap = &module->format_info[DFI_PE]->u.pe_info->fmap;
    unsigned int 		        i;
    const IMAGE_EXPORT_DIRECTORY* 	exports;
    DWORD			        base = module->module.BaseOfImage;
    DWORD                               size;
    IMAGE_NT_HEADERS*                   nth;
    void*                               mapping;

    if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;

    if (!(mapping = pe_map_full(fmap, &nth))) return FALSE;
#if 0
    /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
    /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
    symt_new_public(module, NULL, module->module.ModuleName, FALSE, base, 1);
#endif
    
    /* Add entry point */
    symt_new_public(module, NULL, "EntryPoint", FALSE,
                    base + nth->OptionalHeader.AddressOfEntryPoint, 1);
#if 0
    /* FIXME: we'd better store addresses linked to sections rather than 
       absolute values */
    IMAGE_SECTION_HEADER*       section;
    /* Add start of sections */
    section = (IMAGE_SECTION_HEADER*)
        ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
    for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) 
    {
	symt_new_public(module, NULL, section->Name, FALSE,
                        RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL), 1);
    }
#endif

    /* Add exported functions */
    if ((exports = RtlImageDirectoryEntryToData(mapping, FALSE,
                                                IMAGE_DIRECTORY_ENTRY_EXPORT, &size)))
    {
        const WORD*             ordinals = NULL;
        const DWORD_PTR*	functions = NULL;
        const DWORD*		names = NULL;
        unsigned int		j;
        char			buffer[16];

        functions = RtlImageRvaToVa(nth, mapping, exports->AddressOfFunctions, NULL);
        ordinals  = RtlImageRvaToVa(nth, mapping, exports->AddressOfNameOrdinals, NULL);
        names     = RtlImageRvaToVa(nth, mapping, exports->AddressOfNames, NULL);

        if (functions && ordinals && names)
        {
            for (i = 0; i < exports->NumberOfNames; i++)
            {
                if (!names[i]) continue;
                symt_new_public(module, NULL,
                                RtlImageRvaToVa(nth, mapping, names[i], NULL),
                                FALSE,
                                base + functions[ordinals[i]], 1);
            }

            for (i = 0; i < exports->NumberOfFunctions; i++)
            {
                if (!functions[i]) continue;
                /* Check if we already added it with a name */
                for (j = 0; j < exports->NumberOfNames; j++)
                    if ((ordinals[j] == i) && names[j]) break;
                if (j < exports->NumberOfNames) continue;
                snprintf(buffer, sizeof(buffer), "%d", i + exports->Base);
                symt_new_public(module, NULL, buffer, FALSE, base + (DWORD)functions[i], 1);
            }
        }
    }
    /* no real debug info, only entry points */
    if (module->module.SymType == SymDeferred)
        module->module.SymType = SymExport;
    pe_unmap_full(fmap);

    return TRUE;
}
Пример #21
0
PRUNTIME_FUNCTION
KiLookupFunctionEntry (
    IN ULONG ControlPc
)

/*++

Routine Description:

    This function searches the currently active function tables for an entry
    that corresponds to the specified PC value.

Arguments:

    ControlPc - Supplies the address of an instruction within the specified
        function.

Return Value:

    If there is no entry in the function table for the specified PC, then
    NULL is returned. Otherwise, the address of the function table entry
    that corresponds to the specified PC is returned.

--*/

{

    PLDR_DATA_TABLE_ENTRY DataTableEntry;
    PRUNTIME_FUNCTION FunctionEntry;
    PRUNTIME_FUNCTION FunctionTable;
    ULONG SizeOfExceptionTable;
    LONG High;
    PVOID ImageBase;
    LONG Low;
    LONG Middle;

    //
    // Search for the image that includes the specified PC value.
    //

    ImageBase = KiPcToFileHeader((PVOID)ControlPc,
                                 &ImageBase,
                                 &DataTableEntry);

    //
    // If an image is found that includes the specified PC, then locate the
    // function table for the image.
    //

    if (ImageBase != NULL) {
        FunctionTable = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData(
                            ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION,
                            &SizeOfExceptionTable);

        //
        // If a function table is located, then search the function table
        // for a function table entry for the specified PC.
        //

        if (FunctionTable != NULL) {

            //
            // Initialize search indicies.
            //

            Low = 0;
            High = (SizeOfExceptionTable / sizeof(RUNTIME_FUNCTION)) - 1;

            //
            // Perform binary search on the function table for a function table
            // entry that subsumes the specified PC.
            //

            while (High >= Low) {

                //
                // Compute next probe index and test entry. If the specified PC
                // is greater than of equal to the beginning address and less
                // than the ending address of the function table entry, then
                // return the address of the function table entry. Otherwise,
                // continue the search.
                //

                Middle = (Low + High) >> 1;
                FunctionEntry = &FunctionTable[Middle];
                if (ControlPc < FunctionEntry->BeginAddress) {
                    High = Middle - 1;

                } else if (ControlPc >= FunctionEntry->EndAddress) {
                    Low = Middle + 1;

                } else {

                    //
                    // The capability exists for more than one function entry
                    // to map to the same function. This permits a function to
                    // have (within reason) discontiguous code segment(s). If
                    // PrologEndAddress is out of range, it is re-interpreted
                    // as a pointer to the primary function table entry for
                    // that function.  The out of range test takes into account
                    // the redundant encoding of millicode and glue code.
                    //

                    if (((FunctionEntry->PrologEndAddress < FunctionEntry->BeginAddress) ||
                            (FunctionEntry->PrologEndAddress >= FunctionEntry->EndAddress)) &&
                            (FunctionEntry->PrologEndAddress & 3) == 0) {
                        FunctionEntry = (PRUNTIME_FUNCTION)FunctionEntry->PrologEndAddress;
                    }

                    return FunctionEntry;
                }
            }
        }
Пример #22
0
PUCHAR
GetImageName(
    IN PVOID ImageBase
)
/*++

Routine Description:

    This routine grovels a mapped image to find the name of the image.  We
    cannot currently find the name, unless the image has an export section.
    If we cannot find a name, we make up a unique one.

Arguments:

    ImageBase -- Supplies the base of the mapped image

Return Value:

   returns a pointer to a malloc'ed string containing the image name

--*/
{
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    PUCHAR ImageNameSeekAddress;
    PUCHAR ImageName;
    PUCHAR Name = NULL;
    ULONG DirectoryLength;
    ULONG NameLength = 0;

    //
    // Find the export directory
    //
    ExportDirectory = RtlImageDirectoryEntryToData(
                          ImageBase,
                          FALSE,
                          IMAGE_DIRECTORY_ENTRY_EXPORT,
                          &DirectoryLength
                      );

    //
    // If there is an export directory
    //
    if (ExportDirectory) {

        ImageNameSeekAddress = RvaToSeekAddress(
                                   (PVOID)ExportDirectory->Name,
                                   ImageBase
                               );

        if (ImageNameSeekAddress) {
            ImageName = (PUCHAR)((ULONG)ImageBase + ImageNameSeekAddress);
            NameLength = strlen(ImageName);
            //
            // if it has a name
            //
            if (NameLength) {
                Name = malloc(NameLength + 1);
                strcpy(Name,ImageName);
                return Name;
            }
        }
    }

    //
    // We couldn't find a name for this image
    //
    Name = malloc(UNIQUE_NAME_SIZE);

    if (Name) {
        strcpy(Name,UNIQUE_NAME);
        sprintf(&(Name[UNIQUENESS_OFFSET]),"%x\0",UniqueDllNumber);
        return Name;
    } else {
        return NULL;
    }
}
Пример #23
0
static BOOLEAN
WinLdrpScanImportAddressTable(IN OUT PLIST_ENTRY ModuleListHead,
                              IN PVOID DllBase,
                              IN PVOID ImageBase,
                              IN PIMAGE_THUNK_DATA ThunkData,
                              IN PCSTR DirectoryPath)
{
    PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
    BOOLEAN Success;
    ULONG ExportSize;

    TRACE("WinLdrpScanImportAddressTable(): DllBase 0x%X, "
        "ImageBase 0x%X, ThunkData 0x%X\n", DllBase, ImageBase, ThunkData);

    /* Obtain the export table from the DLL's base */
    if (DllBase == NULL)
    {
        ERR("Error, DllBase == NULL!\n");
        return FALSE;
    }
    else
    {
        ExportDirectory =
            (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase),
                TRUE,
                IMAGE_DIRECTORY_ENTRY_EXPORT,
                &ExportSize);
    }

    TRACE("WinLdrpScanImportAddressTable(): ExportDirectory 0x%X\n", ExportDirectory);

    /* If pointer to Export Directory is */
    if (ExportDirectory == NULL)
    {
        ERR("DllBase=%p(%p)\n", DllBase, VaToPa(DllBase));
        return FALSE;
    }

    /* Go through each entry in the thunk table and bind it */
    while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0)
    {
        /* Bind it */
        Success = WinLdrpBindImportName(ModuleListHead,
                                        DllBase,
                                        ImageBase,
                                        ThunkData,
                                        ExportDirectory,
                                        ExportSize,
                                        FALSE,
                                        DirectoryPath);

        /* Move to the next entry */
        ThunkData++;

        /* Return error if binding was unsuccessful */
        if (!Success)
            return Success;
    }

    /* Return success */
    return TRUE;
}
Пример #24
0
ARC_STATUS
BlScanImportDescriptorTable (
    IN ULONG DeviceId,
    IN PCHAR DeviceName,
    IN PCHAR DirectoryPath,
    IN PLDR_DATA_TABLE_ENTRY ScanEntry
    )

/*++

Routine Description:

    This routine scans the import descriptor table for the specified image
    file and loads each DLL that is referenced.

Arguments:

    DeviceId - Suuplies the device id form which any referenced DLLs
        are to be loaded from.

    DeviceName - Supplies the name of the device from which any
        referenced DLLs are to be loaded from.

    DirectoryPath - Supplies a pointer to a zero terminated directory
        path name.

    DataTableEntry - Supplies a pointer to the data table entry for the
        image whose import table is to be scanned.

Return Value:

    ESUCCESS is returned in the scan is successful. Otherwise, return an
    unsuccessful status.

--*/

{

    PLDR_DATA_TABLE_ENTRY DataTableEntry;
    CHAR FullDllName[256];
    PVOID Base;
    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
    ULONG ImportTableSize;
    ARC_STATUS Status;
    PSZ ImportName;

    //
    // Locate the import table in the image specified by the data table entry.
    //

    ImportDescriptor =
        (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ScanEntry->DllBase,
                                                              TRUE,
                                                              IMAGE_DIRECTORY_ENTRY_IMPORT,
                                                              &ImportTableSize);

    //
    // If the image has an import directory, then scan the import table and
    // load the specified DLLs.
    //

    if (ImportDescriptor != NULL) {
        while ((ImportDescriptor->Name != 0) &&
               (ImportDescriptor->FirstThunk != NULL)) {

            //
            // Change the name from an RVA to a VA.
            //

            ImportName = (PSZ)((ULONG)ScanEntry->DllBase + ImportDescriptor->Name);

            //
            // If the DLL references itself, then skip the import entry.
            //

            if (BlpCompareDllName((PCHAR)ImportName,
                                  &ScanEntry->BaseDllName) == FALSE) {

                //
                // If the DLL is not already loaded, then load the DLL and
                // scan its import table.
                //

                if (BlCheckForLoadedDll((PCHAR)ImportName,
                                        &DataTableEntry) == FALSE) {

                    strcpy(&FullDllName[0], DirectoryPath);
                    strcat(&FullDllName[0], (PCHAR)ImportName);
                    BlOutputLoadMessage(DeviceName, &FullDllName[0]);
                    Status = BlLoadImage(DeviceId,
                                         LoaderHalCode,
                                         &FullDllName[0],
                                         TARGET_IMAGE,
                                         &Base);

                    if (Status != ESUCCESS) {
                        return Status;
                    }

                    Status =
                        BlAllocateDataTableEntry((PCHAR)ImportName,
                                                 &FullDllName[0],
                                                 Base,
                                                 &DataTableEntry);

                    if (Status != ESUCCESS) {
                        return Status;
                   }

                    Status = BlScanImportDescriptorTable(DeviceId,
                                                         DeviceName,
                                                         DirectoryPath,
                                                         DataTableEntry);

                    if (Status != ESUCCESS) {
                        return Status;
                    }
                }

                //
                // Scan the import address table and snap links.
                //

                Status = BlpScanImportAddressTable(DataTableEntry->DllBase,
                            ScanEntry->DllBase,
                            (PIMAGE_THUNK_DATA)((ULONG)ScanEntry->DllBase +
                            (ULONG)ImportDescriptor->FirstThunk));

                if (Status != ESUCCESS) {
                    return Status;
                }
            }

            ImportDescriptor += 1;
        }
    }

    return ESUCCESS;
}
Пример #25
0
ARC_STATUS
BlpBindImportName (
    IN PVOID DllBase,
    IN PVOID ImageBase,
    IN PIMAGE_THUNK_DATA ThunkEntry,
    IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
    IN ULONG ExportSize,
    IN BOOLEAN SnapForwarder
    )

/*++

Routine Description:

    This routine binds an import table reference with an exported entry
    point and fills in the thunk data.

Arguments:

    DllBase - Supplies the base address of the DLL image that contains
        the export directory.  On x86 systems, a NULL DllBase binds the
        import table reference to the OsLoader's exported entry points.

    ImageBase - Supplies the base address of the image that contains
        the import thunk table.

    ThunkEntry - Supplies a pointer to a thunk table entry.

    ExportDirectory - Supplies a pointer to the export directory of the
        DLL from which references are to be resolved.

    SnapForwarder - determine if the snap is for a forwarder, and therefore
       Address of Data is already setup.

Return Value:

    ESUCCESS is returned if the specified thunk is bound. Otherwise, an
    return an unsuccessful status.

--*/

{

    PULONG FunctionTable;
    LONG High;
    ULONG HintIndex;
    LONG Low;
    LONG Middle;
    PULONG NameTable;
    ULONG Ordinal;
    PUSHORT OrdinalTable;
    LONG Result;

#if i386
    if(DllBase == NULL) {
        DllBase = (PVOID)OsLoaderBase;
    }
#endif

    //
    // If the reference is by ordinal, then compute the ordinal number.
    // Otherwise, lookup the import name in the export directory.
    //

    if (IMAGE_SNAP_BY_ORDINAL(ThunkEntry->u1.Ordinal) && !SnapForwarder) {

        //
        // Compute the ordinal.
        //

        Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkEntry->u1.Ordinal) - ExportDirectory->Base);

    } else {

        if (!SnapForwarder) {
            //
            // Change AddressOfData from an RVA to a VA.
            //

            ThunkEntry->u1.AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG)ImageBase +
                                                    (ULONG)ThunkEntry->u1.AddressOfData);
        }

        //
        // Lookup the import name in the export table to determine the
        // ordinal.
        //

        NameTable = (PULONG)((ULONG)DllBase +
                                    (ULONG)ExportDirectory->AddressOfNames);

        OrdinalTable = (PUSHORT)((ULONG)DllBase +
                                    (ULONG)ExportDirectory->AddressOfNameOrdinals);

        //
        // If the hint index is within the limits of the name table and the
        // import and export names match, then the ordinal number can be
        // obtained directly from the ordinal table. Otherwise, the name
        // table must be searched for the specified name.
        //

        HintIndex = ThunkEntry->u1.AddressOfData->Hint;
        if ((HintIndex < ExportDirectory->NumberOfNames) &&
            (strcmp(&ThunkEntry->u1.AddressOfData->Name[0],
                    (PCHAR)((ULONG)DllBase + NameTable[HintIndex])) == 0)) {

            //
            // Get the ordinal number from the ordinal table.
            //

            Ordinal = OrdinalTable[HintIndex];

        } else {

            //
            // Lookup the import name in the name table using a binary search.
            //

            Low = 0;
            High = ExportDirectory->NumberOfNames - 1;
            while (High >= Low) {

                //
                // Compute the next probe index and compare the import name
                // with the export name entry.
                //

                Middle = (Low + High) >> 1;
                Result = strcmp(&ThunkEntry->u1.AddressOfData->Name[0],
                                (PCHAR)((ULONG)DllBase + NameTable[Middle]));

                if (Result < 0) {
                    High = Middle - 1;

                } else if (Result > 0) {
                    Low = Middle + 1;

                } else {
                    break;
                }
            }

            //
            // If the high index is less than the low index, then a matching
            // table entry was not found. Otherwise, get the ordinal number
            // from the ordinal table.
            //

            if (High < Low) {
                return EINVAL;

            } else {
                Ordinal = OrdinalTable[Middle];
            }
        }
    }

    //
    // If the ordinal number is valid, then bind the import reference and
    // return success. Otherwise, return an unsuccessful status.
    //


    if (Ordinal >= ExportDirectory->NumberOfFunctions) {
        return EINVAL;
    } else {
        FunctionTable = (PULONG)((ULONG)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
        ThunkEntry->u1.Function = (PULONG)((ULONG)DllBase + FunctionTable[Ordinal]);

        //
        // Check for a forwarder.
        //
        if ( ((ULONG)ThunkEntry->u1.Function > (ULONG)ExportDirectory) &&
             ((ULONG)ThunkEntry->u1.Function < ((ULONG)ExportDirectory + ExportSize)) ) {
            CHAR ForwardDllName[10];
            PLDR_DATA_TABLE_ENTRY DataTableEntry;
            ULONG TargetExportSize;
            PIMAGE_EXPORT_DIRECTORY TargetExportDirectory;

            RtlCopyMemory(ForwardDllName,
                          (PCHAR)ThunkEntry->u1.Function,
                          sizeof(ForwardDllName));
            *strchr(ForwardDllName,'.') = '\0';
            if (!BlCheckForLoadedDll(ForwardDllName,&DataTableEntry)) {
                //
                // Should load the referenced DLL here, just return failure for now.
                //

                return(EINVAL);
            }
            TargetExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
                RtlImageDirectoryEntryToData(DataTableEntry->DllBase,
                                             TRUE,
                                             IMAGE_DIRECTORY_ENTRY_EXPORT,
                                             &TargetExportSize);
            if (TargetExportDirectory) {

                IMAGE_THUNK_DATA thunkData;
                PIMAGE_IMPORT_BY_NAME addressOfData;
                UCHAR Buffer[128];
                ULONG length;
                PCHAR ImportName;
                ARC_STATUS Status;

                ImportName = strchr((PCHAR)ThunkEntry->u1.Function, '.') + 1;
                addressOfData = (PIMAGE_IMPORT_BY_NAME)Buffer;
                RtlCopyMemory(&addressOfData->Name[0], ImportName, strlen(ImportName)+1);
                addressOfData->Hint = 0;
                thunkData.u1.AddressOfData = addressOfData;
                Status = BlpBindImportName(DataTableEntry->DllBase,
                                           ImageBase,
                                           &thunkData,
                                           TargetExportDirectory,
                                           TargetExportSize,
                                           TRUE);
                ThunkEntry->u1 = thunkData.u1;
                return(Status);
            } else {
                return(EINVAL);
            }
        }
        return ESUCCESS;
    }
}
Пример #26
0
NTSTATUS
NTAPI
LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry,
            IN PLDR_DATA_TABLE_ENTRY ImportLdrEntry,
            IN PIMAGE_IMPORT_DESCRIPTOR IatEntry,
            IN BOOLEAN EntriesValid)
{
    PVOID Iat;
    NTSTATUS Status;
    PIMAGE_THUNK_DATA OriginalThunk, FirstThunk;
    PIMAGE_NT_HEADERS NtHeader;
    PIMAGE_SECTION_HEADER SectionHeader;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    LPSTR ImportName;
    ULONG ForwarderChain, i, Rva, OldProtect, IatSize, ExportSize;
    SIZE_T ImportSize;
    DPRINT("LdrpSnapIAT(%wZ %wZ %p %d)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid);

    /* Get export directory */
    ExportDirectory = RtlImageDirectoryEntryToData(ExportLdrEntry->DllBase,
                                                   TRUE,
                                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
                                                   &ExportSize);

    /* Make sure it has one */
    if (!ExportDirectory)
    {
        /* Fail */
        DbgPrint("LDR: %wZ doesn't contain an EXPORT table\n",
                 &ExportLdrEntry->BaseDllName);
        return STATUS_INVALID_IMAGE_FORMAT;
    }

    /* Get the IAT */
    Iat = RtlImageDirectoryEntryToData(ImportLdrEntry->DllBase,
                                       TRUE,
                                       IMAGE_DIRECTORY_ENTRY_IAT,
                                       &IatSize);
    ImportSize = IatSize;

    /* Check if we don't have one */
    if (!Iat)
    {
        /* Get the NT Header and the first section */
        NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase);
        if (!NtHeader) return STATUS_INVALID_IMAGE_FORMAT;
        SectionHeader = IMAGE_FIRST_SECTION(NtHeader);

        /* Get the RVA of the import directory */
        Rva = NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

        /* Make sure we got one */
        if (Rva)
        {
            /* Loop all the sections */
            for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
            {
                /* Check if we are inside this section */
                if ((Rva >= SectionHeader->VirtualAddress) &&
                    (Rva < (SectionHeader->VirtualAddress +
                     SectionHeader->SizeOfRawData)))
                {
                    /* We are, so set the IAT here */
                    Iat = (PVOID)((ULONG_PTR)(ImportLdrEntry->DllBase) +
                                      SectionHeader->VirtualAddress);

                    /* Set the size */
                    IatSize = SectionHeader->Misc.VirtualSize;

                    /* Deal with Watcom and other retarded compilers */
                    if (!IatSize) IatSize = SectionHeader->SizeOfRawData;

                    /* Found it, get out */
                    break;
                }

                /* No match, move to the next section */
                SectionHeader++;
            }
        }

        /* If we still don't have an IAT, that's bad */
        if (!Iat)
        {
            /* Fail */
            DbgPrint("LDR: Unable to unprotect IAT for %wZ (Image Base %p)\n",
                     &ImportLdrEntry->BaseDllName,
                     ImportLdrEntry->DllBase);
            return STATUS_INVALID_IMAGE_FORMAT;
        }

        /* Set the right size */
        ImportSize = IatSize;
    }

    /* Unprotect the IAT */
    Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                    &Iat,
                                    &ImportSize,
                                    PAGE_READWRITE,
                                    &OldProtect);
    if (!NT_SUCCESS(Status))
    {
        /* Fail */
        DbgPrint("LDR: Unable to unprotect IAT for %wZ (Status %x)\n",
                 &ImportLdrEntry->BaseDllName,
                 Status);
        return Status;
    }

    /* Check if the Thunks are already valid */
    if (EntriesValid)
    {
        /* We'll only do forwarders. Get the import name */
        ImportName = (LPSTR)((ULONG_PTR)ImportLdrEntry->DllBase + IatEntry->Name);

        /* Get the list of forwaders */
        ForwarderChain = IatEntry->ForwarderChain;

        /* Loop them */
        while (ForwarderChain != -1)
        {
            /* Get the cached thunk VA*/
            OriginalThunk = (PIMAGE_THUNK_DATA)
                            ((ULONG_PTR)ImportLdrEntry->DllBase +
                             IatEntry->OriginalFirstThunk +
                             (ForwarderChain * sizeof(IMAGE_THUNK_DATA)));

            /* Get the first thunk */
            FirstThunk = (PIMAGE_THUNK_DATA)
                         ((ULONG_PTR)ImportLdrEntry->DllBase +
                          IatEntry->FirstThunk +
                          (ForwarderChain * sizeof(IMAGE_THUNK_DATA)));

            /* Get the Forwarder from the thunk */
            ForwarderChain = (ULONG)FirstThunk->u1.Ordinal;

            /* Snap the thunk */
            _SEH2_TRY
            {
                Status = LdrpSnapThunk(ExportLdrEntry->DllBase,
                                       ImportLdrEntry->DllBase,
                                       OriginalThunk,
                                       FirstThunk,
                                       ExportDirectory,
                                       ExportSize,
                                       TRUE,
                                       ImportName);

                /* Move to the next thunk */
                FirstThunk++;
            } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
            {
                /* Fail with the SEH error */
                Status = _SEH2_GetExceptionCode();
            } _SEH2_END;

            /* If we messed up, exit */
            if (!NT_SUCCESS(Status)) break;
        }
    }
    else if (IatEntry->FirstThunk)