메모리 보호기법 우회 연구분석보고서 -3-
본 문서는 Stack Overflow 보호기법과 이를 우회하는 방법에 대하여 작성하였습니다. 해당 내용과 테스트 결과가 많은 관계로아래와 같은 주제로 3회에 걸쳐 연재합니다.
1. 'Windows/Linux 환경에서의 Stack Overflow 보호기법'
2. 'ROP(Return Oriented Programming) Exploit'
3. 'SEH(Structed Exception Handling) Overwrite'
1. GS 우회 가능성
GS 옵션으로 컴파일 시, 스택상으론 cookie변수가 buf변수 다음 위치하게 됩니다. 따라서 공격자가 BOF 공격시 스택내에 존재하는 cookie 값을 변조하기 때문에 프로그램은 .data 영역에 있는 cookie 값과의 비교를 통하여 비교결과를 통하여 BOF 공격을 감지합니다. 하지만 .data 영역은 쓰기 권한이 있는 영역이기 때문에 RET 앞에 존재하는 cookie 값과 .data 영역에 존재하는 cookie 값을 동일한 값으로 덮어쓰게된다면 우회가 가능합니다.
다음 화면은 GS cookie 값 테스트 및 검증을 하기 위해 Window XP SP1, Visual Studio .NET 2003 상에서 BOF 공격에 취약한 소스에서 GS 옵션만 설정한 후, 컴파일 한 화면입니다.
[그림 1] GS 옵션 설정
[그림 2] BOF에 취약한 소스코드
다음 화면은 해당 프로그램을 디스어셈블리 한 후, security cookie 를 확인하는 화면입니다. Cookie 값이 설정 된 후, ebp-4 부분에 복사되는 것을 확인 할 수 있습니다. 이는 Buffer 와 RET 사이에 cookie 가 존재한다는 것을 의미합니다.
[그림 3] cookie 확인
다음 화면은 프로그램 상에서 인자값을 “1234567890ABCDEF” 를 입력한 후, 분석을 시도하는 화면입니다. 프로그램에서 10바이트의 스택 공간을 할당하므로, BOF를 시도하여 분석을 하는 상황입니다.
[그림 4] 프로그램 실행
프로그램의 시작 부분에서 디스어셈블리 코드 상에서 확인한 security cookie 구간을 확인 가능합니다.
[그림 5] security cookie
XOR 연산 후에 레지스터에 저장되는 것을 확인 가능합니다.
[그림 6] XOR 연산
다음 화면은 .data 영역에 존재하는 cookie 값과 스택상에서 xor 연산된 cookie 값을 비교하는 화면입니다. 비교값이 같은 경우 에러는 발생하지 않습니다.
[그림 7] cookie 값 비교
2. SEH Overwrite(GS 우회)
GS를 우회하는 대표적인 방법으로 SEH Overwrite가 있습니다. 이 방법은 함수 Epilogue 시 Security Cookie값을 비교하기 전에 Exception을 발생시켜 실행흐름을 변경, GS Check를 우회하는 방법입니다. Exception을 발생시키기 위해서는 소스코드상에서 반드시 try-catch 문이 사용되어야만 합니다.
SEH Overwrite는 스택의 이전 RET영역까지 덮어 씌우는 것이 아닌 스택에 자리잡고 있는 EXCEPTION_RECORD 구조체의 _handler 부분까지만 덮어씌우게 되기 때문에 sfp와 ret값은 아래와 같이 변경되지 않습니다.
[그림 8] SEH Overwrite 개념도
[그림 9]과 같이 _EXCEPTION_RECORD(이하 ER)는 _next와 _handler로 구성됩니다. _next는 다음 ER의 위치를 가리키고 있는 싱글리스트 형태이며, _handler는 해당 Exception이 발생하였을 때 수행되는 코드의 위치가 저장되어 있습니다. ER은 상황에 맞는 다양한 Exception 처리를 위해 다수의 리스트형태(SEH Chain)로 구성됩니다.
[그림 9] SEH 구조
Exception이 발생하게 되면 _exception_handler 함수가 호출 됩니다. 호출 후 스택구성은 다음과 같이 구성 되며 _handler로 지정했던 주소가 내부적인 메커니즘(call ecx)에 의해 명령이 실행됩니다.
우선 생각해 볼 공격 시나리오는 _handler 주소를 원하는 shellcode 영역으로 직접 가리켜 shell을 실행시키는 방법이 있습니다. 이 방법은 Windows 2003에서부터 SEH가 수정되어 등록된 Load Configuration Directory외에 다른 위치의 주소가 가리켜져 있다면 handler를 실행하지 않는 것으로 바뀌었기 때문에 공격이 성공할 수 없습니다. 그래서 다른 시나리오를 생각해 봐야 합니다.
하지만 수정된 SEH는 Load Configuaration Directory외에 외부 모듈(DLL)에 대한 명령어에 대해서는 handler 실행이 허용된다는 것입니다. 이를 이용하여 shellcode를 직접 가리키지 않고 간접적으로 호출하여 특정 스택 부분으로 이동, jmp코르를 사용해서 shellcode를 호출하는 pop-pop-ret, jmp를 사용하는 방법으로 진행하겠습니다.
[그림 10] 공격코드 삽입시 스택 구조
공격코드가 삽입된 후 [그림 10]과 같이 실행순서가 ①~④ 순서로 진행됩니다. pop-pop-ret 명령이 실행하면서 esp+8 위치까지 올라가게되고 Exception이 발생하기 전에 위치가 저장되어있는 _EstablisherFrame 부분(② 위치)에서 ret명령이 실행되면서 ③의 위치로 옮겨지게 됩니다. 이 위치에 있는 명령어 코드가 실행되게되는데 OPCODE eb 10(jmp short eip+16)이 실행되면서 ④의 위치로 옮겨지게 되고 shellcode가 실행됩니다.
본 공격 시나리오는 Windows XP 영문판, 개발환경은 Visualstudio 2003에서 테스트 하였습니다.
다음과 같이 취약한 소스코드를 작성하여 SEH Overwrite를 확인해보겠습니다.
[그림 11] 취약점이 존재하는 소스코드
취약점이 존재하는 소스코드는 strcpy 함수 호출 이후 주소 0번지에 문자를 대입하여 Exception이 발생하도록 유도하였습니다.
프로젝트 옵션에서 Buffer Security Check(GS) 설정하여 Security Cookie가 삽입되도록 하였습니다.
[그림 12] GS 옵션 설정
인자값으로 스트링 100개를 삽입하게되면 Security Cookie를 덮어씌우게 되고 체크로직으로 인해서 Buffer가 넘쳤다는 오류 메시지가 발생합니다.
[그림 13] Buffer overrun detected!
동일한 인자값으로 OllyDBG를 이용하여 스택에 어느부분까지 덮어씌우는지 확인해보았습니다. 우리가 공략하려는 _prev와 _handler 부분까지 덮어씌우려면 아직 12 Byte가 부족합니다.
[그림 14] Buffer Overflow 위치 확인
12 Byte를 더 채우고 확인해보았습니다. _handler부분이 덮어씌어지고 42424242값이 EIP 값이 변경되어 실행되었고 42424242 번지는 존재하지 않는 부분이기 때문에 Error 메시지가 발생합니다.
[그림 15] Buffer Overflow 위치 확인#2
이제 공격 코드를 구성하기 위해 필요한 pop-pop-ret(Gadget)을 찾아보겠습니다. 현재 Process가 아닌 DLL영역의 검색해야하기 때문에 findjmp를 이용하여 검색하였습니다.
[그림 16] pop-pop-ret 검색
Exploit에 사용될 공격 코드는 다음과 같은 형태로 삽입됩니다.
[그림 17] 공격 Payload
앞서 설명했던 공격 시나리오와 위에 공격 Payload 형태로 Exploit을 작성하여 공격해보았습니다.
[그림 18] Exploit 작성
OllyDBG로 계산했던 _prev와 _handler의 위치를 인자값으로 입력하여 공격하면 다음과 같이 shell이 실행됩니다.
[그림 19] 공격 성공
SEH Overwrite를 이용하여 GS를 우회하였습니다. 하지만 이런 공격방법이 성공하자 MS는 SafeSEH 기술을 적용합니다. 다음 화면은 Window 상에서 메모리 보호 기법에 대한 관계도 입니다.
[그림 20] Window 메모리 보호기법
이는 SEH Chain 에 대한 Validation Check를 수행하게 되는데 SafeSEH기술이 적용된 프로그램은 위와 같은 공격은 무용지물이 됩니다. 하지만 SafeSEH 또한 우회하는 기술이 발표되었습니다. 연속적으로 jmp명령을 여러번 수행하여 원하는 쉘코드로 향하게 하는 방법입니다. 이 부분에 대해서는 시간상 추후 연구 과제로 남겨둡니다.
참고 URL
3. http://nchovy.kr/forum/5/article/377
4. http://en.wikipedia.org/wiki/Buffer_overflow_protection
5. http://ko.wikipedia.org/wiki/버퍼 오버플로우
참고 문헌
1. poc09-sotirov.pdf(POC 2009 발표자료)
2. BHUS10_Paper_Payload_already_inside_data_reuse_for_ROP_expl.pdf
(BlackHat 2010 USA 발표자료)
3. Linux Memory Protectiion Mechanism
4. bh08sotirovdowd.pdf(BlackHat 2008 발표자료)
5. BOF_공격방지_매커니즘_구현의_최신_동향.pdf
6. http://www.shell-storm.org/papers/files/732.pdf
7. www.phreedom.org/presentations/reverse.../reverse-engineering-ani.pdf
8. CanSecWest2010 – SEH Overwrite, Shuichiro Suzuki
9. Windows 구조와 원리 (OS를 관통하는 프로그래밍 원리) - 정덕영