今天又看了些基础的机制,有导出表,栈,重定位表,资源等,凡是涉及到编程的部分自己先略过了,有点麻烦,将来集中补。后面的内容就涉及到操作系统了,比较难,自己再学些基础课比如操作系统,计算机组成原理等再来学习这一部分内容。下午看了《加密与解密》,后几天先看看这个。现在把笔记贴在下面。
补一张导入表的图。
5
导出表
描述了PE文件向其他程序提供可供调用函数的情况
大部分DLL都有导出表,EXE文件很少有导出表
功能
通过导出表分析不认识的DLL的功能
向调用者提供函数的地址
获取导出表的位置
数据目录首个IMAGE_DATA_DIRCTORY结构
导出表的组成
导出表首部只有一个IMAGE_EXPORT_DIRECTORY结构
DWORD Characteristics //未使用,总是0
DWORD TimeDateStamp //表明文件产生时刻
WORD MajorVersion //未使用,总是0
WORD MinorVersion //未使用,总是0
DWORD Name //文件名
DWORD Base //导出函数序号起始值
DWORD NumberOfFunctions //导出函数总数
DWORD NumberOfNames //有函数名的导出函数总数
、 PDWORD *AddressOfFunctions //指向包含全部导出函数入口地址的双字数组(入口地址表)
PDWORD *AddressOfNames //指向包含有函数名的函数的函数名的地址的双字数组(函数名地址表)
PWORD *AddressOfNameOrdinals//指向单字数组,与AddressOfNames对应,存出了相应函数名的入口地址在AddressOfFunctions中的索引
从序号查找入口地址
...
得到导出表的地址
从Base获取起始序号
将需要查找的导出序号减去起始序号,得到函数在入口地址表中的索引
检测是否合法
在入口地址表中取出RVA
从函数名称查找入口地址
...
得到导出表的地址
从NumberOfName字段得到已命名函数的总数,构造循环
在函数名地址表中查找
记下索引值
在入口地址表中取出RVA
6
栈
数据结构之栈//略
寻址
SS:ESP指向栈顶,ESP的值自动改变
EBP指向栈底(高地址)
应用
保存临时值/赋值
注意要维持栈平衡
保存程序现场
16位系统分长短调用,区别于是否将SS压栈
32位系统不分长短,不会将SS压栈,SS依旧16位,寻址方式不同了
传递函数参数
invoke:push,push...push,call(EIP压栈),...,ret(EIP出栈)
存放过程中的局部变量
call指令具体调用过程
将调用函数用到的参数入栈
EIP入栈
EBP入栈
EBP指向保存了EBP的那个地址
ESP向低地址调整,构造缓冲区
清理局部变量,EBP出栈(leave)
EIP出栈,清理栈中参数(retn)
栈溢出技术
通过特殊处理使EIP出栈的数据指向自己想要的代码
数据覆盖
高高低低
低不够用,高地址就被覆盖
6
代码重定位
广泛应用于补丁程序设计、病毒程序设计
可以将代码随意部署到内存中,不影响程序的运行
解决的技术问题:对设计全局变量的指令操作数进行修改(绝对地址)
重定位表
第六个表项
.reloc
指向IMAGE_BASE_RELOCATION结构数组,每个数组指向一个页(紧挨着这个结构数组)
DWORD VirtualAddress //起始地址
DWORD SizeOfBlock //本页重定位项个数
//通过页实现,32位页4K,只需要12位二进制就能表示,每一项大小都是一个字
//每一个字的高四位取不同值有不同的含义
//0仅仅对齐使用,3全部修正
//总大小 = 地址地址(4B)+个数(4B)+2*n
//以为零的IMAGE_BASE_RELOCATION结束
方便设计人员在编码中使用全局变量
7
资源表
常用资源类型
位图、光标、图标资源
菜单资源
对话框资源
自定义资源
ID 类型 [DISCARDABLE] 文件名
1000 MP3 "1.mp3"
组织方式
根目录
一级子目录 //资源类型
二级子目录 //资源ID
三级子目录 //代码页分类
文件信息 //资源指针和大小
定位
第3个目录项
.rsrc
根目录
一个IMAGE_RESOURCE_DIRECTORY
Characteristics //0
TimeDateStamp //创建该资源的时间
MajorVersion //0
MinorVersion //0
NumberOfNamedEntries //以名称命名资源的个数a
NumberOfIdEntries //以ID命名资源的个数b
a+b个IMAGE_RESOURCE_DIRECORY_ENTRY
DWORD Name //最高位为1,低地址指向Unicode字符串
//最高位为0,低地址为编号
DWORD OffsetToData //最高位为0,低地址指向描述资源数据的结构
//最高位为1,低地址指向下一级目录块的起始地址
一级子目录同上
二级子目录同上
三级子目录同上
文件信息
一个IMAGE_RESOURCE_DATA_ENTRY
OffsetToData //RVA,指向资源块(还需解析)
Size //大小
CoadPage //代码页,0
Reserved //保留,0
8
延迟加载导入表
延迟实现导入表的功能
应用
提高应用程序加载速度
需要某个DLL才把它加载到内存中,提高初始加载速度
提高应用程序兼容性
某个DLL太久了无法使用,系统会报错。如果它是延迟加载,程序员就可以手动处理
当然,这需要一定的预先准备
提高应用程序可整合性
把软件用的资源和配置什么的都放在一起
定位
第14个目录项
.rdata
IMAGE_DELAY_IMPORT_DESCRIPTOR
DWORD Attributes //0
DWORD Name //RVA,指向DLL名称
DWORD ModuleHandle //RVA,指向DLL句柄
DWORD DelayIAT //RVA,指向延迟加载导入函数地址表
DWORD DelayINT //RVA,指向延迟加载导入函数名称表
DWORD BoundDelayIT //RVA,指向绑定延迟加载导入函数地址表
DWORD UnloadDelayIT //RVA,指向卸载延迟加载导入函数地址表
DWORD TimeStamp //略
延迟加载导入机制
将一个函数_delayLoadHelper嵌入PE文件的可执行模块
从导入表中删除某个DLL的信息
在PE中重构信息,运行_delayLoadHelper,直到DLL被调用