好友
阅读权限10
听众
最后登录1970-1-1
|
肆零柒柒
发表于 2019-12-5 21:51
本帖最后由 肆零柒柒 于 2019-12-6 15:28 编辑
此为准备写壳时遇到的一个问题“怎么构建壳的导入表”,
然后查漏补缺,发现关于程序加载时的过程中导出表与导入表动作不太了解,于是便补充了一下,
在此留下记录,希望能为各位有所帮助。
以下字段皆为RVA ,需转化为VA 后方可获取正确内容...
加载过程中遍历程序导入表结构
通过导入表结构 IMAGE_IMPORT_DESCRIPTOR的Name(+0x0C)字段获取DLL名称字符串,然后加载Dll获取模块基址。
然后查通过对结构体IMAGE_THUNK_DATA32 解析,查看什么导入方式
如果是序号导入:
用此序号减去DLL导出表结构IMAGE_EXPORT_DIRECTORY的Base(+0x0C)字段的序号基数,获取地址表的索引,再用此索引在DLL导出表AddressOfFunction(+0x1C)字段中获取EAT数组中的对应函数地址,然后填充程序的IAT表
如果是名称导入:
遍历DLL导出表中AddressOfName字段所指向的名称数组 与 程序导入表中获取的函数名称字符串相比较 ,找到后记住DLL导出名称表(ENT)对应的索引值 然后在DLL导出序号表(EOT)中对应索引中获取正确数组项的值,在以此值索引地址表(不用和Base做运算) 获取正确函数地址填充程序IAT
运行中调用函数:
对于调用库函数,程序会遍历导入表(猜测是通过比较函数名字符串确定的),然后将导入表地址填充到对应的地址上
file:///C:/Users/三生/Documents/My%20Knowledge/temp/1bbeb16e-0c4a-479d-8f56-2079496e3c01/128/index_files/72179b1f-a169-42ab-8791-afeea55b8f87.png
从上图可以验证
而我们自己所书写的函数则是通过偏移来找到的,在程序编译时便写死的
计算方式:
偏移 = 要跳转的地址 - 当前地址 - 5(减5是因为当前E8这条指令长度为5)
file:///C:/Users/三生/Documents/My%20Knowledge/temp/1bbeb16e-0c4a-479d-8f56-2079496e3c01/128/index_files/f4fd381b-47e7-4daa-aa63-bf20a55323ac.png
如此图 调用我们自己所书写的函数(通过E8调用)
我们试着计算下以验证
0x004126d4 - 0x0040104F - 5 = 0x0011680
小端排序一下 80 16 11 00
就和上图偏移一模一样了
以上!
首次发帖,排版和叙述都有诸多不足,希望各位老板谅解。
如果对于内容有错误和不足希望大家能多多指教。 |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|