跳到主要内容

· 阅读需 4 分钟
陈橘mo

首先,先分析镜像的内核信息:

randark@memory-forensic:~$ vol -f oh-my-linux.mem banner
Volatility 3 Framework 2.0.1
Progress: 100.00 PDB scanning finished
Offset Banner

0x4f000200 Linux version 5.10.0-21-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.162-1 (2023-01-21)
0x58ecc240 Linux version 5.10.0-21-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.162-1 (2023-01-21)

通过内核信息,可以定位到 Debian 5.10.0-21-amd64 的 deb 发行包文件:

Index of /debian-security/pool/main/l/linux

linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb

下载下来后,将其作为 tar.xz 文件进行解压缩,得到 data.tar 文件,解压缩制作符号表需要的文件:

randark@memory-forensic:~/linux-image$ tar -xvf data.tar ./usr/lib/debug/boot/
./usr/lib/debug/boot/
./usr/lib/debug/boot/System.map-5.10.0-21-amd64
./usr/lib/debug/boot/vmlinux-5.10.0-21-amd64

然后开始制作符号表文件

randark@memory-forensic:~$  ./dwarf2json linux --system-map ~/linux-image/usr/lib/debug/boot/System.map-5.10.0-21-amd64 --elf ~/linux-image/usr/lib/debug/boot/vmlinux-5.10.0-21-amd64  >  linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.json
randark@memory-forensic:~$ sudo mv linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.json /usr/local/lib/python3.10/dist-packages/volatility3/symbols/linux/

尝试使用符号表进行分析:

randark@memory-forensic:~$ vol -f oh-my-linux.mem linux.pslist
Volatility 3 Framework 2.0.1
Progress: 100.00 Stacking attempts finished
PID PPID COMM

1 0 systemd
2 0 kthreadd
3 2 rcu_gp
4 2 rcu_par_gp
6 2 kworker/0:0H
8 2 mm_percpu_wq
9 2 rcu_tasks_rude_
10 2 rcu_tasks_trace
11 2 ksoftirqd/0
12 2 rcu_sched
13 2 migration/0
14 2 kworker/0:1
15 2 cpuhp/0
17 2 kdevtmpfs
18 2 netns
19 2 kauditd
20 2 khungtaskd
21 2 oom_reaper
22 2 writeback
23 2 kcompactd0
24 2 ksmd
25 2 khugepaged
43 2 kintegrityd
44 2 kblockd
45 2 blkcg_punt_bio
46 2 edac-poller
47 2 devfreq_wq
48 2 kworker/0:1H
49 2 kswapd0
50 2 kthrotld
......

成功实现 Volatility3 加载符号表,并分析镜像

如果要使用 Volatility2 进行分析的话,需要使用 linux-header,linux-image 等相关软件包进行编译,为了不影响主机环境,以及懒得开虚拟机的话,可以使用 docker 进行编译:

CTF-Archives / profile-builder

编译后,应该会在 ./docker/data 目录下得到编译好的 dwarf 文件,即可开始组装适用于 Volatility2 的配置文件

# 这里用的 System.map 文件,为上面拆 deb 包得到的
randark@memory-forensic:~$ zip Debian_5.10.0-21-amd64_profile.zip module.dwarf ~/linux-image/usr/lib/debug/boot/System.map-5.10.0-21-amd64
randark@memory-forensic:~$ mv Debian_5.10.0-21-amd64_profile.zip ./volatility2/volatility/plugins/overlays/linux/
randark@memory-forensic:~$ python2 ./volatility2/vol.py --info | grep Profile | grep Linux
Volatility Foundation Volatility Framework 2.6.1
LinuxDebian_5_10_0-21-amd64_profilex64 - A Profile for Linux Debian_5.10.0-21-amd64_profile x64
LinuxUbuntu_6_2_0-35-generic_profilex64 - A Profile for Linux Ubuntu_6.2.0-35-generic_profile x64

成功制作并在 Volatility2 中加载了配置文件,并工作正常

