[Windows] 메모리 덤프 형식(Memory Dump Format)
[Windows] 메모리 덤프#01
[Windows] 메모리 덤프#02
[Windows] 메모리 덤프#03

[Linux] 메모리 덤프(Memory Dump)#02
[Linux] 메모리 덤프(Memory Dump)#03

 

[Memory Dump 란?]

Memory Dump 는 System의 물리 Memory 를 File 형태로 저장하는 방법으로, 해당 File 의 구조는 실제 물리 Memory 구조와 동일합니다. 침해사고 분석 시 침해 시스템에 실시간 분석을 수행하면 해당 명령어로 인해 Memory 의 상태 및 Data 가 변경됩니다. 

 

이는 Memory 로부터 얻을 수 있는 중요한 정보를 놓칠 수 있는 가능성이 존재하므로 분석에 불리하게 작용할 수 있습니다. 이 같은 실시간 분석의 단점으로 인해 침해사고 시점의 휘발성 Data 를 File 로 간직하여 Memory 에 변화를 주지 않으면서 분석을 하기위해 Memory Dump 를 수행합니다. 

 

[Linux 에서 Memory Dump]

Linux는 운영체제의 모든 Resource 를 File 형태로 다룹니다. Linux 에서 Memory 접근은 장치 File 을 통해 이루어집니다.

 

과거에는 /dev/mem과 /dev/kmem 통해 직접적으로 리눅스 시스템에서 Memory 를 확보 할 수 있었으나, 보안상의 이유로 최신 커널에서는 이 액세스가 제한되거나 제거되었습니다. 하지만 fmem 이나 LiME(Linux Memory Extractor) 과 같은 프로젝트에서 로드 가능한 커널 모듈이 개발되어 Memory Dump 가 가능하게 되었습니다 . 

 

Linux 는 Kernel 과 함께 동작하는 많은 기능을 Module 의 형태로 제공합니다. 현재 Load 된 Module 을 확인하려면 lsmod 명령을 이용하면 됩니다. Module 은 insmod 명령으로 운영체제가 동작 중인 상태에서 쉽게 Load 할 수 있고, rmmod 로 쉽게 제거할 수 있습니다.

 

Kernel 은 Version 에 따라 구조가 달라질 수 있습니다. Kernel 은 운영체제의 핵심이므로 Kernel 동작을 방해하지 않으려면 Kernel Module 은 이러한 구조와 운영체제 환경에 잘 맞아야 합니다. Kernel 을 직접 다룰 수 있기 때문에 잘못하면 Kernel 의 기능을 오동작시키거나 정지시킬 수도 있습니다. 그래서 보통 Linux Kernel Module 은 Load 시킬 운영체제 환경에서 직접 Compile 합니다.

 

[LiME]

