본문으로 바로가기

volatility vs rekall

category Forensics/project 2017. 5. 1. 21:34

메모리 포렌식


  메모리 포렌식이란 메모리를 포렌식적으로 의미 있는 상태로 보존한 후에 사고와 연관된 정보를 최대한 많이 추출한 후 이를 법정이나, 사고 상황에 대한 결과물로 제출하는 것을 말한다. 메모리 덤프에는 악성 실행파일, 시스템 연관 데이터 구조, 관련 사용자 활동 정보와 악성 이벤트 등 다양한 자료들이 포함되어 있다. 메모리 포렌식을 위한 오픈소스 도구로 대표적으로 CLI 기반 도구인 Volatility와 Rekall, GUI 기반 도구인 Redline이 있다.


  칼리 리눅스에는 기본적으로 Volatility와 Rekall이 설치되어 있고, 이를 활용하여 분석을 진행하였다.


Volatility


  Volatility는 오픈 소스이고 파이썬으로 작성되어 있어서 누구나 도구를 다운로드 받아 분석을 수행할 수 있다. Volatility는 플러그인 형태로 다양한 기능을 제공하고 있는 Memory Forensic Tool이다. Tool에서 제공하는 옵션을 통해서 메모리에서 사용자가 원하는 정보를 추출할 수 있다. 메모리 분석 도구 중 가장 많이 쓰이는 Tool로 알려져 있는, CLI 기반 메모리 분석 도구이다. 


  다음은 Volatility의 공식 사이트 주소이다.

  http://www.volatilityfoundation.org/


  Volatility에서 제공하는 플러그인은 다음과 같다.

(출처: 루멘소프트 보안기술연구팀, Volatility Plugin을 이용한 Windows Memory Dump 분석)


Plugins


Image Identification : 덤프 파일의 하드웨어 정보

  - imageinfo, kdbgscan, kprcscan


Processes and DLLs : 프로세스 분석 및 DLL 분석

  - pslist, pstree, psscan, dlllist, dlldump, handles, getsids, verinfo, enumfunc


Process Memory : 프로세스 메모리 분석

  - memmap, memdump, procmemdump, procexedump, vadwalk, vadtree, vadinfo, vaddump


Kernel Memory and Objects : 커널 분석

  - modules, modscan, moddump, ssdt, driverscan, filescan, mutantscan, symlinkscan, thrdscan


Networking : 네트워크 분석

  - connections, connscan, Sockets, sockscan, netscan


Registry : 레지스트리 분석

  - hivescan, hivelist, printkey, hivedump, hashdump, lsadump, userassist


Crash Dumps, Hibernation, and Conversion : 덤프 분석

  - crashinfo, , hibinfo, imagecopy


Malware and Rootkits : 악성코드 및 루트킷 분석

  - malfind, , svcscan, ldrmodules, impscan, apihooks, idt, gdt, threads, callbacks, driverirp, devicetree, psxview, ssdt_ex, timers


Miscellaneous : 스트링 분석

  - strings, volshell, bioskbd, yarascan



Rekall


  Rekall은 구글에서 2013년부터 volatility를 기반으로 만든 오픈 소스 도구이다. volatility에서는 profile 옵션을 통해 프로파일 정보를 맞춰줘야 하는 것과는 다르게, rekall은 자동으로 프로파일 정보를 검색해준다.

  

  Volatility를 기반으로 만들어졌기 때문에, Rekall의 플러그인은 대부분 Volatility의 플러그인과 겹친다.


  다음은 rekall의 공식 사이트 주소이다.

  http://www.rekall-forensic.com/



Plugins

 

Win32_GUI

atoms, atomscan, desktops, eventhooks, gahti, messagehooks, sessions, userhandles, windows_stations,

 

Registry

getservicesids , hivedump, hives, printkey, regdump, userassist, users

 

Image Identification

  Imageinfo, kdbgscan, kpcr

 

Networking

  connections, connscan, sockets, netscan, netstat

 

Process and DLLs

  dlldump, dlllist, memdump, memmap, procdump, procinfo, pslist, psscan, pstree, psxview, privileges, vacbs, vad, vaddump, vadmap

 

Kernel Memory and Objects

  devicetree, driverscan, dtbscan, dumpfiles, filescan, find_dtb, handles, mftdump, moddump, modscan, modules, mutantscan, object_tree, object_types, pagefiles, phys_map, pool_tracker, pools, rammap, services, sigscan, ssdt, svcscan, symlinkscan, thrdscan, threads, timers, times, unloaded_modules

 