randark@memory-forensic:~$ python2 ./volatility2/vol.py -f oh-my-linux.mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_bash
Volatility Foundation Volatility Framework 2.6.1
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
1014 bash 2023-02-25 15:45:08 UTC+0000 echo $SHELL
1014 bash 2023-02-25 15:45:23 UTC+0000 echo "Bash doesn't feel as good as zsh"
1014 bash 2023-02-25 15:45:27 UTC+0000 echo "lol"
1014 bash 2023-02-25 15:45:29 UTC+0000 zsh

读取 zsh 的历史记录,就能知道怎么解题了

randark@memory-forensic:~$ cat a1
: 1677339944:0;echo $SHELL
: 1677339951:0;sudo apt install curl
: 1677340139:0;sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)"
: 1677340199:0;echo $SHELL
: 1677340205:0;echo "nice"
: 1677340215:0;mv mysecretflag1.zsh-theme ~/.oh-my-zsh/themes
: 1677340217:0;ls
: 1677340222:0;vim ~/.zshrc
: 1677340268:0;source ~/.zshrc
: 1677340271:0;ls
: 1677340299:0;zip -o flag2.zip flag2.txt -P $SHELL
: 1677340311:0;rm -rf flag2.txt
: 1677340315:0;ls
: 1677340324:0;G1v3m3F14ggg3
: 1677340335:0;echo "lol"
: 1677340354:0;sudo ./avml oh-my-linux.mem

· 阅读需 9 分钟
陈橘mo

新建虚拟机,使用 ubuntu-22.04.2-desktop-amd64.iso 作为安装镜像,正常完成安装,选择最小化安装,并且安装过程中不进行自动更新

Ubuntu install option

等待安装完成后,为纯净状态制作快照

Vmware Create Init Capture

然后安装必要的软件包:

  • openssh-server
  • make
  • gcc
  • net-tools
randark@randark-test:~$ sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak
randark@randark-test:~$ sudo nano /etc/apt/sources.list
# 将 apt 的源仓库地址换为 ustc 中科大源
randark@randark-test:~$ sudo apt update
......
randark@randark-test:~$ sudo apt install openssh-server gcc make net-tools
......
randark@randark-test:~$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
randark@randark-test:~$ sudo systemctl start ssh

然后,通过 ssh 与 sftp 进行操作:首先,将 AVML 的二进制文件传输到测试机上,并授予执行权限,然后开始制作镜像

randark@randark-test:~$ chmod +x avml
randark@randark-test:~$ sudo ./avml out.lime
randark@randark-test:~$ ls -lh
total 4.1G
-rwxrwxr-x 1 randark randark 6.4M 10 月 26 00:01 avml
-rw------- 1 root root 4.0G 10 月 26 00:02 out.lime
drwx------ 3 randark randark 4.0K 10 月 25 23:52 snap

成功得到 out.lime 内存镜像文件

接下来,开始构建 dwarf 内核调试文件,与获取 System.map 内存表文件

首先,确定 Linux Kernel 的版本

randark@randark-test:~$ uname -a
Linux randark-test 6.2.0-35-generic #35~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Oct 6 10:23:26 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

然后传输 dwarf 内核调试文件的编译文件:volatility/tools/linux,并尝试进行编译

randark@randark-test:~/linux$ ls -lh
total 32K
drwxrwxr-x 2 randark randark 4.0K 10 月 24 23:54 kcore
-rw-rw-r-- 1 randark randark 384 10 月 24 23:54 Makefile
-rw-rw-r-- 1 randark randark 314 10 月 24 23:54 Makefile.enterprise
-rw-rw-r-- 1 randark randark 18K 10 月 24 23:54 module.c
randark@randark-test:~/linux$ make
make -C //lib/modules/6.2.0-35-generic/build CONFIG_DEBUG_INFO=y M="/home/randark/linux" modules
make[1]: Entering directory '/usr/src/linux-headers-6.2.0-35-generic'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
You are using: gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
CC [M] /home/randark/linux/module.o
/home/randark/linux/module.c:136: warning: "__rcu" redefined
136 | #define __rcu
|
In file included from <command-line>:
././include/linux/compiler_types.h:52: note: this is the location of the previous definition
52 | # define __rcu BTF_TYPE_TAG(rcu)
|
MODPOST /home/randark/linux/Module.symvers
ERROR: modpost: missing MODULE_LICENSE() in /home/randark/linux/module.o
make[2]: *** [scripts/Makefile.modpost:138: /home/randark/linux/Module.symvers] Error 1
make[1]: *** [Makefile:1978: modpost] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-6.2.0-35-generic'
make: *** [Makefile:10: dwarf] Error 2

