由于工作上的需要,之前只是对大概的原理了解,现对此进行详细的分析。
涉及到的关键API以及数据结构:
1. ptrace
PTRACE_ATTACH:挂载到指定的pid进程上,该参数会先发送SIGSTOP信号
PTRACE_GETREGSET:读取目标进程的寄存器,这里注意获取寄存器的结构体类型
PTRACE_POKETEXT:复制一个word的数据
PTRACE_PEEKTEXT:复制一个word的数据
PTRACE_SETREGSET:设置寄存器
PTRACE_CONT:指定pid进程继续执行,此处有坑->只有当进程处于STOP状态时,才能发送SIGCONT信号,否则可能失败
PTRACE_SETOPTIONS:
2. waitpid
WUNTRACED:当指定pid进程暂停后,返回
3. struct iovec
向量元素,主要提供给readv和writev系统调用进行使用
4. mmap
将用户空间一段内存区域映射到内核空间。好处,用户空间的修改直接映射到内核空间,内核空间的修改也直接映射到用户空间。
MAP_ANONYMOUS:不需要传递fd
MAP_PRIVATE:映射一段私有地址空间
PROT_READ | PROT_WRITE | PROT_EXEC:内存地址空间的属性,读/写/可执行
5. __libc_dlopen_mode
RTLD_NOW|RTLD_GLOBAL:
6. __libc_dlsym
1. 主要用来获取动态库中的指定符号的地址、
2. 想要获取主程序(非so)中的符号地址,程序在编译时需要使用-rdynamic选项
7. __libc_dlclose
8. /proc/pid/maps
查看每一个so的内存加载地址
9. 设置关键寄存器
sp:堆栈寄存器
pc:程序执行寄存器
cpsr:状态寄存器
lr:函数返回地址
r0:存储函数返回值寄存器
10. dlopen加载so之后,so在内存中的布局
11. __sync_fetch_and_add 系列命令
12. elf关键数据结构
#define EI_NIDENT (16)
typedef struct //elf文件头
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version