ret 주소와 gadget의 개념에 대해 질문이 있습니다.
-
리턴 가젯은
ret
명령어로 끝나는 어셈블리 코드 조각을 의미한다고 하였는데,pop rdi; ret
의 경우pop rdi
가 실행된 후,ret
가 실행된다는 뜻의 2단계 코드 조각을 말하는 것인가요?? 아니라면 무슨 의미인가요? -
ROPgadget --binary rtl
명령어의 결과가 아래의 사진과 같은데, 여기서 어떤 가젯을 사용 하는 지는 어떻게 정하나요?? 그냥 아무 가젯이나 사용해도 되나요? 풀이에서 왜ret
를 사용했는지 궁금합니다.
-
세 번째로는 이 문제에서 의미없는 문자열로 57byte만큼 채운 후, canary를 leak하고, 다시 의미 없는 문자열로 8byte를 덮은 다음, 원래는 main 함수의 ret 하는 코드가 있지만,
ROPgadget --binary rtl
에서 찾은 코드로 덮어버렸고 그 후pop rdi
로/bin/sh
의 주소를 rdi에 넣고 system 함수를 실행시켜서 shell을 획득하는 것으로 이해를 했는데 여기서pop rdi; ret
가 아니라pop rdi
,/bin/sh의 주소
,system 함수 호출
이렇게 3단계로 진행되어야 하는 거 아닌가요?? 왜pop rdi
가 아니라pop rdi; ret
인지 궁금합니다. pop rdi를 한 후, ret를 해버리면 system 함수를 호출할 수 없는 것 아닌가요??
- 맞습니다. 가젯은 바이너리 내의 ret이나 jmp 로 끝나는 연속된 명령어를 이야기합니다.
- 용도에 맞게 사용합니다. 언급하신 pop rdi, ret을 통해 첫번째 인자에 binsh를 넣고 시스템 함수를 실행하거나 pop rdi, pop rsi, pop rdx, ret(실제로는 없지만)을 통해 3개의 인자가 요구되는 함수를 실행하는 것 처럼요.
- pop rdi로 스택의 값을 rdi에 넣으면 rsp에 8이 더해지고 그 다음 스택의 값으로 ret 합니다. 즉 쉘을 실행시키는거죠
pop rdi -> 스택의 최상단 (rsp가 가리키는 곳)의 값을 rdi에 저장하고 rsp에 8을 더해준다
ret -> ret 명령어는 다음과 같이 기능을 합니다 : pop rip, jmp rip -> 역시 스택 최상단의 값을 rip에 넣은 후 그 값이 가리키는 곳으로 jmp하죠.
이제 오버플로우를 일으킨 상황의 스택을 보면 다음과 같습니다.
<main 함수의 ret 실행 전>
원래 main의 ret주소 (ROP 가젯의 주소가 적혀있게 되죠) -- 0 (rsp)
"/bin/sh" -- +8
system@plt의 주소 -- +16
rsp는 현재 main의 리턴 주소를 가리키고 있고, main 함수에서 ret명령어가 실행되면 이 주소가 rip에 저장되며 점프합니다.
이때 그 주소가 ROP 가젯의 주소기 때문에 ROP 가젯의 주소로 jmp하게 됩니다.
ret 명령어는 pop이 있기 때문에 rsp가 가리키는 값은 rsp+8이 되게 됩니다.
<main 함수의 ret 실행 후>
원래 main의 ret주소 (ROP 가젯의 주소가 적혀있게 되죠) -- 0
"/bin/sh" -- +8 (rsp)
system@plt의 주소 -- +16
현재 프로그램의 흐름은 ROP 가젯의 pop rdi;ret 으로 되어있습니다.
따라서 pop rdi를 실행시키면 현재 rsp가 가리키는 값인 "/bin/sh"가 rdi에 저장이 되고, rsp값은 다시 8증가하게 됩니다.
<ROP 가젯의 pop rdi 실행 후>
원래 main의 ret주소 (ROP 가젯의 주소가 적혀있게 되죠) -- 0
"/bin/sh" -- +8
system@plt의 주소 -- +16 (rsp)
현재 rdi에는 system의 인자로 쓰기 위한 "/bin/sh"가 저장되었고, 이제 ROP 가젯의 ret 명령어가 실행됩니다.
역시 현재 rsp가 가리키는 값인 system@plt의 주소가 rip에 저장이 되고 jmp rip를 하여 system@plt로 흐름을 옮기게 됩니다.
이후 system함수가 호출되고 인자로 rdi가 들어가 있음을 알 수 있습니다.
이처럼 ROP 가젯을 이용하면 pop을 통해 인자로 넣고 ret을 통해 흐름을 연속적으로 바꿀 수 있습니다.
rsp의 위치와 pop, ret등의 명령어의 작동방식을 잘 생각해보시면 도움이 많이 될 것 같습니다.