可以发现编译过程中存在致命错误:modpost: missing MODULE_LICENSE() in /home/randark/linux/module.o

module.c 的文件末尾加上以下语句:

MODULE_LICENSE("GPL");

或者执行:

echo 'MODULE_LICENSE("GPL");' >> module.c

继续尝试编译:

randark@randark-test:~/linux$ make
make -C //lib/modules/6.2.0-35-generic/build CONFIG_DEBUG_INFO=y M="/home/randark/linux" modules
make[1]: Entering directory '/usr/src/linux-headers-6.2.0-35-generic'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
You are using: gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
CC [M] /home/randark/linux/module.o
/home/randark/linux/module.c:136: warning: "__rcu" redefined
136 | #define __rcu
|
In file included from <command-line>:
././include/linux/compiler_types.h:52: note: this is the location of the previous definition
52 | # define __rcu BTF_TYPE_TAG(rcu)
|
MODPOST /home/randark/linux/Module.symvers
CC [M] /home/randark/linux/module.mod.o
LD [M] /home/randark/linux/module.ko
BTF [M] /home/randark/linux/module.ko
Skipping BTF generation for /home/randark/linux/module.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.2.0-35-generic'
dwarfdump -di module.ko > module.dwarf
/bin/sh: 1: dwarfdump: not found

继续发现存在致命错误:/bin/sh: 1: dwarfdump: not found

查阅相关文档 Creating a new profile 后,得知需要安装以下工具:

  • dwarfdump

继续尝试编译:

randark@randark-test:~/linux$ make
make -C //lib/modules/6.2.0-35-generic/build CONFIG_DEBUG_INFO=y M="/home/randark/linux" modules
make[1]: Entering directory '/usr/src/linux-headers-6.2.0-35-generic'
warning: the compiler differs from the one used to build the kernel
The kernel was built by: x86_64-linux-gnu-gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
You are using: gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
CC [M] /home/randark/linux/module.o
/home/randark/linux/module.c:136: warning: "__rcu" redefined
136 | #define __rcu
|
In file included from <command-line>:
././include/linux/compiler_types.h:52: note: this is the location of the previous definition
52 | # define __rcu BTF_TYPE_TAG(rcu)
|
MODPOST /home/randark/linux/Module.symvers
CC [M] /home/randark/linux/module.mod.o
LD [M] /home/randark/linux/module.ko
BTF [M] /home/randark/linux/module.ko
Skipping BTF generation for /home/randark/linux/module.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.2.0-35-generic'
dwarfdump -di module.ko > module.dwarf
make -C //lib/modules/6.2.0-35-generic/build M="/home/randark/linux" clean
make[1]: Entering directory '/usr/src/linux-headers-6.2.0-35-generic'
CLEAN /home/randark/linux/Module.symvers
make[1]: Leaving directory '/usr/src/linux-headers-6.2.0-35-generic'
randark@randark-test:~/linux$ ls -lh
total 3.0M
drwxrwxr-x 2 randark randark 4.0K 10 月 24 23:54 kcore
-rw-rw-r-- 1 randark randark 384 10 月 24 23:54 Makefile
-rw-rw-r-- 1 randark randark 314 10 月 24 23:54 Makefile.enterprise
-rw-rw-r-- 1 randark randark 18K 10 月 26 00:14 module.c
-rw-rw-r-- 1 randark randark 2.9M 10 月 26 00:19 module.dwarf