Malware

  check_pehooks, driverirp, hooks_eat, hooks_iat, hooks_inline, impscan, ldrmodules, malfind, mimikatz, pedump, peinfo, certscan

 

Physical address, Virtual address

pas2vas, ptov, virt_map, vtop

 

Crashdump

  raw2dmp

 

Miscellaneous

yarascan, yarascan_physical


그럼, Memory Forensic에서 쓰이는 가장 대표적인 두 가지 도구들에 대한 비교를 해보자!



[그림] volatility imageinfo

 

[그림] rekall imageinfo


  rekall은 imageinfo를 치면 따로 그 이미지에 대한 정보를 제공해준다.

 

[그림] rekall 실행


[그림] rekall 실행

 

위 그림에서 보면 알 수 있듯이, volatilityrekall은 명령어를 입력할 때 차이점을 확인할 수 있다. 가장 큰 차이점은 volatility에서는 명령어를 입력할 때 profile 정보가 필요하다는 것이다.


rekall은 volatility에서와 같이 명령어를 실행해서 사용할 수도 있지만, 그림에서처럼 인터렉티브 모드로도 사용할 수 있다.

 


[그림] volatility에서의 pslist

 

[그림] rekall에서의 pslist

 

기본적인 명령어인 pslist에서는 큰 차이점이 두드러지지 않았다.

pslist 명령어는 PsActiveProcessHead를 통해 doubly-linked list 형태로 탐색을 한다. 이 명령어는 hidden/unlinked Process는 감지를 못하는 단점이 있다.

Thds와 Hnds의 상태가 0이면, 해당 프로세스는 활성 상태가 아님을 뜻한다.


[그림] volatility pstree


[그림] rekall pstree


  pstree에 대한 정보도 크게 차이점은 없어보인다.

  pstree는 pslist와 비슷한 기능을 하지만 hidden/unlinked Process 까지도 확인할 수 있다는 장점이 있다. 자식 프로세스를 "."을 통해 Tree 형태로 보여준다.


[그림] volatility psscan


[그림] rekall psscan


  psscan은 pool tag scanning을 통해 Process들을 보여주는데, 이미 종료된 프로세스와 루트킷에 의한 hidden/unlinked Process 들도 확인할 수 있다. 프로세스가 종료된 상태면 exit_time에 기록이 남게 된다.



[그림] volatility psxview


[그림] rekall psxview

 

  psxview는 psscan과 pslist 등에서 True와 False로 보여주기 때문에, 수상한 프로세스를 찾을 때 유용하다.


  rekall에서는 pslist를 출력해 주지 않는다.



[그림] rekall dlllist >


인터렉티브 모드가 아닌, volatility에서처럼 명령어를 실행하면 명령한 것을 저장할 수 있다.


[그림] volatility dlllist >

 

[그림] 실행 결과


  dlllist는 봐야하는 양이 많기 때문에, txt 파일로 저장을 했다.

 


[그림] volatility dlllist -p


[그림] rekall dlllist

  

  volatility에서는 -p 옵션을 주어 pid를 넣어주면, 그에 해당하는 dll list들을 볼 수 있다. 여기서 pid 1212 값을 가진 calc는 은닉되어있는데, p 옵션으로는 확인할 수 없었다.


  하지만, rekall에서는 proc_regex로 해당 프로세스의 이름을 넣어주면 은닉된 프로세스가 임포트하는 dll list들을 불러올 수 있었다.

 

  참고로, rekall에서는 -p 옵션이 없다.

 


[그림] volatility ldrmodules


[그림] rekall ldrmodules


[그림] volatility ldrmodules -p


[그림] rekall ldrmodules proc_regex


  PEB 안의 linked list에서 link를 끊는 것을 통해 DLL을 숨기는 DKOM 같은 기법의 경우 VAD(Virtual address Descriptor)에 정보가 남아 있기 때문에 이를 탐지 가능한데, 이 명령어는 unlinked 된 명령어를 출력해 준다.


  해당 명령어의 결과에서 Memory mapping 된 PE File이 PEB List에 존재하면 1, 하지 않으면 0을 출력해준다.

  

  volatility와 rekall 모두 ldrmodules을 사용할 수 있었지만, 특정 프로세스를 선택하는 옵션에서 차이가 난다.


 

[그림] volatility handles

 

[그림] rekall handles


  handles 명령은 프로세스에 의해 열린 핸들의 목록 나타낸다. 프로세스는 CreateFile 같은 함수를 사용하여 핸들을 획득하고, 그러한 핸들은 CloseHandle 함수가 호출되기 전까지 유효하게 사용된다.


  이 역시 별다른 차이점은 없었다.


 

