There is a security check that prevents the program from continuing execution if the user invoking it does not match a specific user id.This one is quite nice. Source code:
This program requires us to run it with a UID of 1000 in order to print the token. But let's think where that token actually comes from. The fact that not all of the source code is shown indicates that the token may be somehow generated (or even hardcoded) and then printed to us. The flag13 binary being SUID serves no purpose. We can easily reverse engineer how the token is generated. You could go for a static analysis approach and use a disassembler (I prefer IDA). This is however one of the cases where a dynamic approach is ideal. Since we don't need the elevated UID from the setuid bit, we can simply make getuid return 1000 ourselves. This could be done using LD_PRELOAD and writing our own getuid function in a library, but there's an even easier way. Simply use a debugger and modify the return value:
level13@nebula:~$ gdb -q ~flag13/flag13 Reading symbols from /home/flag13/flag13...(no debugging symbols found)...done. (gdb) disas main Dump of assembler code for function main: 0x080484c4 <+0>: push %ebp 0x080484c5 <+1>: mov %esp,%ebp 0x080484c7 <+3>: push %edi 0x080484c8 <+4>: push %ebx 0x080484c9 <+5>: and $0xfffffff0,%esp 0x080484cc <+8>: sub $0x130,%esp 0x080484d2 <+14>: mov 0xc(%ebp),%eax 0x080484d5 <+17>: mov %eax,0x1c(%esp) 0x080484d9 <+21>: mov 0x10(%ebp),%eax 0x080484dc <+24>: mov %eax,0x18(%esp) 0x080484e0 <+28>: mov %gs:0x14,%eax 0x080484e6 <+34>: mov %eax,0x12c(%esp) 0x080484ed <+41>: xor %eax,%eax 0x080484ef <+43>: call 0x80483c0And there's our token :)
0x080484f4 <+48>: cmp $0x3e8,%eax 0x080484f9 <+53>: je 0x8048531 0x080484fb <+55>: call 0x80483c0 0x08048500 <+60>: mov $0x80486d0,%edx 0x08048505 <+65>: movl $0x3e8,0x8(%esp) 0x0804850d <+73>: mov %eax,0x4(%esp) 0x08048511 <+77>: mov %edx,(%esp) 0x08048514 <+80>: call 0x80483a0 ---Type to continue, or q to quit---q Quit (gdb) break *main+48 Breakpoint 1 at 0x80484f4 (gdb) commands 1 Type commands for breakpoint(s) 1, one per line. End with a line saying just "end". >set $eax = 1000 >c >end (gdb) r Starting program: /home/flag13/flag13 Breakpoint 1, 0x080484f4 in main () your token is b705702b-76a8-42b0-8844-3adabbe5ac58 [Inferior 1 (process 1330) exited with code 063] (gdb)
Keep in mind that when debugging a SUID binary, it actually runs as a normal binary, effectively dismissing the setuid bit. And LD_PRELOAD wouldn't work with a SUID binary.
Now go ahead and get the flag:
level13@nebula:~$ su flag13 -c getflag Password: You have successfully executed getflag on a target account