滴水三期:day40.1-绑定导入表

解析绑定导入表 一、绑定导入表的作用 有些windows程序,如notepad,为了提高加载速度,会直接把DLL中的函数地址写入到IAT表,省去了加载时的计算。但是这样会有两个问题,第一,当DLL没有占住ImageBase时,IAT中的地址就是错的;第二,当链接的DLL被修改了,那IAT里写的地址也是错的。遇到这两种情形之一,加载时就必须修复IAT了。 对于第二种情形,DLL是否被修改,是根据比较DLL的时间戳和绑定导入表中的记录的DLL时间戳来判断的,如果不一致,说明DLL被修改了。 加载程序时,操作系统根据导入表中的时 阅读详情

一、引入绑定导入表

  • 在day39.1-IAT表和导入表的作业中,发现notepad.exe在运行前IAT表和INT表中的内容不一样,且通过观察,运行前notepad.exe的IAT表中存储的数据直接就是函数在虚拟内存中的绝对地址,而不是像ipmsg.exe程序:在程序运行时----程序的.exe和使用到的DLL加载完成后,再把使用到的DLL中函数的绝对地址写到IAT表中

  • 为什么Windows32位系统自带的一些程序在运行前就把使用到的DLL中的函数的绝对地址绑定到IAT表中呢?

    • 优点:程序启动速度变快

      因为双击程序后,系统会给程序分配一个4GB虚拟内存,接着把程序的.exe和使用的.dll装载到虚拟内存中,装载完成后再遍历INT表,通过系统API得到对应函数的绝对地址,再写到IAT表中;而如果在程序运行前就已经把函数绝对地址绑定到IAT表中,程序启动时就无需上述修改IAT表的步骤,节省时间

    • 缺点:如果程序使用到的DLL装载时没有按照ImageBase位置装载;或者当程序使用到的DLL中的函数被修改了导致函数地址发生变化,那么IAT表中的地址数据就不准确了

    • 综上:系统自带程序之所以敢这样做,可能就是因为这些程序使用的DLL都是设计好的,会按照ImageBase装载,不会出现冲突;且这些DLL不经常修改,函数地址不经常发生变化

  • 程序加载后,系统如何判断一个IAT表中数据是已经绑定好的绝对地址呢?还是指向对应函数名字符串地址的RVA或序号呢?

    • 因为导入表有多个_IMAGE_IMPORT_DESCRIPTOR这种结构,每一个结构对应一个程序使用到的DLL;比如这个导入表结构对应的DLL是user32.dll,那么根据这个导入表结构中的**TimeDataStamp**字段,就可以判断此导入表结构的IAT表中的数据是绝对地址还是RVA

      image-20230419195635001

    • TimeDataStamp

      • 为0(即0x00000000):表示这个导入表结构对应的DLL中的函数绝对地址没有绑定到IAT表中

      • 为**-1**(即0xFFFFFFFF):表示这个导入表结构对应的DLL中函数绝对地址已经绑定到IAT表中

        所以可以通过导入表的时间戳,判断是否有绑定导入表

  • 如果一个导入表结构的TimeDataStamp为**-1**,说明绝对地址已经绑定到IAT表中,那如何知道对应DLL中函数的绝对地址什么时间绑定的?就需要另一个表----绑定导入表,绑定导入表中的TimeDataStamp时间戳,才表示函数地址真正的绑定时间

二、绑定导入表

1.定位

  • 数据目录的第12个结构,就是绑定导入表数据目录项;再通过绑定导入表数据目录中VirtualAddress字段,RVA转成FOA,定位到绑定导入表地址

    201545

