• 滴水逆向-绑定导入表


    课堂知识点

    文字知识点

    点击查看代码
    打印绑定导入表
    
    绑定导入表结构:
    
    PE加载EXE相关的DLL时,首先会根据IMAGE_IMPORT_DESCRIPTOR结构中的TimeDateStamp来判断是否要重新
    计算IAT表中的地址。
    
    TimeDateStamp == 0  未绑定
    
    TimeDateStamp == -1 已绑定 真正的绑定时间为IMAGE_BOUND_IMPORT_DESCRIPTOR的TimeDateStamp
    
    绑定导入表的定位:
    
    绑定导入表位于数据目录的第12项
    
    
    typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
        DWORD   TimeDateStamp;
        WORD    OffsetModuleName;
        WORD    NumberOfModuleForwarderRefs;
    // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
    } IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
    
    typedef struct _IMAGE_BOUND_FORWARDER_REF {
        DWORD   TimeDateStamp;
        WORD    OffsetModuleName;
        WORD    Reserved;
    } IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
    
    特别说明:
    
    当IMAGE_BOUND_IMPORT_DESCRIPTOR结构中的TimeDateStamp与DLL文件标准PE头中的TimeDateStamp值不相符
    时,或者DLL需要重新定位的时候,就会重新计算IAT中的值.
    

    打印绑定导入表相关代码

    点击查看代码
    //绑定导入表打印
    //IMAGE_BOUND_IMPORT_DESCRIPTOR
    VOID LogBoundImportTable(IN LPVOID pFileBuffer)
    {
        PIMAGE_DOS_HEADER pDosHeader = NULL;
        PIMAGE_NT_HEADERS pNTHeader = NULL;
        PIMAGE_FILE_HEADER pPEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pSectionHeader = NULL;
        PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
        PIMAGE_DATA_DIRECTORY pDataDirectory_BoundImportTable = NULL;
        PIMAGE_BOUND_IMPORT_DESCRIPTOR pBoundImportTable = NULL;
        PIMAGE_BOUND_FORWARDER_REF pBoundForwarderTable = NULL;
        
        if (pFileBuffer == NULL)
        {
            printf("FileBuffer获取失败!
    ");
            return;
        }
        
        //判断是否是有效的MZ标志
        if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
        {
            printf("无效的MZ标识
    ");
            return;
        }
        pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
        
        //判断是否是有效的PE标志
        if (*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
        {
            printf("无效的PE标记
    ");
            return;
        }
        
        //定位各种头
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+0x04);
        pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
        pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;
        
        //根据可选PE头里面的数据目录这个数组准确定位到导入表位置,导入表是在数据目录的第二个位置,下面两种方式都可以
        //#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
        //pDataDirectory_BoundImportTable = &pDataDirectory[11];
        pDataDirectory_BoundImportTable = &pDataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
        
        if (!pDataDirectory_BoundImportTable->VirtualAddress)
        {
            printf("pDataDirectory_BoundImportTable 这个程序不存在绑定导入表
    ");
            return;
        }
        
        //验证打印导出表RVA和FOA地址
        printf("BoundImport Table RVA: %#010x
    ",pDataDirectory_BoundImportTable->VirtualAddress);
        DWORD FOA_BoundImportTable = RvaToFileOffset(pFileBuffer,pDataDirectory_BoundImportTable->VirtualAddress);
        printf("BoundImport Table FOA: %#010x
    ",FOA_BoundImportTable);
        //确认好FOA地址之后,开始指针偏移到文件的导入表位置
        pBoundImportTable = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pDosHeader+FOA_BoundImportTable);
    
        //打印查看对应结构体pBoundImportTable的3个字段的值
        printf("pBoundImportTable->NumberOfModuleForwarderRefs: %#x
    ",pBoundImportTable->NumberOfModuleForwarderRefs);
        printf("pBoundImportTable->OffsetModuleName: %#x
    ",pBoundImportTable->OffsetModuleName);
        printf("pBoundImportTable->TimeDateStamp: %#d
    ",pBoundImportTable->TimeDateStamp);
    
        //验证偏移好的pBoundImportTable内存地址和对应内存地址的内容
        printf("*pBoundImportTable: %#010x
    ",*pBoundImportTable);
        printf("pBoundImportTable: %#010x
    ",pBoundImportTable);
        DWORD BoundImportTableBase = (DWORD)pBoundImportTable;
        printf("BoundImportTableBase: %#010x
    ",BoundImportTableBase);
    
        //根据绑定导入表的算法,和上面验证的结果,得出结论是要像得到绑定导入表的名称,需要使用偏移的内存地址;
        //使用此偏移的内存地址然后加上绑定导入表的OffsetModuleName的值,即可得到准确的绑定导入表的名称对应的内存地址;
        //然后就可以直接打印内存地址对应的名称即可;
        while (*(PDWORD)pBoundImportTable)
        {
            PDWORD pOffsetModuleName = (PDWORD)(BoundImportTableBase+pBoundImportTable->OffsetModuleName);
            printf("BoundImportTable Module Name: %#s
    ",pOffsetModuleName);
            pBoundImportTable++;
        }
    }
    

    打印结果

    迷茫的人生,需要不断努力,才能看清远方模糊的志向!
  • 相关阅读:
    day 01
    day14
    day12
    day13
    day11
    day9
    day10
    day08
    day07
    day06
  • 原文地址:https://www.cnblogs.com/autopwn/p/15352962.html
Copyright © 2020-2023  润新知