어쩌다 보니 환경 구축만 계속 여러번 하게 되는 듯 하다.

회사 리눅스 컴이 맛가서 밀고 다시 설치하고, 집컴와서 vm에 Ubuntu 깔고 다시 설치하고 등등... 그냥 이렇게 된 김에 한번 싹 정리하자.

 

Linux에서 포너블 문제풀이든 할 환경을 싹 구축해보자.

사실 그렇게 복잡하진 않다.

Virtualbox에 Ubuntu 18.04 설치

이 과정은 뭐 대충 다 아실거라 생각한다. Virtualbox 설치하고, Ubuntu 18.04 iso 다운받아서, 대충 머신만든 뒤, iso넣어서 부팅하면 아래 처럼 나온다.

Live CD로 플레이하는게 있고, 설치하는게 있는데 당연 설치이다. 언어랑 키보드는 English(US)고르고 그냥 계속 Continue누르면 된다.

Normal install이라고 되있는데 Minimal install으로 바꿔서 했다.

기본 옵션으로 간다.

스왑 알아서 박는다는데 걍 Continue로 간다.

어디있냐는데 Seoul 그대로 간다. 타임존이랑 apt repository 때문에 물어보는거일듯 함.

유저명이랑 패스워드 정하라는데, 어차피 vm안에 놈이니 대충정하자. 좀 기다린다

이제 설치가 다 된거다.

 

virtualbox extension 설치

설치를 하고 나면 화면이 굉장히 작고 host랑 클립보드 공유가 안되는 걸 알 수 있다.

extension을 설치해줘야한다.

게스트 확장 CD 이미지 삽입을 누르면, vbox내에 guest extension 설치 파일이 있는 이미지가 CD로 들어간것처럼 된다

실행하고 안애 파일을 설치시켜주면 된다.

비밀번호를 치면 알아서 설치가 된다.

이제 재부팅을 해주자. 이제 vbox 윈도우를 전체화면을 하면 안에 화면도 꽉차게 된다. 꿀!

 

클립보드 공유도 설정을 해주자.

우분투 화면잠금 해제

Settings -> Privacy -> Screen Lock을 Off해주면 된다.

우분투 sleep mode 해제

Power saving에 never 해준다.

pwntools 설치

일단 python3부터 설치를 해야 한다. 그리고 python3-pwntools를 설치를 하면 된다.

$ sudo apt update && sudo apt install -y python3 python3-dev python3-pip git && pip3 install --upgrade git+https://github.com/arthaud/python3-pwntools.git

 

잘 설치되었는지 한번 확인해보자.

별 다른 에러가 없는거보니, 잘 된 것 같다.

 

gef 설치

$ sh -c "$(curl -fsSL http://gef.blah.cat/sh)"

 

(curl을 미리 설치해야 한다)

 

잘 된다. 사실 뭐 별것없다. 쓰고나니 다 간단하기만 했네

vscode 설치

text editor로 vscode를 깔아보자.

공홈가서 deb 파일을 받은 뒤

$ sudo dpkg -i vscode.deb 하면 된다.

 

References

https://github.com/hugsy/gef

https://github.com/arthaud/python3-pwntools

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(쉘코드 사용하지 않음)

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

 

 

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

 

https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/

 

Exploit writing tutorial part 3 : SEH Based Exploits | Corelan Team

In the first 2 parts of the exploit writing tutorial series, I have discussed how a classic stack buffer overflow works and how you can build a reliable exploit by using various techniques to jump to

www.corelan.be

서문

이번 포스팅은 위 글의 원문을 따라하면서 공부해보는 포스팅입니다.

Part1에서 바로 Part3로 넘어갔는데, Part2는 기존 bof에서 shellcode로 점프하는 다양한 방법들을 소개를 합니다.

 

물론 자만하면 안되지만, 약간 어느정도 아는 내용이기도 하고 해서 잘 모르는 SEH관련 내용인 part3로 바로 넘어왔습니다.

 

저번 포스팅에서 Windows XP및 어느정도 개발 환경을 구축을 한 상태이므로, 거기서 추가적으로 환경 구축을 해야 하는 것들만 설명하면서 넘어가도록 하겠습니다.

 

이번 포스팅에서는 SEH Based Exploit이라는 새로운 개념을 이용한 공격 코드를 작성하는 것을 다루는데, SEH는 Windows에서만 있습니다. 아마 리눅스에도 비슷한 역할을 하는 녀석이 있겠지만 SEH라는 이름과 매커니즘은 윈도우즈 계열 OS에서만 쓰이는 녀석이라고 할 수 있겠지요.

 

따라서 저처럼 리눅스 Exploit을 공부하다가 윈도우로 넘어오신 분들은 생소하실 것이라 생각합니다.

 

환경설정

Windows XP에서 동작하는 C 컴파일러 설치

중간에 예제코드를 빌드한 뒤 확인해보는 과정이 있어서 C 컴파일러를 하나 구해야 한다.

 

구글링을 해보니, MSVC++ 2008 Express가 Windows XP에서 동작한다고 한다.

맨 위의 링크를 누르니, 바로 exe파일이 다운로드 된다. 마소에서 공식적으로는 지원하지 않는데 링크는 남아있어서 받을 수 잇는 모양이다.

Windows XP 가상머신에서 실행해서 설치를 해보자.

다행히 되는 것 같은 느낌이다.

 

조금 오래 걸리는 것 같긴한데, 그래도 되는게 어딘가 하는 마음으로 기다리고 있다.

 

좀 기다려 보니 설치가 잘 되었다.

 

 

ollydbg (올리디버거) 설치

구글링하면 올리디버거 공식홈페이지에서 다운로드 받을 수 있다.

최신버전인 1.10 버전을 받아야지 플러그인을 사용할 수 있어서, 최신버전을 받았다.

XP에서 압축을 풀고 실행해보았다.

 

Ollygraph

 

그리고 코어랜 블로그에서 추천하는 올리디버거 플러그인인 ollygraph를 설치해보자.

 

