## 개요 포렌식 분석에는 각종 아티팩트를 분석해서 결론을 도출하는 일도 있지만, 아티팩트 영역의 기술적 확장이 더뎌지고, 휘발성 데이터에서 쓸모있는 정보를 추출하는 연구 과정들이 인기를 얻으면서 휘발성 데이터의 대표적 예시인 메모리 포렌식이 큰 화제가 되고 있다. 메모리 분석은 어떻게 할까? 라는 생각을 많이들 한다. 막막함에 시작하기도 어려운 것이 사실이다. 메모리 데이터 파일을 열어보면 형식도 없어 보이고 무분별하게 저장된 것처럼 보이기 때문이다. 파일 형태의 구조/데이터에 익숙한 우리에게는 메모리라는 것은 하나의 장벽처럼 느껴지기까지 한다. 기본적인 분석은 `strings` 명령어나 `regex` 같은 문자열들을 나열해 보고 그 중 ”필요가 있어 보이는“ 문자열들을 사용하는 것이다. 이 방식의 근본적인 한계는 결과론적이라는 것이다. 어떤 정보가 있는지 알고 있는 상태에서 그 정보를 찾는 행위는 그 정보가 있음을 증명하는 것 이외에는 할 수 있는게 없다. 찾은 문자열이 어떤 정보인지 왜 생성된 것이고 언제 생성된 것인지, 무엇과 연관이 있는지는 단 하나도 유추할 수 없다. 따라서 메모리 구조를 통해 어떤 프로세스에 의해 남은 정보인지 파악하고, 전체 프로세스는 어떤게 있는지를 포함하여 다양한 정보들을 확인할 수 있도록 플러그인의 형태로 제작해 놓은 것이 바로 Volatility라는 도구이다. 자세히 알아보도록 하자. ## 설치 일단 두가지의 버전이 존재한다. Python2 환경에서 돌아가는 volatility 2와 Python3 환경에서 돌아가는 volatility 3이다. 파이썬을 기반으로 한 프로그램이기 때문에 설치하기 위해서는 공식 설치 방법을 따르면 된다. 이번 글에서는 volatility2 보다는 volatility3를 좀더 집중적으로 다뤄볼 것이다. [Volatility 3 Github](https://github.com/volatilityfoundation/volatility3/tree/develop) 먼저 Python 설치를 해야겠다. Volatility 3 에서 지원하는 파이썬 버전은 3.7.0 이후의 버전들이다. 최소한이기 때문에 3.7.0을 사용할 경우 몇몇 기능을 사용하는데 한계가 있을 수 있어 유의하자. ``` git clone https://github.com/volatilityfoundation/volatility3.git cd volatility3 pip3 install -r requirements-minimal.txt python3 setup.py build python3 setup.py install ``` 이 명령어들을 오류 없이 입력하게 된다면 정상적으로 실행이 될 것이다. 혹은 standalone.exe 버전을 찾아도 된다. > [!NOTE] StandAlone 이 뭔데요? > 말그대로 홀로서기가 가능한 파일이다. 실행 파일의 형태로 필요한 구성품들을 미리 넣어놓고 컴파일을 했기 때문에 파이썬이라던가, 각종 라이브러리같은 추가적인 설치가 필요하지 않은 버전이다. > > 구글링하면 쉽게 찾아볼 수 있을 것이다. ## Prerequisites 일단 사용하기 전에 알아야 하는 것이 있다. 바로 Image Symbol File 이라는 것이다. 뭔지 모를거 다 안다. 이걸 왜 알아야 하는지 알아보도록 하자. 메모리 구조는 운영체제별로 완전히 다르다. 심지어 같은 운영체제를 사용하더라도 그 버전별로 다르기까지 하다. 공통적으로 분석할 방법이 없기 때문에 원래였으면 각 운영체제의 각 버전별로 도구를 만들어야만 했다. 원래 volatility2에서는 이 문제를 해결하기 위해 profile이라는 옵션을 활용했다. 도구를 사용하기 전에 메모리 파일을 스캔하거나, 원본 시스템의 운영체제 버전을 확인해서 해당 버전을 명시해서 옵션으로 넣어주는 일이 선행됬어야 했다. ~~(말로는 간단하지만 프로파일을 탐색하는데 오래 걸리면 몇시간은 걸렸기 때문에 사용에 어려움이 있을 정도였다.)~~ 이 부분을 개선하기 위해서 volatility3에서부터는 ISF (Image Symbol File) 이라는 기능을 도입했다. 다운로드된 파일의 심볼 정보만 넣어준다면 volatility에서 자동으로 맞는 symbol image를 찾아서 툴을 돌리게 된다. 자동으로 찾아준다는 점만 제외하고는 다른 부분이 없어 보이긴 하겠지만, 실질적으로 성능 차이 체감은 크다. Git install을 하게 되었을 때 기본적인 심볼들은 다 들어 있으며, 추가적으로 [심볼을](https://github.com/volatilityfoundation/volatility3/tree/develop#symbol-tables) 사이트에서 제공하기도 한다. 단순히 symbols 경로 하위에만 넣어주면 정상적으로 인식이 될 것이다. > [!Question] 그래도 제가 원하는 심볼 이미지가 없어요! > > 보통 업데이트 주기와 내용 차이가 심한 Linux 기반 운영체제들은 이미지가 없는 경우가 허다하다. 그렇다고 해서 절망할 필요는 없다. 이런 상황을 대비해서 ISF를 직접 만들어서 넣을 수 있기 때문이다. (다만 수많은 삽질이 필요하니 마음을 단단히 먹자) > ㅁ > 기본 명령어는 아래 적어 놓았는데, 자세한 설명과 함께 실행하고 싶은 사람들은 [Volatility Readthedocs - Creating New Symbol Tables](https://volatility3.readthedocs.io/en/latest/symbol-tables.html) 를 참고하도록 하자. > > ```shell > git clone https://github.com/volatilityfoundation/dwarf2json.git > apt install golang-go cd dwarf2json > go mod download github.com/spf13/pflag > go build > > uname -r # 5.15.0-XXXX-aws // Your version > > echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \ sudo tee -a /etc/apt/sources.list.d/ddebs.list > > apt install ubuntu-dbgsym-keyring > apt-key adv --keyserver keyserver.ubuntu.com -—recv-keys F2EDC64DC5AEE1F6B9C621F0C8CAB6595FDFF622 > > apt update > > apt install linux-image-5.15.0-XXXX-aws-dbgsym > // Your version > > cd /dwarf2json > ./dwarf2json linux --elf /usr/lib/debug/boot/vmlinux-5.15.0.XXXX-aws --system-map /boot/System.map-5.15.0.XXXX-aws > Ubuntu22.04-5.15.0.XXXX-aws.json > > mkdir /volatility3/volatility3/symbols/linux > mv ./Ubuntu22.04-5.15.0.XXXX-aws.json /volatility3/volatility3/symbols/linux > ``` ## 기능 여러 심볼 이미지들을 제공하는 정성에 버금가게 다양한 기능 역시 지원하고 있다. 기능들은 각 운영체제 별로 나누어서 사용하게 된다 (운영체제 별로 같은 기능이더라도 명령어 형식이 약간 다르다). 이번 글에서는 기본 제공되는 플러그인들에 대해서만 간략하게 소개를 해 볼 것이며, 사설 플러그인 같은 경우에는 각 플러그인의 제조업자의 설명을 참고하거나 직접 문의하면 되겠다. 모든 명령어들의 사용법은 각 소개하는 명령어 이름을 사용하면 된다. 예를 들어 `Bash` 명령어를 사용한다고 했을 때 실제 명령어는 아래 코드처럼 치면 되겠다. ``` python3 vol.py -f output.raw linux.bash.Bash ``` 이제 명령어 각각에 대한 내용을 적어 놓았다. 주로 많이 사용하게 될 명령어들에 약간의 첨언만 해 놓았다. 가볍게 참고하도록 하자. 아주 세부적인 내용 (구조체, 소스코드)는 공식 Document를 참고하자. ### Linux `isfinfo.IsfInfo` 현재 사용중인 ISF파일에 대한 정보를 출력해 준다. `linux.bash.Bash` Bash history 커맨드를 메모리에서 복구해 준다. 비슷한 내용을 [[Bash History]]에서 다룬 적이 있다. `linux.check_afinfo.Check_afinfo` Verifies the operation function pointers of network protocols. `linux.check_creds.Check_creds` Checks if any processes are sharing credential structures `linux.check_idt.Check_idt` IDT(Interrupt Descriptor Table)의 변조 유무를 확인해 주는 플러그인이다. 악성 코드들에서 실행 분기를 위조하기 위해서 IDT를 수정하곤 하는데, 이 플러그인을 이용해서 변조 유무를 확인할 수 있겠다. `linux.check_modules.Check_modules` 모듈 리스트를 sysfs의 것과 비교한다. `linux.check_syscall.Check_syscall` 시스템 콜 테이블을 확인하게 된다. 후킹이 되어있는지 아닌지 확인해 볼 수 있겠다. IDT와 유사하게 변조해서 활용하는 경우가 잦으니 잘 확인해 보자. `linux.elfs.Elfs` 모든 프로세스의 ELF 파일을 리스트업 해준다. `linux.lsmod.Lsmod` load된 커널 모듈들을 리스트업 해준다. `linux.lsof.Lsof` 열려 있는 모든 프로세스의 메모리 맵 정보를 출력한다. `linux.malfind.Malfind` 굉장히 재밌는 기능인데 도구 자체적으로 악성 코드(외부 코드) 가 들어갈 수 있는 영역을 쭉 보여준다. `linux.proc.Maps` 모든 프로세스의 메모리 맵 정보를 출력한다. Lsof와의 차이점은 사용 중인 것과 아닌 것의 차이겠다. 메모리 맵핑에 중점을 둔 것은 proc.Map이다. `linux.pslist.PsList` 가장 많이 쓰는 명령어가 아닌가 싶다. 사용중인 프로세스 정보를 확인하기 위해 쓴다. `linux.pstree.PsTree` 프로세스의 리스트 말고 그 계층 관계를 확인하고 싶을 때 psTree를 사용해서 특정 프로세스를 호출하는 프로세스는 뭔지 이런 상하관계를 확인하게 된다. ### Windows `windows.bigpools.BigPools` List big page pools. `windows.cachedump.Cachedump` Dumps lsa secrets from memory `windows.cmdline.CmdLine` Lists process command line arguments. `windows.dlllist.DllList` Lists the loaded modules in a particular windows memory image. `windows.driverirp.DriverIrp` List IRPs for drivers in a particular windows memory image. `windows.driverscan.DriverScan` Scans for drivers present in a particular windows memory image. `windows.dumpfiles.DumpFiles` Dumps cached file contents from Windows memory samples. `windows.envars.Envars` Display process environment variables `windows.filescan.FileScan` Scans for file objects present in a particular windows memory image. `windows.getservicesids.GetServiceSIDs` Lists process token sids. `windows.getsids.GetSIDs` Print the SIDs owning each process `windows.handles.Handles` Lists process open handles. `windows.hashdump.Hashdump` Dumps user hashes from memory `windows.info.Info` Show OS & kernel details of the memory sample being analyzed. `windows.lsadump.Lsadump` Dumps lsa secrets from memory `windows.malfind.Malfind` Lists process memory ranges that potentially contain injected code. `windows.memmap.Memmap` Prints the memory map `windows.modscan.ModScan` Scans for modules present in a particular windows memory image. `windows.modules.Modules` Lists the loaded kernel modules. `windows.mutantscan.MutantScan` Scans for mutexes present in a particular windows memory image. `windows.netscan.NetScan` Scans for network objects present in a particular windows memory image. `windows.netstat.NetStat` Traverses network tracking structures present in a particular windows memory image. `windows.poolscanner.PoolScanner` A generic pool scanner plugin. `windows.privileges.Privs` Lists process token privileges `windows.pslist.PsList` Lists the processes present in a particular windows memory image. `windows.psscan.PsScan` Scans for processes present in a particular windows memory image. `windows.pstree.PsTree` Plugin for listing processes in a tree based on their parent process ID. `windows.registry.certificates.Certificates` Lists the certificates in the registry's Certificate Store. `windows.registry.hivelist.HiveList` Lists the registry hives present in a particular memory image. `windows.registry.hivescan.HiveScan` Scans for registry hives present in a particular windows memory image. `windows.registry.printkey.PrintKey` Lists the registry keys under a hive or specific key value. `windows.registry.userassist.UserAssist` Print userassist registry keys and information. `windows.ssdt.SSDT` Lists the system call table. `windows.statistics.Statistics` `windows.strings.Strings` Reads output from the strings command and indicates which process(es) each string belongs to. `windows.symlinkscan.SymlinkScan` Scans for links present in a particular windows memory image. `windows.vadinfo.VadInfo` Lists process memory ranges. `windows.virtmap.VirtMap` Lists virtual mapped sections. ### macOS `mac.bash.Bash` Recovers bash command history from memory. `mac.check_syscall.Check_syscall` Check system call table for hooks. `mac.check_sysctl.Check_sysctl` Check sysctl handlers for hooks. `mac.check_trap_table.Check_trap_table` Check mach trap table for hooks. `mac.ifconfig.Ifconfig` Lists loaded kernel modules `mac.kauth_listeners.Kauth_listeners` Lists kauth listeners and their status `mac.kauth_scopes.Kauth_scopes` Lists kauth scopes and their status `mac.kevents.Kevents` Lists event handlers registered by processes `mac.list_files.List_Files` Lists all open file descriptors for all processes. `mac.lsmod.Lsmod` Lists loaded kernel modules. `mac.lsof.Lsof` Lists all open file descriptors for all processes. `mac.malfind.Malfind` Lists process memory ranges that potentially contain injected code. `mac.mount.Mount` A module containing a collection of plugins that produce data typically foundin Mac's mount command `mac.netstat.Netstat` Lists all network connections for all processes. `mac.proc_maps.Maps` Lists process memory ranges that potentially contain injected code. `mac.psaux.Psaux` Recovers program command line arguments. `mac.pslist.PsList` Lists the processes present in a particular mac memory image. `mac.pstree.PsTree` Plugin for listing processes in a tree based on their parent process ID. `mac.socket_filters.Socket_filters` Enumerates kernel socket filters. `mac.timers.Timers` Check for malicious kernel timers. `mac.trustedbsd.Trustedbsd` Checks for malicious trustedbsd modules `mac.vfsevents.VFSevents` Lists processes that are filtering file system events ## 결론 오늘은 메모리 분석 도구인 volatility에 대해서 알아보았다. 자세한 사용법에 대한 것들을 다루어 보았는데, 이를 분석에 100% 활용만 할 수 있다면 엄청난 분석 능력을 가져다 줄 것이다. 메모리를 분석할 때 strings나 regex 보다 더 개연성 있는 결과를 원한다면 반드시 사용해야 할 도구라고 생각된다. 플러그인 개발도 직접 해볼 수 있으니, 참고해서 본인에게 필요한 기능을 추가해도 좋을 것이다.