linux 内存镜像提取命令,从 Rescue System 中提取 InitRamFs 映像文件

昨天晚上 Jactry 使用 Rescue for Lemote2f 打包龙芯笔记本上的操作系统,发现 Ext4 分区挂载不了,检查发现是内核没有编译进 Ext4 文件系统的支持(当时太粗心,忘记了 :))。

准备重新编译这个 Rescue System,但是当时制作的 InitRamFs 已经早就没有了,在 Wuzhangjin 的帮助下成功的从 Rescue System 中提取出了映像文件。

Rescue System

这是为 Lemote2f 机器编译制作的紧急修复系统,用于在操作系统不能正常启动的情况下修复硬盘中的系统,也可以用于打包硬盘中的操作系统等等。

Rescue System 的实质就是一个 Linux 内核且编译进了一个 RamDisk 文件系统的映像文件,运行时解压到内存盘中用作根文件系统。它是一个 ELF 格式的文件,可以使用 readelf 程序读取其中的信息。

检查是否压缩

readelf -S rescue-lemote2f

readelf -S rescue-lemote2f

There are 26 section headers, starting at offset 0x668610:

Section Headers:

[Nr] Name Type Address Offset

Size EntSize Flags Link Info Align

[ 0] NULL 0000000000000000 00000000

0000000000000000 0000000000000000 0 0 0

[ 1] .text PROGBITS ffffffff80de0000 00010000

0000000000000b10 0000000000000000 AX 0 0 16

[ 2] .text.zlib_update PROGBITS ffffffff80de0b10 00010b10

0000000000000190 0000000000000000 AX 0 0 8

[ 3] .text.nofill PROGBITS ffffffff80de0ca0 00010ca0

0000000000000018 0000000000000000 AX 0 0 8

[ 4] .text.error PROGBITS ffffffff80de0cb8 00010cb8

0000000000000038 0000000000000000 AX 0 0 8

[ 5] .text.memcpy PROGBITS ffffffff80de0cf0 00010cf0

0000000000000048 0000000000000000 AX 0 0 8

[ 6] .text.zlib_inflat PROGBITS ffffffff80de0d38 00010d38

0000000000000978 0000000000000000 AX 0 0 8

[ 7] .text.inflate_fas PROGBITS ffffffff80de16b0 000116b0

0000000000000c80 0000000000000000 AX 0 0 8

[ 8] .text.zlib_inflat PROGBITS ffffffff80de2330 00012330

0000000000000018 0000000000000000 AX 0 0 8

[ 9] .text.zlib_inflat PROGBITS ffffffff80de2348 00012348

0000000000000098 0000000000000000 AX 0 0 8

[10] .text.zlib_inflat PROGBITS ffffffff80de23e0 000123e0

00000000000000e8 0000000000000000 AX 0 0 8

[11] .text.zlib_inflat PROGBITS ffffffff80de24c8 000124c8

00000000000018a8 0000000000000000 AX 0 0 8

[12] .text.zlib_inflat PROGBITS ffffffff80de3d70 00013d70

0000000000000038 0000000000000000 AX 0 0 8

[13] .text.zlib_inflat PROGBITS ffffffff80de3da8 00013da8

0000000000000308 0000000000000000 AX 0 0 8

[14] .text.decompress_ PROGBITS ffffffff80de40b0 000140b0

00000000000004f0 0000000000000000 AX 0 0 8

[15] .text.putc PROGBITS ffffffff80de45a0 000145a0

0000000000000018 0000000000000000 AX 0 0 8

[16] .text.puts PROGBITS ffffffff80de45b8 000145b8

0000000000000078 0000000000000000 AX 0 0 8

[17] .text.puthex PROGBITS ffffffff80de4630 00014630

0000000000000120 0000000000000000 AX 0 0 8

[18] .text.main PROGBITS ffffffff80de4750 00014750

0000000000000018 0000000000000000 AX 0 0 8

[19] .rodata.str1.8 PROGBITS ffffffff80de4768 00014768

00000000000002f8 0000000000000001 AMS 0 0 8

[20] .data PROGBITS ffffffff80de4a60 00014a60

0000000000653a0d 0000000000000000 WA 0 0 16

[21] .bss NOBITS ffffffff81438470 0066846d

0000000000402030 0000000000000000 WA 0 0 16

[22] .gnu.attributes LOOS+ffffff5 0000000000000000 0066846d

0000000000000010 0000000000000000 0 0 1

[23] .shstrtab STRTAB 0000000000000000 0066847d

000000000000018e 0000000000000000 0 0 1

