gpt4 book ai didi

dll - 导入地址表中的 Thunk 表?

转载 作者:行者123 更新时间:2023-12-04 12:14:17 25 4
gpt4 key购买 nike

什么是与 EXE 文件中用于导入外部 DLL 中使用的函数的导入地址表相关的 thunk 表?

这个 thunk 表只是一个包含“Thunk”到其他函数的表吗?

最佳答案

Thunks 是 导入表的一部分 ( IMAGE_DIRECTORY_ENTRY_IMPORT ) 和延迟导入表 ( IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT )。它们被描述为http://msdn.microsoft.com/en-us/library/ms809762.aspx .

我将查看我的旧源代码,稍后将发布一个工作代码,该代码会转储这两个表,包括绑定(bind)信息。

更新:

这是我在一个旧程序中喜欢的代码。它仅支持 32 位 PE,但可以轻松修改为 64 位。顺便说一句,您可以看到,它还转储绑定(bind)信息。要测试此绑定(bind)您要转储的关于 bind.exe 的 PE(例如,使用 bind.exe -u -v Test.dll )。

代码由大约 1000 行组成,所以我不能在这里发布。我收到一条错误消息

哎呀!您的修改无法提交,因为:

  • 正文限制为 30000 个字符;您输入了 55095

  • 所以我把它放在这里: http://www.ok-soft-gmbh.com/ForStackOverflow/PEInfo.c .我希望代码能更好地帮助你作为一个长描述。

    更新 2 : 我看到我的旧答案不适合搜索引擎。所以我包含了 PEInfo.c的部分代码(函数 DumpImportsDumpExports )如下:

    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));
    }
    }
    }
    }

    关于dll - 导入地址表中的 Thunk 表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3430718/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com