├── ELFARM32_lod.py ├── README.md ├── driver test └── jni │ ├── Android.mk │ ├── Application.mk │ ├── bin_wrapper.c │ ├── dump_host.c │ ├── dump_test.c │ └── ptrace_trace.c └── driver ├── Makefile └── REHelper.c /ELFARM32_lod.py: -------------------------------------------------------------------------------- 1 | # For protected ELF32 file 2 | # Author: ThomasKing 3 | # Date: 2015.01.02 4 | 5 | import struct 6 | import sys 7 | import os 8 | 9 | ELF_MAGIC = '\x7f\x45\x4c\x46' 10 | DT_STRTAB = 5 11 | DT_STRSZ = 10 12 | DT_SYMTAB = 6 13 | DT_REL = 17 14 | DT_RELSZ = 18 15 | DT_JMPREL = 23 16 | DT_PLTRELSZ = 2 17 | DT_HASH = 4 18 | DT_INIT_ARRAY = 25 19 | DT_INIT_ARRAYSZ = 27 20 | DT_FINI_ARRAY = 26 21 | DT_FINI_ARRAYSZ = 28 22 | DT_PREINIT_ARRAY = 32 23 | DT_PREINIT_ARRAYSZ = 33 24 | 25 | try: 26 | from awesome_print import ap as pp 27 | except: 28 | from pprint import pprint as pp 29 | 30 | try: 31 | from idaapi import * 32 | from idautils import * 33 | from idc import * 34 | IN_IDA = True 35 | except: 36 | print "Not running in IDA?" 37 | IN_IDA = False 38 | 39 | def SearchGotEnd(data, start, end, rels): 40 | for i in range(end, start, -1): 41 | num = struct.unpack('> 8 240 | [st_name, st_value] = struct.unpack(' 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define LEAK_DEV "REHelper" 25 | #define CMD_BASE 0xC0000000 26 | #define DUMP_MEM (CMD_BASE + 1) 27 | #define SET_PID (CMD_BASE + 2) 28 | #define MODIFY_M (CMD_BASE + 3) 29 | 30 | 31 | void set_target(pid_t pid){ 32 | int fd = open("/dev/REHelper", O_RDWR); 33 | if(fd == -1){ 34 | printf("[*] open error, check USER!"); 35 | return ; 36 | } 37 | ioctl(fd, SET_PID, pid); 38 | close(fd); 39 | } 40 | 41 | static ssize_t mem_rw(struct mm_struct *mm, char __user *buf, 42 | size_t count, unsigned long addr, int write) 43 | { 44 | ssize_t copied; 45 | char *page; 46 | 47 | if (!mm) 48 | return 0; 49 | 50 | page = (char *)__get_free_page(GFP_TEMPORARY); 51 | if (!page) 52 | return -ENOMEM; 53 | 54 | copied = 0; 55 | if (!atomic_inc_not_zero(&mm->mm_users)) 56 | goto free; 57 | 58 | while (count > 0) { 59 | int this_len = min_t(int, count, PAGE_SIZE); 60 | 61 | if (write && copy_from_user(page, buf, this_len)) { 62 | copied = -EFAULT; 63 | break; 64 | } 65 | 66 | this_len = access_remote_vm(mm, addr, page, this_len, write); 67 | if (!this_len) { 68 | if (!copied) 69 | copied = -EIO; 70 | break; 71 | } 72 | 73 | if (!write && copy_to_user(buf, page, this_len)) { 74 | copied = -EFAULT; 75 | break; 76 | } 77 | 78 | buf += this_len; 79 | addr += this_len; 80 | copied += this_len; 81 | count -= this_len; 82 | } 83 | 84 | mmput(mm); 85 | free: 86 | free_page((unsigned long) page); 87 | return copied; 88 | } 89 | 90 | int main(int argc, char const *argv[]){ 91 | int *flag = (int*)mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 92 | 93 | if(flag == (int*)-1){ 94 | perror("mmap error"); 95 | return -1; 96 | } 97 | *flag = 0; 98 | pid_t pid = fork(); 99 | if(pid < 0){ 100 | perror("fork error"); 101 | return -1; 102 | } 103 | if(pid == 0){ 104 | while(!*flag){ 105 | sleep(1); 106 | } 107 | char *cmd[] = {"/data/local/tmp/ptrace_trace", NULL}; 108 | execve(cmd[0], &cmd[0], NULL); 109 | exit(0); 110 | } 111 | set_target(pid); 112 | *flag = 1; 113 | waitpid(pid, 0, 0); 114 | munmap(flag, 0x1000); 115 | 116 | return 0; 117 | } -------------------------------------------------------------------------------- /driver test/jni/dump_host.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Author: ThomasKing 3 | ** Date: 2015/02/23 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define CMD_BASE 0xC0000000 25 | #define DUMP_MEM (CMD_BASE + 1) 26 | #define SET_PID (CMD_BASE + 2) 27 | 28 | struct dump_request{ 29 | pid_t pid; 30 | unsigned long addr; 31 | ssize_t count; 32 | char *buf; 33 | }; 34 | 35 | char buf[4096]; 36 | 37 | int main(int argc, char const *argv[]){ 38 | struct dump_request request; 39 | if(argc < 2){ 40 | printf("Input target pid\n"); 41 | return -1; 42 | } 43 | request.pid = atoi(argv[1]); 44 | request.addr = 0x40000000; 45 | request.buf = buf; 46 | request.count = 1000; 47 | 48 | int fd = open("/dev/REHelper", O_RDWR); 49 | if(fd == -1){ 50 | printf("[*] open error, check USER!"); 51 | return -1; 52 | } 53 | ioctl(fd, DUMP_MEM, &request); 54 | close(fd); 55 | 56 | if(buf[0] == 0xcc){ 57 | printf("Dump ok\n"); 58 | } 59 | printf("Done !\n"); 60 | return 0; 61 | } -------------------------------------------------------------------------------- /driver test/jni/dump_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Author: ThomasKing 3 | ** Date: 2015/02/23 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | int main(int argc, char const *argv[]){ 25 | printf("dump_test pid[%d]\n", getpid()); 26 | void *base = mmap((void*)0x40000000, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 27 | if(base == (void*)-1){ 28 | printf("mmap error\n"); 29 | return -1; 30 | } 31 | memset(base, 0xcc, 0x1000); 32 | getchar(); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /driver test/jni/ptrace_trace.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Author: ThomasKing 3 | ** Date: 2015/02/25 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | int check_status(){ 28 | int debugged = 0; 29 | int fp = fopen("/proc/self/status", "r"); 30 | if(fp){ 31 | // ... 32 | fclose(fp); 33 | } 34 | return debugged; 35 | } 36 | 37 | int add_notity(){ 38 | int fd_notity = inotify_init(); 39 | if(fd_notity > 0){ 40 | inotify_add_watch(fd_notity, "/proc/self/mem", IN_OPEN | IN_ACCESS | IN_MODIFY); 41 | //... 42 | } 43 | return 0; 44 | } 45 | 46 | int main(int argc, char **argv){ 47 | struct pt_regs regs; 48 | memset(®s, 0, sizeof(struct pt_regs)); 49 | 50 | check_status(); 51 | add_notity(); 52 | 53 | pid_t pid = fork(); 54 | if(pid == 0){ 55 | void *base = mmap((void*)0x40000000, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); 56 | if(base == (void*)-1){ 57 | perror("mmap"); 58 | } 59 | memset(base, 0xaa, 0x1000); 60 | *(unsigned long*)(base + 4) = 0xbbbbbbbb; 61 | if(ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0){ 62 | perror("ptrace_traceme"); 63 | } 64 | kill(getpid(), 19); 65 | exit(0); 66 | }else if(pid > 0){ 67 | sleep(1); 68 | printf("pid: %d, child_pid: %d\n", getpid(), pid); 69 | 70 | if(ptrace(PTRACE_SYSCALL, pid, NULL, 0) < 0 ){ 71 | perror( "ptrace_syscall" ); 72 | return -1; 73 | } 74 | waitpid(pid, NULL, WUNTRACED ); 75 | 76 | if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL ) < 0) { 77 | perror("ptrace_syscall"); 78 | return -1; 79 | } 80 | waitpid(pid, NULL, WUNTRACED); 81 | 82 | unsigned long data = ptrace(PTRACE_PEEKDATA, pid, 0x40000000, 0); 83 | printf("data: 0x%lx\n", data); 84 | if(data != 0xaaaaaaaa){ 85 | printf("modify from kernel, data: %lx\n", data); 86 | } 87 | kill(pid, 9); 88 | waitpid(pid, NULL, 0); 89 | }else{ 90 | printf("fork error\n"); 91 | } 92 | return 0; 93 | } -------------------------------------------------------------------------------- /driver/Makefile: -------------------------------------------------------------------------------- 1 | WORKDIR := /media/psf/kernel_source 2 | KERNELDIR := $(WORKDIR)/msm 3 | PWD := $(shell pwd) 4 | ARCH=arm 5 | CROSS_COMPILE=$(WORKDIR)/toolchains/arm-eabi-4.8/bin/arm-eabi- 6 | CC=$(CROSS_COMPILE)gcc 7 | LD=$(CROSS_COMPILE)ld 8 | obj-m := REHelper.o 9 | modules: 10 | $(MAKE) -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules 11 | clean: 12 | rm *.o *.ko *.mod.c *.order -------------------------------------------------------------------------------- /driver/REHelper.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Author: ThomasKing 3 | ** Date: 2015/02/23 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define RE_DEV "REHelper" 19 | #define CMD_BASE 0xC0000000 20 | #define DUMP_MEM (CMD_BASE + 1) 21 | #define SET_PID (CMD_BASE + 2) 22 | #define MODIFY_M (CMD_BASE + 3) 23 | 24 | static int (*access_remote_vm)(struct mm_struct *, unsigned long, void *, int, int); 25 | 26 | struct dump_request{ 27 | pid_t pid; 28 | unsigned long addr; 29 | ssize_t count; 30 | char __user *buf; 31 | }; 32 | 33 | pid_t monitor_pid = -1; 34 | 35 | asmlinkage int jsys_open(const char *pathname, int flags, mode_t mode){ 36 | pid_t current_pid = current_thread_info()->task->tgid; 37 | 38 | if(!monitor_pid || (current_pid == monitor_pid)){ 39 | printk(KERN_INFO "[open] pathname %s, flags: %x, mode: %x\n", 40 | pathname, flags, mode); 41 | } 42 | 43 | jprobe_return(); 44 | return 0; 45 | } 46 | 47 | asmlinkage int jsys_openat(int dirfd, const char *pathname, int flags, mode_t mode){ 48 | pid_t current_pid = current_thread_info()->task->tgid; 49 | 50 | if(!monitor_pid || (current_pid == monitor_pid)){ 51 | printk(KERN_INFO "[openat] dirfd: %d, pathname %s, flags: %x, mode: %x\n", 52 | dirfd, pathname, flags, mode); 53 | } 54 | 55 | jprobe_return(); 56 | return 0; 57 | } 58 | 59 | asmlinkage long jsys_ptrace(long request, long pid, unsigned long addr, 60 | unsigned long data){ 61 | pid_t current_pid = current_thread_info()->task->tgid; 62 | 63 | if(!monitor_pid || (current_pid == monitor_pid)){ 64 | switch(request){ 65 | case PTRACE_TRACEME: { 66 | printk(KERN_INFO "PTRACE_TRACEME: [src]pid = %d\n", current_pid); 67 | }break; 68 | case PTRACE_PEEKDATA: { 69 | printk(KERN_INFO "PTRACE_PEEKDATA: [src]pid = %d --> [dst]pid = %d, addr: %lx, data: %lx\n", 70 | current_pid, pid, addr, data); 71 | }break; 72 | 73 | default:{ 74 | 75 | }break; 76 | } 77 | } 78 | 79 | jprobe_return(); 80 | return 0; 81 | } 82 | 83 | asmlinkage int jinotify_add_watch(int fd, const char *pathname, uint32_t mask){ 84 | pid_t current_pid = current_thread_info()->task->tgid; 85 | 86 | if(!monitor_pid || (current_pid == monitor_pid)){ 87 | printk(KERN_INFO "[inotify_add_watch]: fd: %d, pathname: %s, mask: %x", 88 | fd, pathname, mask); 89 | } 90 | 91 | jprobe_return(); 92 | return 0; 93 | } 94 | 95 | static struct jprobe ptrace_probe = { 96 | .entry = jsys_ptrace, 97 | .kp = { 98 | .symbol_name = "sys_ptrace", 99 | }, 100 | }; 101 | 102 | static struct jprobe open_probe = { 103 | .entry = jsys_open, 104 | .kp = { 105 | .symbol_name = "sys_open", 106 | }, 107 | }; 108 | 109 | static struct jprobe openat_probe = { 110 | .entry = jsys_openat, 111 | .kp = { 112 | .symbol_name = "sys_openat", 113 | }, 114 | }; 115 | 116 | static struct jprobe inotify_add_watch_probe = { 117 | .entry = jinotify_add_watch, 118 | .kp = { 119 | .symbol_name = "sys_inotify_add_watch", 120 | }, 121 | }; 122 | 123 | static struct jprobe *my_jprobe[] = { 124 | &open_probe, 125 | &openat_probe, 126 | &ptrace_probe, 127 | &inotify_add_watch_probe 128 | }; 129 | 130 | static ssize_t mem_rw(struct mm_struct *mm, char __user *buf, 131 | size_t count, unsigned long addr, int write) 132 | { 133 | ssize_t copied; 134 | char *page; 135 | 136 | if (!mm) 137 | return 0; 138 | 139 | page = (char *)__get_free_page(GFP_TEMPORARY); 140 | if (!page) 141 | return -ENOMEM; 142 | 143 | copied = 0; 144 | if (!atomic_inc_not_zero(&mm->mm_users)) 145 | goto free; 146 | 147 | while (count > 0) { 148 | int this_len = min_t(int, count, PAGE_SIZE); 149 | 150 | if (write && copy_from_user(page, buf, this_len)) { 151 | copied = -EFAULT; 152 | break; 153 | } 154 | 155 | this_len = access_remote_vm(mm, addr, page, this_len, write); 156 | if (!this_len) { 157 | if (!copied) 158 | copied = -EIO; 159 | break; 160 | } 161 | 162 | if (!write && copy_to_user(buf, page, this_len)) { 163 | copied = -EFAULT; 164 | break; 165 | } 166 | 167 | buf += this_len; 168 | addr += this_len; 169 | copied += this_len; 170 | count -= this_len; 171 | } 172 | 173 | mmput(mm); 174 | free: 175 | free_page((unsigned long) page); 176 | return copied; 177 | } 178 | 179 | static ssize_t mem_read(struct mm_struct *mm, char __user *buf, 180 | size_t count, unsigned long addr) 181 | { 182 | return mem_rw(mm, buf, count, addr, 0); 183 | } 184 | 185 | static ssize_t mem_write(struct mm_struct *mm, char __user *buf, 186 | size_t count, unsigned long addr) 187 | { 188 | return mem_rw(mm, (char __user*)buf, count, addr, 1); 189 | } 190 | 191 | static int REHelper_open(struct inode *inode, struct file *file) 192 | { 193 | printk(KERN_INFO "REHelper device open success!\n"); 194 | return 0; 195 | } 196 | 197 | static long REHelper_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ 198 | long ret = 0; 199 | void __user *argp = (void __user *)arg; 200 | struct task_struct *target_task; 201 | struct dump_request *request = (struct dump_request *)argp; 202 | 203 | switch(cmd){ 204 | case DUMP_MEM: 205 | target_task = find_task_by_vpid(request->pid); 206 | if(!target_task){ 207 | printk(KERN_INFO "find_task_by_vpid(%d) failed\n", request->pid); 208 | ret = -ESRCH; 209 | return ret; 210 | } 211 | request->count = mem_read(target_task->mm, request->buf, request->count, request->addr); 212 | break; 213 | case SET_PID: 214 | monitor_pid = (pid_t) arg; 215 | printk(KERN_INFO "Set monitor pid: %d\n", monitor_pid); 216 | break; 217 | case MODIFY_M: 218 | 219 | break; 220 | default: 221 | ret = -EFAULT; 222 | } 223 | return ret; 224 | } 225 | 226 | static struct file_operations REHelper_fops = { 227 | .owner = THIS_MODULE, 228 | .unlocked_ioctl = REHelper_unlocked_ioctl, 229 | .open = REHelper_open 230 | }; 231 | 232 | static int major = 0; 233 | 234 | struct cdev REHelper_cdev; 235 | 236 | static struct class *REHelper_cls; 237 | 238 | static int REHelper_init(void){ 239 | dev_t dev_id; 240 | int ret = 0; 241 | 242 | if(major){ 243 | dev_id = MKDEV(major, 0); 244 | register_chrdev_region(dev_id, 1, RE_DEV); 245 | } else { 246 | alloc_chrdev_region(&dev_id, 0, 1, RE_DEV); 247 | major = MAJOR(dev_id); 248 | } 249 | cdev_init(&REHelper_cdev, &REHelper_fops); 250 | cdev_add(&REHelper_cdev, dev_id, 1); 251 | REHelper_cls = class_create(THIS_MODULE, RE_DEV); 252 | device_create(REHelper_cls, NULL, dev_id, NULL, RE_DEV); 253 | 254 | access_remote_vm = (int (*)(struct mm_struct *, unsigned long, void *, int, int))kallsyms_lookup_name("access_remote_vm"); 255 | if(!access_remote_vm){ 256 | printk(KERN_INFO "Cannot find access_remote_vm [%p]", access_remote_vm); 257 | return -1; 258 | } 259 | printk(KERN_INFO "Find access_remote_vm [%p]", access_remote_vm); 260 | 261 | ret = register_jprobes(&my_jprobe, sizeof(my_jprobe) / sizeof(my_jprobe[0])); 262 | if (ret < 0) { 263 | printk(KERN_INFO "register_jprobe failed, returned %d\n", ret); 264 | return -1; 265 | } 266 | 267 | return 0; 268 | } 269 | 270 | static void REHelper_exit(void){ 271 | device_destroy(REHelper_cls, MKDEV(major, 0)); 272 | class_destroy(REHelper_cls); 273 | cdev_del(&REHelper_cdev); 274 | unregister_chrdev_region(MKDEV(major, 0), 1); 275 | 276 | unregister_jprobes(&my_jprobe, sizeof(my_jprobe) / sizeof(my_jprobe[0])); 277 | } 278 | 279 | module_init(REHelper_init); 280 | module_exit(REHelper_exit); 281 | MODULE_LICENSE("GPL"); 282 | MODULE_AUTHOR("ThomasKing"); --------------------------------------------------------------------------------