'wfp'에 해당되는 글 1건

  1. 2011.08.17 [Tip and Tech] WFP(Windows File Protection) 무력화 방법 (4)

WFP(Windows File Protection)란 프로그램에 의해 중요한 Windows 시스템 파일이 변경되지 않도록 하기 위한 기능이다. 두 개의 DLL(%system%sfc.dll, %system%sfc_os.dll)에 구현된 WFP는 주요 폴더에 대하여 ReadDirectoryChangesW를 사용하여 변경 여부를 검사한다. 만약 보호 대상 파일이 변경되었을 경우 이 파일이 올바른 버젼이 아니면 WFP는 새 파일을 캐시 폴더 또는 설치 원본에 있는 파일로 교체한다. WFP의 파일 검색 순서는 다음과 같다.

1. 캐시 폴더(기본적으로 %system%dllcache)

2. 네트워크 설치 경로(네트워크 설치를 사용하여 설치한 경우)

3. Windows CD-ROM(CD-ROM을 사용하여 시스템을 설치한 경우)

WFP는 주요 윈도우 파일을 보호하는 메커니즘으로 그 중요성만큼 악성코드에 의한 타깃이 되고 있다. 최근에도 주요 시스템 파일을 교체 또는 패치하는 형태의 악성코드가 다수 등장하고 있으며, 이로 인한 시스템 불안정, BSOD등이 발생하고 있다. 그렇다면 WFP를 무력화 할 수 있는 방법은 어떤 것들이 있을까?

   

Method 1. 핸들 변경을 통한 특정 폴더에 대한 WFP 무력화

winlogon.exe이 갖고 있는 Directory change notification handle을 종료함으로써 특정 폴더에 대한 WFP를 재부팅 전까지 무력화 할 수 있다. [그림 1]과 같이 WFP 대상이 되는 핸들을 강제로 종료할 경우 해당 폴더에 대한 WFP기능이 동작하지 않는다. 본인은 특정 툴을 이용하여 해당 핸들을 강제로 종료한 뒤 테스트를 진행하였지만 악성코드 제작자의 입장에서는 ntdll.NtDuplicateHandle 또는 kernel32.DuplicateHandle 함수를 이용하여 구현이 가능할 것이다.

 

[그림 1]

   

Method 2. SFC API를 이용한 리부팅 전까지 WFP 무력화

winlogon.exe 프로세스의 쓰레드를 살펴보면 [그림 2]와 같이 파일 변경을 감시하는 SFC Watcher Thread가 존재한다. 따라서 해당 쓰레드 종료시 WFP는 리부팅 전까지 무력화된다.

 

[그림 2]

해당 쓰레드 종료 방법은 SFC_OS.DLL의 Ordinal 2번 함수인 SfcTerminateWatcherThread()함수를 이용한다. 프로그램 상으로 구현시 winlogon.exe 프로세스에 가상 메모리 할당 후 SfcTerminateWatcherThread 함수를 해당 메모리로 복사 후 CreateRemoteThread를 호출하는 code injection 방법을 사용하면 가능하다.

Code injection을 위한 Thread procedure 선언 부분은 다음과 같이 구현한다.

DWORD WINAPI ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam                = (PTHREAD_PARAM)lParam;
HMODULE hMod                        = NULL;
FARPROC pFunc                        = NULL;
 
// LoadLibrary("sfc_os.dll");
// pPram->pFunc[0] = kernel32!GetModuleHandleA();
// pPram->szBuf[0] = "sfc_os.dll";
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);
 
// GetProcAddress("SfcTerminateWatcherThread");
// pPram->pFunc[1] = kernel32!GetProcAddress();
// pPram->szBuf[1] = "2";  SfcTerminateWatcherThread
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, (LPCSTR)2);
 
((PFSFCTERMINATER)pFunc)();
 
return 0;
}

winlogon.exe에 생성되는 remote thread의 parameter는 다음과 같이 넘겨준다.