2.绑定导入表结构

  • 结构如下:

    struct _IMAGE_BOUND_IMPORT_DESCRIPTOR{						
        DWORD TimeDateStamp;  //时间戳					
        WORD OffsetModuleName;	//DLL的名字RVA(加第一个结构中RVA才是字符串真正RVA,详见下面)	
        WORD NumberOfModuleForwarderRefs;  //这个绑定导入表结构后面还有几个_IMAGE_BOUND_FORWARDER_REF这种结构					
    };  //绑定导入表有很多这种结构或者_IMAGE_BOUND_FORWARDER_REF这种结构,最后如果有sizeof(_IMAGE_BOUND_IMPORT_DESCRIPTOR)个0,表示绑定导入表结束	
    
1)TimeDateStamp
  • 绑定导入表的时间戳:表示程序使用到的DLL中的函数绝对地址真正绑定到IAT表中的时间
  • 作用:系统通过程序使用到的DLL对应的**绑定导入表结构中TimeDateStamp和该DLL的可选PE头中的TimeDateStamp**对比
    • 如果两个时间戳一样:表明DLL的创建时间和把DLL中的函数绝对地址绑定到IAT表的时间是一样,则在绑定以后,DLL没有更新或者修改
    • 如果两个时间戳不一样:表明在绑定以后,此DLL又被更新或者修改了,那么绑定到IAT表中的地址可能不准确了!(因为DLL中的函数地址可能变了,但绑定到IAT中的数据可能是以前的函数地址)
2)OffsetModuleName
  • 对应DLL的名字:因为一个程序的导入表结构对应一个使用到的DLL;一个程序的绑定导入表结构也对应一个程序使用到的DLL,这个绑定导入表结构记录了该DLL中函数绝对地址绑定到IAT表的时间戳、该DLL的名字、还有该DLL使用到别的DLL的个数

  • 注意:不管是_IMAGE_BOUND_IMPORT_DESCRIPTOR结构中的OffsetModuleName、还是后面要讲的_IMAGE_BOUND_FORWARDER_REF 结构中的OffsetModuleName,都==必须加上绑定导入表起始RVA值==,才是这个结构对应DLL名字的真正RVA

    因为通过Winhex打开notepad.exe发现:绑定导入表的起始地址是在节表后面!!而上述DLL名字字符串紧跟在绑定导入表后面!(这就解决了以前学新增节时,为什么说节表后面如果有数据,不要随便动!)

    233255
3)NumberOfModuleForwarderRefs
  • 因为一个DLL可能还会使用到别的DLL中的函数,所以NumberOfModuleForwarderRefs字段的值是多少,就表明当前绑定导入表对应的DLL还使用了多少个别的DLL,同样表示这个绑定导入表结构后面跟了多少个_IMAGE_BOUND_FORWARDER_REF这种结构

  • _IMAGE_BOUND_FORWARDER_REF结构如下:

    struct _IMAGE_BOUND_FORWARDER_REF {			
        DWORD TimeDateStamp;  //时间戳		
        WORD OffsetModuleName;  //对应DLL的名字
        WORD Reserved;  //保留(未使用)	
    };
    
    • TimeDataStamp:和绑定导入表结构中的时间戳含义和用途是一样的
    • OffsetModuleName:加上绑定导入表起始RVA,才是真正对应DLL的名字
    • Reserved:保留字段(未使用),没有任何含义
  • 具体结构关系如下:比如一个程序的绑定导入表先是一个_IMAGE_BOUND_IMPORT_DESCRIPTOR结构,该结构中NumberOfModuleForwarderRefs字段值为2(表示该DLL使用了另外两个DLL中的函数),则该结构后面跟了两个_IMAGE_BOUND_FORWARDER_REF结构(每一个REF结构对应一个DLL);后面以此类推,直到有8字节个0x00表示绑定导入表结束

    image-20230419205008853

3.作用

  • 综上:当IMAGE_BOUND_IMPORT_DESCRIPTOR结构中的TimeDateStamp与DLL文件标准PE头中的TimeDateStamp值不相符时(或者DLL需要重定位的时候),程序在装载完成后才会修改对应DLL的导入表结构中的IAT表中的数据

