본문 바로가기

My Study/Reversing

IceSword ?! 뭐하는 놈?

쫌 오래된 툴이지만 중국인이 만든 IceSword 라는 툴을 다들 사용해보고 들어보셨을 것입니다. Windows XP 까지 대표적인지 아닌지는 모르겠지만 많이 사용되던 루트킷 탐지 툴이였지요. 그 외에도 이것저것 기능도 많구요. 하지만 그 툴을 쓸 당시까지만 해도 드라이버 개발도 해보지 않았고 리버싱도 기껏해야 크랙미 1~2번 풀던 시절이었지요. 

( 제가 공부를 많이 늦게 시작했습니다.. ㅠ )


하지만 그 찰나 Vista가 나오고 Windows 7이 나왔습니다. 결국 해당 플랫폼에서 안돌아가는 IceSword는 버렸고 다른 툴들을 쓰게됬었죠. 불행한 점은 IceSword를 분석을 못해봤다는 것입니다. 하지만 오늘 밥을 먹다가 한 이야기를 들었는데 IceSword 안티리버싱이 쫌 되어있는거 같다는 것이었습니다. 그래서 결국 기억속에서 지워진 IceSword를 XP에서 다시 켰습니다. 시간이 많지않아 깊이 있는 분석은 못하지만 그래도 눈에 보이는 정도만 분석을 해보려합니다.


===========================================================================



IceSword는 패킹이 되어있는데 보호목적은 아니고 단순 용량을 줄이기 위해 사용되었습니다. 간단히 언패킹을 해주시면 됩니다. 또한 IceSword는 루트킷 탐지 프로그램이기 때문에 드라이버를 로드합니다.



저 위치에 sys 파일을 드랍시키고 로드를 합니다. 

로드된 드라이버는 



6개의 Nt 함수들에 대해 inline 후킹을 수행합니다. 저 부분에 대해서는 보지 않았지만 함수명들만 보면 생성되는 프로세스나 스레드 감시 그리고 자기 자신을 보호하기 위한 행위들을 해논 것 같습니다. 당연히 작업관리자 같은 툴로는 IceSword를 종료시킬 수 없습니다.


또한 WinDbg에 의해 해당 OS가 Attach 되어 있다면 자동으로 Detach를 해버립니다. 커널 디버깅을 이러한 점 때문에 할 수가 없죠. 저 inline 후킹된 부분을 디버깅하기 위해서라도 이 점을 우회해야합니다. 이제부터 간단히 IceSword를 리버싱 해보면서 

어디가 어떻게 구현되어 있는지 보도록 하겠습니다.



별로 중요한 부분은 아니지만 저 부분에서 디버거를 탐지하고 있습니다. IceSword니까 쫌 특별한 안티리버싱 기술을 사용했을까요??



그냥 기본적인 방법을 사용해놨습니다.


일단 커널 디버깅을 해야되므로 WinDbg를 Detach 하지 못하게끔 해야합니다. 

이 부분을 한번 보도록 하겠습니다.



코드를 보면 이런 부분들이 있는데 CreateFile 함수를 그대로 쓰는게 아닌 ZwCreateFile을 아에 통채로 구현해서 박아넣었습니다. 어쩐지 CreateFile 같은 함수에 백날 BP를 걸고 실행해봤자 안멈추는 이유를 알았군요. 저 루틴을 끝까지 따라가보면

INT 2E가 나옵니다. 예전에 만들어진 프로그램이라 SYSENTER 로 안했나보군요.

저 때 CreateFile 하는 대상은 "\DosDevices\IsDrv118" 입니다. 하지만 아직은 Driver Load도 안된 상태이기 때문에 해당 디바이스가 있을리가 없죠. 일단 저긴 실패.!



실패 후 그 아래 루틴에서 "C:\WINDOWS\System32\drivers" 에 "IsDrv118.sys" 파일을 생성합니다.