근데 wingraph32.exe라는 IDA에 있는 분석 툴이 있어야 한다.

 

후 이젠 구버전 IDA까지 구해야 한다니 이건 좀 에반거같긴하다.

못구했기 때문에 일단 안쓰는것도 괜찮을듯 ㅠ

 

그래도 일단 플러그인 설치를 하자면 아래와 같이 진행하면된다.

 

http://www.openrce.org/downloads/details/173/OllyGraph

 

OpenRCE

File Information OllyDbg Plugins Yes 18,014 Download from OpenRCE MD5 Sum: DCE10D99E7B21D6EAE6D1B06F378CE80 Last updated on Aug 2, 2005 with the following description: Initial release Author Information Description This plugin allows you to generate VCG-co

www.openrce.org

OpenRCE라는 곳에서 다운받을 수 있다.

 

압축을 푼 다음 위에 있는 ollygraph 안에 있는 모든 파일들을 Ollydbg가 있는 폴더에 다 같이 넣어주면 플러그인이 설치된다고 한다.

 

올리디버거를 재시작 하면 Plugins에 Ollygraph가 보이게 된다.

 

SEH(Structured Exception Handling)이란?

구글에 SEH를 치면 꽤 많은 자료가 나오긴 합니다. 위키백과에도 한글로 된 문서가 있네요. Microsoft에서 예외 처리를 하는 루틴이라고 볼 수 있습니다. 그리고 이 SEH라는 예외 처리 매커니즘은 라이선스에 특허권이 있어서 오픈소스 운영체제들은 이 SEH 기반 매커니즘을 사용하지 않는다고 합니다. 따라서 리눅스에서 하는 방식과 다를 수 밖에 없군요.

 

SEH에 대한 자세한 설명을 한 글들은 다른데도 많을 것으로 생각됩니다. 저는 상단에 표기된 코어랜 튜터리얼을 따라하는 것에 포커스를 맞추어 보도록 하겠습니다.

 

예외 처리(Exception handling)이란?

프로그램이 실행중에는 여러 예외가 나타날 수 있지요. 0으로 나눈다던지, 스택오버플로가 나서 segmentation fault가 난다던지 등등이 일어날 수 있습니다.

어플리케이션단에선 try ~ catch 구문으로 어느정도 예외를 처리할 수 있는데, 이 앱단에서 예외를 다 처리하지 못하면 OS단으로 넘어가게 됩니다.

 

이 OS단에서 예외를 처리할 때 윈도우는 SEH라는 것에 기반해서 처리를 하게 됩니다.

 

근데 이 예외 처리하는 루틴들의 주소가 스택에 저장이 되게 됩니다.

코어렌 블로그에서 퍼온 이미지입니다.

 

Local vars에서 buffer overflow가 나게 되면, 지역변수 밑에 있는 saved ebp, saved eip(ret addr) 및 함수 인자들과 이런 것들을 다 덮어쓰게 되는데, 맨 마지막에 address of exception handler가 보이지요?

 

요녀석 까지 원하는 다른 값으로 덮어쓰게 되면, 나중에 Exception이 발생했을때 내가 원하는 루틴으로 점프를 뛰게 만들 수 있다는 것이 핵심입니다.

 

SEH로 넘어가게 되면, 무슨무슨 앱이 크래시 나서 꺼졌습니다~ 라는 OS단의 에러메시지가 나게 되는데, 따라서 훌륭한 개발자라면 SEH로 넘어가기 전에 개발 언어 자체에 있는 예외 처리 루틴에서 최대한 처리하도록 해주는게 좋습니다.

 

기본적으로는 이러한 개발자가 만든 예외 핸들러가 먼저 돌고, 이 녀석들이 다 예외를 제대로 처리하지 못하면 최후의 보루로 Windows OS에서 제공하는 SEH가 쓰이게 되는 것이지요.

 

SEH 채인 구성요소의 구조

SEH는 스택 프레임의 구성요소입니다. 따라서 스택 프레임에 저장되지요.

대충 구조를 보자면, SEH 구조체는 8바이트 크기이고 4바이트 요소 2개로 구성됩니다.

하나는 다음 SEH 구조체의 주소이고, 하나는 예외 핸들러의 주소입니다. 그래서 만약 지금 핸들러로 예외를 처리하지 못하면 다음 핸들러로 넘어가는 식이고, 따라서 Single Linked list형태가 됩니다. 

그리고 이 SEH 체인의 첫번째 주소를 가리키는 포인터는, 앱의 main 함수가 있는 곳의 데이터 블럭, 혹은 TEB(Thread Environment Block, 쓰레드 정보를 가지고 있는 OS 자료구조, TIB; Thread information block라고도 불림)에 저장됩니다.

그리고 요녀석(TEB)은 FS라는 세그먼트 레지스터가 가리키고 있나봅니다. 그래서 SEH 체인은 FS:[0] 체인이라고 불리기도 한답니다.

위키에 안그래도 잘 설명이 되어 있네요. FS:[0]에는 SEH 프레임의 주소가 4바이트로 저장되어있다고 합니다.

 

FS, GS는 x86 아키텍쳐에서는 그냥 여분의 세그먼트 레지스터인데, Windows 운영체제에서는 쓰레드 관련된 정보들을 가리키는데 사용하는 것 같습니다.

 

그래서 인텔 CPU머신에서는 SEH 코드를 디스어샘블 해보면, move DWORD ptr from FS:[0]와 같은 명령어를 볼 수 있습니다. 요 명령어로 예외 핸들러가 쓰레드에 설정되고 에러가 났을때 처리할 수 있게 되는 것이지요. 이 명령어의 기계어 opcode는 64A64A100000000 인데요, 만약 이 코드를 못봣다면, 해당 앱이나 쓰레드는 예외 핸들러가 없는 것입니다.

 

코어랜에서 제공한 예제코드를 한번 빌드를 해보겠습니다.

