https://www.corelan.be/index.php/2009/09/21/exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/

 

Exploit writing tutorial part 6 : Bypassing Stack Cookies, SafeSeh, SEHOP, HW DEP and ASLR | Corelan Team

Introduction In all previous tutorials in this Exploit writing tutorial series, we have looked at building exploits that would work on Windows XP / 2003 server. The success of all of these exploits (w

www.corelan.be

본 포스팅은 위 링크 글을 번역 및 공부하면서 따라해보는 포스팅입니다.

 

------------------------------------------

도입

이전 튜토리얼 시리즈에서 우리는 Windows XP랑 2003 서버에서 익스플로잇을 작성해보았습니다. 기존에 성공한 익스플로잇들은 pop/pop/ret 가젯 주소가 잘 찾아진다는 것과 안정적인 return을 할 수 있다는 것에 기반해서 쉘코드로 성공적으로 점프했죠. 모든 경우에서 우리는 운영체제의 dll이나 앱의 dll에서 적당한 주소를 찾아가지고 갔습니다. 

그리고 이러한 주소들은 재부팅을 하더라도 동일하게 유지가 되어서 안정적으로 익스플로잇을 작성할 수 있었지요.

 

하지만 다행스럽게도 엄청난 수의 윈도우즈 계열 사용자들은 윈도우즈 시스템에 기본적으로 내장된 보호기법들이 적용되어 있습니다.

 

- 스택 쿠키(/GS Switch 쿠키)

- Safeseh (/Safeseh 컴파일러 switch)

- 데이터 실행 방지(DEP) (소프트웨어 기반이든 하드웨어 기반이든)

- 주소공간 배열 랜덤화(ASLR)

 

스택 쿠키 /GS 보호기법

스택 쿠키는 컴파일러 옵션입니다. 함수의 프롤로그와 에필로그에 스택 기반 오버플로를 막는 코드들을 삽입하는 거죠.

 

프로그램 실행 시 Data 섹션에 쿠키 원래값(Authoritive cookie)을 하나 랜덤하게 만들어서 저장을 해 놓고, 함수 프롤로그에 스택 사이에 스택 쿠키를 삽입하고, 리턴하기 직전에 스택 쿠키값이 Data 섹션에 있는 녀석과 같은지를 확인하는 방식입니다.

스택 프레임이 다음과 같이 구성되겠지요

 

[지역 변수][stack cookie][saved ebp][ret addr][param]

---------------------------------------->

그래서 ret addr를 변조하려면 stack cookie가 먼저 변조가 되게 됩니다.

 

그래서 stack 영역에 있는 buffer overflow 기반으로 인한 공격들을 막을 수 있게 됩니다. 

그리고 이 보호기법의 성능 이슈를 줄이기 위해서, 지역변수에 뭔가 입력을 받는 버퍼가 없는 경우에는 스택 쿠키를 삽입하지 않습니다. 

 

그리고 /GS 보호기법에는 스택 쿠키 외에도, 지역변수 순서 변경(reordering)도 있습니다. 크기가 좀 있는 버퍼들의 경우, 즉 char[]과 같은 문자열 버퍼같은 녀석은 스택의 상위 주소로 두어서, 이 녀석이 buffer overrun이 되어도 int 와 같은 지역변수들을 오염시키지 못하게 합니다.

 

스택 쿠키 /GS 우회하기

스택 쿠키를 우회하는 방법은 다양하게 있겠지만, 쿠키 값을 알아내거나(추측하거나 계산하거나 메모리 값을 들여다 보는 경우)하는 경우 같은 값을 다시 넣어주면 됩니다.

 

그렇게 하지 않더라도 .Data 섹션에 있는 원래 쿠키값(Authoritive cookie)를 변경하는 방법도 있습니다.

이걸 하려면은 메모리에 대하여 arbitrary write이 가능해야겠지요? 임의의 메모리 주소에 값을 쓸 수 있어야지 .Data 섹션의 authoritive cookie를 덮어쓸 수 있을 것입니다.

 

그 외에도 SEH가 있다면 이전 포스팅에서 했던 것 처럼, SEH overwrite으로 우회가 가능합니다.

왜냐면 함수가 리턴하기 전에 스택 쿠키 값이 valid한지 체크를 하는데, 만약 authoritive cookie와 값이 다르다면 Exception이 발생하게 됩니다. 따라서 SEH로 제어권이 넘어가게 되는데, 이때 SEH는 우리가 덮어쓴 값이므로 결국 제어권이 공격자의 손에 떨어지게 되지요.

 

그 외에도 buffer write이 없는 함수의 스택 프레임에는 쿠키가 없으므로 이를 이용해서 공격을 하는 경우나, ret나 saved ebp까지 덮어쓰지 않고 스택에 있는 지역변수만 덮는 식으로도 공격이 가능한 경우에도 스택쿠키를 우회할 수 있습니다.

 

스택 쿠키 값을 추측하거나 계산해서 풀기도 하고, 쿠키 값이 변하지 않는경우(static) 이를 이용해서 우회하기도 합니다.

 

혹은 가상함수 포인터를 호출할 때, 호출하는 변수가 스택에 남아있는 경우가 있습니다. 이런경우에도 지역변수만을 덮어써도 제어권을 가져갈 수 있습니다.

 

 

SafeSEH

SafeSEH는 SEH overwrite을 막기 위한 보호기법입니다. 기존의 SafeSEH가 적용되지 않은 녀석과 다른점이라고 하면, 컴파일할때 SEH가 가능한 함수 주소 리스트를 다른곳에 따로 가지고 있습니다. 그리고 SEH에서 Exception Handling을 할 때, SEH에 쓰여있는 주소가 가능한 함수 주소 리스트에 있는 녀석이 맞는지 확인을 한 뒤, 맞는 경우에만 SEH로 넘어가게 됩니다. 여기 리스트에 해당하지 않는 경우에는 변조된 핸들러로 넘어가지 않고 그냥 프로그램이 종료되게 됩니다. MS에서 이 옵션을 꽤 안정적이게 잘 만들었고, 그래서 많은 OS모듈들이 이 옵션을 가지고 컴파일이 됩니다.

 

SafeSEH 우회하기

가장 쉬운 방법은 SEH based exploit을 안하면 됩니다.

 

아니면 다른 로드된 모듈중에서 SafeSEH가 안되있는 녀석이 있으면 그녀석을 이용해서 익스플로잇을 하면 됩니다.

 

SafeSEH는 어쨋든 우회하기 꽤 빡센 보호기법 중 하나라고 볼 수 있습니다.

 

하지만 우회할 수 있는 몇가지 방법들이 있긴합니다. 케이스 별 특징을 몇가지 알아보겠습니다.

- 만약 handler의 주소가 로드된 모듈의 주소 범위 밖이라면 실행이 됩니다.(SafeSEH가 안전하다고 판단하고 실행해버림)

- 만약에 핸들러 주소가 로드된 모듈 주소 범위안에 있는 경우, 그리고 그 모듈이 Load Configuration Directory가 없는 경우 이 DLL 특성은 SE Handler Verification 시험을 통과해서, handler가 실행이 될 것입니다.

- 만약 핸들러의 주소가 스택 주소 범위라면, 실행이 안 될 것입니다. 하지만 힙 주소로 overwrite되었다면 실행이 됩니다.(하지만 힙 주소는 예측하기가 훨신 어렵지요)

- 만약 handler 주소가 이미 등록된 핸들러 주소로 덮어쓰였다면, 정상적으로 SEH로 넘어가게 됩니다. 이 경우는 기존에 있는 핸들러가 쉘코드를 깨지 않고 익스플로잇 하는데에 도움이 되는 경우입니다. 그리고 이런경우가 드물긴 한데 실제로 일어나기도 한다고 합니다.

 

범위 주소 밖 모듈 이용하기

위에서 SafeSEH에서 Handler 주소가 안전한지 확인하는 과정 중에서 자신의 로드된 모듈 주소 범위를 벗어나는 경우 안전한것으로 간주한다는 점이 있습니다. 다른 모듈의 경우 또다시 확인을 해야하는 번거로움이 있어서 그냥 진행하는 것으로 보입니다. 이를 이용해서 공격이 가능합니다.

 

물론 다른 모듈을 이용한다는 것은 다른 프로세스가 떠있다는 것을 가정하고 공격이 이루어지는것인데, 이게 OS모듈을 이용해서 공격을 한다면, 이 공격은 OS 버전에 따라 모듈이 달라질 수 있으므로 덜 reliable한 익스플로잇이 되게 됩니다.

따라서 좀 더 복잡한 공격이 될 수 있습니다.

 

 

DEP(Data Execution Prevention)

여태까지 쉘코드를 다 스택에다가 올려놓고 실행을 시켰는데, 이 스택 영역은 원래 데이터 영역이라 코드가 실행되는 구간이 아닙니다. 이를 이용해서 데이터 영역은 코드 실행 권한을 빼버리는 방식의 보안 기법이 고안되었는데 이것이 DEP입니다.

 

DEP는 윈도우 XP 서비스팩2에서 도입이 되었습니다. 그리고 이 DEP는 하드웨어 DEP가 데이터 영역 실행 방지라고 보면되고, 소프트웨어 DEP는 SafeSEH랑 똑같다고 볼 수 있습니다.

 

소프트웨어 DEP는 NX나 XD 비트와는 전혀 관련이 없습니다. 만약 프로세서나 시스템에서 NX/XD 비트가 지원이 되고 활성화가 되어 있으면 Windows DEP는 하드웨어 DEP와 동일합니다. 만약 프로세서가 지원을 하지 않는다면 DEP는 없고 SafeSEH만 가능하다고 보면 됩니다.

 

프로세서 벤더의 양대 산맥은 자기들만의 실행불가한 페이지 보호기법(하드웨어 DEP)을 구현했습니다.

 

암드(AMD)는 no-execute page-protection(NX) 비트를 사용하고 인텔은 Execute Disable Bit(XD) 기능을 개발했습니다.

 

NX/XD 비트

하드웨어 도입 DEP는 호환이 되는 CPU에서 32비트 윈도우 커널에서 PAE(Physical Address Extension)나 아니면 네이티브 64비트 커널의 사용을 통해서 NX비트를 활성화 시킵니다. 윈도 비스타 DEP는 일부 메모리 바트를 데이터용으로만 쓰겟다고 마킹을 한 뒤, NX비트나 XD비트를 체크해서 프로세서가 이 부분은 실행하지 않도록 합니다.

 

NX 보호기법의 컨샙은 매우 간단합니다. 만약 하드웨어가 지원하는 NX가 있다면, BIOS에서 NX를 활성화 시키고, 운영체제가 지원한다면 시스템 서비스는 보호받을 수 있습니다. MSVC와 같은 컴파일러에서 링킹 시 flag를 주어서(/NXCOMPAT) 어플리케이션에 DEP 보호기법을 적용하도록 할 수 있습니다.

 

HW DEP 우회하기

DEP를 우외하는 몇가지 잘 알려진 테크닉들을 소개합니다.

 

ret2libc(쉘코드 사용하지 않음)

이 테크닉은 쉘코드로 점프뛰는 대신, 이미 존재하는 라이브러리나 함수를 호출하는 방식입니다. 이미 존재하는 함수들로 공격자의 악성 코드를 실행하는 것입니다.

 

 

-------------------------------------------------------------

 

+ Recent posts