// Thread Parameter
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2];                        // LoadLibraryA(), GetProcAddress()
char szBuf[2][128];                        // "sfc_os.dll", #2 -> "SfcTerminateWatcherThread", 
}THREAD_PARAM, *PTHREAD_PARAM;
......
 
hMod = GetModuleHandleA("kernel32.dll");
// set THREAD_PARAM
param.pFunc[0] = GetProcAddress(hMod, "GetModuleHandleA");
param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
strcpy_s(param.szBuf[0], "sfc_os.dll");
strcpy_s(param.szBuf[1], "SfcTerminateWatcherThread"); // #2

실제로 예제 소스를 작성하여 테스트 결과 [그림 2]의 쓰레드가 모두 종료되었으며 재부팅전까지 WFP 기능은 무력화 되었다. 악용의 소지가 있어서 소스 전체를 공개하지는 않겠지만 프로그래밍의 깊이가 매우 얕은 필자의 경우에도 무리없이(?) 구현이 가능했다. SfcTerminateWatcherThread 함수 원형은 다음과 같다.

Ordinal 2:

DWORD WINAPI SfcTerminateWatcherThread();


Method 3. SFC API를 이용하여 특정 파일에 대한 WFP 1분 동안 무력화

실제로 악성코드가 주로 사용하는 방법으로 sfc_os.dll 파일의 ordinal 5번 함수인 SfcFileException을 이용하면 특정 파일에 대하여 1분간 WFP 기능이 무력화 된다. 실제 악성코드의 사례로 [그림 3]과 같이 sfc_os.dll의 Ordinal 5번 함수에 대한 주소를 얻어온다.

 

[그림 4]

SfcFileException 함수에 대한 주소를 얻어온 뒤 [그림 4]와 같이 특정 파일(%system%ws2help.dll)에 대한 WFP를 무력화한다.

 

[그림 5]

SfcFileException 함수의 원형은 다음과 같다.

Ordinal 5:

DWORD WINAPI SfcFileException(DWORD dwUnknown0, PWCHAR pwszFile, DWORD dwUnknown1);


Method 4. undocumented 레지스트리 값을 이용한 WFP 영구 무력화

네번째 방법은 Windows 2000 SP1 이전 버젼에서 WFP를 무력하 위한 undocumented 레지스트리 값을 이용하는 방법으로 현재는 패치가 나와 있으며, sfc.dll과 sfc_os.dll 이전 버젼으로 변경 후 사용 가능하다. 위의 방법들에 비해서 들여야하는 노력이 커서 거의 사용되지 않을 듯 하다. 해당 레지스트리의 값은 다음과 같다.

Undocumented SFCDisable value:

Key: HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Windows File Protection

Value name: SFCDisable

Value: 0xFFFFFF9D

   

Method 5. Protected file list를 패치하여 특정 파일에 대한 WFP 영구 무력화

sfcfiles.dll 파일에는 [그림 6]과 같이 WFP 보호 대상 리스트를 저장하고 있으며, 해당 대상이 되는 파일에 대한 내용을 패치시에 특정 파일에 대한 WFP를 영구적으로 무력화 할 수 있다.

 

[그림 6]

   

참고문헌

- Microsoft : Windows 파일 보호 기능에 대한 설명 http://support.microsoft.com/kb/222193

- Windows File Protection - How to replace a system DLL http://www.bitsum.com/aboutwfp.asp

- Windows Internals : Chapter 5. 시작과 종료

- Code Injection 기법 : http://www.reversecore.com/82

                                                                                                    +---------------------------------+
                                                                                                    | Infinite Flow..                              |
                                                                                                    | mail : reverseinsight@gmail.com    |
                                                                                                    | Blog : http://sinun.tistory.com       |
                                                                                                    | twitter : @unpacker                      |
                                                                                                    | CISSP, SIS1급                             |
                                                                                                    +----------------------------------+

신고
Posted by By. PHR34K