MSVC++ 2008 Express를 켜서, Win32 Console App 프로젝트를 생성을 합니다.

 

뭔가 옛날 생각이 새록새록 나네요. 프로젝트 명은 sehtest로 했습니다.

곧이어서 Empty Project에 체크를 하고 Finish를 한 뒤 Hello world를 찍어보겠습니다.

Xp에서 코딩하는 맛이란 참 특이하네요. 그러면 corelan 예제코드를 한번 빌드해보도록 하겠습니다.

빌드를 합니다.

바로 실행을 하니 Exception이 뜹니다. 아마 argv[1]이 존재하지 않아서 그런 것 같네요. Exception handler가 호출이 된 모습도 보입니다.

argv[1]를 넣어서 실행하니 App launched만 뜹니다. 예외가 발생안하고 그런 모습이지요.

일단 그러면 코어랜 블로그에서는 저 바이너리를 디버거 붙여서 보라고 했으니 한번 그렇게 해보도록 하겠습니다.

 

Windbg를 킨 뒤, File - Open Executable로 sehtest.exe를 열어보았습니다. 실행을 해버리면 크래시가 나니 이 상태만 보라고 하네요.

sehtest.exe는 00400000와 0041b000 범위의 주소에 할당되어 메모리에 올라갔네요. 여기서 64 A1을 한번 찾아보겠습니다.

잘 있네요. Exception Handler가 있다는 걸 알 수 있습니다. TEB를 한번 까봅시다. FS 레지스터가 가리키는 메모리를 보면 됩니다. 

0c fd 12 00가 첫번째 SEH 구조체(Record)임을 알 수 있습니다. 엔디안을 고려해서 0x12fd0c가 주소가 되겠지요.

첫번째 SEH 레코드 입니다. 첫 4바이트가 0xffffffff로 SEH의 마지막 레코드이라는 것을 나타내는데, 이게 프로그램이 실행이 되지 않아서 이런거라고 합니다. F5를 누르거나 명령어 g를 쳐서 프로그램을 실행시킨 뒤 다시 확인해볼 수 있습니다.

실행을 하고 SEH 첫번째 레코드와 두번째 레코드의 모습입니다.

마지막 레코드는 0xffffffff로 끝나는 걸 알 수 있지요.

 

올리디버거로 보면 이게 더 쉽게 보이게 되어있다고 합니다.

 

View - SEH Chain을 누르면 다음과 같게 쉽게 볼 수 있습니다.

첫 SEH 레코드가 0x12ff58에 있다는걸 알려줍니다.

여기서 두번째 SEH Record의 SE handler가 0x411078 ExceptionHandler()라고 합니다. 한번 찾아가봅시다.

또 jmp를 하는군요. 블로그랑은 좀 다르게 되어있긴 합니다.

 

대충 이런식이라 하네요. 그래서 Exception이 발생하면 맨 위에 SEH Record부터 착착 하고 넘어가고, 거기서 처리를 못하면 다음 녀석으로 가고 이런식으로 반복이 된다고 합니다.

그리고 마지막 SEH Record는 윈도우에서 제공하는 Exception handler라고 합니다.

 

최종보스인 운영체제에서 처리를 하는 경우가 되는 거죠.

 

익스플로잇 작성

 

익스플로잇 전략

이번에는 소리통이라고 하는 고전 프로그램의 취약점을 익스플로잇 해볼건데, 이때 SEH를 이용해서 공격한다고 합니다.

공격 전략은 다음과 같습니다.

 

선행조건들입니다.

1. Exception을 발생시킵니다. 그래야지 SEH를 이용해먹을 수 있거든요.

2. 다음 SEH Record의 포인터를 jmp 코드로 덮어써놓습니다.

3. SE Handler의 포인터를 2에서 덮은 점프코드를 실행하도록 다른걸로 덮어놓습니다.

4. 쉘코드는 덮어쓰여진 SE Handler 바로 뒤에 있어야 합니다.

익스플로잇이 발동되는 시퀀스를 그린 그림입니다. (1)에서 Exception발생이 되서 SEH로 넘어오게 됩니다.

그리고 SE Handler로 넘어가는데, 요녀석은 pop pop ret 가젯으로 덮어쓰여져 있습니다. 

Exception Handler에서 다음 SEH Record의 주소는 esp+8에 저장된다고 합니다. 그래서 pop pop ret을 하면 다음 SEH Record의 주소로 뛰게 되는데, 이 주소 역시 아까 쉘코드로 jmp뛰는 코드로 덮어놓았지요.

그렇게 연계 공격이 되는 것입니다.

 

esp+8에 다음 SEH Record 주소가 저장되는 거는, Exception handler 작성하는 Convention인 것 같습니다. 소스코드 레벨이든 어샘블리 레벨이든간에 말이죠.

 

크래시 재현

이번에 쓸 취약 프로그램은 소리통이라는 프로그램입니다. 

 

http://pds.dnavi.info/windows95/121987

 

DNAVI PDS - Windows95/98 - 소리통

소리바다를 개발한 소리나라에서 개발한 음악플레이어 소리통입니다. 인터페이스가 독특한 플레이어하고 스킨도 변경이 가능합니다. 다운로드 : sori10k.exe 홈페이지 : http://sorinara.com/ko/soritong/index.html

pds.dnavi.info

위 링크에서 다운받을 수 있습니다. 링크를 얻는데에는 블랙펄의 콘치님이 작성한 블로그 글이 도움이 되었습니다.

 

여기서 취약점이 터지는 부분은 프로그램의 UI가 저장되는 txt파일에서 bof가 터진다고 합니다.

설치 경로/Skin/Default/UI.txt가 있습니다. 

저녀석을 덮어써보도록 하지요.

 

A를 5천개 넣어서 UI.txt를 만든 뒤 실행을 해보도록 하겠습니다.

그냥 켜졌다가 조용히 꺼지게 되네요.

 

코어랜 블로그 말로는 Exception이 나서 Exception Handler로 넘어갔는데, 적절한 SEH를 못찾아서 그런거라고 합니다. 왜냐면 SEH Record도 우리가 덮어써 버렸기 때문이지요.

 

