이번 글에서는 SEH Based Exploit이라는 새로운 공격 기법을 알아 보겠습니다.
1. SEH(Structured Exception Handling)?
우선 예외 처리(Exception handling)이란 프로그램이 실행 중에는 여러 예외가 나타날 수 있습니다.
0으로 나누거나, overflow가 나서 segmentation fault가 난다던지 등등 예외가 발생할 수 있습니다.
이때, 어플리케이션단에서 try ~ catch 구문으로 어느정도 예외를 처리할 수 있지만, 예외를 전부 처리하지 못할 경우 OS단으로 넘어가게 됩니다.
이 OS단에서 예외를 처리할 때 window는 SEH라는 것에 기반해서 처리를 하게 됩니다.
문제는 예외 처리하는 루틴들의 주소가 stack에 저장되어 있습니다.
위 그림 Local vars에서 BOF 취약점이 존재해 Address of exception handler에 원하는 주소를 덮어쓰게 되면, 나중에 Exception 발생 시 원하는 루틴으로 점프 뛰게 할 수 있다는 것이 핵심입니다.
2. SEH Chain
SEH 구조체는 8byte 크기이고 4byte 요소 2개로 구성됩니다.
하나는 다음 SEH 구조체의 주소이고, 하나는 예외 핸들러의 주소입니다.
최초 예외 발생 시 Pointer to Exception Handler 함수가 호출됩니다.
해당 핸들러에서 예외을 처리하지 못할 경우 Pointer to next SEH record를 참조하여 다음 핸들러를 호출합니다.
이를 계속 반복합니다!
Pointer to next SEH record에 0xFFFFFF가 할당되어 있는 Default 핸들러까지 도달할 경우 예외를 커널로 넘겨 프로세스를 재개하거나 종료시킵니다.
SEH Chain의 첫 번째 주소를 가리키는 포인터는, TEB/TIB에 저장됩니다.
그리고 TEB는 FS 세그먼트 레지스터가 가리키고 있습니다. 그래서 SEH Chain은 FS:[0] Chain이라고 불리기도 합니다.
위 그림은 확인하면 FS:[0]에는 SEH 프레임의 주소가 4byte로 저장되어 있다고 합니다.
지금까지 내용을 위 그림을 통해 정리할 수 있습니다.
쉽게 Excption이 발생하면 맨 위 SEH Record부터 실행되고, 거기서 처리를 못하면 다음 Record로 가고 <- 반복입니다.
그리고 마지막 SEH Record는 windows에서 제공하는 Exception handler라고 합니다.
3. exploit
1. Exception을 발생시킵니다. <- SEH Chain을 사용하기 위해(ret를 이상한 곳으로 위치 시키면 발생함 <- 0xffffffff 등등)
2. next SEH record의 포인터를 JMP 코드로 덮습니다.
3. SE Handler의 포인터를 2번에서 덮은 JMP 코드가 실행되기 위해 PPR 가젯으로 덮습니다.
4. shellcode는 SE Handler 바로 뒤에 있어야 합니다.
위는 선행 조건들입니다.
쉽게 설명하면 아래와 같습니다.
1) Next SEH Record에는 shellcode로 점프하는 코드를, 예외 핸들러는 PPR 가젯 주소를 넣습니다.
2) 이 상태에서 예외를 발생시키면, PPR 가젯이 실행되고, RET 코드를 통해 Next SEH Record의 주소에 있는
점프 코드를 실행합니다. 점프 코드를 실행하면 shellcode에 도착합니다!
Exception Handler에서 다음 SEH Record의 주소는 esp+8에 저장된다고 합니다. esp+8에 다음 SEH Record 주소가 저장되는 거는, Exception handler 작성하는 Convention이라고 합니다.
위 말이 이해가 안되면 카테고리 윈도우 공부 - windows -0x05를 보자!
4. SEH Overwrite 개념
질문1) 레지스터 값에 shellcode 주소 넣고 jmp 하는 게 편한 거 아닌가?
위 방법은 windows XP SP1 이전에는 가능했지만, SP1 이후부터는 보호기법이 생겨서, Exception handling 하기 전에 모든 레지스터 값들이 XOR 됩니다. 따라서 SEH로 넘어가도 레지스터는 쓸모가 없어집니다.
질문2) RET overwrite 보다 SEH exploit의 장점?
기존의 stack base bof에서 ret를 덮으면 간단한데 SEH exploit을 하는 이유는 Stack guard(SG), Stack shield(SS), Stack cookie, canary 등 여러가지 이름으로 불리는 보호기법을 우회하기 위해 사용합니다.
5. 실습
http://pds.dnavi.info/windows95/121987
SEH 실습을 위해 위 프로그램을 사용합니다.
취약점은 프로그램의 UI가 저장되는 txt 파일에서 bof가 발생한다고 합니다.
설치경로/Skin/Default/UI.txt가 있습니다.
UI.txt 파일 내용을 A 5천개로 만든 뒤 프로그램을 실행 시켜보겠습니다.
프로그램이 실행되었다 종료됩니다..
이는 Exception이 발생해서 Exception Handler로 넘어 갔지만 적절한 SEH를 찾지 못해 그렇다고 합니다.
왜냐하면 SEH Record도 overwrite 했기 때문입니다.
이를 디버거를 통해 확인해 보겠습니다.
소리통에 windbg를 붙인 뒤 실행 시켜보겠습니다.
Exception이 일어나기 전에 windbg가 알아서 멈춰 버립니다.
!exchain 명령어를 통해 Exception handler를 덮었다는 것을 알 수 있습니다.
g 명령어를 치거나, F5를 눌러 진행 해보면 EIP가 0x41414141로 변견되는 것을 알 수 있습니다.
Next SEH Pointer와 SE Handle Pointer 위치를 알기 위해 UI.txt에 패턴 값을 넣습니다.
At6A가 됩니다.
exploit 코드를 짜보면 SE Handle가 정상적으로 덮인 걸 확인할 수 있습니다.
이제 PPR 가젯과 jmp 4 opcode만 알아내면 완성입니다.
Player.dll에서 null byte가 없는 가젯을 사용합니다.
Next SEH Pointer 값은 eb 06 90 90(jmp relative 6byte)인데 지금으로부터 6byte 앞으로 뛴다고 합니다.
short jump의 opcode가 0xeb라고 합니다. 그리고 그 뒤에 나오는 수 만큼 지금 eip에 상대 주소만큼 jmp한다고 합니다.
위 내용이 이해가 안되면 블로그 카테고리 중 윈도우 공부에서 JMP SHORT를 보자!
정보정보
1) SEH로 넘어가게 되면, ~~~ 앱이 크래시 나서 종료되었습니다~ 라는 OS단의 에러메시지가 나타나는데, 따라서 실력있는 개발자라면 SEH로 넘어가기 전에 개발 언어 자체에 있는 예뢰 처리 루틴에서 최대한 처리하도록 해주는게 좋습니다.
기본적으로 개발자가 만든 예외 핸들러가 먼저 돌고, 그럼에도 예외를 처리 못 할경우 windows OS단에서 제공하는 SEH가 작동 되는 것입니다.
2) FS, GS는 x86 아키텍처에서 여분의 세그먼트 레지스터로 window OS에서는 쓰레드와 관련된 정보들을 가리키는데 사용합니다.
3) 32bit에서만 SEH 우회가 가능하다. 64bit은 SEH가 다른 영역에 존재합니고 합니다.
참고
https://jjuns-studyroom.tistory.com/entry/Exploit-writing-tutorial-part3-SEH-base-exploit
https://eine.tistory.com/entry/코어렌-튜토리얼-Windows-Exploit-작성-튜토리얼-part3-SEH
https://c0wb3ll.tistory.com/entry/Training-2020-5-1-SEHEggHunter
'윈도우 버그 헌팅' 카테고리의 다른 글
Exploit writing tutorial part 8 (0) | 2024.03.06 |
---|---|
Exploit writing tutorial part 7 (0) | 2024.03.05 |
Exploit writing tutorial part 6 (0) | 2024.03.01 |
Exploit writing tutorial part 2 (0) | 2024.02.20 |
Exploit writing tutorial part 1 (0) | 2024.02.20 |