그 아래선 리소스에 있는 파일 내용을 가져와 생성된 IsDrv118 파일에 드랍니다.


전형적인 파일드랍 방식입니다.



드라이버 용량이! 157KB나 되군요. 꽤 큽니다.. ㅠ ㅠ

이젠 보나마나 드라이버 로드 코드가 있겠지요.


하지만 전형적인 방법으로 SCM 함수들을 사용해 로드했을까요?? 아니겠지요.

일단 내부적으로 레지스트리 키를 직접 생성해서 값을 셋팅합니다.



위와 같이 값을 셋팅합니다.


Start 값이 1이므로 커널이 초기화될 때 자동으로 로드되겠네요.

또한 안전모드 일 때 서비스 등록도합니다.


"System\CurrentControlSet\Control\SafeBoot\Minimal\IsDrv118.sys"


로 레지스트리 키를 또 생성하네요. 


이제 "\Registry\Machine\System\CurrentControlSet\Service\IsDrv118" 키를 가지고 UNICODE_STRING 을 초기화합니다.

그리고 위  값을 인자로 NtLoadDriver 함수를 호출합니다.



MSDN 설명입니다.


무튼간 시스템에 드라이버를 로드하는 함수이군요. 루트킷 책에 나와있는 SCM방식이라던지 ZwSetSystemInformation 함수를 사용하는 방법은 아니었습니다.


그리고나서 지금까지 생성한 레지스트리 키는 전부 삭제합니다.


이제 "\DosDevices\IsDrv118" 디바이스에 다시 CreateFile을 합니다. 하지만 여기서 뻑납니다. ㅡ ㅡ;

일단 재부팅을 쫌 하고..;;


IsDrv118.sys 파일은 꺼내왔으니 IDA로 잠깐 살펴보기만 하겠습니다.

살펴보니..;; 허무하군요.



KdDisableDebugger 라는 함수를 사용하고 있었습니다. 커널 디버거를 Disable 시켜주는 함수입니다.

해당 함수를 호출하는 부분을 보겠습니다. 3군대 있지만 다 구현방식은 같습니다.



KdDebuggerEnable 값이 0인지 확인 후 0 이 아니면 KdDisableDebugger 함수를 호출해 커널디버거를 비활성화 시켜버립니다. 


KdDisableDebugger 함수는 내부적으로 KdDisableCount 값이 0, KdDebuggerEnabled 값이 1 인지 확인 후 두 조건을 다 만족하면 KdpBreakpointTable 테이블에서 값을 제거해버리는 방식입니다. 저 함수가 수행되면 WinDbg는 Disable 상태가 되는 것입니다. BP를 제거하는 이유는 WinDbg가 Disable 됬는데 BP가 걸려있는 부분을 실행해버리면 뻑?!

일단은 KdDebuggerEnabled 값이 0이면 무조건 WinDbg는 먹통이됩니다.


그러면 위 조건을 어떻게하면 무력화 할 수 있을까요..

먼저 KdEnableDebugger 함수를 사용해 제꺼 드라이버를 올렸더니 다시 WinDbg가 활성화는 되었지만 IceSword도 계속적으로 

KdDisableDebugger 함수를 호출하기 때문에 쫌 애매합니다.


그러면 바로 코드를 수정해도 될까? Hex Edit로 점프되는 부분을 수정했지만 드라이버 초기화 과정에서 수정된 부분을 감지하고 드라이버 로드를 실패하게된다. 드라이버가 로드되고나서 수정을 했을 땐 잘됩니다.


뭐 DriverEntry 부분을 분석하면 탐지하는 부분도 있을 것입니다. 시간상.. 그 부분과 후킹해서 먼짓을 하는지는 기회가 되면 해봐겠네요.

그냥 그 부분에 관계없이 분석을 하고싶다면 드라이버가 로드된 후 KdEnableDebugger 로 다시 WinDbg 제어를 얻고 점프문을 수정해주면 끝납니다.