RTL에 관한 문서를 작성하면서 RET 다음에 집어넣어주는 4바이트의 Dummy가 해당 함수의 리턴 어드레스라고 설명을 해 두었는데, 그것에 대해 자세한 설명을 작성하는 것은 RTL Chaining 문서를 만들 때로 미뤄두었기 때문에 이렇게 글을 쓴다.
이 부분은 이미 익숙한 사람이라면 대충 명령어를 머릿속에 떠올리는 것 만으로도 충분히 이해가 가능하지만
아직 RTL에 익숙하지 않은 사람은 어째서 저게 RET인지 이해하기 어려울 수도 있다.
그림으로 보며 하나하나 확인해 보자.
위 스택이 정상적인 스택이고, 아래 스택은 RTL을 위해 변조한 스택이다.
현재 함수 에필로그 중 leave만 실행되어 EBP는 어딘가로 가버린 상태고, EIP는 ret을 가리키고 있을 것이다.
ret을 실행하면 ESP가 가리키던 &system이 EIP에 들어가 system 함수가 실행된다.
call로 실행한 것과는 달리 jmp로 이동한 것과 다름없기 때문에 따로 RET이 저장되지 않는다.
system 함수의 프롤로그가 진행된다.
push EBP가 실행되면서 system 함수의 SFP가 저장된다.
ESP는 원래 &system으로 덮여 있던 장소에 SFP를 쓰게 된다.
mov EBP, ESP 명령에 의해 EBP와 ESP는 같은 부분을 가리키게 된다.
이 부분을 보면 system 함수의 인자인 &/bin/sh는 정확히 EBP에서 8바이트 떨어져 있어
정상적으로 참조가 가능함을 알 수 있다.
이후 함수 에필로그이다.
함수 내부에서 스택을 사용했다면 ESP가 이동했겠지만 이동하든 말든 별로 관계 없으므로 진행하겠다.
leave 명령을 수행하면서 저장된 SFP가 EBP로 넘어가게 되므로 EBP는 원래 있던 자리로 되돌아가고,
ESP에는 pop에 의해 4가 더해지므로 Dummy를 가리키게 된다.
여기서 ret을 수행하면 Dummy의 값이 pop %eip에 의해 EIP에 들어가게 되고 EIP는 그곳으로 점프한다.
만약 Dummy에 exit함수의 주소를 넣었다면 바로 exit함수가 실행되는 것이고,
pop-ret 가젯을 넣었다면 인자인 &/bin/sh를 pop으로 건너뛰고
그 다음 4바이트를 ret으로 참조하게 되므로 다시 한 번 함수 주소를 써 주는 것으로 함수 체이닝이 가능할 것이다.
'Knowledge' 카테고리의 다른 글
libcapstone-dev 설치 방법 (0) | 2016.03.12 |
---|---|
PE 파일과 Memory-Mapped File (0) | 2015.12.24 |
Wireshark로 인증서 추출하기 (0) | 2015.11.02 |
제한적 ASLR 해제 방법 (0) | 2015.10.22 |
레지스터 (Register) (0) | 2015.10.12 |