Frage

Was ist eine Thunk -Tabelle in Bezug auf die Importadressetabelle, die in EXE -Dateien verwendet wird, um Funktionen zu importieren, die in externen DLLs verwendet werden?

Ist dieser Thunk -Tisch nur eine Tabelle mit "Thunks" zu anderen Funktionen?

War es hilfreich?

Lösung

Thunks sind a Teil der Importtabelle (IMAGE_DIRECTORY_ENTRY_IMPORT) und verzögern die Importtabelle (IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT). Sie werden beschrieben http://msdn.microsoft.com/en-us/library/ms809762.aspx.

Ich werde meinen alten Quellcode betrachten und später einen Arbeitscode veröffentlichen, der beide Tabellen inklusive Bindungsinformationen abgelegt hat.

AKTUALISIERT:

Hier ist ein Code, den ich in einem meiner alten Programme mag. Es unterstützt nur 32-Bit-PE, kann jedoch einfach auf 64-Bit modifiziert werden. Übrigens, wie Sie sehen können, dass es auch Bindungsinformationen ablegen. Um dieses Binden zu testen, das Sie mit Respekt von bind.exe abwerfen möchten (zum Beispiel verwenden, verwenden, bind.exe -u -v Test.dll).

Der Code besteht aus etwa 1000 Zeilen, daher konnte ich ihn hier nicht veröffentlichen. Ich erhalte eine Fehlermeldung

Hoppla! Ihre Bearbeitung konnte nicht eingereicht werden, weil:

  • Der Körper ist auf 30000 Zeichen begrenzt; Sie haben 55095 eingegeben

Also habe ich es hier platziert: http://www.ok-soft-gmbh.com/forstackoverflow/peinfo.c. Ich hoffe, der Code wird Ihnen als lange Beschreibung besser helfen.

Aktualisiert 2: Ich sehe, dass meine alte Antwort nicht gut für die Suche nach Engine ist. Also schließe ich den Teil des Code von ein PEInfo.c (die Funktionen DumpImports und DumpExports) unter:

void MakeIdent (UINT nOffset)
{
    for (; nOffset; nOffset--)
        printf ("    ");    // 4 blanks
}

void DumpDword (UINT nOffset, LPCSTR pszPrefix, DWORD dw)
{
    MakeIdent(nOffset);

    if (dw < 100)
        printf ("%s: %d\n", pszPrefix, dw);
    else if (dw%(256*256) == 0)
        printf ("%s: 0x%X\n", pszPrefix, dw);
    else
        printf ("%s: %d (0x%X)\n", pszPrefix, dw, dw);
}

void DumpTimeDateStamp (UINT nOffset, LPCSTR pszTimeDateStampPrefix, DWORD dwTimeDateStamp)
{
    //struct tm tmTime;//= localtime_s ((time_t *)&dwTimeDateStamp);
    //errno_t err = localtime_s (&tmTime, ((time_t *)&dwTimeDateStamp));

    struct tm *ptmTime = _localtime32 ((__time32_t *)&dwTimeDateStamp);
    SYSTEMTIME stSystemTime;
    static CHAR szString[128];

    stSystemTime.wYear = (WORD)(1900 + ptmTime->tm_year);
    stSystemTime.wMonth = (WORD)(ptmTime->tm_mon + 1);
    stSystemTime.wDay = (WORD)ptmTime->tm_mday;
    stSystemTime.wDayOfWeek = (WORD)(ptmTime->tm_wday + 1);
    stSystemTime.wHour = (WORD)ptmTime->tm_hour;
    stSystemTime.wMinute = (WORD)ptmTime->tm_min;
    stSystemTime.wSecond = (WORD)ptmTime->tm_sec;
    stSystemTime.wMilliseconds = 0;

    MakeIdent(nOffset);
    printf ("%s: 0x%8X (", pszTimeDateStampPrefix, dwTimeDateStamp);

    if (GetDateFormatA (LOCALE_USER_DEFAULT, 0, &stSystemTime, NULL, 
        szString, sizeof(szString)/sizeof(TCHAR)) != 0) {
        printf (szString);
    }

    if (GetTimeFormatA (LOCALE_USER_DEFAULT, 0, &stSystemTime, NULL, 
                       szString, sizeof(szString)/sizeof(TCHAR)) != 0) {
        if (szString[0] != 0)
            printf (" ");
        printf (szString);
    }
    printf (")\n");
}

