注入so,也就是让另一个正在运行的进程加载我们指定的so,之后我们的so里面的代码就可以自动运行,这个主要是用来进行API拦截的。windows下的API拦截非常方便,而linux下的就比较复杂。
如果去网上搜,基本上找到的是http://linux.chinaunix.net/techdoc/net/2007/04/06/954355.shtml,这个是2002年的,它的思路是使用ptrace,attach目标进程,然后搜索目标进程符号表,找到_dl_open的地址,保存寄存器,然后修改寄存器,设置_dl_open函数的参数,运行_dl_open函数。还有一种思路是在目标进程申请一块自由空间,当然这个也是要搜索符号表找到malloc等的地址,然后在申请到的空间写入shellcode。主意这里不要随意的将shellcode写入bss段等。关于shellcode的编写这个就涉及到汇编了。
可是随着linux内核版本的改变,一些函数或者实现机制变了,上文中提到的搜索_dl_open已经行不通了。我这几天找到了一个老外写的C库,叫hotpatch。地址https://github.com/vikasnkumar/hotpatch
关于ptrace
形式
#include <sys/ptrace.h>
int ptrace(int request, int pid, int addr, int data);
描述
Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心image。它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生一个信号。则进程被中止,并且通知其父进程。在进程中止的状态下,进程的内存空间可以被读写。父进程还可以使子进程继续执行,并选择是否是否忽略引起中止的信号。
Request参数决定了系统调用的功能:
PTRACE_TRACEME
本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
从内存地址中读取一个字节,内存地址由addr给出。
PTRACE_PEEKUSR
从USER区域中读取一个字节,偏移量为addr。
PTRACE_POKETEXT, PTRACE_POKEDATA
往内存地址中写入一个字节。内存地址由addr给出。
PTRACE_POKEUSR
往USER区域中写入一个字节。偏移量为addr。
PTRACE_SYSCALL, PTRACE_CONT
重新运行。
PTRACE_KILL
杀掉子进程ÿ