( GS + SafeSEH 우회 익스플로잇 : http://5kyc1ad.tistory.com/312 )

SEH Overwrite에 대한 기초적인 내용은 http://5kyc1ad.tistory.com/308 여기와 위 링크를 참고하시기 바랍니다.

 

SEHOP : Linked-List 형태인 SEH 체인을 참조하여 마지막 SEHSEHRecord->pNextSEHRecord에는 0xFFFFFFFF, SEHRecord->pExceptionHandler에는 Ntdll!FinalExceptionHandler 함수 주소가 지정되어 있는지 확인하는 보호 기법.

 

 * 이하에서 익스플로잇에 사용한 프로그램에 스택 기반 BOF SEH Overwrite 취약점이 존재하지만 NULL을 입력할 수 없는 문제가 있어 실습을 위해 메모리에 직접 수정을 가해서 입력되었다는 가정 하에 익스플로잇 실습을 진행했습니다. 해당 프로그램은 위 ‘GS + SafeSEH 우회 익스플로잇에서 사용한 것과 동일합니다.


 

 

[정상적인 SEH 체인]

 

[비정상적인 SEH 체인]

 기존에 SafeSEH를 피해 SEH Overwrite를 했던 기법을 그대로 사용하면 pNextSEHRecordRelative Short JMPOPCode로 변조되어버리기 때문에 SEH 체인이 끊기고 SEHOP에 탐지되어 정상적으로 Exploit이 실행되지 않습니다.

 

GS + DEP + SafeSEH + SEHOP가 적용되어 있고 ASLR이 있다고 가정할 경우 공격 방법은 다음과 같습니다.

 

[덮어쓸 SEHRecord 주소와 값 확인]

 스택에서 덮어쓸 SEHRecord 주소와 pNextSEHRecord 값을 확인합니다. pNextSEHRecord 0x18FA90이며 바로 밑에 다음 SEHRecord가 있는 것을 볼 수 있습니다. SEH 체인을 끝까지 다 따라가면서 덮어씌워주기는 힘드므로 저 두 번째 체인을 0xFFFFFFFF Ntdll!FinalExceptionHandler 함수 주소로 변조하여 정상적으로 보이는 SEH 체인을 만들어야 합니다

 

[마지막 SEHRecord ]

 마지막 SEHRecord까지 계속 참조하여 Ntdll!FinalExceptinHandler 주소값이 0x772E7428인 것을 확인할 수 있습니다.

 여기까지를 페이로드로 작성하면 다음과 같습니다.

Dummy(0x54) + 0x18FA90 + ???? + Dummy(4) + 0xFFFFFFFF + 0x772E7428

 

[익셉션 발생 직후 Handler 함수]

 익셉션 발생으로 SEHRecord->pExceptionHandler가 호출된 직후의 ESP의 위치를 확인하기 위해 Handler 함수에 바로 BP를 걸고 강제로 익셉션을 발생시켜 ESP0x18F448에 위치하게 됨을 확인했습니다. 위에서 인위적으로 만든 종료 체인 이후 스택 주소가 0x18FA98 이므로 0x18FA98 - 0x18F448 = 0x650 이상 ESPPOP 또는 ADD ESP로 옮긴 후 ret을 해야 원하는 대로 ROP 체인 구성이 가능합니다.

 

[Ollydbg Search for All Sequences]

 해당하는 가젯을 찾기 위해 Ollydbg CPU 창에서 우클릭 -> Search for -> All Sequences 창을 열고 위와 같이 와일드카드 문자 CONSTR32를 이용하여 가젯을 검색했습니다. (pop 없이 해봤더니 적당한 가젯이 나오지 않았습니다)

 

[발견한 가젯]

 바이너리 내에서 해당 가젯을 찾아내었습니다. ADD ESP, 0x800 POP 1번 후 ret을 하므로 총 0x804만큼 ESP가 움직이게 됩니다. 0x650 - 0x804 = -0x1b4 이므로 총 0x1b4개만큼 Dummy를 추가로 넣은 후 적당한 함수 주소를 넣어 주면 ROP가 가능할 것으로 보입니다.

 

여기까지 페이로드는 다음과 같습니다.

Dummy(0x54) + 0x18FA90 + 0x452336 + Dummy(4) + 0xFFFFFFFF + 0x772E7428 + Dummy(0x1b4) + ROP Chain

 

[익스플로잇 스택 구조도]

 실제 스택 주소 기반으로 페이로드가 들어가 익스플로잇된 스택 구조를 그려봤습니다. 익셉션이 터지는 순간 익셉션 처리 과정에서 스택이 추가로 늘어나고 0x18F448ESP가 위치하게 됩니다. 이후 &GadgetpExceptionHandler 위치이므로 이 가젯을 실행하게 되는데 여기에는 ADD ESP, 0x800POP, ret이 있으므로 ROP Chain이 존재하는 0x18FC4C에서 ret을 하게 되고, ROP Chain이 실행되어 익스플로잇에 성공하게 될 것입니다. ROP Chain 위의 Dummy 부분은 어차피 말 그대로 Dummy이므로 그곳에 문자열을 넣고 간단히 MessageBox를 호출하도록 짜서 돌려봤습니다.

 

[Exploit 1]

 익셉션 발생하기 직전의 샘플, EAX0x90909090이 들어 있는데 포인터 참조하여 익셉션이 발생하려고 하고 있고 pExceptionHandler는 이미 0x452336으로 변조된 상황입니다.

 

[Exploit 2]

익셉션이 발생하고 0x452336BP에서 멈춘 상태. ESP0x18F448까지 내려갔고, ADD ESP, 800Pop이후 ret이 실행되므로 0x18FC4C의 값이 ret 될 것으로 예상 가능합니다.

 

[Exploit 3]

정확히 0x18FC4C의 값을 ret하며, 그 밑에 두번째 인자로 0x1B4 크기의 Dummy에 넣은 문자열 “Exploited!!”가 들어가는 것을 볼 수 있습니다.

 

[Exploit 4]

해당 함수는 MessageBoxA 함수였으며, 넣은 값 그대로 출력 후 종료됩니다. POP~RET 가젯도 찾아두었으니 여기에 라이브러리 함수를 연결해서 돌리기만 하면 ROP 체인을 계속 연결해 나갈 수 있겠습니다.

 ASLR이 걸려있지 않았기 때문에 주소값 넣는 데에 지장이 없었지만 ASLR까지 걸려있다면 주소를 Leak할 수 있는 취약점이 없는 이상 익스플로잇은 어려워 보입니다.

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,