본문 바로가기

취약점 분석/SEH

아드레날린 SEH 취약점 분석

반응형

1       아드레날린 POC

POC  파이썬   스크립트

exploit-db 올라온 exploit poc이다.

POC 내용을 보면 [BOF유발’A’*2140 + SEH overwrite + 쉘코드] 심플하게 구성돼있다.

 

exploit test

POC 파이썬 스크립트를 실행하면 .wvx 파일이 생성된다.

아드레날린을 열고 .wvx파일을 드래그하면 계산기가 팝업된다.

 

그런지, 실제로 어떻게 동작하게 되는 건지 원인으 분석해보자.

 

 

2       POC 실행 테스트

크래시   위치   확인

아무 BP없이 무작정 poc파일을 올려보았다. 앞서 POC 스크립트를 봐서 SEH 취약점이라는 것을 알고있기도 하지만, 쉘코드가 진행되지 않고 예외처리를 묻는 과정에서 멈춘다는 점에서 다시한번 SEH 취약점이구나를 짐작할 있다.

 

우측 스택을 보면 이미 많은 "AAAA"들로 가득차서 BOF 진행된 상태다.

 

예외가 발생한 어셈블리 코드를 보니 [ECX-C] 값과 0 비교하는 CMP구문인데, 값을 참조할 없어서 예외가 발생하는 .

 

SEH   체인   확인

SEH체인을 보면 역시나 오염되어 있는 상태를 확인할 있다. 주소에 BP 걸어 놓고 해당 주소의 어셈블리 코드를 보자.

PPR 위치한 것을 보아 전형적인 SEH 취약점 공략방식임을 있다.

 

 

 

 

PPR  확인

exception handler 함수의 두번째 인자가 SEH체인의 시작주소를 가지고 있다는 점을 이용한 공략방식이다.

exception handler함수를 호출하여 들어오는 것이므로 들어온 직후 스택 최상단에는 RETRUN주소가 담기며, 다음으로 exception handler 인자가 차례로 놓인다.

따라서 두번째 인자를 이용하기 위해서 POP POP RET 있는 주소로 덮어쓴 것이다.

Except_handler  인자설명

SEH 취약점에서 예외처리 함수로 들어온 직후 PPR 있는 코드로 가도록 해놓은 이유에 대하여 except_handler 함수 인자를 참조하자.

 

 

 

short jump -> shellcode

PPR 거쳐서 except_handler 두번째 인자인 SEH구조체의 시작주소로 점프한 상태이다.

어셈블리 명령어를 보면 short jump 위치해있는데, 이는 BOF에서 SEH구조체를 덮어씌울 아래에 있는 쉘코드로 점프하여 쉘코드를 실행시키기 위함이다.

 

기본적으로 스택상에서 SEH구조체는 [next_SEH, SE Handler] 순으로 구성되기에 이렇게 만든 것이다.

short jump 점프하는 주소를 보면 BOF 덮어씌워져있는 수많은 "AAAA" 이후에 오는 쉘코드임을 있다.

 

3       원인분석

이제 취약점이 발생한 원인에 대해 분석해보자. 스택 기반의 취약점이므로 크래시가 터진 근처에서 원인을 쉽게 찾을 있다.

 

크래시   발생   당시

다시 재실행하여 취약점이 트리거 되기 전인, 예외가 발생하여 SEH 구조체를 참조하기를 기다리는 상태로 돌아왔다. 먼저 상태에서 주변 정보를 살펴보자.

 

 

 

리턴주소   추적

BOF 진행되어 AAAA 가득찬 스택상황을 확인하였음에도 스택 최상단 근처에는 RETRUN주소가 살아있음 확인하였다. 이는 BOF 먼저 발생한 이후 Call 명령어가 수행됐기 때문이다.

이런 경우는 정말 편하게 원인분석이 가능하다.

 

RETURN주소를 타고 한칸 위를 보면 크래시 유발함수를 호출한 Call 명령어가 보인다.

그리고 근방을 찾아보면 BOF 유발하는 버퍼와 관련된 부분을 바로 찾을 있다.

ASCII "%s" 문자열 있다는 점에서 format string 형식으로 버퍼에 값이 옮겨졌음을 추측할 있다. (실제로도 그렇다)

 

 

ida 로   원인   확인

ida 보면 함수명과 함께 조금 구체적으로 있다.

CStdioFile::ReadString 함수를 호출하여 특정 파일로부터 문자열을 읽어온다.

 

 

 

이어서 목적지가 버퍼를 0으로 초기화하는 코드가 나타나는데 크기를 보면 0x7FF(Dst Buffer 크기)임을 있다.

 

이후 sprintf 함수를 호출하며 Src에서 Dst %s형식으로 데이터를 옮긴다. 여기서 Src Dst 크기를 검사하는 루틴이 없으므로 Src 크기가 크더라도 무작정 덮어쓰므로 BOF 발생하는 것이다. 원인분석이 정말 간단하게 끝났다.

 

 

CStdioFile::ReadString
ReadString 단일인자

앞서 ReadString 인자는 다루지 않았는데 여기서 살펴보겠다.

ReadString 호출할 전달한 인자는 1개로, 두번째 가상함수 형식과 동일하다.

 

nMax-1개의 문자까지 읽어올 있는데, Dst버퍼의 크기를 0x7FF 고정을 시켜놨다는 점과 취약한 sprinf 함수를 사용함에도 앞에 크기를 비교하여 예외처리를 하는 구문이 없다는 점이 이같은 BOF 유발시키게 것이다.

아드레날린 POC 취약점 분석은 여기서 마무리한다.

반응형