이제 그러면 디버거를 붙여서 어떻게 된 건지 자세히 알아봐야겠지요?

 

디버거로 분석 - 올리디버거

올리디버거나 이뮤니티 디버거를 이용해서 소리통을 실행시킨 뒤, play 버튼을 눌러서 앱을 실행시켜 봅시다.

Loading Skin에서 앱이 멈춰있습니다.

디버거도 Paused라고 뜨네요.

 

SEH Chain을 확인해보겠습니다.

 

정말로 41414141로 덮어져 있군요.

 

블로그에서 보면, Current Stack Frame을 일단 살펴보네요.

0xFFFFFFFF가 보이는 걸로 봐서 SEH 체인의 끝이라고 보고 있습니다. 바로 위에서 본 SEH Chain 주소랑은 다른데,

아마 다른 스택 프레임이라서 그런 것 같네요. 창으로 별도로 뜬 SEH Chain 주소는 주소값이 더 큽니다. 따라서 스택은 아래로 자라므로 Caller function의, 즉 더 부모 함수의 스택 프레임인 것 같습니다.

 

그리고 FFFFFFFF가 가리키는 0x7e41882a가 기본 Exception handler의 주소인걸로 보이네요.

그리고 해당 주소는 USER32.DLL에 있는 주소입니다. View - Executable Modules를 누르면 나오는 창입니다.

 

그리고 크래시가 난 때에 스택프레임의 더 높은 주소들을 뒤져봐도 별다른 예외 핸들러가 보이지 않는 것으로 보아서, 적어도 크래시를 낸 함수는 예외 핸들러 루틴이 없다고 가정을 하네요.(블로그에서요)

이미 덮어쓰여져서 꼭 그런지는 모르겠는데 말입니다.

 

디버거로 분석 - Windbg 윈디버거

아까 올리디버거로 크래시난 상황을 SEH 을 분석하는 것을 윈디버거로 똑같이 해보겠습니다.

 

윈디버거로 소리통을 킨 뒤 명령어 g (go)를 친 뒤 엔터로 실행을 시켜보겠습니다.

Exception이 일어나기 전에 windbg가 알아서 멈춰버리는군요.

 

스택을 좀 구경해보면, 0xffffffff로 SEH Chain의 마지막 부분이 보입니다.

!analyze -v 명령어를 한번 사용해보도록 하지요.

이 외에도 엄청 긴 값이 나옵니다. 어떤 Exception 상황인지 등등이 나오네요.

 

!exchain 이라는 명령어를 쳐봅시다.

Exception handler를 덮어썻다는 걸 알 수 있네요.

 

여기서 g 명령어를 치거나, F5를 눌러서 진행을 해보면 EIP가 41414141로 변경되는 것을 알 수 있습니다.

레지스터값에 쉘코드 주소를 바로 박는다면?

레지스터에 쉘코드 주소를 넣고 바로 점프를 뛴다고 생각해봅시다. 근데 이 방법은 Windows XP SP1 이전에는 가능했지만, SP1 이후부터는 보호기법이 생겨서, exception handling 하기 전에 모든 레지스터의 값들이 XOR되어서 0으로 셋팅됩니다. 그래서 SEH로 넘어가게 되면 레지스터들은 쓸모가 없어지지요.

 

스택 BOF에서 ret 주소 덮어쓰기 보다 SEH 기반 익스플로잇의 장점은?

기존 stack base bof에서 ret addr를 덮어쓰면 간단한데 SEH 기반 익스플로잇을 하는 이유가 무엇일까요?

안정성에서 차이가 납니다. 만약 dll에서 jmp 명령어를 찾지 못한다면 주소를 하드코딩해서 박아서 넘어가야하는데, 이런경우 익스플로잇이 언제는 동작하고 언제는 동작하지 않겠지요.

그리고 버퍼사이즈가 적어서 쉘코드를 박기 힘든 경우에도 고생하게 됩니다.

그래서 스택 bof로 ret 주소를 덮어쓸 수 있다면 더 덮어서, SEH 체인까지 닿을 수 있도록 하는게 좋습니다. 그리고 스택에 있는 ret 주소를 쓰래기 값으로 덮었으면 exception은 어차피 일어나게 되고 SEH exploit으로 변경이 되는 것이지요.

 

SEH 기반 익스플로잇은 어떻게 이루어지죠?

간단합니다. SEH 포인터 주소와 SE 핸들러 주소를 덮어쓰고, 쉘코드를 넣으면 됩니다. 그리고 Exception Handler 내부에서 쉘코드로 뛰도록 하면 됩니다.

대충 위와 같은 그림인데, Exception이 실행이 되면 예외 핸들러 주소가 가리키는 데로 EIP가 이동합니다. 그리고 pop pop ret을 하게 되는데, 예외 핸들러에서는 esp+8에 다음 SEH 주소가 써잇는 스택 메모리의 주소가 써있습니다.

따라서 pop pop ret을 하면 EIP는 다음 SEH 주소가 써잇는 스택 영역으로 가게 되죠.

다음 SEH 주소에 있는 instruction을 실행하게 되는데 여기에 relative jmp instruction opcode가 있으면 요녀석을 실행해서 지금 주소의 4바이트 정도를 앞으로 뛰어넘게 됩니다. 이 jmp instruction opcode가 4바이트 이하의 크기이기 때문에 가능한 것이겠지요. 그러면 예외 핸들러 주소 다음에 있는 쉘코드로 이동하게 되고 쉘코드가 실행되지요.

 

물론 쉘코드는 예외 핸들러 이후에 몇바이트 더 뒤에 두고, jmp opcode를 더 많이 뛰게 해도 됩니다.

 

그럼 익스를 해봅시다

일단 Next SEH Pointer와 SE Handle Pointer를 덮어쓰는 양을 알아내야겠죠? UI.txt에 패턴을 줘서 알아내봅시다.

