Ret2esp / Ret2reg
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
ESP(스택 포인터)는 항상 스택의 맨 위를 가리키기 때문에, 이 기술은 EIP(명령 포인터)를 jmp esp
또는 call esp
명령의 주소로 교체하는 것을 포함합니다. 이렇게 하면 셸코드가 덮어쓴 EIP 바로 뒤에 배치됩니다. ret
명령이 실행되면 ESP는 다음 주소를 가리키며, 정확히 셸코드가 저장된 위치입니다.
**주소 공간 배치 무작위화(ASLR)**가 Windows 또는 Linux에서 활성화되지 않은 경우, 공유 라이브러리에서 발견된 jmp esp
또는 call esp
명령을 사용할 수 있습니다. 그러나 ASLR이 활성화된 경우, 이러한 명령을 찾기 위해 취약한 프로그램 자체를 살펴봐야 할 수 있습니다(그리고 PIE를 우회해야 할 수도 있습니다).
게다가 EIP 손상 이후에 셸코드를 배치할 수 있는 것은, 스택의 중간이 아닌, 함수의 작동 중에 실행되는 push
또는 pop
명령이 셸코드에 간섭하지 않도록 보장합니다. 셸코드가 함수의 스택 중간에 배치되었다면 이러한 간섭이 발생할 수 있습니다.
RIP를 덮어쓴 후에 쓸 공간이 부족한 경우(아마도 몇 바이트 정도), 다음과 같은 초기 jmp
셸코드를 작성하세요:
그리고 스택의 초기에 셸코드를 작성합니다.
이 기술의 예시는 https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp에서 찾을 수 있으며, 최종 익스플로잇은 다음과 같습니다:
이 기술의 또 다른 예는 https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html에서 볼 수 있습니다. NX가 활성화되지 않은 상태에서 버퍼 오버플로우가 발생하며, $esp
의 주소를 줄이기 위해 가젯을 사용한 다음, 셸코드로 점프하기 위해 jmp esp;
를 사용합니다:
유사하게, 함수가 쉘코드가 저장된 주소를 반환하는 것을 알고 있다면, call eax
또는 jmp eax
명령어(일명 ret2eax 기법)를 활용하여 쉘코드를 실행할 수 있는 또 다른 방법을 제공합니다. eax와 마찬가지로, 흥미로운 주소를 포함하는 다른 레지스터도 사용할 수 있습니다(ret2reg).
여기에서 몇 가지 예를 찾을 수 있습니다:
**strcpy
**는 쉘코드가 저장된 버퍼의 주소를 **eax
**에 저장하고 **eax
**는 덮어쓰이지 않으므로 ret2eax
를 사용할 수 있습니다.
ARM64에서는 SP 레지스터로 점프할 수 있는 명령어가 없습니다. sp를 레지스터로 이동시키고 그 레지스터로 점프하는 가젯을 찾는 것이 가능할 수 있지만, 내 Kali의 libc에서는 그런 가젯을 찾을 수 없었습니다:
내가 발견한 유일한 방법은 sp가 점프하기 전에 복사된 레지스트리의 값을 변경하는 것이었다(그래서 그것은 쓸모없게 된다):
레지스트리에 흥미로운 주소가 있다면 적절한 명령어를 찾아 점프하는 것이 가능하다. 다음과 같은 방법을 사용할 수 있다:
ARM64에서는 **x0
**가 함수의 반환 값을 저장하므로, x0가 사용자가 제어하는 버퍼의 주소를 저장하고 있을 수 있으며, 이 버퍼에는 실행할 쉘코드가 포함되어 있습니다.
예제 코드:
함수의 디스어셈블리를 확인하면 버퍼에 대한 주소(bof에 취약하며 사용자에 의해 제어됨)가 x0
에 저장된 것을 볼 수 있습니다. 이는 버퍼 오버플로우에서 반환하기 전에 발생합니다:
또한 do_stuff
함수에서 br x0
가젯을 찾을 수 있습니다:
우리는 이 가젯을 사용하여 점프할 것입니다. 이진 파일은 PIE 없이 컴파일되었습니다. 패턴을 사용하여 버퍼 오버플로우의 오프셋이 80임을 확인할 수 있으므로, 익스플로잇은 다음과 같습니다:
fgets
대신 **read
**와 같은 것을 사용했다면, 반환 주소의 마지막 2바이트만 덮어쓰는 것으로 br x0;
명령어로 돌아가는 것이 가능했을 것입니다. 전체 주소를 알 필요 없이.
fgets
는 끝에 널(0x00) 바이트를 추가하기 때문에 작동하지 않습니다.
NX: 스택이 실행 가능하지 않다면, 스택에 쉘코드를 배치하고 이를 실행하기 위해 점프해야 하므로 도움이 되지 않습니다.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)