Stack Pivoting - EBP2Ret - EBP chaining
기본 정보
이 기술은 **베이스 포인터 (EBP)**를 조작하여 EBP 레지스터와 leave; ret
명령어 시퀀스를 신중하게 사용하여 여러 함수의 실행을 연결하는 능력을 악용합니다.
leave
는 기본적으로 다음을 의미합니다:
그리고 EBP가 EIP보다 먼저 스택에 있기 때문에 스택을 제어하여 EBP를 제어할 수 있습니다.
EBP2Ret
이 기술은 EBP 레지스터를 변경할 수 있지만 EIP 레지스터를 직접적으로 변경할 방법이 없을 때 특히 유용합니다. 함수가 실행을 마치면서 동작을 활용합니다.
fvuln
의 실행 중에 스택에 가짜 EBP를 삽입하여 셸코드 주소가 위치한 메모리 영역을 가리키도록 설정하면(4바이트를 pop
작업을 고려하여 더한 상태), 간접적으로 EIP를 제어할 수 있습니다. fvuln
이 반환되면 ESP는 이 조작된 위치로 설정되고, 이후의 pop
작업은 ESP를 4만큼 감소시키므로, 사용자가 설정한 주소를 가리키도록 효과적으로 만듭니다.
여기서 2개의 주소를 알아야 한다는 점에 주목하세요: ESP가 이동할 위치 및 ESP가 가리키는 주소를 써야 하는 주소.
Exploit 구성
먼저 임의의 데이터/주소를 쓸 수 있는 주소를 알아야 합니다. ESP는 여기를 가리키고 첫 번째 ret
를 실행할 것입니다.
그런 다음, 임의의 코드를 실행할 ret
에 사용되는 주소를 알아야 합니다. 다음을 사용할 수 있습니다:
유효한 ONE_GADGET 주소.
system()
주소 뒤에 4바이트의 쓰레기 바이트와"/bin/sh"
주소(x86 비트).jump esp;
가젯(ret2esp) 주소 뒤에 실행할 셸코드.일부 ROP 체인
제어 가능한 메모리의 이 부분에 이러한 주소 중 어느 것이든 사용하기 전에 4
바이트가 있어야 합니다. leave
명령의 pop
부분 때문에 이 4바이트를 악용하여 두 번째 가짜 EBP를 설정하고 실행을 계속 제어할 수 있습니다.
Off-By-One Exploit
이 기술의 특정 변형인 "Off-By-One Exploit"이라고 알려진 것이 있습니다. 이는 EBP의 가장 낮은 유효 바이트만 수정할 수 있는 경우 사용됩니다. 이 경우, ret
로 이동할 주소를 저장하는 메모리 위치는 EBP와 처음 세 바이트를 공유해야 하므로, 더 제약 조건으로 유사한 조작이 가능합니다.
보통 가장 멀리로 이동하기 위해 바이트 0x00을 수정합니다.
또한, 스택에 RET 슬레드를 사용하고 실제 ROP 체인을 끝에 놓아 새 ESP가 RET SLED 내부를 가리키고 최종 ROP 체인이 실행될 가능성을 높일 수 있습니다.
EBP Chaining
따라서, 스택의 EBP
항목에 제어 가능한 주소를 넣고 EIP
에 leave; ret
주소를 넣으면 ESP
를 스택의 제어 가능한 EBP
주소로 이동할 수 있습니다.
이제 **ESP
**가 원하는 주소를 가리키고 실행할 다음 명령이 RET
인 상태입니다. 이를 악용하기 위해 제어 가능한 ESP 위치에 다음을 놓을 수 있습니다:
&(다음 가짜 EBP)
->leave
명령의pop ebp
로 새 EBP를 로드합니다.system()
->ret
에 의해 호출됩니다.&(leave;ret)
-> 시스템이 종료된 후 호출되며, ESP를 가짜 EBP로 이동시키고 다시 시작합니다.&("/bin/sh")
->system
의 매개변수
기본적으로 이 방법을 사용하여 프로그램의 흐름을 제어하는 여러 가짜 EBPs를 연결할 수 있습니다.
이는 ret2lib과 유사하지만, 명백한 이점은 없지만 일부 특수한 경우에 흥미로울 수 있습니다.
또한, 여기에는 이 기술을 사용하여 승리 함수를 호출하는 스택 누출을 사용하는 도전 과제 예제가 있습니다. 이것은 페이지의 최종 페이로드입니다:
EBP가 사용되지 않을 수 있음
이 게시물에서 설명한대로, 일부 최적화로 컴파일된 이진 파일의 경우 EBP는 ESP를 제어하지 못합니다, 따라서 EBP를 제어하여 작동하는 모든 exploit은 기본적으로 실제 효과가 없기 때문에 실패할 것입니다. 이는 이진 파일이 최적화되었을 때 프롤로그와 에필로그가 변경되기 때문입니다.
최적화되지 않음:
최적화됨:
RSP를 제어하는 다른 방법
pop rsp
가젯
pop rsp
가젯이 페이지에서 이 기술을 사용한 예제를 찾을 수 있습니다. 이 도전 과제에서는 2개의 특정 인수를 사용하여 함수를 호출해야 했으며 pop rsp
가젯이 있으며 스택에서의 누출이 있었습니다:
xchg <reg>, rsp 가젯
jmp esp
여기서 ret2esp 기술을 확인하세요:
pageRet2esp / Ret2reg참고 자료 및 다른 예제
64 bits, off by one exploitation with a rop chain starting with a ret sled
64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing
.fini_array
entries + calling__libc_csu_fini
(more info here). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
ARM64
ARM64에서 함수의 프롤로그와 에필로그는 SP 레지스트리를 저장하고 검색하지 않습니다. 더구나 RET
명령은 SP가 가리키는 주소로 돌아가지 않고 x30
안의 주소로 돌아갑니다.
그러므로 기본적으로 에필로그를 남용하여 스택 내부의 데이터를 덮어쓰는 것으로 SP 레지스트리를 제어할 수 없습니다. 그리고 SP를 제어할 수 있다 하더라도 x30
레지스터를 제어해야 합니다.
프롤로그
에필로그
ARM64에서 스택 피봇을 수행하는 방법은 SP
를 제어할 수 있어야 하며, 그 레지스터의 값이 SP
로 전달되거나 SP
가 스택에서 주소를 가져오는 이유가 있어야 합니다. 그런 다음 에필로그를 남용하여 제어된 SP
에서 x30
레지스터를 로드하고 **RET
**로 이동해야 합니다.
또한 다음 페이지에서 ARM64에서 Ret2esp의 동등한 내용을 볼 수 있습니다:
pageRet2esp / Ret2regLast updated