- 가짜 스택 프레임 포인터(Stack Frame Pointer)를 만들어 프로그램의 실행 흐름을 제어하는 것이다.
Instruction | 64 bit | 32 bit |
leave |
MOV RSP, RBP POP RBP |
MOV ESP, EBP POP EBP |
ret |
POP RIP JMP RIP |
POP EIP JMP EIP |
[EXAMPLE]
- 함수 프롤로그가 진행되어, ebp와 esp가 같을 때의 모습이다.
- buf + 4 위치에 Shellcode를 넣고, buf에는 Shellcode의 시작 주소 &(buf + 4)를 넣는다.
- SFP는 &(buf - 4), RET는 leave-ret Gadget으로 덮어 씌운다.
- 다음 상태에서 함수 에필로그의 leave 명령어가 진행된다.
- leave 명령어가 수행되면서 ebp는 &(buf - 4)로가고, esp는 RET을 가리킬 것이다.
- ret 명령어도 진행해 보자
- ret 명령어로, esp는 RET+4, eip는 RET을 가리키며 JMP eip로 인해 다시 leave-ret이 실행된다.
- leave 명령어가 수행되어 esp가 buf의 시작 주소로 이동한다. (mov esp, ebp ; pop ebp)
- 현재 esp는 buf의 시작 주소를 가리키고 있다. buf의 시작 주소에는 Shellcode의 시작 주소가 들어 있다.
- ret 명령어가 수행되어 Shellcode의 시작 주소가 EIP로 저장되고, JMP EIP를 통해 Shellcode가 실행된다.
- buf ~ ret : 66 bytes
- RTL을 사용하기 위해 printf, system, /bin/sh의 offset을 구한다.
- leave-ret Gadget을 libc에서 찾고, gdb에서 해당 offset이 맞는지 확인한다. 이제 준비는 끝났다.
- 다음과 같이 Stack 영역을 덮어써서 Frame faking을 사용할 수 있다.
buf[0] | 0x90909090 |
buf[4] | system function address in libc |
buf[8] | dummy |
buf[12] | "/bin/sh" address |
- | - |
Frame Pointer | buf[0] STACK address |
Return Address | leave-ret address in libc |
REF: https://www.lazenca.net/pages/viewpage.action?pageId=12189944
https://d4m0n.tistory.com/88?category=796362
댓글 영역