LiME 은 Joe Sylve 가 만든 툴이며 리눅스뿐만 아니라 안드로이드와 같은 리눅스 기반 디바이스의 Memory 를 덤프 할 수 있습니다. 안드로이드의 Memory 를 처음으로 Full Dump 를 한 도구이며 TCP 를 통해서도 Memory 를 덤프할 수 있습니다. Memory 를 획득하는 과정에서 Kernel 과 User 간의 상호작용을 최소화하여 획득 도구에 의한 Memory 의 훼손을 최소화 시켰습니다. LiME 은 다음의 웹페이지 (https://github.com/504ensicsLabs/LiME) 에서 다운로드 할 수 있습니다.

 

LiME 은 바이너리없이 소스로 배포되므로 직접 Compile 해야합니다. 먼저 미리 Compile 된 LKM 이 있는지 확인하거나 가상 컴퓨터에서 컴파일 및 테스트를 먼저 수행하는 것이 좋습니다. LiME 이 미리 Compile 한 LKM 를 확인할 수 있는 평판이 좋은 사이트 중 하나는 Cert.org 의 Linux Forensics Tools Repository(https://forensics.cert.org/) 입니다. Red Hat Enterprise Linux, CentOS 및 Fedora 를 위한 사이버포렌식 도구의 RPM 정보를 제공합니다.

 

:: 장점 ::

  • LKM 에 컴파일 된 LiME 은 크기가 작습니다.
  • 프로세스를 다시 시작할 필요가 없습니다.
  • LKM 에 신속하게 추가/제거 할 수 있습니다.
  • Memory Dump 를 로컬 디스크에 쓰지 않고 네트워크를 통해 전송할 수 있습니다.
  • Memory Dump 는 Volatility 와 호환됩니다.

 

:: 단점 ::

  • 실행파일이 아닌 컴파일방식으로 Memory Dump 를 수행하는 부분은 시스템이 변조되기 때문에 무결성이 손실될 수 있습니다.

 

[사용방법]

LiME 을 다운로드하고 컴파일을 합니다.

make 전에는 리눅스 개발 환경에서 컴파일, 링크, 빌드 등에 필요한 필수적인 도구들을 모아놓은 build-essential 패키지가 설치 되어있어야 합니다.

[root@vmtest ~]# apt-get install build-essential

 

폴더를 만들고 LiME을 다운로드해 압축을 해제하고 빌드합니다.

[root@vmtest ~]# mkdir lime; cd lime
[root@vmtest lime]# wget https://github.com/504ensicsLabs/LiME/archive/master.zip
[root@vmtest lime]# upzip master.zip 
[root@vmtest lime]# LiME-master
[root@vmtest lime]# cd src 
[root@vmtest src]# make
….
make -C /lib/modules/2.6.32-431.5.1.el6.x86_64/build M=/root/lime/src modules

[root@vmtest src]# ls lime*.ko
lime-2.6.32-431.5.1.el6.x86_64.ko

 

방법1. 로컬 시스템에 Memory 를 추출합니다.

추출된 결과파일을 저장할 경로와 이름, 파일형식을 지정해줍니다.

[root@vmtest ~]# insmod lime-2.6.32-431.5.1.el6.x86_64.ko "path=/tmp/mem.img format=raw"

"File exists"에러가 발생하면 "rmmod lime"을 입력하여 모듈을 언로드 후 다시 실행하면 동작합니다.

 

:: 옵션 ::

path 를 이용하여 물리 메모리 이미지를 파일로 저장할 수 있으며 또한 원격지 서버로 전송할 수 있습니다. 

ex. 파일경로와 파일이름 혹은 tcp:<port>

format 은 메모리 이미지의 포맷을 결정하는 옵션입니다. 

ex. raw : RAW 포맷 이미지, lime : LiME 포맷 이미지

 

방법2-1. 원격 시스템에 Memory 를 추출합니다.

LiME의 가장 큰 장점은 로컬 디스크 또는 실제 파일에 대한 출력에만 국한되지 않는다는 것입니다. 로컬 시스템에 path=/tmp/mem.img 와 같이 출력 경로를 지정하는것 대신 path=tcp:4444 와 같이 TCP 서비스를 작성합니다.

[root@vmtest ~]# insmod lime-2.6.32-431.5.1.el6.x86_64.ko "path=tcp:4444 format=lime"

 

그리고 netcat을 사용하여 원격 시스템에 연결하여 메모리 이미지를 조사용 랩톱으로 전송할 수 있습니다. 

[User@laptop ~]# nc target.server.com 4444 > /tmp/mem.img

 

방법2-2. 원격 시스템에 Memory 를 추출합니다.

조사용 랩톱에서 netcat 을 이용해 포트 80 포트를 오픈합니다.

[User@laptop ~]# nc –l 80 > /tmp/mem.img

 

원격 시스템에 LiME LKM을 실행하고 포트 4444에서 TCP 연결을 대기하도록 구성합니다.

[root@vmtest ~]# insmod lime-2.6.32-431.5.1.el6.x86_64.ko "path=tcp:4444 format=lime"

 

원격 시스템의 다른 셸에서 netcat 을 이용하여 조사용 랩톱 (60.70.80.90은 랩톱 IP 주소)의 80 포트로  메모리 이미지를 전송합니다.

[root@vmtest ~]# nc localhost 4444 | nc 60.70.80.90 80

 

Memory Dump 정보를 확인합니다.

[root@vmtest ~]# ls -lah /tmp/mem.img 
-r--r--r--. 1 root root 1.0G Mar 9 08:11 /tmp/mem.img
[root@vmtest ~]# strings /tmp/mem.img | head -n 3
EMiL
root (hd0,0)
kernel /vmlinuz-2.6.32-431.5.1.el6.x86_64 ro root=/dev/mapper/vg_livecd-lv_root rd_NO_LUKS 

 

Memory Dump 가 완료되었으면 커널 모듈을 제거합니다.

[root@vmtest ~]# rmmod lime

 

Memory Dump 분석 전 복사본을 생성하여 분석작업을 진행하도록 합니다. 이때 빠지지않고 해야되는 중요한 것은 해시값을 계산하는 것입니다. md5sum 이나 shasum 을 사용해서 해시값을 계산하면 됩니다.

[root@vmtest ~]# md5sum mem.img
db5fd6e1dabb055f8bc77fd67d95b588 mem.img


[root@vmtest ~]# sha1sum mem.img
0a67af1d5fdc59bf42f4ae93d97580135786fe3c mem.img


[root@vmtest ~]# sha256sum mem.img
63e5814134a140691b452ac6e353bab73458263709da4cebd2fd6484d33b8954 mem.img

 

이렇게 얻은 Memory Dump 파일은 Volatility 등의 분석툴을 사용하여 분석할 수 있습니다.

 

 

[별첨]

LiME Github에서 2020년 8월 26일 이후 더 이상 유지 관리되고 있지 않다고 해서 우분투 24.04에서 테스트 해봤습니다.

[root@vmtest ~]# uname -a
Linux swordfish 6.11.0-25-generic #25~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 17:20:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

 

경고가 뜨긴 하지만 커널 모듈 빌드는 완료됩니다.

[root@vmtest src]# make
make -C /lib/modules/6.11.0-25-generic/build M="/root/lime/LiME-master/src" modules
make[1]: Entering directory '/usr/src/linux-headers-6.11.0-25-generic'
warning: the compiler differs from the one used to build the kernel
  The kernel was built by: x86_64-linux-gnu-gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
  You are using:           gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
  CC [M]  /root/lime/LiME-master/src/disk.o
/root/lime/LiME-master/src/disk.c:45:5: warning: no previous prototype for ‘setup_disk’ [-Wmissing-prototypes]
   45 | int setup_disk(char *path, int dio) {
      |     ^~~~~~~~~~
/root/lime/LiME-master/src/disk.c:77:6: warning: no previous prototype for ‘cleanup_disk’ [-Wmissing-prototypes]
   77 | void cleanup_disk(void) {
      |      ^~~~~~~~~~~~
  CC [M]  /root/lime/LiME-master/src/hash.o
/root/lime/LiME-master/src/hash.c:53:5: warning: no previous prototype for ‘ldigest_init’ [-Wmissing-prototypes]
   53 | int ldigest_init(void) {
      |     ^~~~~~~~~~~~
/root/lime/LiME-master/src/hash.c:97:5: warning: no previous prototype for ‘ldigest_update’ [-Wmissing-prototypes]
   97 | int ldigest_update(void *v, size_t is) {
      |     ^~~~~~~~~~~~~~
/root/lime/LiME-master/src/hash.c:142:5: warning: no previous prototype for ‘ldigest_final’ [-Wmissing-prototypes]
  142 | int ldigest_final(void) {
      |     ^~~~~~~~~~~~~
/root/lime/LiME-master/src/hash.c:172:5: warning: no previous prototype for ‘ldigest_write_tcp’ [-Wmissing-prototypes]
  172 | int ldigest_write_tcp(void) {
      |     ^~~~~~~~~~~~~~~~~
/root/lime/LiME-master/src/hash.c:189:5: warning: no previous prototype for ‘ldigest_write_disk’ [-Wmissing-prototypes]
  189 | int ldigest_write_disk(void) {
      |     ^~~~~~~~~~~~~~~~~~
/root/lime/LiME-master/src/hash.c:215:6: warning: no previous prototype for ‘ldigest_clean’ [-Wmissing-prototypes]
  215 | void ldigest_clean(void) {
      |      ^~~~~~~~~~~~~
  LD [M]  /root/lime/LiME-master/src/lime.o
  MODPOST /root/lime/LiME-master/src/Module.symvers
  CC [M]  /root/lime/LiME-master/src/lime.mod.o
  LD [M]  /root/lime/LiME-master/src/lime.ko
  BTF [M] /root/lime/LiME-master/src/lime.ko
Skipping BTF generation for /root/lime/LiME-master/src/lime.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.11.0-25-generic'
strip --strip-unneeded lime.ko
mv lime.ko lime-6.11.0-25-generic.ko

 

경고를 해결해 보겠습니다.

lime.h에 아래 선언들을 추가하세요

[root@vmtest src]# vi lime.c
...
#ifndef _LIME_DISK_H
#define _LIME_DISK_H

#include <linux/types.h>

int setup_disk(char *path, int dio);
void cleanup_disk(void);
ssize_t write_vaddr_disk(void *v, size_t is);

#endif

// hash
int ldigest_init(void);
int ldigest_update(void *v, size_t is);
int ldigest_final(void);
int ldigest_write_tcp(void);
int ldigest_write_disk(void);
void ldigest_clean(void);

// deflate
int deflate_begin_stream(void *out, size_t outlen);
int deflate_end_stream(void);
ssize_t deflate(const void *in, size_t inlen);
...

 

다음 줄을 main.c에서 수정하세요.

extern int ldigest_clean(void); // 수정 전
extern void ldigest_clean(void); // 수정 후

[root@vmtest src]# vi main.c
...
extern void ldigest_clean(void);
...

 

build.sh을 별도로 만드세요.

[root@vmtest src]# vi build.sh
#!/bin/bash

# build
make -C /lib/modules/$(uname -r)/build M="$(pwd)" CC=x86_64-linux-gnu-gcc-13 modules

# processing
if [ -f lime.ko ]; then
  strip --strip-unneeded lime.ko
  mv lime.ko lime-$(uname -r).ko
  echo "Done: lime-$(uname -r).ko created"
else
  echo "Error: lime.ko not found"
fi

[root@vmtest src]# chmod +x build.sh
[root@vmtest src]# ./build.sh
make: Entering directory '/usr/src/linux-headers-6.11.0-25-generic'
  LD [M]  /root/lime/LiME-master/src/lime.ko
  BTF [M] /root/lime/LiME-master/src/lime.ko
Skipping BTF generation for /root/lime/LiME-master/src/lime.ko due to unavailability of vmlinux
make: Leaving directory '/usr/src/linux-headers-6.11.0-25-generic'
Done: lime-6.11.0-25-generic.ko created

 

정상적으로 메모리가 덤프됩니다.(2025.05.20)

[root@vmtest src]# insmod lime-6.11.0-25-generic.ko "path=/tmp/mem.img format=raw"
[root@vmtest src]# ls -la /tmp/mem.img
-r--r--r-- 1 root root 4294367232 May 20 23:35 /tmp/mem.img

 

 

+ Recent posts