[그림] volatility memdump


[그림] rekall memdump


  memdump 명령어를 사용해서 프로세스의 다양한 Memory Segment에서 모든 데이터를 추출하여 덤프파일로 생성한다.


  volatility와는 다르게, rekall에서는 memdump라는 명령을 치면, 모든 프로세스에 대한 덤프 파일을 생성해 주었다.


 


[그림] volatility vadwalk



[그림] rekall vad

 

VAD tree(Virtual Address Descriptor tree)란 자체 밸런싱 바이너리 트리를 말한다. 이는 특정 노드의 왼쪽은 특정 노드 보다 낮은 값의 노드, 오른쪽은 특정 노드보다 높은 값의 노드로 이루어져 있는 트리를 말한다. Windows memory manager에서 프로세스가 할당 받은 메모리를 표현하기 위해 사용된다.

명령어를 통해 vad 노드들을 확인 할 수 있다.

그림에서 볼 수 있듯이, volatility에서는 vadwalk라는 명령어로, rekall에서는 vad라는 명령어를 사용한다.

 



[그림] volatility vadtree

 

  vad 노드들을 트리 형태로 보여주는 명령어이다. volatility에만 존재하고 rekall에는 존재하지 않는다.

 


[그림] volatility vadinfo

 

Virtual address의 시작/, Tag, Flag, Kernel MemoryMMVAD 구조체 주소, Memory Protection 등을 보여주는 명령어이다.

이 명령어는 volatility에만 존재하고, rekall에는 존재하지 않는다.

 


[그림] rekall vadmap

 

  volatility에는 존재하지 않고, rekall에 존재하는 vadmap이라는 명령어는 vad의 각 페이지의 주소 변환 상태를 보여준다.

 


[그림] volatility vaddump

 


[그림] rekall vaddump

 

vaddump는 각각의 VAD Segment에 포함된 Datadump하는 명령어이다. memdump와는 달리 두 도구에서 dump되는 dmp 파일의 이름이 Memory 주소 영역으로 되어있다. PhysicalOffset이 파일명에 들어가는 이유는 같은 이름을 가진 2개 이상의 프로세스들을 구분하기 위함이다.

rekall에서는 Length를 표시해주고, Comment를 이용해 data의 위치까지 표시해준다.

 


[그림] volatility modules

 


[그림] rekall modules

 

시스템에 로드된 커널 드라이버들을 보여주는 명령어다. 이 명령어는 PsLoadedModeulList가 가리키는 _LDR_DATA_TABLE_ENTRY 구조의 이중 연결 목록을 살펴본다. hidden/unlinked kernel driver는 출력해주지 않는다.

volatilityrekall 두 도구 모두 이 명령어를 지원하며, 같은 기능을 수행한다.

기본적으로 Virtual address로 출력하며, volatilty에서는 Physical address를 보고 싶다면 -P 옵션을 추가하면 된다.

 


[그림] volatility modscan



[그림] rekall modscan

 

modscan 명령어는 실제 메모리에서 풀 태그를 검색하여 LDR_DATA_TABLE_ENRY 구조를 찾는다. 이전에 로드 되었던 드라이버, 루트킷에 의해 hidden/unlinked된 드라이버도 출력해준다.

volatility에서는 physical address로 보여주는 반면, rekall에서는 virtual address로 출력해준다.

 


[그림] volatility moddump

 


[그림] rekall moddump

 


[그림] rekall moddump Filter

 

moddump는 커널 드라이버를 파일로 덤프해주는 명령어이다. 이 명령어는 정규 표현식과, Physical Offset을 이용한 필터를 지원해 준다. 모든 드라이버들을 덤프하고 싶으면 아무런 필터를 적용하지 않으면 된다.

 


[그림] volatility ssdt

 


[그림] rekall ssdt

 

SSDT(System Service Descriptor Table)는 유저 영역과 커널 영역 사이의 주된 인터페이스이다. 과거에는 악성코드가 SSDT 후킹을 시도하곤 하였지만, 마이크로 소프트에서 PatchGuard를 발표하면서 지금은 거의 사라진 후킹 방법이다.

ssdt 명령어는 Native/GUI SSDT의 함수들을 list 시켜주는 명령어이다. ETHREAD 객체를 스캔한 후, 모든 유일한 ETHREAD.Tcb.ServiceTable Pointer들을 모아서 확인하기 때문에 루트킷에 의해 덮어 쓰거나 복사된 SSDT 미탐을 탐지할 수 있다.

두 도구 모두 동일한 역할을 하는 것을 확인할 수 있다.



