#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <wait.h>
#include <sys/user.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <elf.h>
#include <link.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include "p_elf.h"
#include "p_dbg.h"
void call_dl_open(int pid, unsigned long addr, char *libname);
void call_dlopen(int pid, unsigned long addr, char *libname);
void usage(void);
const char *libc_path = "/lib/i386-linux-gnu/libc-2.19.so";
const char *linker_path = "/lib/i386-linux-gnu/ld-2.19.so";
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", pid);
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
if (fp != 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 find_pid_of(const char *process_name)
{
int id;
pid_t pid = -1;
DIR* dir;
FILE *fp;
char filename[32];
char cmdline[256];
struct dirent * entry;
if (process_name == NULL)
return -1;
dir = opendir("/proc");
if (dir == NULL)
return -1;
while((entry = readdir(dir)) != NULL) {
id = atoi(entry->d_name);
if (id != 0) {
sprintf(filename, "/proc/%d/cmdline", id);
fp = fopen(filename, "r");
if (fp) {
fgets(cmdline, sizeof(cmdline), fp);
fclose(fp);
if (strcmp(process_name, cmdline) == 0) {
/* process found */
pid = id;
break;
}
}
}
}
closedir(dir);
return pid;
}
int ptrace_getregs(pid_t pid, struct user_regs_struct * regs)
{
if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) {
perror("ptrace_getregs: Can not get register values");
return -1;
}
return 0;
}
int ptrace_setregs(pid_t pid, struct user_regs_struct * regs)
{
if (ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) {
perror("ptrace_setregs: Can not set register values");
return -1;
}
return 0;
}
int ptrace_readdata(pid_t pid, uint8_t *src, uint8_t *buf, 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 = buf;
for (i = 0; i < j; i ++) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, 4);
src += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, remain);
}
return 0;
}
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;
}
int ptrace_continue(pid_t pid)
{
if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0) {
perror("ptrace_cont");
return -1;
}
return 0;
}
long ptrace_call_ext(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct user_regs_struct * regs)
{
regs->esp -= (num_params) * sizeof(long) ;
ptrace_writedata(pid, (void *)regs->esp, (uint8_t *)params, (num_params) * sizeof(long));
long tmp_addr = 0x00;
regs->esp -= sizeof(long);
ptrace_writedata(pid, regs->esp, (char *)&tmp_addr, sizeof(tmp_addr));
regs->eip = addr;
if (ptrace_setregs(pid, regs) == -1
|| ptrace_continue( pid) == -1) {
printf("error\n");
return -1;
}
int stat = 0;
//printf("start waiting\n");
waitpid(pid, &stat, WUNTRACED);
//printf("finished\n");
return 0;
}
int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct user_regs_struct * regs)
{
printf("[+] Calling %s in target process.\n", func_name);
if (ptrace_call_ext(target_pid, (uint32_t)func_addr, parameters, param_num, regs) == -1)
return -1;
if (ptrace_getregs(target_pid, regs) == -1)
return -1;
//printf("[+] Target process returned from %s, return value=%x, pc=%x \n", func_name, ptrace_retval(regs), ptrace_ip(regs));
return 0;
}
long ptrace_retval(struct user_regs_struct * regs)
{
return regs->eax;
}
void call_dlopen(int target_pid, unsigned long dlopen_addr, char *library_path)
{
void *mmap_addr;
struct user_regs_struct regs;
struct user_regs_struct original_regs;
long parameters[10];
uint8_t *map_base = 0;
if (ptrace_getregs(target_pid, ®s) == -1)
goto exit;
memcpy(&original_regs, ®s, sizeof(regs));
mmap_addr = enumprocesssym(target_pid, "libc", "mmap");
parameters[0] = 0; // addr
parameters[1] = 0x4000; // size
parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot
parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags
parameters[4] = 0; //fd
parameters[5] = 0; //offset
if (ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, ®s) == -1)
goto exit;
map_base = ptrace_retval(®s);
printf("\n--------mapbase=%x--------\n",map_base);
if(map_base==0){
goto exit;
}
ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1);
parameters[0] = map_base;
parameters[1] = RTLD_NOW| RTLD_GLOBAL;
if (ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, ®s) == -1)
goto exit;
void * sohandle = ptrace_retval(®s);
printf("sohandle = %x\n", sohandle);
exit:
ptrace_setregs(target_pid, &original_regs);
}
#define PRINT(a,ehdr) printf(#a"=%x\n",ehdr->a);
#define PRINTA4(a,ehdr) printf(#a"=%2.2x %c%c%c\n",ehdr->a[0],ehdr->a[1],ehdr->a[2],ehdr->a[3]);
void printehdr(Elf32_Ehdr *ehdr)
{
puts("------------printehdr---------------");
PRINTA4(e_ident,ehdr)
PRINT(e_type,ehdr)
PRINT(e_machine,ehdr)
PRINT(e_version,ehdr)
PRINT(e_entry,ehdr)
PRINT(e_phoff,ehdr)
PRINT(e_shoff,ehdr)
PRINT(e_flags,ehdr)
PRINT(e_ehsize,ehdr)
PRINT(e_phentsize,ehdr)
PRINT(e_phnum,ehdr)
PRINT(e_shentsize,ehdr)
PRINT(e_shnum,ehdr)
PRINT(e_shstrndx,ehdr)
printf("ehsize=%x phsize=%x shsize=%x\n",sizeof(Elf32_Ehdr),sizeof(Elf32_Phdr),sizeof(Elf32_Shdr));
}
#define PRINTSWITCH(a,type) if(a==type){puts(#a);return;}
void printptype(int type)
{
PRINTSWITCH(PT_NULL,type)
PRINTSWITCH(PT_LOAD,type)
PRINTSWITCH(PT_DYNAMIC,type)
PRINTSWITCH(PT_INTERP,type)
PRINTSWITCH(PT_NOTE,type)
PRINTSWITCH(PT_SHLIB,type)
PRINTSWITCH(PT_PHDR,type)
PRINTSWITCH(PT_TLS,type)
PRINTSWITCH(PT_NUM,type)
PRINTSWITCH(PT_LOOS,type)
PRINTSWITCH(PT_GNU_EH_FRAME,type)
PRINTSWITCH(PT_GNU_STACK,type)
PRINTSWITCH(PT_GNU_RELRO,type)
PRINTSWITCH(PT_LOSUNW,type)
PRINTSWITCH(PT_SUNWBSS,type)
PRINTSWITCH(PT_SUNWSTACK,type)
PRINTSWITCH(PT_HISUNW,type)
PRINTSWITCH(PT_HIOS,type)
PRINTSWITCH(PT_LOPROC,type)
PRINTSWITCH(PT_HIPROC,typ