三、作业

1.打印绑定导入表

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;

#define MZ 0x5A4D
#define PE 0x4550
#define IMAGE_SIZEOF_SHORT_NAME 8

//DOS头
struct _IMAGE_DOS_HEADER {
	WORD e_magic;  //MZ标记
	WORD e_cblp;
	WORD e_cp;
	WORD e_crlc;
	WORD e_cparhdr;
	WORD e_minalloc;
	WORD e_maxalloc;
	WORD e_ss;
	WORD e_sp;
	WORD e_csum;
	WORD e_ip;
	WORD e_cs;
	WORD e_lfarlc;
	WORD e_ovno;
	WORD e_res[4];
	WORD e_oemid;
	WORD e_oeminfo;
	WORD e_res2[10];
	DWORD e_lfanew;  //PE文件真正开始的偏移地址
};

//标准PE头
struct _IMAGE_FILE_HEADER {
	WORD Machine;  //文件运行平台
	WORD NumberOfSections;  //节数量
	DWORD TimeDateStamp;  //时间戳
	DWORD PointerToSymbolTable;
	DWORD NumberOfSymbols;
	WORD SizeOfOptionalHeader;  //可选PE头大小
	WORD Characteristics;  //特征值
};

//数据目录
struct _IMAGE_DATA_DIRECTORY{
    DWORD VirtualAddress;
    DWORD Size;
};

//可选PE头
struct _IMAGE_OPTIONAL_HEADER {
	WORD Magic;  //文件类型
	BYTE MajorLinkerVersion;
	BYTE MinorLinkerVersion;
	DWORD SizeOfCode;   //代码节文件对齐后的大小
	DWORD SizeOfInitializedData;  //初始化数据文件对齐后的大小
	DWORD SizeOfUninitializedData;  //未初始化数据文件对齐后大小
	DWORD AddressOfEntryPoint;  //程序入口点(偏移量)
	DWORD BaseOfCode;  //代码基址
	DWORD BaseOfData;  //数据基址
	DWORD ImageBase;   //内存镜像基址
	DWORD SectionAlignment;  //内存对齐粒度
	DWORD FileAlignment;  //文件对齐粒度
	WORD MajorOperatingSystemVersion;
	WORD MinorOperatingSystemVersion;
	WORD MajorImageVersion;
	WORD MinorImageVersion;
	WORD MajorSubsystemVersion;
	WORD MinorSubsystemVersion;
	DWORD Win32VersionValue;
	DWORD SizeOfImage;  //文件装入虚拟内存后大小
	DWORD SizeOfHeaders;  //DOS、NT头和节表大小
	DWORD CheckSum;  //校验和
	WORD Subsystem;
	WORD DllCharacteristics;
	DWORD SizeOfStackReserve;  //预留堆栈大小
	DWORD SizeOfStackCommit;  //实际分配堆栈大小
	DWORD SizeOfHeapReserve;  //预留堆大小
	DWORD SizeOfHeapCommit;  //实际分配堆大小
	DWORD LoaderFlags;
	DWORD NumberOfRvaAndSizes;  //目录项数目
	_IMAGE_DATA_DIRECTORY DataDirectory[16]; //数据目录
};

//NT头
struct _IMAGE_NT_HEADERS {
	DWORD Signature;  //PE签名
	_IMAGE_FILE_HEADER FileHeader;
	_IMAGE_OPTIONAL_HEADER OptionalHeader;
};

//节表
struct _IMAGE_SECTION_HEADER{
	BYTE Name[IMAGE_SIZEOF_SHORT_NAME];  //节表名
	union{
		DWORD PhysicalAddress;
		DWORD VirtualSize;  //内存中未对齐大小
	}Misc;
	DWORD VirtualAddress;  //该节在内存中偏移地址
	DWORD SizeOfRawData;  //该节在硬盘上文件对齐后大小
	DWORD PointerToRawData;  //该节在硬盘上文件对齐后偏移地址
	DWORD PointerToRelocations;
	DWORD PointerToLinenumbers;
	WORD NumberOfRelocations;
	WORD NumberOfLinenumbers;
	DWORD Characteristics;  //该节特征属性
};

