我的英文名是 the king of demo,请叫我DEMO之王,谢谢
注入任意so动态链接库到指定pid进程,用法
so_injector xxxxx.so target_pid
get_module_base
ptrace_writedata
这几个函数是直接copy的
http://bbs.pediy.com/showthread.php?t=141355
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdint.h>
void* get_module_base(pid_t pid, const char* module_name)
{
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
if (pid < 0) {
/* self process */
snprintf(filename, sizeof(filename), "/proc/self/maps");
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
if (fp == NULL)
return NULL;
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, module_name)) {
pch = strtok( line, "-");
addr = strtoul(pch, NULL, 16);
if (addr == 0x8000)
addr = 0;
break;
}
}
fclose(fp);
return (void *)addr;
}
int ptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data, size_t size)
{
uint32_t i, j, remain;
uint8_t *laddr;
union u {
long val;
char chars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = data;
for (i = 0; i < j; i++) {
memcpy(d.chars, laddr, 4);
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
dest += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace( PTRACE_PEEKTEXT, pid, dest, 0 );
for (i = 0; i < remain; i++) {
d.chars[i] = *laddr++;
}
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
}
return 0;
}
//libc -> __libc_dlopen_mode
//libdl -> dlopen
void * __libc_dlopen_mode (const char *name, int mode);
#if __WORDSIZE == 64
#define REGS_IP(r) r.regs.rip
#define REGS_SP(r) r.regs.rsp
#define REGS_AX(r) r.regs.rax
#else
#define REGS_IP(r) r.regs.eip
#define REGS_SP(r) r.regs.esp
#define REGS_AX(r) r.regs.eax
#endif
int main(int argc, char** argv)
{
pid_t pid = 0;
int status = 0;
struct user oregs, iregs;
uintptr_t p, dlopen_addr;
uint8_t *sp;
if (argc < 3) {
printf("usage:so_injector so_path target_pid\n");
return -1;
}
pid = atoi(argv[2]);
dlopen_addr = (uintptr_t)dlsym(NULL, "dlopen") +
((uintptr_t)get_module_base(pid, "libdl") -
(uintptr_t)get_module_base(-1, "libdl"));
printf("dlopen_addr:%p\n", (void*)dlopen_addr);
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
return -1;
waitpid(-1, &status, 0);
ptrace(PTRACE_GETREGS, pid, NULL, &oregs);
iregs = oregs;
/*
* write args to stacks
* lib_name_string
* arg2 mode
* arg1 pLibName
* ret_addr <- SP
*/
REGS_SP(iregs) = REGS_SP(iregs) - 0x200;
sp = (uint8_t *)REGS_SP(iregs);
p = 0;
ptrace_writedata(pid, sp, (uint8_t*)&p, sizeof(p));
p = (uintptr_t)sp + 3*sizeof(size_t);
ptrace_writedata(pid, sp + sizeof(size_t), (uint8_t*)&p, sizeof(p));
p = RTLD_LAZY | RTLD_GLOBAL;
ptrace_writedata(pid, sp + 2*sizeof(size_t), (uint8_t*)&p, sizeof(p));
ptrace_writedata(pid, sp + 3*sizeof(size_t), (uint8_t*)argv[1], strlen(argv[1]) + 1);
#if __WORDSIZE == 64
iregs.regs.rdi = (uintptr_t)sp + 3*sizeof(size_t); //arg1
iregs.regs.rsi = RTLD_LAZY | RTLD_GLOBAL; //arg2
#endif
REGS_IP(iregs) = dlopen_addr;
REGS_AX(iregs) = 0;
//ptrace continue
ptrace(PTRACE_SETREGS, pid, NULL, &iregs);
ptrace(PTRACE_CONT, pid, NULL, NULL);
waitpid(pid, &status, 0);
ptrace(PTRACE_GETREGS, pid, NULL, &iregs);
printf("call dlopen_addr:%p ret %p %p %x\n",
(void*)dlopen_addr,
(void*)REGS_AX(iregs),
(void*)REGS_IP(iregs),
status
);
//restore context and exit
ptrace(PTRACE_SETREGS, pid, NULL, &oregs);
ptrace(PTRACE_CONT, pid, NULL, NULL);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
test.so是一个测试so,加载后就会在tmp目录下输出一个日志,ubuntu10.4 x64测试ok
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)