[그림] volatility driverscan

 


[그림] rekall driverscan

 

driverscan은 메모리의 DRIVER_OBJECT를 스캔하는 명령어이다. 이는 커널 모듈을 찾을 수 있는 또 다른 방법이며, 모든 커널 모듈이 DRIVER_OBJECT와 관련된 것은 아니다.

 


[그림] volatility filescan

 


[그림] rekall filescan

 

filescan은 메모리의 FILE_OBJECT를 스캔하는 명령어이다. 이는 루트킷이 디스크에 파일을 숨기고, 루트킷이 실제 시스템의 open handle을 숨기는 기능을 하는 API 함수들을 후킹하더라도 open File을 찾을 수 있다.

두 도구 모두 FILE_OBJECToffset, file name, number of pointers to the object 등을 결과로 출력해준다.

 


[그림] volatility mutantscan

 


[그림] rekall mutantscan

 

mutantscan 명령어는 메모리에서 KMUTANT 객체를 스캔하는 명령어이다. mutant는 윈도우에서 named semaphore를 구현한 것이다. 이것은 악성코드의 단일 복사본이 동시에 실행되도록 하기 위해 악성코드가 사용한다.  CID 컬럼은 ProcessID ThreadID를 보여준다. 특정 악성코드 가닥이 사용하는 mutant의 이름을 분석하면, 악성코드가 시스템에서 실행 중인지 즉시 알 수 있다.

volatility에서보다는 rekall에서 name을 조금 더 상세히 표현해 주는 것을 확인할 수 있었다.

 


[그림] volatility thrdscan

 


[그림] rekall thrdscan

 

thrdscan는 메모리의 ETHREAD 객체를 스캔하여 보여주는 명령어이다. ETHREAD는 부모 프로세스를 식별할 수 있는 정보를 가지고 있기 때문에 이는 hidden Process를 찾는데 도움을 준다.

volatilityrekall보다 생성시간과 종료시간을 좀 더 잘 표현해준다.

 


[그림] volatility threads

 


[그림] rekall threads

 

threads는 모든 프로세스를 반복하고, 모든 프로세스의 모든 스레드를 나열하는 명령어이다.

volatlityrekall보다 더 상세하게 스레드를 나열하는 것을 확인할 수 있다.

 


[그림] volatility netscan

 


[그림] rekall netscan

 

netscan Vista, 2008 or Windows 7 이미지에서 connectionssocket을 확인할 수 있는 명령어이다.

 


[그림] rekall netstat

 

위 그림처럼, rekall에서는 netstat이라는 명령어를 사용해서 active network connection을 출력해준다.

 


[그림] volatility hivescan

 

hivescan은 메모리 덤프로부터 CMHIVEs(Registry hives)Physical address를 찾아주는 명령어이다.

rekall에는 존재하지 않고, hives라는 명령어로 대신한다.

 


[그림] volatility hivelist

 


[그림] rekall hives

 

hivelist는 메모리 덤프로부터 Registry hivesvirtual addressDisk상의 절대 경로를 출력해주는 명령어이다.

rekallhives라는 명령어를 사용하여 Registry hivesvirtual address와 디스크 상의 절대 경로를 출력한다..

 


[그림] volatility userassist

 


[그림] rekall userassist

 

userassist는 시스템에서 실행되었던 프로그램의 목록과 실행 횟수, 그리고 마지막 실행시간 등의 정보를 출력해주는 명령어이다.

 


[그림] volatility crashinfo

 

crashinfo Crash dump header 정보를 출력해주는 명령어이다. Crash dump는 프로그램이 죽었을 때의 메모리 내용을 파일로 남기는 것을 말하는데, 이 파일을 분석하면 어떤 프로그램의 오류 때문에 죽었는지를 분석할 수 있다.

rekall에는 존재하지 않는다.

 


[그림] volatility malfind

 


[그림] rekall malfind

 

malfind 명령어는 일반적인 방법이나 툴로 찾아내지 못하는 Code/DLLs VAD tag Page Permission과 같은 특성에 기반하여 확인할 수 있다. malfind의 목적은 일반적인 Method/Tool로는 확인 할 수 없는 DLL들을 찾는 것이므로, CreateRemoteThread -> LoadLibrary를 이용하여 삽입된 DLL hidden 상태가 아니므로 dlllist 명령어를 사용해서 확인해야 한다.

 


[그림] volatility svcscan

 


[그림] rekall svcscan

 