//绑定导入表
struct _IMAGE_BOUND_IMPORT_DESCRIPTOR{						
    DWORD TimeDateStamp;  //时间戳					
    WORD OffsetModuleName;	//DLL的名字RVA(加第一个结构中RVA才是字符串真正RVA,详见下面)	
    WORD NumberOfModuleForwarderRefs;  //这个绑定导入表结构后面还有几个_IMAGE_BOUND_FORWARDER_REF这种结构					
};  //绑定导入表有很多这种结构或者_IMAGE_BOUND_FORWARDER_REF这种结构,最后如果有sizeof(_IMAGE_BOUND_IMPORT_DESCRIPTOR)个0,表示绑定导入表结束
struct _IMAGE_BOUND_FORWARDER_REF{			
    DWORD TimeDateStamp;  //时间戳		
    WORD OffsetModuleName;  //对应DLL的名字
    WORD Reserved;  //保留(未使用)	
};
	
/*计算文件大小函数
参数:文件绝对路径
返回值:返回文件大小(单位字节)
*/
int compute_file_size(char* filePath){
	FILE* fp = fopen(filePath,"rb");
    if(!fp){
		printf("打开文件失败");
		exit(0);
	}
    fseek(fp,0,2);
	int size = ftell(fp);
	//fseek(fp,0,0); 单纯计算文件大小,就不需要还原指针了
	fclose(fp);
	return size;
}

/*将文件读入FileBuffer函数
参数:文件绝对路径
返回值:FileBuffer起始地址
*/
char* to_FileBuffer(char* filePath){
    FILE* fp = fopen(filePath,"rb");
    if(!fp){
		printf("打开文件失败");
		exit(0);
	}
    int size = compute_file_size(filePath);
    
	char* mp = (char*)malloc(sizeof(char) * size);  //分配内存空间
    if(!mp){
        printf("分配空间失败");
        fclose(fp);
        exit(0);
    }
    
    int isSucceed = fread(mp,size,1,fp);
    if(!isSucceed){
        printf("读取数据失败");
        free(mp);
        fclose(fp);
        exit(0);
    }
    
    fclose(fp);
    return mp;
}

/*虚拟内存偏移地址->文件偏移地址函数
参数:FileBuffer起始地址,RVA地址值
返回值:RVA对应的FOA,返回0则表示非法RVA
*/
DWORD RVA_to_FOA(char* fileBufferp,DWORD RVA){
	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_SECTION_HEADER* _image_section_header = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)fileBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(fileBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_section_header = (_IMAGE_SECTION_HEADER*)((char*)_image_optional_header + 
		_image_file_header->SizeOfOptionalHeader);

	bool flag = 0; //用来判断最终RVA值是否在节中的非空白区
	if(RVA < _image_section_header->VirtualAddress)
		return RVA;
	for(int i = 0;i < _image_file_header->NumberOfSections;i++){
		if(RVA >= _image_section_header->VirtualAddress 
			&& RVA < _image_section_header->VirtualAddress + _image_section_header->Misc.VirtualSize){
			flag = 1;
			break;
		}else{
			_image_section_header++;
		}
	}
	if(!flag)
		return 0;
	DWORD mem_offset_from_section = RVA - _image_section_header->VirtualAddress;
	return _image_section_header->PointerToRawData + mem_offset_from_section;	
}

