본문 바로가기

My Study/Reversing

ZwSetSystemInformation

 ZwSetSystemInformation 이라는 함수는 Undocumented 함수입니다.

예전에 루트킷 책을 보면서 드라이버 로드 방법에서 2가지 방법을 공부해보았습니다.
하나는 OpenSCManagerCreateServiceStartService사용해 로드시키는 방법입니다.
레지스터를 생성시키며 정상적으로 로드 시키는 방법이지요.

그리고 다른 하나는 ZwSetSystemInformation 함수를 사용해 로드 시키는 방법도 소개가 됬었습니다.
하지만 위 함수를 사용해 로드시킬 경우 레지스트리에 값이 생성도 되지 않아 똑같은 드라이버를 여러번 로드가 가능하며
단점으로는... 언로드 또한 할 수 없습니다.

등록되어야 하는 레지 값 위치 : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services

그 당시에는 그냥 " 아~ 그런가보다 " 하고 넘어갔지만 지금 와서 궁금증이 생겼습니다.
그래서 깊게는 아니지만 함수 위주로 ZwSetSystemInformation 루틴을 훑어보았습니다.

먼저 유저 영역에서 ZwSetSystemInforamtion을 호출하면 커널로 들어가기위해 SYSENTER명령어를 수행합니다.
그리고 KiFastCallEntry 함수에서는 KiServiceTable.NtSetSystemInformation 함수 주소를 가져와 호출합니다.

NtSetSystemInformation 함수 내부 입니다.

이 함수 내부에서는 가장 처음에 ZwSetSystemInformation 첫번째 인자인 0x26 값을 가지고 if문을 사용해 적당한 루틴을 찾아가게 됩니다.

그 이후로 호출되는 함수입니다.

SeSinglePrivilegeCheck   -> Thread Context에서 통과하는 특권 값 체크하는 함수?!
ExAllocatePoolWithTag    -> 34Byte만큼 NonPaged 영역을 할당 ( 이상한 값 채움.. ;; 무슨 값인진 모르겠습니다. )
ZwSetSystemInformation -> 내부적으로 또 호출하더군요. 
첫번째(0x26)와 세번째(0x8) 인자는 그대로지만 두번째 인자는 커널 스택 주소에 있는 UNICODE_STRING 포인터였습니다.
그리고 UNICODE_STRING의 문자열 부분에는"\??\C:\simple.sys" 가 들어있었습니다. ( 로드 하려는 sys파일 절대 경로 )

응용 프로그램에서 ZwSetSystemInformation 첫번째 인자를 0x26으로 주는 이유가 이건가 보군요.

다시 NtSetSystemInformation 내부로 들어오게됩니다.
들어와서는 위 3개의 함수를 호출했던 부분을 건너뛰고 ZwSetSystemInformation 호출 후 루틴으로 가게 됩니다.

그 아래서 호출되는 함수들입니다.

MmLoadSystemImage -> 첫번째 인자 "\??\C:\simple.sys" 가 들어있는 UNICODE_STRING 주소
인자로 들어간 이미지를 시스템에 로드 시키는 함수입니다. 아에 실행하는게 아닌 메모리에 로드만 시키는 것입니다.
메모리에 로드가 된 후 마지막 인자 구조체에 해당 모듈의 ImageBase 주소가 들어가 있습니다.

RtlImageNtHeader -> IMAGE_NT_HEADERS 주소 구해오는 함수
위에서 구한 ImageBase를 가지고 IMAGE_NT_HEADERS 주소를 구합니다. 당연히 " PE " 라는 문자열로 시작하겠지요.

그리고 어셈 코드를 보면 IMAGE_NT_HEADERS 에서 
IMAGE_NT_HEADER -> OptionalHeader -> AddressOfEntryPoint
이렇게 최종적으로 AddressOfEntryPoint 주소를 구해옵니다. ( RVA 값.. )

그리고 ImageBase + AddressOfEntryPoint 한 값을 call 합니다.

고로 메모리에 로드된 simple.sys의 DriverEntry로 들어오게 되는 것이죠.

과정을 보면 그냥 특정 경로에 있는 이미지를 로드시키고 실행하는 일만 하게 됩니다.
그러므로 당연히 언로드 또한 하지 못하고 중복 로드도 가능한 것이지요.

NtSetSystemInformation 함수 내부입니다. DriverEntry Call하는 부분까지 입니다. 보실 분만;;

그냥 어떻게 동작하는지 대충 알아보았습니다.

이걸 어떻게 생각해냈을까요??? -_-?? 대단하신 분이군요...

'My Study > Reversing' 카테고리의 다른 글

ARM CPU 공부시작.. ㅠ_ㅠ  (6) 2012.01.25
Code Virtualized  (9) 2011.06.27
User Callback Address  (0) 2011.01.10
Cheat Engine의 축하 메시지??  (3) 2010.12.27
Visual C++ SEH Filter,Handler 루틴  (0) 2010.11.11