commit c9048bd2b40b7edd604c4b7ad18617e96a987975 Author: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Mon Apr 10 01:53:45 2017 +0300 Initial commit diff --git a/proc.c b/proc.c new file mode 100644 index 0000000..4411114 --- /dev/null +++ b/proc.c @@ -0,0 +1,89 @@ +#include "proc.h" + +int is_numeric(char* s) +{ + while(*s) + { + if(!isdigit(*s)) + return 0; + s++; + } + return 1; +} + +int walk_proc(walk_proc_callback func,void *data) +{ + struct dirent* dr; + DIR* d; + if(!(d = opendir("/proc"))) + return -1; + while((dr = readdir(d))) + { + if(dr->d_type == DT_DIR) + { + if(is_numeric(dr->d_name)) + { + if(func(atoi(dr->d_name),data)) + return 1; + } + } + } + closedir(d); + return 0; +} + +int walk_thread(pid_t pid,walk_thread_callback func,void *data) +{ + struct dirent* dr; + DIR* d; + char path[256]; + sprintf(path,"/proc/%d/task",pid); + if(!(d = opendir(path))) + return -1; + while((dr = readdir(d))) + { + if(dr->d_type == DT_DIR) + { + if(is_numeric(dr->d_name)==1) + { + if(func(atoi(dr->d_name),data)) + return 1; + } + } + } + closedir(d); + return 0; +} + +int suspend_proc_callback(pid_t tid,void *data) +{ + int status; + if(*(bool*)data == true) + { + ptrace(PTRACE_ATTACH,tid,0,0); + waitpid(tid,&status,0); + } + else + { + ptrace(PTRACE_DETACH,tid,0,0); + waitpid(tid,&status,0); + } + return 0; +} + +int suspend_proc(pid_t pid,bool suspend) +{ + return walk_thread(pid,&suspend_proc_callback,(void*)&suspend); +} + +int open_proc(pid_t pid) +{ + char path[256]; + sprintf(path,"/proc/%d/mem",pid); + return open(path,O_RDWR); +} + +void close_proc(int pd) +{ + close(pd); +} diff --git a/proc.h b/proc.h new file mode 100644 index 0000000..4f6359d --- /dev/null +++ b/proc.h @@ -0,0 +1,26 @@ +#ifndef __PROC_H +#define __PROC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef int (*walk_proc_callback)(int pid,void *data); +typedef int (*walk_thread_callback)(pid_t tid,void *data); + +int walk_proc(walk_proc_callback func,void *data); +int walk_thread(pid_t pid,walk_thread_callback func,void *data); + +int suspend_proc(pid_t pid,bool suspend); + +int open_proc(pid_t pid); +void close_proc(int pd); + +#endif diff --git a/sh2load b/sh2load new file mode 100644 index 0000000..5e611f8 Binary files /dev/null and b/sh2load differ diff --git a/sh2load.c b/sh2load.c new file mode 100644 index 0000000..b8b69f7 --- /dev/null +++ b/sh2load.c @@ -0,0 +1,162 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc.h" +#include "vmap.h" + +#ifdef __i386__ + +char shellcode[] = { + 0x6A,0x01,0xEB,0x07,0xFF,0xD3,0x83,0xC4, + 0x08,0x5B,0xC3,0xE8,0xF4,0xFF,0xFF,0xFF, + 0x90 +}; + +#define STR_OFFSET 0x10 +#define SHELL_SIZE 0x10 + +#elif __x86_64__ + +char shellcode[] = { + 0x48,0x31,0xF6,0xEB,0x08,0x5F,0x48,0xFF, + 0xC6,0xFF,0xD3,0x5B,0xC3,0xE8,0xF3,0xFF, + 0xFF,0xFF,0x90 +}; + +#define STR_OFFSET 0x12 +#define SHELL_SIZE 0x12 + +#endif + +void emu_push(pid_t pid,struct user_regs_struct *regs, + unsigned long value) +{ +#ifdef __i386__ + regs->esp -= sizeof(unsigned long); + if(ptrace(PTRACE_POKEDATA,pid,regs->esp,value) < 0) + perror("ptrace_pokedata"); +#elif __x86_64__ + regs->rsp -= sizeof(unsigned long); + if(ptrace(PTRACE_POKEDATA,pid,regs->rsp,value) < 0) + perror("ptrace_pokedata"); +#endif +} + +unsigned long getfuncaddr(const char* name) +{ + void* mod; + if(!(mod = dlopen("libc.so.6",RTLD_LAZY))) + return -1; + return (unsigned long)dlsym(mod,name); +} + +int main(int argc,char** argv) +{ + pid_t pid = atoi(argv[1]); + struct user_regs_struct regs; + struct stat st; + vmap_t shell,libc,local_libc; + unsigned long dlpn_off,dlpn_addr; + char* local_shell; + size_t path_size,total_size; + int pd,wr; + char filename[PATH_MAX]; + + + if(vmap_reqeust(pid,VMAP_WALK_SHELL,&shell) < 0) + { + fputs("[-] Place for shellcode not found!\n",stderr); + exit(0); + } + + if(vmap_reqeust(pid,VMAP_WALK_LIBC,&libc) < 0) + { + fputs("[-] Libc not found!\n",stderr); + exit(0); + } + + if(vmap_reqeust(getpid(),VMAP_WALK_LIBC,&local_libc) < 0) + { + fputs("[-] Local libc not found!\n",stderr); + exit(0); + } + + suspend_proc(pid,true); + + if((pd = open_proc(pid)) < 0) + { + perror("open_proc"); + suspend_proc(pid,false); + exit(1); + } + + realpath(argv[2],filename); + path_size = strlen(filename) + 1; + total_size = path_size + SHELL_SIZE; + + local_shell = (char*)malloc(total_size); + if(!local_shell) + { + perror("malloc"); + suspend_proc(pid,false); + exit(1); + } + + memcpy((void*)local_shell,shellcode,SHELL_SIZE); + memcpy((void*)(local_shell+STR_OFFSET),filename,path_size); + + printf("%lx-%lx\n",shell.vm_start,shell.vm_end); + + if((wr = pwrite(pd,(void*)local_shell, + total_size,(off_t)shell.vm_start)) < 0) + { + perror("pwrite"); + goto ex; + } + else + printf("[+] Shellcode written %d\n",wr); + + if(!(dlpn_addr = getfuncaddr("__libc_dlopen_mode"))) + { + perror("getfuncaddr"); + goto ex; + } + + printf("__libc_dlopen_mode %lx\n",dlpn_addr); + dlpn_off = dlpn_addr - local_libc.vm_start; + printf("offset %lx\n",dlpn_off); + dlpn_addr = dlpn_off + libc.vm_start; + printf("remote __libc_dlopen_mode %lx\n",dlpn_addr); + + ptrace(PTRACE_GETREGS,pid,0,®s); +#ifdef __i386__ + emu_push(pid,®s,regs.eip); + emu_push(pid,®s,regs.ebx); + + regs.eip = (unsigned long)shell.vm_start+2; + regs.ebx = (unsigned long)dlpn_addr; +#elif __x86_64__ + emu_push(pid,®s,regs.rip); + emu_push(pid,®s,regs.rbx); + + regs.rip = (unsigned long)shell.vm_start+2; + regs.rbx = (unsigned long)dlpn_addr; +#endif + + ptrace(PTRACE_SETREGS,pid,0,®s); +ex: + suspend_proc(pid,false); + + free((void*)local_shell); + close_proc(pd); + return 0; +} diff --git a/sh2load32 b/sh2load32 new file mode 100644 index 0000000..b858dfa Binary files /dev/null and b/sh2load32 differ diff --git a/vm_shell32.bin b/vm_shell32.bin new file mode 100644 index 0000000..03a0c4e Binary files /dev/null and b/vm_shell32.bin differ diff --git a/vm_shell32.s b/vm_shell32.s new file mode 100644 index 0000000..08c4b8b --- /dev/null +++ b/vm_shell32.s @@ -0,0 +1,14 @@ +use32 + +push 1 +jmp _text +_code: + +call ebx +add esp,8 +pop ebx +ret + +_text: +call _code +db "/something/library/path",0 ;offset 0x10 diff --git a/vm_shell64.bin b/vm_shell64.bin new file mode 100644 index 0000000..36f69da Binary files /dev/null and b/vm_shell64.bin differ diff --git a/vm_shell64.s b/vm_shell64.s new file mode 100644 index 0000000..af76d65 --- /dev/null +++ b/vm_shell64.s @@ -0,0 +1,16 @@ +use64 + +xor rsi,rsi +jmp _text +_code: + +pop rdi +inc rsi +call rbx + +pop rbx +ret + +_text: +call _code +db "/something/library/path",0 diff --git a/vmap.c b/vmap.c new file mode 100644 index 0000000..2fb085c --- /dev/null +++ b/vmap.c @@ -0,0 +1,60 @@ +#include "vmap.h" + +void vmap_parse(vmap_t* map,const char* str) +{ + sscanf(str,"%lx-%lx %s %08d %*02d:%*02d %*s %s", + &map->vm_start,&map->vm_end,map->perms, + &map->magic_num,map->path); +} + +int vmap_walk(pid_t pid,walk_map_callback func,void *arg) +{ + char buf[256]; + char path[64]; + vmap_t map; + FILE* fmap; + + sprintf(path,"/proc/%d/maps",pid); + if(!(fmap = fopen(path,"rb"))) + return -1; + + while(fgets(buf,256,fmap) != NULL) + { + vmap_parse(&map,buf); + if(func(&map,arg)) + return 1; + } + return 0; +} + +int walk_map_func(vmap_t *map,void *arg) +{ + vmap_request_t *vreq = (vmap_request_t*)arg; + vreq->status = VMAP_NOTFOUND; + if(vreq->type == VMAP_WALK_SHELL && strchr(map->perms,'x')) + { + vreq->status = VMAP_OK; + memcpy(vreq->map,map,sizeof(vmap_t)); + return 1; + } + else if(vreq->type == VMAP_WALK_LIBC && strstr(map->path,"libc-")) + { + vreq->status = VMAP_OK; + memcpy(vreq->map,map,sizeof(vmap_t)); + return 1; + } + return 0; +} + +int vmap_reqeust(pid_t pid,request_t what,vmap_t *map) +{ + vmap_request_t vreq; + + vreq.type = what; + vreq.map = map; + vmap_walk(pid,&walk_map_func,(void*)&vreq); + if(vreq.status == VMAP_OK) + return 0; + + return -1; +} diff --git a/vmap.h b/vmap.h new file mode 100644 index 0000000..f6e89f6 --- /dev/null +++ b/vmap.h @@ -0,0 +1,41 @@ +#ifndef __VMAP_H +#define __VMAP_H + +#include +#include +#include +#include +#include +#include + +typedef enum { + VMAP_WALK_SHELL, + VMAP_WALK_LIBC, +} request_t; + +typedef enum { + VMAP_OK, + VMAP_NOTFOUND, +} status_t; + +typedef struct { + uintptr_t vm_start; + uintptr_t vm_end; + char perms[5]; + uint32_t magic_num; + char path[256]; +} vmap_t; + +typedef struct { + request_t type; + status_t status; + vmap_t *map; +} vmap_request_t; + +typedef int (*walk_map_callback)(vmap_t *map,void *arg); + +void vmap_parse(vmap_t* map,const char* str); +int vmap_walk(pid_t pid,walk_map_callback func,void *arg); +int vmap_reqeust(pid_t pid,request_t what,vmap_t *map); + +#endif