hook wargame 질문

안녕하세요. 해당 워게임을 풀이하던 중 2가지 궁금증이 생겨서 이렇게 질문을 남깁니다.

free(ptr);
free(ptr);

system("/bin/sh");

에서, free(ptr);이 2번 실행되는 대신에 __free_hook에 원가젯을 대입해서 바로 문제를 풀이하려고 했는데, 아래의 원가젯 중 첫번째 원가젯을 __free_hook이 가리키도록 했을 때만 익스플로잇이 가능했습니다.

image.png

image.png
(해당 조건은 free가 실행되기 전 아래의 상태입니다. read(0, ptr, size)에서 제대로 된 주소를 넣어주지 않아서 segfault가 난건지 더이상 진행이 안되서 여기서 검사했습니다. 혹시 여기서 segfault가 안나게 gdb에서 입력을 해주는 팁이 있다면 알려주시면 감사드리겠습니다 ㅠㅠ)

image.png

근데 여기서 셋다 조건을 만족하지 않는데, 첫번째 원가젯만 p.send(p64(free_hook) + p64(og))을 통해 전달했을 때 익스플로잇이 되는 이유가 무엇인지 궁금합니다.

그리고 사실 og 대신에 libcsystem, write, read 등 아무 함수나 넣어줘도 인자를 따로 설정해주지 않아도 아래의 system("/bin/sh");이 수행되는데 그 이유도 궁금합니다..

  1. 풀이를 보면서 위 방법이 아닌 바이너리의 system("/bin/sh") 이 수행되도록 free_hook에 대입을 해주라는 것을 통해 아래와 같이 og 대신 0x400a11을 전달해주어서 익스플로잇을 성공하긴 했습니다.

image.png

근데 여기서, 0x400a11PIE가 적용되지 않아서 고정된 가상 주소이기 때문에 전달이 가능하다는 것으로 유추하였는데 PIE가 적용되지 않은 경우 코드 영역의 베이스 주소를 구해서 0x400a11 대신 존재하는 가상 주소 오프셋을 더해줘야 하는건가요?

PIE가 적용되어서 gdb에 나오는 가상 주소가 오프셋이더라도, 그걸 그대로 0x400a11 처럼 전달해주면 알아서 해당 코드가 존재하는 영역을 찾아가지 못하는 이유는 무엇인가요..?

#pwnable
작성자 정보
답변 1

안녕하세요.

  1. 문제 소스를 읽어 봤는데, main에서 free가 두 번 실행된 뒤 system("/bin/sh")이 실행됨을 알 수 있습니다. 즉, 두 번의 free에서 crash가 나지 않고 잘 실행된다면 쉘을 딸 수 있다는 것을 알 수 있습니다. free_hook에 정상적으로 return할 수 있는 가젯을 넣으셨기에 그대로 main함수의 system("/bin/sh")이 실행되었을 거라고 생각됩니다. 조건이 맞지 않는 원가젯도 그런 이유가 아닐까 생각됩니다.

  2. PIE가 적용되지 않은 경우... gdb에서 보이는 가상 주소와 실제 프로세스의 실행 도중 가상 주소가 완전히 동일합니다. PIE가 적용되지 않은 바이너리에서 gdb에 나오는 주소는 offset이 아닌 실제 주소 그대로입니다. 조금 더 자세히 말씀드리면 일반적으로 PIE가 꺼져 있을 시에 코드 베이스(Image Base)는 0x400000으로 고정되며 거기에 가상 주소 offset 0xa11이 더해져서 0x400a11이 됩니다. PIE에서 gdb에서 가상 주소 offset을 제시하는 경우는 실행되지 않은 시점에서 offset 주소를 제시해 줍니다. 실행 도중 bp를 걸어서 주소를 확인해보면 offset이 아닌 실제 base에 offset이 더해진 주소를 보여줍니다. offset만 전달해준다면 당연히 실제 주소와 다르기에 해당 코드를 자동으로 찾아가던가의 행위는 하지 못합니다. 질문 주신 것을 읽어보셨을 때 어딘가 잘못 이해하고 계신 부분이 있으신 것으로 생각됩니다. 제가 해당 부분을 잘 집어서 설명드렸길 바라며, 제 답글로 의문이 해결되지 못하셨다면 추가 질문 부탁드립니다.

2024.08.17. 05:13
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기