이번에는 메모리 동적 할당에 대해 알아보겠습니다.

Ring3에서는 동적으로 메모리를 할당할 때 malloc이나 HeapAlloc 같은 함수를 사용해보셨을겁니다.

그러나 드라이버에서는 이 함수를 사용할 수 없습니다.

그럼 어떻게 동적 메모리를 생성할 수 있을까요?

커널엔 메모리 풀이라는 것이 있는데 이것이 커널모드 힙입니다.

커널에서 힙을 할당하기 위해선 ExAllocatePool 이라는 함수를 사용합니다.

주목해볼만한건 인자로 NonPagedPool을 주었는데요. 인자 값으로 아래 두가지가 있습니다.

NonPagedPool : 항상 메모리에 존재

PagedPool : 페이지 아웃 혹은 인이 될 수 있음

페이지 아웃이 되면 공포의 BSoD가 뜨겠죠? 그것을 방지하기 위해서 NonPagedPool을 인자로 주어야 합니다.

 

잘 뜹니다~

주의하실 점은 동적 메모리를 반드시 해제해 주어야 합니다. 안그러면 커널 메모리에서 둥둥 떠다닙니다~

저는 WDK를 처음 접하고 코딩을 했을때, Ring3 어플리케이션에서 쓰이는 printf, malloc 같은 함수들을 사용하지 못해서 적잖이 당황한 기억이 있습니다.

그래서 WDK관련 책들을 샀는데, 입문자가 보기엔 너무 생소하고 난해한 용어들이 많아 바로 책을 덮어버렸습니다.

책을 덮고.. 독자적으로 여러 소스들을 분석하여 얻은 결론 하나, 내부 동작 원리에 대해 잘 몰라도 개발할 수 있다는 것입니다.

물론 심도있는 개발을 위해 전부 필요한 내용이지만, 일단 진입장벽부터 넘어야 하지 않겠습니까?

우선 들어가기 전에 이 글을 읽는 대상은..

1. Ring3 에서 c/c++ 기반 시스템 프로그래밍 개발 가능한 분

2. 윈도우즈 동작 메커니즘에 대해 어느정도 이해하고 계신 분

3. 위의 두가지 조건에 충족하며 드라이버 제작을 처음으로 해보시려는 분

따라서 아주 기초적이고 구구절절한 내용은 생략합니다.

그럼, 아주 심플한 제작부터 시작해보겠습니다.

드라이버 제작에 앞서 필수적인 파일 2가지가 있습니다. 아래 두가지 파일을 작성 후 프로젝트 폴더에 저장하면 됩니다.

MAKEFILE

!INCLUDE $(NTMAKEENV)\makefile.def

SOURCES

TARGETNAME=simple
TARGETPATH=.\sys
TARGETTYPE=DRIVER
SOURCES=simple.c

그 다음, simple.c를 작성합니다.

 

정말로 이렇게 심플한 코드가 실행이 될까요? 책에선 드라이버 스택이 어쩌고 저쩌고.. 익스텐션이 어쩌고저쩌고..

뭐 일단, 빌드를 해 봅니다.

 

 

빌드된 sys는 \sys\i386 경로에 있을 것 입니다. (xp로 빌드한 경우) 그럼 이 드라이버를 커널에 올려 봅시다.

드라이버를 상주시키는 파일은 구글에서 instdrv로 검색하시면 나옵니다. 로깅 뷰어는 DebugView를 사용하면 됩니다.

 

 

짜잔~ 실행이 되었군요. VC++ 로 작성하였던 내용과 별반 다르지 않군요.

이제부터 이 내용을 뼈대삼아 살을 붙여나갈 예정입니다.

 

브라우저 취약점 쉘코드를 작성하여, html의 unescape 부분에 %ue8fc%u00c3%u0000%u8960 이런 형태로 붙여넣었습니다. 그런데 작동이 되지 않았습니다.

원인을 찾아봤는데, bad character라고 하여 \x00 이 들어가면 동작이 되지 않던 것이었습니다.

이는 메타스플로잇에서 공개한 브라우저 취약점 공격 PoC에서도 확인할 수 있습니다.

http://www.exploit-db.com/exploits/23785/

 

 

아래는 메타스플로잇에서 제공하는 어셈블리어 코드로 쉘코드를 생성하는 방법입니다. LoadLibrary기능을 하는 쉘코드이며, generate 로 생성이 가능합니다. bad char 0x00 이 포함되어있어서 브라우저에서 정상동작하지 않습니다. 

https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/single/single_loadlibrary.asm

그대로 디버거에 붙여넣은 화면입니다.  

 

아래는 옵션을 주어 0x00을 제거하였습니다. 디폴트로 시카타가 나이라는 인코더가 선택됩니다. (일본어로, "어쩔수가 없지". 이름을 재미있게 지었군요. 

 그대로 디버거에 붙여넣은 화면입니다.  

디코더가 처음 부분에 삽입되어 있어서 한 라인씩 실행하다 보면, 평문으로 복호화가 됩니다. 

# 쉘코드 인코딩 하는 방법

msfencode라는 프로그램이 내장되어 있습니다.

옵션 설명

-e x86/shikata_ga_nai : 인코더 선택

-b '\x00' : Bad Character 제거

-i /root/loadlibrary.bin : 경로명 (쉘코드를 바이너리로 저장해주세요)

-t c : C언어 변수 타입으로 출력

+ Recent posts