随笔-150  评论-223  文章-30  trackbacks-0
Linux共享库库函数挂钩主流两种方法。一是替换函数对应的GOT/PLT条目,GOT/PLT原理类似Windows的IAT;二是inline挂钩,即替换函数序言的几个字节(x86是5或7字节)为jmp/call,若发现稍远处有jmp或call(前提在入口基本块内,若不在入口基本块内要修改分支控制条件,这有点复杂也无必要),则其目标地址可被替换,这样就不用替换序言的几字节了。Windows的IAT挂钩检测很方便,因为dll的baseaddr及size可通过API VirtualQueryEx(https://learn.microsoft.com/zh-cn/windows/win32/api/memoryapi/nf-memoryapi-virtualqueryex)或toolhelp库的Module32First/Module32Next(https://learn.microsoft.com/zh-cn/windows/win32/api/tlhelp32/nf-tlhelp32-module32first)接口来获取。同理linux也可以拿到有两种方法,一种是读/proc/pid/maps(这里pid为实际目标进程号)获取so库代码段的baseaddr和size,另一种用dl_iterate_phdr(https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html)拿到代码段(pt_load类型+可执行标志)的baseaddr及size。只要模块(代码段)的baseaddr及size确定了,检测方法同IAT,即看替换函数地址是否不在代码段空间内,若不在或地址不是原函数则认为被挂钩了,否则需进一步用针对inline挂钩法的检测处理,见下文描述。另外dladdr(https://man7.org/linux/man-pages/man3/dladdr.3.html)判断一个地址是否跟一个so库及符号相关,因此也可用于检测挂钩。如果是inline挂钩法,那么分析函数入口基本块内(不管替换序言几字节还是已有jmp/call目标地址,都在入口基本块)jmp/call的目标地址(最好用成熟的反汇编引擎分析,比如llvm的mc库反汇编功能,或https://salsa.debian.org/debian/distorm3),看是否超出so库的代码段空间
posted on 2023-09-26 16:47 春秋十二月 阅读(2086) 评论(0)  编辑 收藏 引用 所属分类: System

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理