In Level13 we are given the following code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#define FAKEUID 1000
int main(int argc, char **argv, char **envp)
{
int c;
char token[256];
if(getuid() != FAKEUID) {
printf("Security failure detected. UID %d started us, we expect %d\n", getuid(), FAKEUID);
printf("The system administrators will be notified of this violation\n");
exit(EXIT_FAILURE);
}
// snip, sorry :)
printf("your token is %s\n", token);
}
In order to receive the token we need to FAKE our UID to bypass the if statement.
Now, we could solve this a few different ways. The two that pop into mind are: 1.) Write a fake getuid() program to trick the call. 2.) Use a debugger.
I personally decided to use a debugger to refresh some of my knowledge, but don’t let my decision dictate yours.
Small caveat: This blog post is not an extensive walk-through on how to use a debugger. There are tons of better resources to learn up on gdb.
Let’s load the program into gdb, which my friend Derrick refers to as “The real man’s debugger,” and set a breakpoint at main:
level13@nebula:/home/flag13$ gdb flag13
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/flag13/flag13...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x80484c9
Looks good, let’s run it:
(gdb) r
Starting program: /home/flag13/flag13
Breakpoint 1, 0x080484c9 in main ()
(gdb) x/20i main
0x80484c4 <main>: push %ebp
0x80484c5 <main+1>: mov %esp,%ebp
0x80484c7 <main+3>: push %edi
0x80484c8 <main+4>: push %ebx
=> 0x80484c9 <main+5>: and $0xfffffff0,%esp
0x80484cc <main+8>: sub $0x130,%esp
0x80484d2 <main+14>: mov 0xc(%ebp),%eax
0x80484d5 <main+17>: mov %eax,0x1c(%esp)
0x80484d9 <main+21>: mov 0x10(%ebp),%eax
0x80484dc <main+24>: mov %eax,0x18(%esp)
0x80484e0 <main+28>: mov %gs:0x14,%eax
0x80484e6 <main+34>: mov %eax,0x12c(%esp)
0x80484ed <main+41>: xor %eax,%eax
0x80484ef <main+43>: call 0x80483c0 <getuid@plt>
0x80484f4 <main+48>: cmp $0x3e8,%eax
0x80484f9 <main+53>: je 0x8048531 <main+109>
0x80484fb <main+55>: call 0x80483c0 <getuid@plt>
0x8048500 <main+60>: mov $0x80486d0,%edx
0x8048505 <main+65>: movl $0x3e8,0x8(%esp)
0x804850d <main+73>: mov %eax,0x4(%esp)
We hit our first breakpoint and I run x/20i main
to view the first 20 lines of the main() function.
I set another break using break *main + 48
and continued stepping through:
(gdb) break *main + 48
Breakpoint 2 at 0x80484f4
(gdb) cont
Continuing.
FYI: The new breakpoint is set at 0x80484f4
, which is right after the first getuid@plt call. As you can see in main(), the program compares $0x3e8 (1000 in Hex) and %eax.
Breakpoint 2, 0x080484f4 in main ()
(gdb) print $eax
$1 = 1014
(gdb) set $eax = 1000
(gdb) print $eax
$2 = 1000
Next, we check $eax, which is currently set at 1014. Looking back at the source code, this UID will cause us to fall into the if block and generate the error message, so we modify $eax to our fake id of 1000.
As we continue, the if statement evaluates to false and we are presented with the token.
(gdb) cont
Continuing.
your token is b705702b-76a8-42b0-8844-3adabbe5ac58
[Inferior 1 (process 3567) exited with code 063]
Let’s try logging into the flag13 account with the token:
$ ssh flag13@192.168.98.138
_ __ __ __
/ | / /__ / /_ __ __/ /___ _
/ |/ / _ \/ __ \/ / / / / __ `/
/ /| / __/ /_/ / /_/ / / /_/ /
/_/ |_/\___/_.___/\__,_/_/\__,_/
exploit-exercises.com/nebula
For level descriptions, please see the above URL.
To log in, use the username of "levelXX" and password "levelXX", where
XX is the level number.
Currently there are 20 levels (00 - 19).
flag13@192.168.98.138's password:
Welcome to Ubuntu 11.10 (GNU/Linux 3.0.0-12-generic i686)
* Documentation: https://help.ubuntu.com/
New release '12.04 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
flag13@nebula:~$ id
uid=986(flag13) gid=986(flag13) groups=986(flag13)
flag13@nebula:~$ getflag
You have successfully executed getflag on a target account
It worked. This was one of my favorite levels so far!