특히 루트킷에 의해서 숨겨진 프로세스를 찾는 것은 안티루트킷 도구들과 메모리 분석으로 할 수 있는데, 안티루트킷 도구를
사용하면 조사환경에 어떠한 영향을 주기 때문에 포렌식적으로는 메모리 분석보다 좋지 못한 방법이다.(아예 안좋다는 것은 아님)
메모리에서 프로세스를 찾기전에 프로세스가 어떻게 정보를 저장하고 어떻게 관리가 되는지부터 공부를 해야한다.
이러한 이유로 이번에는 윈도우에서 프로세스를 어떻게 관리하고 다루는지 알아 볼 것이다.
또 프로세스를 숨기는 방법 중 가장 대표적인 DKOM(Direct Kernel Object Manipulation)의 원리도 공부해 볼 것이다.
윈도우에서는 EPROCESS라는 구조체로 프로세스의 모든정보가 들어가 있다.
아래는 windbg 커널 디버깅 모드로 본 XP SP2의 EPROCESS 구조체 정보이다.
위 이미지 말고도 더 많은 정보들이 나왔지만 글이 쓸데없이 길어지는 것을 방지하기 위해 위 이미지만 첨부하였다.
위 이미지를 보면 : 를 기준으로 왼쪽은 항목이름이고 오른쪽은 데이터 타입이다.
직관적인 이름의 항목들이 많이 보이고 프로그래밍을 해본 사람이라면 얼추 이해할 데이터 타입들도 눈에 띈다.
하지만 포렌식 관점에서 중요한 부분은 EPROCESS 구조체에서 몇가지 되지 않는다.
지금 중요하지 않은 정보들도 추후 어떠한 연구를 위해 중요할 수 있으니 한번쯤 훑어보는 것도 좋을 것 같다.
포렌식 관점에서는 아래와 같은 항목들을 주로 본다.
[포렌식 관점에서의 EPROCESS 항목]
- PCB(Process Control Block) : DISPATCHER_HEADER, 디렉터리 테이블 주소, KTHREAD 목록, 우선순위,
커널/유저 CPU 시간 등에 대한 정보를 가지고 있음.
- CreateTime : 프로세스가 시작된 시간 정보를 가지고 있으며, 64bit 윈도우 시간 형식을 지님.
- ExitTime : 프로세스가 종료된 시간 정보를 가지고 있으며, 64bit 윈도우 시간 형식을 지님.
- UniqueProcessId : 프로세스의 ID값을 가지고 있음.
- ActiveProcessLinks : ActivceProcess List를 구성하는 이중 링크드 리스트
- ObjectTable : 오브젝트 핸들 테이블의 위치를 가리키는 포인터 값
- WorkingSetPage : 프로세스 WorkingSetPage
- Peb(Process Environment Block) : 프로세스 실행에 필요한 정보들을 담고 있으며, BaseAddress, Module List,
Heap/Stack 정보가 들어있음.
* WorkingSet : 어떠한 특수 프로세스전용으로 할당된 물리적 메모리 페이지의 그룹
만약 메모리 덤프파일에서 프로세스를 찾는다면 PCB와 ActiveProcessLinks 항목을 주로 이용할 것이며, 프로세스 정보를
찾는다면 나머지 필드들과 Peb 항목을 주로 이용 할 것이다.
EPROCESS의 PCB 항목 데이터 타입을 보면 KPROCESS라고 되어 있는데 이 또한 구조체로서 EPROCESS의 하부 구조체이다.
KPROCESS의 하부 구조체 중 DISPATCHER_HEADER 이라는 하부 구조체가 있는데 이 구조체는 프로세스들 사이의 동기화에
필요한 구조체이며 메모리 덤프에서 오브젝트를 찾을 때 중요할 역할을 한다.
커널 영역에 있는 또 다른 구조체인 ETHREAD, KTHREAD는 위에서 설명하였던 구조체들과 구조는 같으나 다루고 있는
대상이 스레드라는 점에서만 차이가 있다.
아래 이미지는 KPROCESS 구조체의 정보를 windbg 커널 디버깅 모드로 확인한 이미지이다.
이번에는 PEB를 설명하겠다.
PEB는 EPROCESS의 하부 구조체 중 하나로써, 프로세스의 환경 설정 값을 가지고 있다.
하지만, 직접 값을 가지고 있지는 않고 사용자 영역에 있는 PEB에 대한 포인터 값만을 가지고 있다.
커널 영역에 속하는 PEB를 왜 사용자 영역에 하나 더 두고 그것을 포인터 값으로 가지고 있는지는 아래와 같이 설명 할 수 있다
PEB에 저장되는 데이터는 사용자 모드로 접근하는 이미지로더(Image Loader), 힙 매니저(Heap Manager), 윈도우 시스템 DLL 파일이 필요로 하는 정보이기 때문이다.
그렇기 때문에 커널영역에 있으면 접근을 하지 못하므로 사용자 영역에 저장하고 있는 것이다.
아래는 PEB 구조체의 정보이다.
이제는 ActiveProcessLink에 대해서 알아 볼 것이다.
ActiveProcessLink는 환형 이중 링크드 리스트로 이루어져 있으며, 이 항목을 통해 프로세스의 목록을 얻을 수 있다.
이중 링크드 리스트는 간단히 그림으로 표현하면 아래와 같이 볼 수 있다.
환형 이중 링크드 리스트는 이중 링크드 리스트에 PsActiveProcessLink라는 커널 전역변수를 추가 해 순환 구조를 만들어 준 것이다.
그림으로 표현하면 아래와 같다.
그림을 한눈에 봐서는 이해가 잘 안갈지도 모른다.
하나의 화살표를 눈으로 응시한 후 화살표를 따라가다 보면 어느새 눈은 그림을 따라 맴돌고 있을 것이다.
PsActiveProcessLink 변수에 대해서 좀 더 설명을 하자면, 이 변수는 ActiveProcessLink와 같은 구조로 되어 있고, 이 변수에
접근하려면 커널 프로세스의 권한이 필요하다.
참고로 작업관리자를 열면 System(4)라는 프로세스를 볼 수 있는데 이 프로세스는 윈도우 커널을 의미하며, 언제나
ActiveProcessLink의 첫번째 프로세스가 된다.
이제는 DKOM 기법에 대해서 알아 볼 차례이다.
DKOM 기법은 커널 오브젝트(EPROCESS)를 수정하여 프로세스를 숨기는 방법으로 정상적인 프로세스 환형 이중 링크드 리스트에서 숨기고자 하는 프로세스를 환형 이중 링크드 리스트에서 빼내는 것이다.
이렇게하면 일반적으로 ActiveProcessLink를 참조하여 프로세스 목록을 얻는 도구들은 숨겨진 프로세스를 찾을 수 없다.
일반적인 프로세스 순환 구조라면 그림 5가 되겠지만, 해커나 악의적인 루트킷에 의해 프로세스가 숨겨졌다면 아래와 같은 구조가 된다.
숨겨진 프로세스는 자신을 가리키도록 만드는데 이렇게 하는 이유는 숨겨진 프로세스에 의해 BSOD가 일어나지 않게 하기
위함이다.
커널이 프로세스를 관리하기 위해 참조하는 ActiveProcessLink에서 제외되면 커널의 관리를 받지 못하므로 프로세스가
종료되거나 해야 하는데 종료되지 않는 이유는 무엇일까?
숨겨진 해당 프로세스가 점유하고 있는 자원이 회수되지 않고 메모리에 그대로 남아 있기 때문에 프로세스는
생존 할 수 있는 것이다.
또 윈도우는 프로세스 단위가 아닌 스레드 단위로 처리 기준을 정해놨기 때문에 프로세스가 종료되더라도 스레드만
살아있으면 얼마든지 어떠한 행위의 동작이 가능하다.
이제는 이러한 지식을 바탕으로 메모리 덤프파일에서 프로세스를 찾는 방법을 알아보도록 한다.
프로세스를 찾는 방법은 리스트 워킹 방법과, 패턴매칭 방법이 있다.
[프로세스(오브젝트) 검색 방법]
1. 리스트 워킹 : 하나의 단서를 근거로 하여 목적지까지 거슬러 올라가는 방법이다. 이 방법은 Mariusz Burdach의
'An Introduction to windows memory forensic' 문서에 자세히 설명되어 있다.
위에서 설명했던 것처럼 어떤 프로세스의 ActiveProcessLink를 알고 있다면 앞이나 뒤의 프로세스를
계속 찾다보면 결국 다시 처음 출발하였던 곳으로 돌아올 것이고 그동안 거쳐왔던 프로세스를 나열하면
프로세스 목록이 얻어지는 것이다. 하지만 위에서 설명한 DKOM 기법을 이용하면 이 검색방법으로는
숨겨진 프로세스를 찾을 수 없다.
2. 또다른 리스트 워킹 : 명칭은 같지만 방식이 다른 이 리스트 워킹 방법은 Ruichao Zhang, Lianhai Wang,
Shuhui Zhang이 함께 발표한 'Windows Memory Analysis Based in KPCR' 논문에서
소개되었다. 이 기법은 EPROCESS가 아닌 또 다른 커널 구조체인 KPCR을 기초로 한다.
KPCR은 XP, 2003에서 가상 주소 0xFFDFF000에 위치하며 KPCR의 확장 영역인 KPCRB는
같은 버전에서 0xFFDFF120에 위치한다. KPCRB는 EPROCESS의 KTHREAD 구조체에 대한
포인터값이 들어있어 KPCRB를 통해 KTHREAD를 알면 EPROCESS의 위치도 알 수 있다.
또 이 방법은 위 기존의 리스트 워킹 방법과 마찬가지로 DKOM 기법이 적용된 프로세스는 찾지
못하며, Vista 이후의 버전들의 KPCR 주소가 컴퓨터마다 달라 Vista 이후 버전에는 적용하기가
힘들다.
3. 패턴매칭 : 리스트 워킹의 한계를 극복하기 위해 개발된 기법이다. 이 기법은 Andreas Schuster의
'Searching for processes and threads in Microsoft Windows memory dumps'에서 소개 되었다.
이 기법의 원리는 다음과 같다.
- 프로세스나 스레드는 기본적인 내부구조는 같으며, 버전마다 조금씩 상이할 뿐이다. 이 사실을 이용하여 패턴을
추출하고 이것을 검증할 수 있는 룰을 만들 수만 있다면 메모리덤프로부터 숨겨진 프로세스와 스레드를 찾을 수
있을 것이다.
패턴 매칭 조건은 다음과 같다.
- 윈도우의 커널은 프로세스와 스레드를 오브젝트로 정의하고 있으며, 모든 오브젝트는 그 앞에 OBJECT_HEADER
이라는 구조체를 가지고 있다. 이 구조체는 타입에 따라 구조가 일정하고, 이 구조체의 일부 값들은 몇몇 윈도우
버전에서 동일하다.
- 프로세스와 스레드는 동기화를 하며, 동기화가 가능한 오브젝트들은 특별한 구조체를 공유하는데 이 구조체
이름은 DISPATHCER_HEADER이다. 이 구조체는 몇몇 윈도우 버전마다 일정한 값을 가지고 있다.
- 윈도우는 메모리 관리를 위해서 메모리 공간이 부족하게 되면 앞으로 사용되지 않을 것 같은 오브젝트의 메모리
영역을 페이지 파일로 스왑(Swap)한다. 스왑이 되면 커널에 의해서 paged pool에 저장이 되고 스왑이 되지 않는
오브젝트들은 non-paged pool에 저장이 된다. 프로세스와 스레드의 경우 앞으로 사용이 되지 않을 것 같아도
빈번히 접근되는 오브젝트이기 때문에 paged pool이 아닌 non-paged pool에 저장된다.
이것을 담당하는 것이 POOL_HEADER 구조체이다.
이 기법은 커널변수나 테이블에 의존하지 않고 오브젝트를 찾을 수 있으며, 이미 종료된 오브젝트라도 다른
오브젝트에 의해 데이터가 덮어씌어지지 않았다면 종료된 오브젝트를 찾을 수 있다.
패턴매칭의 경우 논문저자가 어떤 패턴 규칙을 만들었는지 논문에서 확인 할 수 있다.
'[+] Forensic' 카테고리의 다른 글
Registry (1) (0) | 2012.01.02 |
---|---|
Memory Analysis (8) (3) | 2011.12.28 |
Memory Analysis (6) (0) | 2011.12.26 |
Memory Analysis (5) (0) | 2011.12.26 |