/*打印绑定导入表
参数:需要打印的PE文件绝对路径
返回值:无
*/
void boundImportTable_print(char* filePath){
	char* fileBufferp = to_FileBuffer(filePath);

	_IMAGE_DOS_HEADER* _image_dos_header = NULL;
	_IMAGE_FILE_HEADER* _image_file_header = NULL;
	_IMAGE_OPTIONAL_HEADER* _image_optional_header = NULL;
	_IMAGE_DATA_DIRECTORY* _image_data_directory = NULL;
	_IMAGE_BOUND_IMPORT_DESCRIPTOR* _image_bound_import_descriptor = NULL;
	_IMAGE_BOUND_FORWARDER_REF* _image_bound_forwarder_ref = NULL;

	_image_dos_header = (_IMAGE_DOS_HEADER*)fileBufferp;
	_image_file_header = (_IMAGE_FILE_HEADER*)(fileBufferp + _image_dos_header->e_lfanew + 4);
	_image_optional_header = (_IMAGE_OPTIONAL_HEADER*)((char*)_image_file_header + 20);
	_image_data_directory = (_IMAGE_DATA_DIRECTORY*)(_image_optional_header->DataDirectory + 11);  //指向绑定导入表数据目录项
	if(_image_data_directory->VirtualAddress == 0){
		printf("此文件没有绑定导入表");
		getchar();
		exit(0);
	}

	_image_bound_import_descriptor = (_IMAGE_BOUND_IMPORT_DESCRIPTOR*)(fileBufferp + RVA_to_FOA(fileBufferp,_image_data_directory->VirtualAddress));
	DWORD bound_import_table_RVA = (DWORD)_image_data_directory->VirtualAddress; //记录下绑定导入表起始RVA

	//打印绑定导入表
	printf("\n***************绑定导入表***************\n");
	while(1){
		//根据绑定导入表结构中是否为全0判断绑定导入表是否结束
		for(int i = 0;i < sizeof(*_image_bound_import_descriptor);i++){
			if(*((char*)_image_bound_import_descriptor) != 0){
				break;
			}
		}
		if(i == sizeof(*_image_bound_import_descriptor)){
			break;
		}

		printf("OffsetModuleName:%04X--->%s\n",_image_bound_import_descriptor->OffsetModuleName,fileBufferp + RVA_to_FOA(fileBufferp,_image_bound_import_descriptor->OffsetModuleName + bound_import_table_RVA));
		printf("TimeDateStamp:%08X\n",_image_bound_import_descriptor->TimeDateStamp);
		printf("NumberOfModuleForwarderRefs:%04X\n",_image_bound_import_descriptor->NumberOfModuleForwarderRefs);
		
		//打印_IMAGE_BOUND_FORWARDER_REF结构
		if(_image_bound_import_descriptor->NumberOfModuleForwarderRefs != 0){
			printf("-----ModuleForwarders-----\n");
			for(i = 0;(WORD)i < _image_bound_import_descriptor->NumberOfModuleForwarderRefs;i++){
				_image_bound_forwarder_ref = (_IMAGE_BOUND_FORWARDER_REF*)(_image_bound_import_descriptor + 1 + i);	
				printf("OffsetModuleName:%04X--->%s\n",_image_bound_forwarder_ref->OffsetModuleName,fileBufferp + RVA_to_FOA(fileBufferp,_image_bound_forwarder_ref->OffsetModuleName + bound_import_table_RVA));
				printf("TimeDateStamp:%08X\n",_image_bound_forwarder_ref->TimeDateStamp);
				printf("Reserved(未使用):%04X\n\n",_image_bound_forwarder_ref->Reserved);
			}
		}
		
		printf("\n");
		_image_bound_import_descriptor = (_IMAGE_BOUND_IMPORT_DESCRIPTOR*)(_image_bound_import_descriptor + 1 + _image_bound_import_descriptor->NumberOfModuleForwarderRefs);
	}
	
}

int main(int argc, char* argv[])
{
	char* filePath = "D:/C-language/file/notepad.exe";
	boundImportTable_print(filePath);
	return 0;
}