void DumpImports (UINT nOffset, IMAGE_OPTIONAL_HEADER32 *pOptionalHeader, PBYTE pbyFile,
                  IMAGE_SECTION_HEADER *pSectionHeader, IMAGE_NT_HEADERS32 *pNtHeader) // header of the section, which contains export section
{
    IMAGE_IMPORT_DESCRIPTOR *pImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData +
        pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - pSectionHeader->VirtualAddress);
    DWORD dwBoundImportVA = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
    IMAGE_BOUND_IMPORT_DESCRIPTOR *pFirstBoundImportDescriptor = NULL, *pBoundImportDescriptor;

    //DumpDword (nOffset, TEXT("Characteristics"), pImportDescriptor->Characteristics);
    if (dwBoundImportVA) {
        UINT i;
        IMAGE_SECTION_HEADER *pFirstSectionHeader = (IMAGE_SECTION_HEADER *)((PBYTE)pOptionalHeader + //sizeof(IMAGE_OPTIONAL_HEADER32));
                                                                                pNtHeader->FileHeader.SizeOfOptionalHeader);

        for (i=0; i<pNtHeader->FileHeader.NumberOfSections; i++) {
            if (pFirstSectionHeader[i].VirtualAddress <= dwBoundImportVA &&
                dwBoundImportVA < pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize) {

                pFirstBoundImportDescriptor = (IMAGE_BOUND_IMPORT_DESCRIPTOR *)((PBYTE)pbyFile + pFirstSectionHeader[i].PointerToRawData +
                                            dwBoundImportVA - pFirstSectionHeader[i].VirtualAddress);
                break;
            }
        }
        if (i >= pNtHeader->FileHeader.NumberOfSections)
            pFirstBoundImportDescriptor = (IMAGE_BOUND_IMPORT_DESCRIPTOR *)((PBYTE)pbyFile + dwBoundImportVA);
    }

    for (;pImportDescriptor->Characteristics; pImportDescriptor++) {
        IMAGE_THUNK_DATA *pOriginalFirstThunk = (IMAGE_THUNK_DATA *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData +
            pImportDescriptor->OriginalFirstThunk - pSectionHeader->VirtualAddress);
        IMAGE_THUNK_DATA *pFirstThunk = (IMAGE_THUNK_DATA *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData +
            pImportDescriptor->FirstThunk - pSectionHeader->VirtualAddress);
        IMAGE_THUNK_DATA *pOriginalThunk, *pThunk;

        MakeIdent(nOffset);
        printf ("%s ", pbyFile + pSectionHeader->PointerToRawData + pImportDescriptor->Name - pSectionHeader->VirtualAddress);
        //DumpDword (nOffset, TEXT("Ordinal Base"), pExportDirectory->Base);

        if (pImportDescriptor->TimeDateStamp == 0) {
            //MakeIdent(nOffset);
            printf ("(DLL is Not bound)\n");
        }
        else if (pImportDescriptor->TimeDateStamp == -1) {
            //if bound, and real date\time stamp
            //                                    //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
            //MakeIdent(nOffset);
            printf ("(DLL bound with New BIND)\n");
        }
        else {
            //MakeIdent(nOffset);
            printf ("(DLL bound with Old BIND) ");
            DumpTimeDateStamp (nOffset, "TimeDateStamp", pImportDescriptor->TimeDateStamp);
        }

        MakeIdent(nOffset+1);
        if (pImportDescriptor->TimeDateStamp)   // if bound
            printf (TEXT("      Ordinal          hint BoundAddrs Name\n"));
        else
            printf (TEXT("      Ordinal          hint Name\n"));

        for (pOriginalThunk=pOriginalFirstThunk, pThunk=pFirstThunk; pOriginalThunk->u1.AddressOfData; pOriginalThunk++, pThunk++) {
            if (IMAGE_SNAP_BY_ORDINAL32(pOriginalThunk->u1.Ordinal)) {
                MakeIdent(nOffset+1);
                // Ordinal
                if (pImportDescriptor->TimeDateStamp)
                    printf (TEXT("%4u (0x%04X)               0x%08X\n"),
                            pOriginalThunk->u1.Ordinal & ~IMAGE_ORDINAL_FLAG32,
                            pOriginalThunk->u1.Ordinal^IMAGE_ORDINAL_FLAG32,
                            pThunk->u1.AddressOfData);
                else
                    // pThunk->u1.AddressOfData == pOriginalThunk->u1.Ordinal so don't print it 
                    printf (TEXT("%4u (0x%04X)\n"),
                            pOriginalThunk->u1.Ordinal & ~IMAGE_ORDINAL_FLAG32,
                            pOriginalThunk->u1.Ordinal^IMAGE_ORDINAL_FLAG32);
            }
            else {
                IMAGE_IMPORT_BY_NAME *pImportByName = (IMAGE_IMPORT_BY_NAME *) (pOriginalThunk->u1.AddressOfData +
                    (PBYTE)pbyFile + pSectionHeader->PointerToRawData - pSectionHeader->VirtualAddress);

                MakeIdent(nOffset+1);
                // Hint - Index into the Export Name Pointer Table. A match is attempted first with this value.
                // If it fails, a binary search is performed on the DLL’s Export Name Pointer Table.
                if (pImportDescriptor->TimeDateStamp)   // if bound
                    printf (TEXT("%18u (0x%04X) 0x%08X %hs\n"), pImportByName->Hint, pImportByName->Hint, pThunk->u1.AddressOfData,
                        pImportByName->Name);
                else
                    printf (TEXT("%18u (0x%04X) %hs\n"), pImportByName->Hint, pImportByName->Hint, pImportByName->Name);
            }
        }
    }

    if (pFirstBoundImportDescriptor) {
        MakeIdent(nOffset);
        printf ("PE Header contains the following bound import information:\n");

        for (pBoundImportDescriptor=pFirstBoundImportDescriptor; pBoundImportDescriptor->TimeDateStamp;
            pBoundImportDescriptor = (IMAGE_BOUND_IMPORT_DESCRIPTOR *)((PBYTE)(pBoundImportDescriptor+1) + pBoundImportDescriptor->NumberOfModuleForwarderRefs*sizeof(IMAGE_BOUND_FORWARDER_REF))) {
            PSTR pszDllName = (PSTR) ((DWORD)pFirstBoundImportDescriptor + pBoundImportDescriptor->OffsetModuleName);
            IMAGE_BOUND_FORWARDER_REF *pRef = (IMAGE_BOUND_FORWARDER_REF *)(pBoundImportDescriptor+1);

            MakeIdent(nOffset+1);
            printf ("Bound to %hs", pszDllName);
            DumpTimeDateStamp (0, "", pBoundImportDescriptor->TimeDateStamp);
            if (pBoundImportDescriptor->NumberOfModuleForwarderRefs) {
                UINT i;

                for (i=0;i<pBoundImportDescriptor->NumberOfModuleForwarderRefs;i++) {
                    PSTR pszDllName = (PSTR) ((DWORD)pFirstBoundImportDescriptor + pRef->OffsetModuleName);

                    MakeIdent(nOffset+2);
                    printf ("Contained forwarders bound to %hs", pszDllName);
                    DumpTimeDateStamp (0, "", pRef->TimeDateStamp);
                }
            }
        }
    }
}

