[DH] iofile_vtable
Writeup
2025. 7. 29.
Ubuntu 16.04
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
launchpad를 통해 glibc 버전이 2.23임을 확인할 수 있다.
분석 (바이너리)
주어진 바이너리를 실행시키면 사용자로부터 8바이트 입력을 받아 global varible에 저장하고, print, error, read, chance 옵션을 출력한다.
print옵션은 "good"을 printf한다.error옵션은 "ERROR"을 stderr로 fprintf한다.read옵션은 stdin으로 fgetc한다.chance옵션은 stdin으로부터 8바이트를 읽고 stderr+1에 저장한다.
이론
이 글에서 FSOP에 대해 정리했다.
분석 (구조)
stderr+1이 무엇을 가리키는지 알 필요가 있다.
GDB를 통해 확인해 보면 stderr에 0xD8만큼의 오프셋을 더한 주소를 가리킨다. 즉, vtable을 가리킨다.
Note:
stderr은FILE구조체이므로stderr + 1은stderr의 주소에서sizeof(FILE)만큼 더한 주소를 의미한다. 그리고 그것은 곧stderr의*vtable을 가리킨다.
따라서 입력값으로 vtable의 주소를 변경할 수 있다!
마침 초기에 name을 입력하는 곳이 있으니 name에 win 함수의 주소를 넣고 vtable이 name을 가리키도록 하자.
이때, 주의할 점은 이후 error 옵션을 통해서 fprintf를 호출할 때 win이 실행되기는 원하므로 vtable의 0x38 offset이 win을 가리키도록 해야 한다.
Solution
shell = 0x0040094A
name = 0x006010D0
p = connect()
p.send(p64(shell))
p.sendline(b"4")
p.send(p64(name - 0x38))
p.interactive()
p.close()