메타스플로잇에 rulez라는 녀석을 이용해서 만든것 같군요.

 

엔디안 고려하면 패턴은 At6A가 됩니다.

이를 바탕으로 기본 Exploit 코드를 좀 짜보면

위와 같이 대충 됩니다. !exchain이라고 쳣을때 제대로 나오는 것 같네요. g를 한번 더 쳐서 eip가 어떤놈을 가리키는지도 봤는데 정상적으로 ehandler 부분을 가리킵니다.

 

이제 pop pop ret 가젯과 jmp 4 opcode만 알아내서 채우면 익스플로잇이 완성될 것 같습니다.

 

코어랜 블로그에선 findjmp.exe란 녀석을 썻는데, 찾아보니, 깃헙에 있습니다.

https://github.com/nickvido/littleoldearthquake/blob/master/corelan/findjmp/findjmp/bin/findjmp.exe

 

nickvido/littleoldearthquake

littleoldearthquake. Contribute to nickvido/littleoldearthquake development by creating an account on GitHub.

github.com

다운받아서 한번 써보도록 하지요.

 

Player.dll에서 pop pop ret 가젯 중 주소값에 Null byte가 없는 녀석을 사용해봅시다.

촤라락 하고 나온다.

 

이제 그러면 full exploit을 작성하고 실행해보자.

후 성공했다.

 

eb 06 90 90이게 jmp relative 6byte라는 녀석이라는데, 지금으로부터 6바이트 앞으로 뛴다고 한다.

 

이녀석은 내가 skip햇던 part2에 설명이 있는데 short jump(jmp)의 opcode가 0xeb라고 한다. 그리고 그 뒤에 나오는 수만큼 지금 eip에 상대 주소만큼 점프뛴다고 한다.

크흐 드디어 끝!. 이제 잘 수 있다.

 

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

https://c9x.me/x86/html/file_module_x86_id_147.html

http://pds.dnavi.info/windows95/121987

https://bpsecblog.wordpress.com/2016/12/15/seh_02/

https://ko.wikipedia.org/wiki/Win32_%EC%8A%A4%EB%A0%88%EB%93%9C_%EC%A0%95%EB%B3%B4_%EB%B8%94%EB%A1%9D

https://go.microsoft.com/?linkid=7729279

https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#Segment_Registers

https://stackoverflow.com/questions/10810203/what-is-the-fs-gs-register-intended-for

https://bpsecblog.wordpress.com/2016/11/23/seh_01/

https://ko.wikipedia.org/wiki/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%86%8C%ED%94%84%ED%8A%B8%EC%9D%98_%EC%98%88%EC%99%B8_%EC%B2%98%EB%A6%AC_%EB%A9%94%EC%BB%A4%EB%8B%88%EC%A6%98

https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/

 

Exploit writing tutorial part 1 : Stack Based Overflows | Corelan Team