验证一下:使用LordPE打开notepad.exe,打开绑定导入表,与VC6输出结果比对:(由于截图受限,这里选择ADVAPI32.dll和KERNEL32.dll对应的绑定导入表结构进行验证)

235457
别再乱改宏定义了!STM32F103程序移植保姆级教程(从C8T6到ZET6实战) 本文详细解析了STM32F103程序从C8T6移植到ZET6的实战步骤,重点介绍了硬件差异、开发环境配置、时钟陷阱及外设处理等关键点。通过修改宏定义(如STM32F10X_HD)、调整启动文件和时钟配置,确保移植顺利进行。适合嵌入式开发者参考,避免常见移植问题。 阅读详情

相关推荐

小红书爬取实战指南

以上方案仅供技术学习参考,请确保遵守目标网站的服务条款和相关法律法规。

monk all the way 6926

13.PE文件之绑定导入表(IMAGE_BOUND_IMPORT_DESCRIPTOR)

绑定导入数据的存在主要是为了优化导入信息,提高PE的加载效率. 当PE文件被加载到内存时,加载器会先检查导入表,然后把需要加载的DLL载入到地址空间中. 加载器还有一项比较重要的工作是根据导入信息的描述使用动态链接库里输入函数的实际地址去替换IAT表的内容,这个步骤会花去一部分时间.但是如果知道函数实际的地址,就可以直接把数组中的元素替换为地址,这能节省相当多的时间.这种方法就称为绑定(Binding). 绑定导入表定位以及解析(手动FileBuffer) 测试文件Win7 x86下note..

kernelhack 4423

【Fluent】太阳辐射模型—Solar Ray Tracing

一、引言Fluent提供了一个太阳能负载模型,可用于计算进入计算域的太阳光线的辐射效应。该模型可以分为:太阳光线追踪和太阳辐照。其中太阳辐照需要使用DO或MC模型,直接向辐射模型提供外光束方向和强度参数。太阳光线追踪不限制辐射模型,可以独立于辐射方程使用,甚至可以在辐射模型off的情况下使用。本文主要介绍太阳光线追踪模型。该模型非常适用于以下领域汽车气候控制 (ACC) 应用建筑物中的人体热舒适建模应用该模型使用着色算法进行太阳光线追踪。光线会透过半透明的面加载在照射面上。

a5567899的博客 7588

关于绑定导入表

0x01 绑定导入表概念 绑定导入表(The Bound Import Directory)。它包含了可以让加载器判断绑定的地址是否合法的信息。描述它的数据结构是IMAGE_BOUND_IMPORT_DESCRIPTOR,目录表就是这种结构的数组,每一项都对应一个被绑定过的DLL。 每当PE装载器装入PE文件时,检查导入表并将相关DLL映射到进程空间地址。然后通过遍历IA...

abns44296的博客 903

基于CLICKHOUSE的数据仓库分层规范

接入层。

zjyy1987的博客 769

NIST随机性测试实战:从理论公式到结果解读

本文详细解析了NIST随机性测试的实战应用,从基础测试到高级测试,涵盖频数测试、块频数测试、游程测试等核心方法。通过实际案例和参数设置经验,帮助读者理解如何解读测试结果并排查常见问题,提升随机数生成质量。文章还分享了自动化测试流程和硬件RNG特殊处理技巧,适合密码学和区块链开发者参考。

weixin_29323365的博客 314

PE文件(十五)绑定导入表

我们在分析Windows自带的一些程序时,常常发现有的程序,如notepad,他的IAT表在文件加载内存前已经完成绑定,存储了函数的地址。这样做可以使得程序是无需修改IAT表而直接启动,这时程序启动速度变快。但这种方式只适用于dll按照预先设定ImageBase装载而不重分配的情况当dll没有按照预先设定的ImageBase进行装载,IAT表在文件加载内存前进行绑定就会出现问题了。

2301_78838647的博客 1032

FPGA,关于安装使用libero IDE V9.2 及其gold floating license配置