成功得到了 dwarf 内核调试文件。接下来获取 System.map 内存表文件

randark@randark-test:~/linux$ ls -lh /boot/System.map-$(uname -r)
-rw------- 1 root root 7.7M 10 月 6 17:29 /boot/System.map-6.2.0-35-generic

确定 System.map 内存表文件的路径之后,就可以开始打包适用于 Volatility2 的配置文件:

randark@randark-test:~/linux$ sudo zip $(lsb_release -i -s)_$(uname -r)_profile.zip module.dwarf /boot/System.map-$(uname -r)
adding: module.dwarf (deflated 91%)
adding: boot/System.map-6.2.0-35-generic (deflated 82%)

成功得到适用于 Volatility2 的配置文件,以及内存镜像之后,就可以使用 Volatility2 进行分析。首先,将制作好的配置文件加入到 Volatility2 的配置文件文件夹

randark@memory-forensic:~$ mv Ubuntu_6.2.0-35-generic_profile.zip ./volatility2/volatility/plugins/overlays/linux/
randark@memory-forensic:~$ python2 ./volatility2/vol.py --info | grep Profile
Volatility Foundation Volatility Framework 2.6.1
Profiles
LinuxUbuntu_6_2_0-35-generic_profilex64 - A Profile for Linux Ubuntu_6.2.0-35-generic_profile x64
......

然后使用 profile 进行内存镜像的解析

randark@memory-forensic:~$ python2 ./volatility2/vol.py -f ~/out.lime linux_banner --profile=LinuxUbuntu_6_2_0-35-generic_profilex64
Volatility Foundation Volatility Framework 2.6.1
Traceback (most recent call last):
File "./volatility2/vol.py", line 192, in <module>
main()
File "./volatility2/vol.py", line 183, in main
command.execute()
File "/home/randark/volatility2/volatility/plugins/linux/common.py", line 67, in execute
commands.Command.execute(self, *args, **kwargs)
File "/home/randark/volatility2/volatility/commands.py", line 116, in execute
if not self.is_valid_profile(profs[self._config.PROFILE]()):
File "/home/randark/volatility2/volatility/plugins/overlays/linux/linux.py", line 218, in __init__
obj.Profile.__init__(self, *args, **kwargs)
File "/home/randark/volatility2/volatility/obj.py", line 862, in __init__
self.reset()
File "/home/randark/volatility2/volatility/plugins/overlays/linux/linux.py", line 232, in reset
self.load_vtypes()
File "/home/randark/volatility2/volatility/plugins/overlays/linux/linux.py", line 269, in load_vtypes
vtypesvar = dwarf.DWARFParser(dwarfdata).finalize()
File "/home/randark/volatility2/volatility/dwarf.py", line 72, in __init__
self.feed_line(line)
File "/home/randark/volatility2/volatility/dwarf.py", line 163, in feed_line
self.process_statement(**parsed) #pylint: disable-msg=W0142
File "/home/randark/volatility2/volatility/dwarf.py", line 267, in process_statement
d = data['DW_AT_data_member_location']
KeyError: 'DW_AT_data_member_location'

经过对这个报错的跟踪,发现已有人提出了相关 issue:Linux Profile Error - KeyError: 'DW_AT_data_member_location' #828

根据 issue 的发展历史,可以定位到问题的起因是 Volatility2 对于新版 dwarfdump 生成的 dwarf 文件的支持性不加所导致的。将前辈所制作的新版 dwarf.py volatility/dwarf.py 替换掉原版 Volatility2 的 dwarf.py 文件

randark@memory-forensic:~/volatility2/volatility$ ls -lh | grep dwarf
-rw-rw-r-- 1 randark randark 15K 10 月 24 23:54 dwarf.py
randark@memory-forensic:~/volatility2/volatility$ mv dwarf.py dwarf.py.bak
randark@memory-forensic:~/volatility2/volatility$ nano dwarf.py
randark@memory-forensic:~/volatility2/volatility$ ls -lh | grep dwarf
-rw-rw-r-- 1 randark randark 16K 10 月 26 00:48 dwarf.py
-rw-rw-r-- 1 randark randark 15K 10 月 24 23:54 dwarf.py.bak