[24] .symtab SYMTAB 0000000000000000 00668c90

0000000000002a00 0000000000000018 25 417 8

[25] .strtab STRTAB 0000000000000000 0066b690

0000000000000a70 0000000000000000 0 0 1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings)

I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)

O (extra OS processing required) o (OS specific), p (processor specific)

There are 26 section headers, starting at offset 0x668610:

Section Headers:

[Nr] Name Type Address Offset

Size EntSize Flags Link Info Align

[ 0] NULL 0000000000000000 00000000

0000000000000000 0000000000000000 0 0 0

[ 1] .text PROGBITS ffffffff80de0000 00010000

0000000000000b10 0000000000000000 AX 0 0 16

[ 2] .text.zlib_update PROGBITS ffffffff80de0b10 00010b10

0000000000000190 0000000000000000 AX 0 0 8

[ 3] .text.nofill PROGBITS ffffffff80de0ca0 00010ca0

0000000000000018 0000000000000000 AX 0 0 8

[ 4] .text.error PROGBITS ffffffff80de0cb8 00010cb8

0000000000000038 0000000000000000 AX 0 0 8

[ 5] .text.memcpy PROGBITS ffffffff80de0cf0 00010cf0

0000000000000048 0000000000000000 AX 0 0 8

[ 6] .text.zlib_inflat PROGBITS ffffffff80de0d38 00010d38

0000000000000978 0000000000000000 AX 0 0 8

[ 7] .text.inflate_fas PROGBITS ffffffff80de16b0 000116b0

0000000000000c80 0000000000000000 AX 0 0 8

[ 8] .text.zlib_inflat PROGBITS ffffffff80de2330 00012330

0000000000000018 0000000000000000 AX 0 0 8

[ 9] .text.zlib_inflat PROGBITS ffffffff80de2348 00012348

0000000000000098 0000000000000000 AX 0 0 8

[10] .text.zlib_inflat PROGBITS ffffffff80de23e0 000123e0

00000000000000e8 0000000000000000 AX 0 0 8

[11] .text.zlib_inflat PROGBITS ffffffff80de24c8 000124c8

00000000000018a8 0000000000000000 AX 0 0 8

[12] .text.zlib_inflat PROGBITS ffffffff80de3d70 00013d70

0000000000000038 0000000000000000 AX 0 0 8

[13] .text.zlib_inflat PROGBITS ffffffff80de3da8 00013da8

0000000000000308 0000000000000000 AX 0 0 8

[14] .text.decompress_ PROGBITS ffffffff80de40b0 000140b0

00000000000004f0 0000000000000000 AX 0 0 8

[15] .text.putc PROGBITS ffffffff80de45a0 000145a0

0000000000000018 0000000000000000 AX 0 0 8

[16] .text.puts PROGBITS ffffffff80de45b8 000145b8

0000000000000078 0000000000000000 AX 0 0 8

[17] .text.puthex PROGBITS ffffffff80de4630 00014630

0000000000000120 0000000000000000 AX 0 0 8

[18] .text.main PROGBITS ffffffff80de4750 00014750

0000000000000018 0000000000000000 AX 0 0 8

[19] .rodata.str1.8 PROGBITS ffffffff80de4768 00014768

00000000000002f8 0000000000000001 AMS 0 0 8

[20] .data PROGBITS ffffffff80de4a60 00014a60

0000000000653a0d 0000000000000000 WA 0 0 16

[21] .bss NOBITS ffffffff81438470 0066846d

0000000000402030 0000000000000000 WA 0 0 16

[22] .gnu.attributes LOOS+ffffff5 0000000000000000 0066846d

0000000000000010 0000000000000000 0 0 1

[23] .shstrtab STRTAB 0000000000000000 0066847d

000000000000018e 0000000000000000 0 0 1

[24] .symtab SYMTAB 0000000000000000 00668c90

0000000000002a00 0000000000000018 25 417 8

[25] .strtab STRTAB 0000000000000000 0066b690

0000000000000a70 0000000000000000 0 0 1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings)

I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)

O (extra OS processing required) o (OS specific), p (processor specific)

从上面我们看出有几个代码段包含 zlib 关键词,说明内核编译进了压缩支持,多数是压缩内核。

提取映像

readelf -s rescue-lemote2f | grep image

readelf -s rescue-lemote2f | grep image

424: ffffffff81438480 8 OBJECT GLOBAL DEFAULT 21 zimage_start

425: ffffffff8143846d 0 NOTYPE GLOBAL DEFAULT 20 __image_end