svcscan는 메모리에 어떤 서비스가 등록되었는지 확인하는 명령어이다. 각 윈도우 서비스에 대한 프로세스 ID와 서비스 이름, 서비스 타입, 서비스의 현재 상태 등을 확인 할 수 있다.

 


[그림] volatility ldrmodules

 


[그림] rekall ldrmoudles

 

PEB 안의 linked list에서 Unlinking을 통해 DLL을 숨기는 기법의 경우, VAD에 정보(Base address, Full path)가 남아 있기 때문에 이를 탐지 가능하다. ldrmoudles Unlinked된 명령어를 출력해준다.

해당 명령어의 결과에서 Memory mapping PE File PEB List에 존재하면 True, 하지 않으면 False를 출력해준다.

volatility에서는 -v 또는 –verbose option을 사용하여 모든 Entry Full Path를 확인 할 수 있다.

rekall에서는 verbosity = 10 파라미터를 전달하여 Full Path를 확인 할 수 있다.

 


[그림] volatility impscan

 


[그림] rekall impscan

 

impscan importfunction에 대한 call을 검색하는 명령어이다. Base address를 지정해주지 않으면 프로세스의 main module 끝까지 검색한다.

 


[그림] volatility apihooks

 

User-mode 또는 Kernel-mode에서의 API Hooking을 탐지하기 위해서 사용하는 명령어로, IAT, EAT, Inline Hooking을 찾아낼 수 있다.

 


[그림] rekall hooks_iat

 

  hooks_iat는 커널 메모리와 프로세스에서 IAT EAT를 탐지하는 명령어이다.

 


[그림] rekall hooks_eat

 

  hooks_eat는 커널 메모리와 프로세스에서 EAT hook을 탐지하는 명령어이다.

 


[그림] rekall hooks_inline

 

  hooks_inline은 커널 메모리와 프로세스에서 API hook을 탐지하는 명령어이다.

 


[그림] volatility threads

 


[그림] volatility threads -L

 


[그림] rekall threads

 

volatility

각 쓰레드에 속한 레지스터 정보, 쓰레드 시작 주소의 디스어셈블 코드 등 조사에 관련된 다양한 정보를 제공해주는 명령어이다. ETHREAD 객체의 가상 주소, pid, tid, Thread 와 관련된 모든 tag(SystemThread, AttachedProcess, HookedSSDT), 생성/종료 시간, 상태, 순서, 시작 주소 등을 확인 가능하며 SSDT base 주소와 각 Service Table, Table 앆의 Hook 된 함수도 출력해 준다.

rekall

threads 플러그인은 모든 프로세스를 반복하고 모든 프로세스의 스레드를 나열하는 명령어이다.

 


[그림] volatility callbacks

 


[그림] rekall callbacks

 

callback은 다양한 소스들로부터 설치된 콜백 루틴들을 단순히 열거하는 명령어이다. Rekall은 주소 확인자를 가지고 있으며 각 콜백 위치에 존재하는 것에 대해 더 많이 언급할 수 있다. 일반적으로 rekall은 특정 바이너리(; 커널)의 프로필만 추적한다.

 


[그림] volatility driverirp

 


[그림] rekall driverirp

 

driverirpIRP Major Function Table을 보기 위해서 사용하는 명령어이다. 해당 명령어는 드라이버의 IRP Inline Hooking을 감지하기 위한 명령어이다.

 


[그림] volatility devicetree

 


[그림] rekall devicetree

 

devicetree_DRIVER_OBJECT.DeviceObject.NextDevice를 통해 드라이버 객체와 장치의 관계를 보여주며, _DRIVER_OBJECT.DeviceObject.AttachedDevice를 통해 연결된 장치의 관계를 보여준다.

  Windows 는 계층화된 Driver Architecture 또는 Driver chain 을 사용하므로, 여러 개의 Driver를 검사 또는 IRP 에 응답할 수 있다. Rootkit Driver Device 를 이러한 Chain 에 검사 우회의 목적으로 삽입한다.

 


[그림] volatility psxview

 


[그림] rekall psxview

 

psxview는 다양한 프로세스 리스트를 통해 hidden process를 찾는 명령어이다.

 


[그림] volatility timers

 


[그림] rekall timers

 

timers Kernel times(KTIMER)와 관련된 DPC(Deferred Procedure Calls)를 출력해주는 명령어이다. DPC 주소와 KTIMES를 통해 악성코드가 다양한 방법으로 커널 공간에 숨어 있는 것을 빠르게 찾을 수 있다.

 


[그림] volatility volshell

 

  WinDbg와 비슷한 인터페이스를 제공해주며, Memory Image를 대화형식으로 조사할 수 있다.