Last friday (july 17th 2009), somebody (nick)named 'Crazy_Hacker' has reported a vulnerability in Easy RM to MP3 Conversion Utility (on XP SP2 En), via packetstormsecurity.org. (see . The vu

www.corelan.be

이 글은 위 글을 바탕으로 공부해서 실습까지 해보는 그러한 글입니다.

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

 

조만간 윈도우 환경에서 Exploit을 할 일이 있을 것 같으니, 윈도우즈 Exploit 관련 공부를 좀 해 볼까 한다.

 

사실 이 BOF 파트는 리눅스랑 거의 같은 것 같아서 그냥 대충 읽어만 보고 넘어갈려고 했는데, 뭐 컴퓨터 하는 사람이라면 직접 해봐야 알지 않겠는가?

 

무려 10년도 전에 작성된 글이라서 자료가 많이 다르고 할 수 있지만, 열심히 환경 구축해서 따라가보도록 하자.

 

환경구축

Windows XP 32bit

일단 윈도우즈 XP가 필요하다. 버그리포트는 SP2에서 되었지만, 코어랜 글 저자는 SP3에서 했다고 하니 어쨋든 XP와 virtual box를 이용해서 OS환경 구축을 해보자.

 

iso 이미지를 어디서 구해야 할지 모르겠는데, 일단 microsoft 공홈에서는 64bit만 있는 것 같다.

구글링 해보니, 여기서 받을 수 있었다.

https://isoriver.com/windows-xp-iso-download/

 

Windows XP ISO: Windows XP free download (32 & 64 bit) - ISORIVER

Windows XP was released on the 24th of August in 2001. It was probably one of the most interesting products from Microsoft since Windows 95 was released. It’s b

isoriver.com

 

Virtual box에 Windows XP Service Pack 3 32bit ISO를 넣어서 열심히 설치를 해보고 있다.

나오는걸 그냥 엔터엔터 엔터 동의함 엔터엔터 하면 그냥 설치가 된다.

 

XP를 오랜만에 보니 좀 신기한듯.

라이센스 키를 쓰라고 으름장을 놓는데, 인터넷에 구글링해서 아무거나 쳐서 쓰도록 하겠다.

테스트용이기도 하고, 가상머신 안에 설치한것이기도 하고, 이미 판매가 종료된 버전이기도 하니깐, 큰 문제는 없지않을까? 하는 그런상황쓰이다.

 

 

Easy RM to MP3 Converter v2.7.3.700

이게 취약 프로그램인데, 코어랜 홈페이지에서는 다운로드 받으려면 로그인을 하라고 한다.

근데 회원가입 기능이 없다.

 

따라서 그냥 구글링을 해 보았는데, 나름 유명한 프로그램인지 쉽게 구할 수 있었다.

아래 링크로 가면 다운받을 수 있다.

https://easy-rm-to-mp3-converter.en.softonic.com/

심지어 버전도 같다. 굿!

 

이제 저녀석을 Windows XP VM안에다가 설치를 해버리면 될 것 같다.

 

파일 VM에 배포

이제 필요한 파일들을 VM안에 배포를 해야 하는데, 어떻게 옮겨야 할까?

 

안에 IE가 브라우저로 있긴 하지만 매우 오래된 버전이기도 하고, 크롬같은 경우에는 최근 버전들은 호환이 되지 않아서, 별도로 낮은 버전을 구해서 깔아야 한다. 그래서 그냥 호스트에서 필요한 파일들을 받아서 넘기기로 했다.

 

일단 Virtual box Guest 확장을 설치해야 한다.

위에 매뉴를 누르면 슥삭 하고 설치가 시작될 것이다.

중간에 계속 Warning이 뜰건데, 어쨋든 계속한다를 계속 눌러주면 된다.

 

게스트 확장을 설치하면, 파일공유도 되고 해상도 자동 조정도 된다 캬!

 

그리고 공유폴더를 지정하면 Host와 Guest간에 파일 공유가 되게 된다.

 

 

 

호스트 OS 공유폴더에는 필요한 파일을 다운받는 중이고, 게스트 공유폴더에 들어가보니, 다운로드 중인 파일이 보인다.

정상적으로 잘 다운이 되는 중인듯 하다.

 

Windows XP에 파이썬 설치

호스트에서 파이썬 스크립트로 페이로드 파일을 만들어서 넘겨도 되지만, 게스트에서 직접 스크립트를 실행하는 것도 괜찮아보인다. 사실 호스트-게스트간 파일 공유 시 약간 랙이 있어서 조금 답답할 수 있는 것 같다.

 

파이썬 공식 홈페이지를 보니 Python 3.5버전부터는 WinXP나 그 이전 버전에서 호환이 안되는 것 처럼 보인다. 그러니 3.4.1버전을 한번 받아보도록 하겠다.

https://www.python.org/downloads/windows/

가장 하단에 있는 Windows x86 MSI Installer로 파일을 받아보겠다.

다행히 잘 설치되는 것 같다. 그리고 환경변수까지 지정을 해 주자.

 

 

 

 

 

익스플로잇 재현

이제 환경구축은 얼추 끝난 것 같으니까, 취약점을 익스플로잇 해보도록 하자.

프로그램 실행

일단 취약한 프로그램인 Easy RM to MP3 Converter라는 프로그램을 한번 실행시켜보자.

공유폴더에서 바탕화면으로 설치 파일을 옮긴 뒤 실행을 해 보았다. 근데 이게 뭐하는 프로그램인지 아직은 잘 모르겠는데 RM이라는 포맷을 MP3로 변환해주는 그런 프로그램인가보다.

 

일단은 코어랜 블로그에서 \x41를 1만개 넣어서 파일을 만든 뒤 그냥 실행해보았었으니, 나도 똑같이 해보겠다.

코어랜에서는 perl로 스크립트를 짰던거같은데 나는 파이썬으로 짜겠다.

 

일단 crash.m3u파일을 만들었으니 저 파일을 guest vm으로 보내서 실행해보도록 하자.

 

Load를 누른 뒤 crash.m3u파일을 여니 아래와 같이 에러가 뜬다.

 

파일 이름을 덮어쓴걸로 봐서 bof가 일어난 듯 하다.

여기에 A를 2만개를 반복하는 것 까지 저렇게만 버그가 난다고 한다. 근데 3만개가 되면 프로그램 크래시로 종료가 된다.

 

 

Windbg 설치

맨처음에는 올리디버거를 써야 하나 싶었는데, 코어랜 블로그에서는 윈디버거(Windbg)를 쓴다고 했으니, 이번에 안써본 윈 디버거를 한번 써보도록 하겠다.

 

근데 Microsoft 공식 windbg 다운로드 페이지로 가니, Windows SDK를 설치할 때 그 패키지 안에 같이 포함되어있다고 한다. 그중 Debugging Tools for Windows를 고르면 된다고 한다.

 

Win10이전의 버전들은 별도의 페이지가 있다고 한다.

 

근데 해당 페이지로 가보면 Win8과 7까지밖에 없다.

근데 가장 과거인 Win7 SDK를 보면, Win XP도 사용 가능하다고 되어있다. 이를 설치해보도록 하자.

흠 근데 대략 이런 에러가 뜬다. .NET Framework 2.0 redistributable을 다운받아달라고 한다. 

 

구글링을 하니 다운로드 페이지가 뜬다.

서비스 팩 1이라고 뜨긴 하는데, x64는 아닐테니 x86인 요녀석을 한번 받아보자.

 

다행히 설치는 잘 되는 듯 하다. 다시 Win SDK 설치를 시도해보자.

일부 컴포넌트는 설치가 불가능하다고 하는데, 어차피 나는 Windbg만 설치하면 되기 때문에 Ok를 눌러서 진행해본다.

잠시 반응이 없길래 설치가 안되는줄 알았는데, 조금 기다리니 위와 같은 창이 떴다.

Next랑 Agree를 누르니 아래와 같은 창이 나타났다.

Windbg는 당연 Debugging Tools에 있을 거니 체크를 해서 설치를 해주자. 나머지는 다 설치 체크를 해제한뒤 진행해보겠다.

 

근데 설치가 다 된거같은데, 우리의 windbg는 어디있을까...?

 

그래서 찾기로 가서 windbg로 검색해보니 아무것도 안나와서 debug로 검색을 해 보았더니 무언가가 나왔다.

dbg_x86라는 녀석 아이콘을 보니 또다시 설치파일인것 같았다. 더블클릭해서 실행해서 설치를 진행해보자.

 

 

그리고 나서 windbg로 검색을 해보니, windbg가 나타났다.

 

환경구축이 제일 빡샌거같기도 하고. 어쨋든 windbg까지 설치가 되었다.

그리고 코어랜 블로그에서 했던 것 처럼 postmortem debugger로 설정도 해주었다.

post-mortem 뜻을 검색해보니 사후(죽은 뒤)라는 뜻이라서, 아마 프로그램 크래시가 나서 종료되면 그 것들을 처리하는 기본 디버거라는 뜻 인것 같다.

 

그리고 "xxx프로그램이 문제가생겨서 꺼야합니다~"라는 팝업을 안 뜨게 하기위해서 레지스트리도 수정해주었다. 실행 창에서 regedit을 치면 레지스트리 수정 창을 띄울 수 있고, HKLM/Software/Microsoft/Windows NT/CurrentVersion/AeDebug/Auto를 0으로 셋팅하면 된다.

 

<TODO : 제대로 동작하게 하기>

그리고 windbg가 심볼이 없다고 불평하는 것을 막기 위해서 설정을 해준다.

하드드라이브에 폴더를 하나 만들고, c:\windbgsymbols와 같이 만들었다고 치자.

File-Symbol Search Path에 위와 같이 써준다.

근데 동작은 안하는것 같다. ㅠ

크래시 디버깅 - EIP 덮어쓰기

이렇게 설정을 하고 다시 Easy RM to MP3 프로그램을 크래시를 내보자.

 

A가 3만개 들어있는 파일을 열라고 시도하자 다음과 같이 나타난다.

저기서 Debug를 누르면 windbg가 숑 하고 나타날 것이다.

여기서 디버그 버튼을 눌러보자.

Windbg가 나타나고, eip가 41414141이 된 것을 알 수 있다.

 

이걸로 2만개 A는 크래시가 안나고 3만개 A는 크래시가 난다는 점을 이용해서 2만과 3만 사이 어딘가의 크기의 A를 쓰면 bof가 난다는 걸 알 수 있다.

 

이를 이용해서 정확히 얼마 A를 채워야 프로그램이 터지는지를 한번 알아보자.

 

그냥 간단하게 A를 2만5천개, B를 5천개를 넣고 확인, 그리고 그 결과에 따라서 다시 변경해서 확인 이런식으로 반복을 하면 알아낼 수 있다.

 

A를 2만5천개, B를 5천개를 넣으니 EIP가 42424242가 나온다. 즉 5천개인 B의 범위에 있다는 뜻.

 

따라서 25,000 ~ 30,000 사이의 값이다.

25,000 ~ 27,500 사이의 값인것을 알 수 있다. 일종의 바이너리 서치 같은 개념으로 볼 수 있다.

이번에도 42424242에서 터졌으니 B에서 터졌다고 보면 된다.

25,000 ~ 26,500 사이의 값이다.

D의 범위에서 터졌으니 대충 26,000 ~ 26,500 의 범위에 있다.

 

B에서 터졌다. 26,000 ~ 26,150 사이의 범위이다. 계속 쭉쭉 범위가 줄어들고 있다.

 

C의 범위이다.

26,050 ~ 26,100의 범위에 있다. 이러한 식으로 계속 줄여보자.

26,065 ~ 26,080에 있다.

결국 26067의 더미와 + (ret_addr)를 넣으면 eip를 덮어쓸 수 있다는 걸 알 수 있다.

 

이제 쉘코드를 넣은 뒤, 쉘코드로 점프만 뛰면 쉘을 띄울 수 있다.

 

쉘코드 넣을 자리를 찾기

그리고 d esp라고 치면 esp 주소에 있는 메모리 값들을 볼 수 있는데, gdb로 치면 x/x $esp와 비슷한 명령어 인 것 같다. 덮어쓴 eip이후의 값들이 그대로 있다. 

 

코어랜 블로그에서 했던 것 처럼 EIP를 덮어쓴 뒤 esp가 가리키는 곳에 값을 쓰는 부분에 쉘코드를 올리도록 준비를 해 보자. 아래와 같이 m3u파일을 생성해서 실행해보니, 쉘코드의 0~3까지 즉 4byte가 잘리고 나머지 부분이 잘 올라가있다.

이러한 부분도 한번 고려를 해야 한다는 것이다. 아마 잘린 4byte는 saved ebp, 이전 스택 프레임 포인터에 해당할 것이다.

 

따라서 덮어쓴 eip 다음 값 4바이트를 버린 뒤 쉘코드를 올리면 될 것 같다.

 

그래서 아래와 같이 esp 주소로 점프를 하고, esp에는 NOP과 cc로 브레이크 포인트를 잡는 페이로드를 작성해서 실행해 보았다.

그런데 이게 왠걸, esp에는 알수없는 널값들이 좀 있고, 크래시가 또 났다.

 

eip는 잘 뛰었는데 왜그런걸까.

안전하게 쉘코드로 점프하기

 

esp주소에는 0x000ff730이다. 마지막에 널값이 있어서 Null terminate된다. 이렇게 하면 안될 것 같다. 그러면 어떻게 해야 할까?

 

만약 jmp esp와 같은 명령어를 실행시킬 수 있다면 esp로 안전하게 뛸 수 있을 것이다.

 

일단 windbg와 익스할 컨버터 프로그램을 다시 띄운 뒤, attach to the process를 이용해서 windbg를 붙여보자.

그리고 밑에 커맨드 창에 a 치고 엔터를 친다. 그러면 assemble 모드가 된다.

그리고 jmp esp를 치고 엔터를 친다.

그러면 지금 주소값에 jmp esp가 등록이 된다.

그리고 다시 엔터를 치면 assemble모드가 꺼진다.

그리고 u 7c90120e를 치면 아까 우리가 쓴 값의 부분이 디스어셈블되서 보인다.

여기서 우리가 알게된 것은 jmp esp의 opcode가 ffe4라는 점이다.

 

그러면 이 컨버터 프로그램이 실행하는 dll 라이브러리 중에 ffe4라는 opcode를 갖고 있는 녀석이 있을까?

 

커널 DLL말고 어플리케이션 dll중에 codec02라는 녀석으로 패턴을 찾아보았다. 코어랜 블로그와는 dll 로드되는 주소가 다르긴 했는데 잘 찾아졌다.

그리고 익스플로잇 코드를 조금 손봤다.

그런다음에 windbg랑 컨버터를 다시 새로 키고, 디버거를 붙인 뒤, g명령어로 실행을 시키고 해당 익스플로잇 파일을 로드해보았다.

 

breakpont에 잘 걸렸고, esp에 쉘코드도 잘 보인다.

Real 쉘코드 삽입 및 익스플로잇 마무리

이제 NOP + \xcc로 디버거 브레이크만 잡는게 아닌, 실제 쉘코드를 넣어서 익스플로잇이 잘 되는지를 확인해보도록 하자.

 

윈도에서는 계산기를 띄우는 쉘코드를 많이 쓰니, 이를 한번 이용한다. 메타스플로잇에 있는 쉘코드 generator를 이용해서 쉘코드를 얻는 것 같다.

 

쉘코드를 복붙하는게 귀찮으니, 호스트에서 만들어서 넘기도록 하겠다.

근데 안된다..

 

쉘코드 점프까진 되는데 왜 안되지.

 

그래서 코어랜 익스코드처럼 앞에 NOP을 25개 정도 붙이고 다시 해보았다.

 

위와 같이 익스코드를 생성해보았다.

그니깐 되네. 왜그럴까..

 

하고 생각을 해보았는데, 아마 쉘코드 내용에서 스택을 쓰는 녀석들이 있을 것이다.

 

push pop 등등을 좀 할건데, 쉘코드가 거기에 곧바로 있으면 실행하면서 그 쉘코드 자체를 변경해버려서 그렇게 되지 않을까 하는 추측이 된다.

 

쉘코드 시작부분이다.

일단 pop eax가 한번 나타난다. push 하는게 없었으니, 쉘코드가 하나 떨어져 나가겠다.

그리고 보면, NOP을 안넣었을때 크래시가 나는 곳이 0xff75f 부분인데 eax + 68에 접근을 한다. eax는 근데 쉘코드 맨 앞 부분과 관련이 있으므로 NOP을 넣으면 그 부분이 다른 값이 들어가게 된다.

 

뭐 어쨋든 NOP을 넣어서 꼭된다 이런거는 아니긴 하다. 영 아니면 다른 쉘코드를 집어넣거나 쉘코드도 직접 만드는 방법도 있겠다.

 

어쨋든 계산기를 봤으니 이만 글은 줄인다.

 

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

https://www.microsoft.com/ko-kr/download/details.aspx?id=16614

https://docs.microsoft.com/ko-kr/windows-hardware/drivers/debugger/debugger-download-tools

https://www.giannistsakiris.com/2007/09/28/virtualbox-access-shared-folders-from-windows-xp-guest-os/

https://woosunbi.tistory.com/62

개요

이 글에서는 유니코드 쉘코드와 베니스 쉘코드에 대하여 간단하게 알아본다.

 

유니코드를 기본 값으로 사용하는 시스템에서 Payload를 주입했을 때, 중간에 Null byte가 삽입되는 경우가 있을 수 있다. 이는 입력값을 Unicode로 처리하기 때문에 일어날 수 있는데, 이러한 경우 홀수번째 값이 Null byte인 값으로 쉘코드를 만들수 있을 것인지에 대한 내용을 다루어보도록 하자.

 

베니스 쉘코드(venetian shellcode)

일단 PC는 원하는 주소로 잘 변경했다고 가정을 한 뒤 생각해보자.

 

그냥은 쉘코드를 만들기에는 중간에 null byte가 들어있는 기계어 코드는 많지 않으므로 제약사항이 많을 수 있다.

 

하지만 몇가지 코드들을 이용해서 메모리에 값을 쓰도록 한다던지, 레지스터 값을 +1를 한다던지 등의 작업은 할 수 있다.

 

위와 같이 코드를 구성한다면 중간중간에 Null byte가 들어가지만, 원하는 동작들은 할 수 있다.

 

그리고 또한 inc instruction도 쓸만하다.

위와 같이 구성을 하면 조건에 맞게 shellcode를 만들 수 있다.

 

이를 이용해서 eax를 하나씩 늘려가면서 eax를 가리키는 메모리 주소에 원하는 1byte를 쓸 수 있다.

그리고 null byte align을 맞추기 위해서 [ebp]가 가리키는 곳에 ch 레지스터의 값을 더할 수 있는데 보통 이 값은 0이므로 아무일도 일어나지 않는다.

 

이러한 걸 이용해서 베니스 쉘코드란걸 작성을 할 것인데, 아이디어는 간단하다.

 

베니스 코드라는 녀석을 이용해서 메모리 적당한 곳에 Null byte가 없는 우리가 원래 쓰던 진짜 쉘코드를 쓰게 만든다.

베니스 코드는 유니코드로 인코딩되어서 중간중간에 null byte가 있지만, 위에서 하는방식으로 원하는 값을 1byte씩 한땀 한땀 작성할 수 있다.

그리고 우리가 베니스 코드로 작성한 진짜 쉘코드(null byte가 없는)녀석으로 점프를 뛰면 끝이다.

블랙햇 발표자료 슬라이드에 해당 내용을 나타낸 곳이다. UNICODE인 베니스 코드가 리얼 쉘코드를 한땀 한땀 쓰는 모습이다.

 

그외에도 NOP이나 byte값 변경이라던지 등에 유용한 어샘 코드들이 좀 있다.

저런 녀석들을 이용해서 리얼 쉘코드를 만든 뒤 점프뛰면 되겠다

add al, 0는 NOP에 해당하고

inc byte ptr[eax]는 1바이트 값 변경, mov byte ptr[eax]도 mov를 이용한 바이트 값 변경에 해당된다.

 

대신 이 쉘코드는 꽤 길어지는 경향이 있긴 한데 그래도 꽤 쓸만하다.

 

 

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

https://www.corelan.be/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/

https://www.blackhat.com/presentations/win-usa-04/bh-win-04-fx.pdf

https://www.kisec.com/_core/_download.php?file_url=lab&file_name=album_5b69337831c13.pdf&real_name=%5Bexploit+writing%5D+7_%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C.pdf

+ Recent posts