网上说的PE文件输入表原理太绕:
归纳下:硬盘上PE文件的Characteristics和FirstThunk指向2个IMAGE_THUNK_DATA结构, 当加载到内存后, PE装载器通过 OriginalFirstThunk找到IMAGE_THUNK_DATA再找到IMAGE_IMPORT_BY_NAME,
根据shell32dll.shellaboutA信息, 计算出函数的真实地址, 把真实地址填写到FirstThunk->IMAGE_THUNK_DATA中。
PS:
函数的真实地址 =dll加载基地址+函数RAV. 这个地址是PE加载器算出来的, PE文件不保存函数的RAV.
EXE程序加载后, FirstThunk指向的为函数的真实地址。
APIHOOK替换地址就是 *FirstThunk, CALL DWORD ptr[FirstThunk]
IMAGE_IMPORT_DESCRIPTOR STRUCT 20个字节 union Characteristics DWORD ? //固定的IMAGE_THUNK_DATA结构的地址 OriginalFirstThunk DWORD ? ends TimeDateStamp DWORD ? ForwarderChain DWORD ? Name DWORD ? FirstThunk DWORD ? //会被PE加载器重写的MAGE_THUNK_DATA地址,PE装载器加载exe后, 把这个IMAGE_THUNK_DATA改写dll里 函数的真实地址
IMAGE_IMPORT_DESCRIPTOR ENDS
IMAGE_THUNK_DATA STRUC 4个字节
union u1 ForwarderString DWORD ? ; 指向一个转向者字符串的RVA Function DWORD ? ; 被输入的函数的内存地址 Ordinal DWORD ? ; 被输入的API 的序数值 AddressOfData DWORD ? ; 指向 IMAGE_IMPORT_BY_NAME ends IMAGE_THUNK_DATA ENDS
IMAGE_IMPORT_BY_NAME STRUCT
Hint WORD ? //函数序号 Name BYTE ? //动态库名称和 函数名称的指针 比如shell32dll.shellaboutA, PE装载器就是根据这个来计算出真实函数地址的 IMAGE_IMPORT_BY_NAME ENDS
/*-----------------------------------------------PE输入表已经长话短说完毕--------------------------------------------------------------------*/
如何给系统的程序打个补丁,让它在退出的时候启动我们的程序了。
这拿XP系统的calc.exe 程序开刀。
想要calc.exe能启动自己的程序 必须要有能利用的导入函数, 比如shell32.dll!ShellExecuteA
用LordPE工具查看发现calc.exe没有导入表函数shell32.dll!ShellExecuteA
如上图, 这里没有shell32.dll!ShellExecuteA 只有ShellAboutW
因为ShellExecuteA比ShellAboutW字节数不一样, 不能直接改名, 所以添加一个区块,在新建区块的添加导入表函数shell32.dll!ShellExecuteA
如上图 .Silvana 这个区块就是新添加的, ShellExecuteA函数也添加进去了,这里用LordPE工具添加
用OD打开calc.exe, 在.data里面找空闲位置 填写字符串信息如图, 下图 在 10149e0 处添加
##################提示 如果出现内存不能写情况,检查下写是否在有效的区块内,如下图
找到calc.exe退出的位置,覆盖添加如下代码,如图(直接覆盖填写就行 ,不用把指令写到空白的地方,jmp跳指令,在跳回来)
如下图 在010125f3处写代码
push 5
push 0
push 10149e0
push 10149e8
push 10149f5
push 0
call DWORD ptr[ShellExecuteA]
push 0
call DWORD ptr[exit]
到这里已经全部完成! 不要做坏事喔!
CalcPro.exe 是要启动的程序 启动参数apprun,
系统的calc.exe 和 打好补丁的calc1.exe, CalcPro.exe