3、license安装根据,下面的提示进行,跟随setting up the license server on a host教程操作。1、从官网下载Libero IDE v9.2(如下图中的Libero IDE v9.2 software)4、下载完成license解压包后还需要下载 Daemons license ,地址如下。(2)第一行并不是在内填写,而是直接用您电脑名替换掉(1)修改license.bat前四行是,其务必保持和案例位置相同(避免出错)............

JasonK的博客 4297

PE文件学习笔记(五):导入表、IAT、绑定导入表解析

1、导入表(Import Descriptor)结构解析:导入表是记录PE文件中用到的动态连接库的集合,一个dll库在导入表中占用一个元素信息的位置,这个元素描述了该导入dll的具体信息。如dll的最新修改时间、dll中函数的名字/序号、dll加载后的函数地址等。而一个元素即一个结构体,一个导入表即该结构体的数组,其结构体如下所示:typedef struct _IMAGE_IMPORT_DESCR

Apollon_krj的博客 1万+

HCIE-Datacom笔试题库

关于HCIE Datacom笔试考试题目整理!

坏坏-5的博客 609

PE结构之绑定导入表

IAT 中的 IMAGE_THUNK_DATA 结构将被导入函数的实际地址覆盖。加载绑定的可执行文件时,Windows 加载程序可以绕过查找每个导入的 API 并将其写入 IAT 的步骤。IAT 表中的数据,在文件中可能已经不和INT表一样了,已经保存了需要导入的函数的VA(内存地址或者说绝对地址). 如果IMAGE_IMPORT_DESCRIPTOR结构(导入表的结构)中的。TimeDateStamp==0 ,表示 没有绑定 ,如果为-1,说明已经绑定,这时 IAT表的数据已经是导入函数的VA了。

weixin_43751677的博客 376

Debezium报错处理系列之二十一:Unable to connect: Communications link failure.The driver has not received any

Debezium报错系列之二十一:Unable to connect: Communications link failure.The driver has not received any。

zhengzaifeidelushang的博客 547

PE文件解析-加载配置表、绑定导入表、导入地址表与延迟导入表

一、加载配置表 1.位置与简介     载入配置表早期是用于描述当PE文件头或PE可选头无法描述或者因为太大而无法描述的各种功能。     后来以XP及以后的系统主要是为了存储SEH句柄,称为安全结构化异常处理程序列表,如果SEH异常处理没有经过注册,在载入配置表中没有句柄,这个异常处理就不会被执行。     据微软官方说明,这个载入配置表的作用是为了防止“x86异常处理程序劫持”的漏洞。因为...

zhyulo的博客 1933

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

滴水逆向三期实践17:绑定导入表

上一章最后讲到,打印导入表时如果打印的某些 exe 比如 xp系统自带的 记事本 即notepad.exe(win10 的 notepad.exe已经没有这种情况了),那上面打印的结果就不一定是如上一章所说的了,因为我们默认了 FirstThunk 也就是IAT 表的内容不是函数编号就是函数名的 RVA,实际上在文件中的 IAT 表仍然有第三种情况,这就是本章讲的内容了 IAT 表在文件中存储的内容未必是序号和函数名的 RVA,还有可能直接就是上章讲的文件运行加载进内存后呈现的真正的函数地址。而这个.

Rivival_S 的博客 1437

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

绑定导入表

我们之前分析过导入表,在PE文件加载前IAT表和INT表相同,只有文件加载后才能根据INT表通过序号或名称使用GetProcessAddress函数获得函数地址贴到IAT表中 我们观察记事本程序,记事本程序在PE文件加载前就把函数地址贴到IAT表中了。这种情况叫做绑定导入表 这样做的好处是程序运行快,坏处是万一dll没有占住要使用的ImageBase,会出现错误,还有万一dll被修改了,值会发生改变 如果导入表中的时间戳为0代表dll的所有函数地址还没有绑定,当时间戳为-1时,意味着函数地址已经被绑定 那么