void DumpExports (UINT nOffset, IMAGE_OPTIONAL_HEADER32 *pOptionalHeader, PBYTE pbyFile,
                  IMAGE_SECTION_HEADER *pSectionHeader) // header of the section, which contains export section
{
    UINT i;
    UINT iNames;
    PDWORD pdwAddressOfFunctions;
    PWORD pwOrdinals;
    PDWORD pdwNameRVA;
    IMAGE_EXPORT_DIRECTORY *pExportDirectory = (IMAGE_EXPORT_DIRECTORY *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData +
        pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress - pSectionHeader->VirtualAddress);
    DWORD dwVAExportStart = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    DWORD dwVAExportEnd = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + 
                          pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

    DumpDword (nOffset, TEXT("Characteristics"), pExportDirectory->Characteristics);
    DumpTimeDateStamp (nOffset, "TimeDateStamp", pExportDirectory->TimeDateStamp);

    MakeIdent(nOffset);
    printf ("DllName: %s\n", pbyFile + pSectionHeader->PointerToRawData + pExportDirectory->Name - pSectionHeader->VirtualAddress);
    DumpDword (nOffset, TEXT("Ordinal Base"), pExportDirectory->Base);

    MakeIdent(nOffset);
    printf (TEXT("Version: %d.%d\n"), pExportDirectory->MajorVersion, pExportDirectory->MinorVersion);

    DumpDword (nOffset, TEXT("Number of exported functions"), pExportDirectory->NumberOfFunctions);
    DumpDword (nOffset, TEXT("Number of functions exported by name"), pExportDirectory->NumberOfNames);

    MakeIdent(nOffset+1);
    printf (TEXT("Ordn hint RVA      Name\n"));

    pdwAddressOfFunctions = (PDWORD)(pbyFile + pSectionHeader->PointerToRawData + pExportDirectory->AddressOfFunctions - pSectionHeader->VirtualAddress);
    pwOrdinals = (PWORD)(pbyFile + pSectionHeader->PointerToRawData + pExportDirectory->AddressOfNameOrdinals - pSectionHeader->VirtualAddress);
    pdwNameRVA = (PDWORD)(pbyFile + pSectionHeader->PointerToRawData + pExportDirectory->AddressOfNames - pSectionHeader->VirtualAddress);

    for (iNames = 0; iNames < pExportDirectory->NumberOfNames; iNames++) {
        MakeIdent(nOffset+1);

        // AddressOfFunctions MUST be ouf of Export Directory. If it is not so, it is a Forwarding entry
        if (pdwAddressOfFunctions[pwOrdinals[iNames]] < dwVAExportStart ||
            pdwAddressOfFunctions[pwOrdinals[iNames]] > dwVAExportEnd)
            // AddressOfFunctions is normaly in .text section and export table in .edata or .rdata section, so
            // AddressOfFunctions must be not in Export Directory
            printf("%4u %4u %08X %s\n",
                    pwOrdinals[iNames] + pExportDirectory->Base, iNames, pdwAddressOfFunctions[pwOrdinals[iNames]],
                    (pbyFile + pSectionHeader->PointerToRawData + pdwNameRVA[iNames] - pSectionHeader->VirtualAddress));
        else
            printf("%4u %4u          %s (forwarded to %s)\n",
                    pwOrdinals[iNames] + pExportDirectory->Base, iNames,
                    (pbyFile + pSectionHeader->PointerToRawData + pdwNameRVA[iNames] - pSectionHeader->VirtualAddress),
                    (PSTR)(pbyFile + pSectionHeader->PointerToRawData + pdwAddressOfFunctions[pwOrdinals[iNames]] - pSectionHeader->VirtualAddress));
    }

    // print functions exported by ordinal
    for (i = 0; i < pExportDirectory->NumberOfFunctions; i++) {
        if (pdwAddressOfFunctions[i] != 0) {
            // if EXPORTS in DEF-file look like 
            //
            // EXPORTS
            //    Message1  @100
            //    Message2  @200
            //    Message3  @300
            //    Message4  @400
            //    Message5  @500
            // it will be added in export section 401 (500-100+1) entries. 5 from there with not 0 address and the rest
            // empty entries with 0
            // we will dump only not empty entries

            UINT iNames;
            WORD wOrdinal = (WORD)(i + pExportDirectory->Base);

            // try to find (i + pExportDirectory->Base) ordinal in the list of pwOrdinals
            for (iNames = 0; iNames<pExportDirectory->NumberOfNames; iNames++) {
                if (pdwAddressOfFunctions[pwOrdinals[iNames]] == pdwAddressOfFunctions[i])
                    break;
            }

            if (iNames >= pExportDirectory->NumberOfNames) {
                // if not found as exported by name, print it here
                MakeIdent(nOffset+1);
                if (pdwAddressOfFunctions[i] < pSectionHeader->VirtualAddress ||
                    pdwAddressOfFunctions[i] > pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize)
                    printf("%4u      %08X [NONAME]\n", wOrdinal, pdwAddressOfFunctions[i]);
                else
                    printf("%4u               [NONAME] (forwarded to %s)\n",
                           wOrdinal, (PSTR)(pbyFile + pSectionHeader->PointerToRawData + pdwAddressOfFunctions[i] - pSectionHeader->VirtualAddress));
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top