429: ffffffff80de4a60 0 NOTYPE GLOBAL DEFAULT 20 __image_begin

424: ffffffff81438480 8 OBJECT GLOBAL DEFAULT 21 zimage_start

425: ffffffff8143846d 0 NOTYPE GLOBAL DEFAULT 20 __image_end

429: ffffffff80de4a60 0 NOTYPE GLOBAL DEFAULT 20 __image_begin

从上面的数据看到 __image_begin 和 __image_end 两个符号没有类型且没有长度,应该是静态常量用于标记映像文件的位置地址,结合上面的 Section Headers 发现标记的这段数据正好处于 .data 段,而 zimage_start 则是一个 .bss 段的变量,一定不是我们需要的信息。

我们看到 __image_begin 的内存地址是 ffffffff80de4a60,__image_end 内存地址是 ffffffff8143846d,计算出长度是 ffffffff8143846d – ffffffff80de4a60 = 653a0d,从 Section Headers 检查发现整个 .data 段就是这个映像文件。从 Section Headers 我们找到了 .data 段在文件中的偏移地址 00014a60。有了这些信息我们就可以使用 dd 命令提取出映像文件了。

全部转换成十进制数

偏移地址 00014a60 = 84576

长度 653a0d = 6633997

dd if=rescue-lemote2f of=vmlinux skip=84576 bs=1 count=6633997

dd if=rescue-lemote2f of=vmlinux skip=84576 bs=1 count=6633997

映像类型检查

file vmlinux

file vmlinux

vmlinux: gzip compressed data, from Unix, last modified: Tue May 25 20:59:46 2010, max compression

vmlinux: gzip compressed data, from Unix, last modified: Tue May 25 20:59:46 2010, max compression

获取 gz 文件头

获取文件头用于后面查找 ramdisk.cpio.gz 文件的开始地址

hexdump vmlinux | grep 0000000

hexdump vmlinux | grep 0000000

0000000 8b1f 0008 c9c2 4bfb 0302 5cec 740d 5514

0000000 8b1f 0008 c9c2 4bfb 0302 5cec 740d 5514

我们看到当时打包的 gz 文件前四个字节是 8b1f 0008

解压 vmlinux 文件

从上面我们得知 vmlinux 实际是 gzip 压缩文件,我们解压它,得到了新的 vmlinux 文件。

mv vmlinux vmlinux.gz

gunzip vmlinux.gz

mv vmlinux vmlinux.gz

gunzip vmlinux.gz

查找 ramdisk.cpio.gz 的开始地址

我们先使用 hexdump 将整个文件都 dump 出来保存到一个文本文件中,便于后面的查找。

hexdump vmlinux > vmlinux.txt

vim vmlinux.txt

hexdump vmlinux > vmlinux.txt

vim vmlinux.txt

通过搜索,我们在这个文件中找到了两处 8b1f 0008,分别是

03b4520 4d50 8028 ffff ffff 47f8 8028 ffff ffff

03b4530 4b80 8028 ffff ffff 4810 8028 ffff ffff

03b4540 4b49 4643 5f47 5453 8b1f 0008 c8c2 4bfb

03b4520 4d50 8028 ffff ffff 47f8 8028 ffff ffff

03b4530 4b80 8028 ffff ffff 4810 8028 ffff ffff

03b4540 4b49 4643 5f47 5453 8b1f 0008 c8c2 4bfb

04b6c80 0000 0000 0000 0000 0000 0000 0000 0000

*

04b8000 8b1f 0008 6c56 4bd5 0302 5ab4 707d 555b

04b6c80 0000 0000 0000 0000 0000 0000 0000 0000

*

04b8000 8b1f 0008 6c56 4bd5 0302 5ab4 707d 555b

我猜测后者的可能性比较大,也可以每个都 dd 出解压看看。

提取 ramdisk.cpio.gz

从上面我们得到了ramdisk.cpio.gz在文件中的偏移地址 04b8000 = ,但是没有长度,实际也不需要长度,因为 gunzip 肯定能够从 gz 文件中得知需要读取多少个字节,就让它交给 gunzip 处理吧。我们从这个地址开始取到文件结束。

dd if=vmlinux of=ramdisk.cpio.gz skip=4947968 bs=1

dd if=vmlinux of=ramdisk.cpio.gz skip=4947968 bs=1

解压 ramdisk.cpio.gz

gunzip ramdisk.cpio.gz

gunzip ramdisk.cpio.gz

我们得到了完整的 ramdisk.cpio 文件了!

Over!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值