若面朝大海边竹妮春暖花开的博客 333

PE结构(四) 绑定导入表

1.关于绑定导入 一般情况下,在程序加载前IAT表和INT表中的内容相同,都是程序引用的dll中的函数的函数名或序号; 加载完成后IAT表中将替换为函数的真正地址; 但在加载前IAT表中直接写绝对地址是可以实现的; 加载前在IAT表中保存绝对地址的优点:启动程序快; 在启动程序时需要:申请4gb内存空间、贴exe、贴dll、将IAT表修复为地址等等; 如果直接用绝对地址,则省去了修复IAT表的操作...

weixin_37673331的博客 730

PE文件:绑定导入表

绑定导入表是为了加快程序的加载程序,因为正常PE加载的时候,要去检查导入表并将相关的DLL映射到进程空间地址,并将导入表的FirstThunk指向的数组填入函数的真实地址,这一步需要花费很多时间,绑定导入表就是为了解决此环节的问题,**绑定导入表中保存了导入函数的真实地址,PE加载的时候系统会检测是否有绑定导入表,就会直接将函数地址写入FirstThunk。**

weixin_43742894的博客 541

滴水逆向三期 PE基础 绑定导入表

分析 系统软件会有绑定导入表 也就是IAT已经被设定为函数地址, 但是WIN10中即便是记事本也没了, 只能用xp的notepad代替. 这个表的目的是减少程序启动时间, 在导入表中时间戳为-1时代表有绑定导入表. OffsetModule这个值需要加上第一个IMAGE_BOUND_IMPORT_DESCRIPTOR的地址, 而不是当前dll的地址 NumOfModuleForwarderRefs表示当前dll所需要的其它dll, 在当前绑定导入表之后紧跟的结构就是 typedef struct _IMA

四位的博客 471

PE文件绑定导入表

BOUND IMPORT TABLE 绑定导入表是一种提高DLL加载速度的技术. 对于PE文件而言是可选项, 不是必须. 当修改PE文件时, 如果添加导入的DLL文件, 需要注意有没有绑定导入表, 如果有需要删除或修改绑定导入表, 否则会运行时出错. PEview查看绑定导入表 Winhex查看相应位置 ...

fa1c4的blog 379

PE文件学习笔记(三):导出表(Export Table)解析

数据目录表(Data Directory):16个_IMAGE_DATA_DIRECTORY结构体元素,该结构体数组时可选PE头中最后一个成员。这十六个元素分别存储了不同信息,分别是:导入表、导出表、资源、异常信息、安全证书、重定位表、调试信息、版权所有、全局指针、TLS、加载配置、绑定导入、IAT、延迟导入、COM信息、最后一个保留未使用。和程序运行时息息相关的表有:导出表、导入表、重定位表、IA

Apollon_krj的博客 7242

打印导入表

【代码】打印导入表。

qq_52442096的博客 215

打印绑定导入表

【代码】打印绑定导入表。

qq_52442096的博客 209

PE结构&绑定导入实现

简介 作用 绑定导入是一种提高PE加载速度的技术。它只能起辅助性作用,它的存在与否只影响加载过程,并不影响PE的最终加载结果和运行结果。 为什么说是辅助性呢? 因为不同的操作系统中,动态链接库的基地址是不一样的。举个例子,kernel32.dll,在Windows 2000中其加载到进程空间的基地址为0x77e60000,而在Windows XP SP3中其加载地址则是0x7c800000。同一动态链接库加载后处于不同的基地址,直接导致了同一个导入函数在不同操作系统中其导入地址VA是不一样的。 因此经过绑定

寻梦&之璐 8050
上一篇: 滴水三期:day39.1-IAT表和导入表
下一篇: 滴水三期:day41.1-导入表注入
EdimadeZhou
博客等级 码龄5年 241粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值