• PE 绑定导入表


    什么是绑定导入

    PE在加载前 INT表和IAT表都指向一个名称表

    但是有些程序,如果你打印该程序的IAT表的时候会指向地址中发现里面是地址?

    比如如下:我先正常打印发现IAT表中的地址RVA转换FOA都直接转换失败了,那么肯定是地址中的值肯定有问题

    那么就不进行RVA转换到FOA,可以先尝试直接打印地址中的值进行观察:

    原因:我们的PE程序在加载的时候, PE中导入表中的IAT表会根据INT表来进行填写函数地址。但是这就造成了一个问题,PE程序启动慢,因为每次启动都要给IAT表填写函数地址

    如果我们事先先把IAT表中的所需要用到的DLL函数地址都填好的话,是不是能够节省程序启动的时间?

    答案:是的,但是缺点是万一需要被用到的DLL的Imagebase并没有加载到符合的位置,这样就需要修复重定位表中的地址

    那么如何判断该程序是否进行了绑定导入的操作呢?

    在文件中IAT表是否填写地址,依据的地方 就是 导入表中的 TimeDateStamp (时间戳)成员, 如果为0 则是这个DLL没有绑定, 如果为-1 则是这个DLL进行了绑定导入

    如下图:这个是进行了绑定导入的操作,所以打印PIMPORT_DESCRIPTOR的TimeDateStamp为ffffffff,有符号也就是-1

    什么是绑定导入表

    怎么判断导入表中的 IAT表函数地址是否绑定 根据 TimeDataStamp进行判断. 0未绑定 -1绑定

    真正的绑定时间存放在绑定导入表IMAGE_BOUND_IMPORT_DESCRIPTOR的TimeDateStamp的属性中

    TimeDateStamp == 0 未绑定

    TimeDateStamp == -1 已绑定

    定位方法:

    在PE可选头结构中的数据目录的第12项

    typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
        DWORD   TimeDateStamp;                //真正的时间戳,
        WORD    OffsetModuleName;              //DLL的名字. PE的文件名
        WORD    NumberOfModuleForwarderRefs;        //依赖的另外的DLL有几个
    // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
    } IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
    

    我们的一个DLL可能依赖其他的DLL, 所以导入表的最后一个成员是依赖的DLL有几个,如果有两个,那么紧跟着下面就是依赖的DLL的绑定导入表结构

    关于依赖DLL的结构体如下:

    typedef struct _IMAGE_BOUND_FORWARDER_REF {
        DWORD   TimeDateStamp;
        WORD    OffsetModuleName;
        WORD    Reserved; // 保留 无作用
    } IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
    

    打印绑定导入表的代码:

    void PrintBindImportTable(PVOID 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_BOUND_IMPORT_DESCRIPTOR pIMAGE_BOUND_IMPORT_DESCRIPTOR = NULL;
    	PIMAGE_BOUND_FORWARDER_REF pIMAGE_BOUND_FORWARDER_REF = NULL;
    
    	char ModuleName[20] = {0};
    	DWORD BOUNG_IMPORT_DESCRIPTOR_TEMP = NULL;
    	int i = 0;
    	DWORD RVA = 0;
    	DWORD FOA = 0;
    	
        pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);  
        pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); 
    	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
    	
    	RVA_TO_FOA(pFileBuffer, pOptionHeader->DataDirectory[11].VirtualAddress,&FOA);
    
    	//保存第一个DESCRIPTOR的地址 后面加OffsetModuleName来进行使用
    	BOUNG_IMPORT_DESCRIPTOR_TEMP = (DWORD)pFileBuffer+(DWORD)FOA;
    
    	
    	//开始进行打印操作
    	pIMAGE_BOUND_IMPORT_DESCRIPTOR = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer+(DWORD)FOA);
    	
    	while (*(PDWORD)pIMAGE_BOUND_IMPORT_DESCRIPTOR)
    	{
    		printf("
    ");
    		strcpy(ModuleName, (PVOID)((DWORD)BOUNG_IMPORT_DESCRIPTOR_TEMP + (DWORD)pIMAGE_BOUND_IMPORT_DESCRIPTOR->OffsetModuleName));
    		printf("模块名称: %s 
    ",ModuleName);
    		printf("模块的时间戳为: %x 
    ", pIMAGE_BOUND_IMPORT_DESCRIPTOR->TimeDateStamp);
    		printf("当前模块引用的dll的数量为: %x
    ",pIMAGE_BOUND_IMPORT_DESCRIPTOR->NumberOfModuleForwarderRefs);
    
    		for(i=0;i<pIMAGE_BOUND_IMPORT_DESCRIPTOR->NumberOfModuleForwarderRefs;i++){
    			pIMAGE_BOUND_IMPORT_DESCRIPTOR++;
    			pIMAGE_BOUND_FORWARDER_REF = (PIMAGE_BOUND_FORWARDER_REF)pIMAGE_BOUND_IMPORT_DESCRIPTOR;
    			strcpy(ModuleName, (PVOID)((DWORD)BOUNG_IMPORT_DESCRIPTOR_TEMP + (DWORD)pIMAGE_BOUND_FORWARDER_REF->OffsetModuleName));
    			printf("	引用的模块名称: %s 
    ",ModuleName);
    			printf("	引用的模块的时间戳: %x
    ", pIMAGE_BOUND_FORWARDER_REF->TimeDateStamp);
    		}
    	
    		pIMAGE_BOUND_IMPORT_DESCRIPTOR++;
    	}
    }
    

  • 相关阅读:
    MongoDB学习
    Linux 硬盘分区、分区、删除分区、格式化、挂载、卸载
    openstack中数据库连接数太多--pymysql.err.OperationalError,1040, u'Too many connections'
    openstack各服务端口使用情况
    linux常用命令
    云计算---OpenStack Neutron详解
    shell---数据流重定向
    云计算---openstack创建虚拟机过程
    SpringMvc面试题
    Linux 本机/异机文件对比
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/13071219.html
Copyright © 2020-2023  润新知