Linux内存取证

Linux内存取证一般有两种方法:

  • 制作profile文件并配合vol2进行取证
  • 制作符号表并配合vol3进行取证

下面以“第七届强网杯-强网先锋-找到PNG了吗”为例,通过制作profile文件进行取证

识别镜像文件镜像版本和内核版本

查看附件,镜像版本为:ubuntu 20.04,内核版本为:Linux version 5.4.0-100-generic

strings png.mem | grep "Linux version"

安装ubuntu20.04的虚拟机,并使用以下命令查看已经安装的内核镜像

dpkg --get-selections | grep linux-image

在虚拟机中使用以下命令安装对应内核版本:

sudo apt install linux-image-x.x.x-xx-lowlatency linux-headers-x.x.x-xx-lowlatency
# apt install linux-image-5.4.0-100-generic linux-headers-5.4.0-100-generic

安装完成后再查看发现对应内核已安装完成(ps:5.4.0-100-lowlatency那个安装错了,可以忽略)

切换内核版本

修改grub文件,使得每次开机可以自己选择要启动的内核版本

vim  /etc/default/grub

GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
↓↓↓
#GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=10

修改完成后更新grub文件并重启,可以在Advanced options中选择下载好的内核版本

sudo update-grub
sudo reboot

进入后发现内核已经切换完成

simho@simho-virtual-machine:~/Desktop$ uname -a
Linux simho-virtual-machine 5.4.0-100-lowlatency #113-Ubuntu SMP PREEMPT Thu Feb 3 19:24:13 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

制作profiile文件

首先安装build-essentialdwarfdump,在/boot目录下找到对应内核版本的System.map-xx文件

然后传输 dwarf 内核调试文件的编译文件,并进行编译,编译后会在当前目录生成module.dwarf文件

接着将以上两个文件打包成zip,放到volatility/plugins/overlays/linux

apt install build-essential dwarfdump
cd volatility/tools/linux
make
zip ./Ubuntu_5_4_0-100-generic_profile.zip ./module.dwarf /boot/System.map-`uname -r`

利用vol2进行取证

查看 profile 文件是否已经能够识别,识别到后就可以使用 profile 进行内存镜像的解析

python2 vol.py --info | grep Profile

查看banner信息

python2 vol.py -f png.mem --profile=LinuxUbuntu_5_4_0-100-generic_profilex64 linux_banner

PS:这里根据巨魔的博客,解析过程中可能会出现报错,需要对相应文件进行patch,不过我这里能直接正常解析

查看文件

python2 vol.py -f png.mem --profile=LinuxUbuntu_5_4_0-100-generic_profilex64  linux_enumerate_files | grep "Desktop"

提取文件

python2 vol.py -f png.mem --profile=LinuxUbuntu_5_4_0-100-generic_profilex64 linux_find_file -i 0xffff9ce28fe300e8 -O ./have_your_fun.jocker

发现文件为空,直接winhex全局搜索have_your_fun.jocker文件,得到完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_IP "192.168.6.1"
#define SERVER_PORT 110
unsigned char buff[20000];
void swap(char* a, char* b) {
    char temp = *a;
    *a = *b;
    *b = temp;
}
void rc4_encrypt_decrypt(unsigned char* key, unsigned char* data, int data_length) {
    int i, j = 0, t;
    int s[256];
    int key_length = strlen((const char*)key);

    for (i = 0; i < 256; i++) {
        s[i] = i;
    }

    for (i = 0; i < 256; i++) {
        j = (j + s[i] + key[i % key_length]) % 256;
        t = s[i];
        s[i] = s[j];
        s[j] = t;
    }

    i = j = 0;
    for (int k = 0; k < data_length; k++) {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        t = s[i];
        s[i] = s[j];
        s[j] = t;
        data[k] ^= s[(s[i] + s[j]) % 256];
    }
}
int main()
{
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == -1) {
        printf("socket failed!\n");
        return 1;
    }
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_PORT);
    serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
    connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    int result = recv(clientSocket, buff, sizeof(buff), 0);
    int a=0;
    char q[10];
    unsigned char key[]="do_not_care";
    unsigned char key2[] = "where_is_the_key";
    FILE* file = fopen("have_your_fun.jocker", "wb");
    if (file == NULL) {
        printf("open file failed!\n");
        return 1;
    }
    unsigned char *str;
    str = (char *) malloc(20000);
    memcpy(str, buff, 20000);
    rc4_encrypt_decrypt(key2, str, 20000);
    printf("please give me the key of fun:");
    scanf("%s",q);
    rc4_encrypt_decrypt(key, str, 20000);

    fwrite(buff, 1, 20000, file);
    printf("maybe you go wrong");
    fclose(file);
    close(clientSocket);
    return 0;
}

主要功能是将 png 进行两次RC4加密,得到的文件就是 have_your_fun.jocker,将 png 文件头进行RC4加密得到e5afbeba

接着全局搜索,将含该头的字符串复制,RC4解密得到flag

flag{It's_So_Hard_To_Find_A_Picture}

参考博客:

内存取证实验 - 镜像 + 配置文件 | Randark_JMT - 陈橘墨

制作Linux内存镜像+制作对应的volatility_profile

发表回复