再次尝试分析:

randark@memory-forensic:~$ python2 ./volatility2/vol.py -f ~/out.lime --profile=LinuxUbuntu_6_2_0-35-generic_profilex64 linux_banner
Volatility Foundation Volatility Framework 2.6.1
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
No suitable address space mapping found
Tried to open image as:
MachOAddressSpace: mac: need base
LimeAddressSpace: lime: need base
WindowsHiberFileSpace32: No base Address Space
WindowsCrashDumpSpace64BitMap: No base Address Space
WindowsCrashDumpSpace64: No base Address Space
HPAKAddressSpace: No base Address Space
VMWareMetaAddressSpace: No base Address Space
VirtualBoxCoreDumpElf64: No base Address Space
VMWareAddressSpace: No base Address Space
QemuCoreDumpElf: No base Address Space
WindowsCrashDumpSpace32: No base Address Space
SkipDuplicatesAMD64PagedMemory: No base Address Space
WindowsAMD64PagedMemory: No base Address Space
LinuxAMD64PagedMemory: No base Address Space
AMD64PagedMemory: No base Address Space
IA32PagedMemoryPae: No base Address Space
IA32PagedMemory: No base Address Space
OSXPmemELF: No base Address Space
MachOAddressSpace: MachO Header signature invalid
MachOAddressSpace: MachO Header signature invalid
LimeAddressSpace: Invalid Lime header signature
WindowsHiberFileSpace32: PO_MEMORY_IMAGE is not available in profile
WindowsCrashDumpSpace64BitMap: Header signature invalid
WindowsCrashDumpSpace64: Header signature invalid
HPAKAddressSpace: Invalid magic found
VMWareMetaAddressSpace: VMware metadata file is not available
VirtualBoxCoreDumpElf64: ELF Header signature invalid
VMWareAddressSpace: Invalid VMware signature: -
QemuCoreDumpElf: ELF Header signature invalid
WindowsCrashDumpSpace32: Header signature invalid
SkipDuplicatesAMD64PagedMemory: Incompatible profile LinuxUbuntu_6_2_0-35-generic_profilex64 selected
WindowsAMD64PagedMemory: Incompatible profile LinuxUbuntu_6_2_0-35-generic_profilex64 selected
LinuxAMD64PagedMemory - EXCEPTION: 'state'
AMD64PagedMemory - EXCEPTION: 'state'
IA32PagedMemoryPae: Incompatible profile LinuxUbuntu_6_2_0-35-generic_profilex64 selected
IA32PagedMemory: Incompatible profile LinuxUbuntu_6_2_0-35-generic_profilex64 selected
OSXPmemELF: ELF Header signature invalid
FileAddressSpace: Must be first Address Space
ArmAddressSpace - EXCEPTION: 'state'

很不幸,依然存在问题。根据问题细节,可以追踪到这个 issue:Update Linux DTB scanner to handle newer Linux kernel versions (>= 5.14-rc1) #852

根据 issue 中前辈们给出的方案,将这两个 PR 做出的更改加入到本地的 Volatility2 源码中

PR #852 #1

PR #852 #2

继续尝试分析:

randark@memory-forensic:~$ python2 ./volatility2/vol.py -f ~/out.lime --profile=LinuxUbuntu_6_2_0-35-generic_profilex64 linux_banner
Volatility Foundation Volatility Framework 2.6.1
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
Linux version 6.2.0-35-generic (buildd@bos03-amd64-016) (x86_64-linux-gnu-gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #35~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Oct 6 10:23:26 UTC 2 (Ubuntu 6.2.0-35.35~22.04.1-gene

成功基于配置文件,实现对内存镜像的读取分析


参考资料

How to generate a Volatility profile for a Linux system