逆向工程固件映像并重建TI-AR7的Linux内核

时间:2016-01-10 14:16:58

标签: linux linux-kernel reverse-engineering firmware

我正在尝试构建自己的Linux衍生产品,以便在TI-AR7主板上运行。我从旧的Telekom Speedport W 501V路由器上取下了主板。要了解固件如何闪存到设备上,我已下载了最新的official firmware。使用Linux file命令,我确定图像是一个tar存档,可以轻松提取。

ubuntu@ip-172-31-23-210:~/reverse$ ls
fw_speedport_w501v_v_28.04.38.image
ubuntu@ip-172-31-23-210:~/reverse$ file fw*
fw_speedport_w501v_v_28.04.38.image: POSIX tar archive (GNU)
ubuntu@ip-172-31-23-210:~/reverse$ tar -xvf fw*
./var/
./var/tmp/
./var/tmp/kernel.image
./var/tmp/filesystem.image
./var/flash_update.ko
./var/flash_update.o
./var/info.txt
./var/install
./var/chksum
./var/regelex
./var/signature
ubuntu@ip-172-31-23-210:~/reverse$

根据我发现的wiki (Firmware-Image)./var/tmp/kernel.image包含实际固件。在更新过程中,此映像将写入mtd1设备。如wiki (LZMA-Kernel)中所述,lzma压缩内核以幻数0xfeed1281开头。 kernel.image的hexdump在其开头包含该数字。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ hexdump -n 4 kernel.image
0000000 1281 feed
0000004
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$

上一个wiki条目中给出的以下脚本应解压缩内核。

#! /usr/bin/perl

use Compress::unLZMA;
use Archive::Zip;

open INPUT, "<$ARGV[0]" or die "can't open $ARGV[0]: $!";

read INPUT, $buf, 4;
$magic = unpack("V", $buf);
if ($magic != 0xfeed1281) {
  die "bad magic";
}

read INPUT, $buf, 4;
$len = unpack("V", $buf);

read INPUT, $buf, 4*2; # address, unknown

read INPUT, $buf, 4;
$clen = unpack("V", $buf);
read INPUT, $buf, 4;
$dlen = unpack("V", $buf);
read INPUT, $buf, 4;
$cksum = unpack("V", $buf);
printf "Archive checksum: 0x%08x\n", $cksum;

read INPUT, $buf, 1+4; # properties, dictionary size
read INPUT, $dummy, 3; # alignment
$buf .= pack('VV', $dlen, 0); # 8 bytes of real size
#$buf .= pack('VV', -1, -1); # 8 bytes of real size
read INPUT, $buf2, $clen;

$crc = Archive::Zip::computeCRC32($buf2);
printf "Input CRC32: 0x%08x\n", $crc;
if ($cksum != $crc) {
  die "wrong checksum";
}
$buf .= $buf2;

$data = Compress::unLZMA::uncompress($buf);
unless (defined $data) {
  die "uncompress: $@";
}

open OUTPUT, ">$ARGV[1]" or die "can't write $ARGV[1]";
print OUTPUT $data;
#truncate OUTPUT, $dlen;

要使用该脚本,您可能需要安装Compress::unLZMAArchive::Zip perl模块。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ tar -xvf Compress*
Compress-unLZMA-0.04/
Compress-unLZMA-0.04/Makefile.PL
Compress-unLZMA-0.04/ppport.h
Compress-unLZMA-0.04/Changes
Compress-unLZMA-0.04/lzma_sdk/
[...]
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ cd Compress*
ubuntu@ip-172-31-23-210:~/reverse/var/tmp/Compress-unLZMA-0.04$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for Compress::unLZMA
Writing MYMETA.yml and MYMETA.json
ubuntu@ip-172-31-23-210:~/reverse/var/tmp/Compress-unLZMA-0.04$ make
cp lib/Compress/unLZMA.pm blib/lib/Compress/unLZMA.pm
/usr/bin/perl /usr/share/perl/5.18/ExtUtils/xsubpp  -typemap /usr/share/perl/5.18/ExtUtils/typemap  unLZMA.xs > unLZMA.xsc && mv unLZMA.xsc unLZMA.c
cc -c  -I. -Ilzma_sdk/Source -D_REENTRANT -D_GNU_SOURCE
[...]
ubuntu@ip-172-31-23-210:~/reverse/var/tmp/Compress-unLZMA-0.04$ sudo make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Installing /usr/local/lib/perl/5.18.2/auto/Compress/unLZMA/unLZMA.bs
Installing /usr/local/lib/perl/5.18.2/auto/Compress/unLZMA/unLZMA.so
Installing /usr/local/lib/perl/5.18.2/Compress/unLZMA.pm
Installing /usr/local/man/man3/Compress::unLZMA.3pm
Appending installation info to /usr/local/lib/perl/5.18.2/perllocal.pod
ubuntu@ip-172-31-23-210:~/reverse/var/tmp/Compress-unLZMA-0.04$ # same for Archive::Zip module

安装这些依赖项后,脚本成功解压缩了内核。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ ./decompress.pl kernel.image kernel.decompressed
Archive checksum: 0x29176e12
Input CRC32: 0x29176e12
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$

但是kernel.decompressed是什么类型的文件?如何从我的Linux内核源生成类似的文件?我继续使用filebinwalk进行分析。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ file kernel.decompressed
kernel.decompressed: data
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ binwalk kernel.decompressed

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1509632       0x170900        Linux kernel version "2.6.13.1-ohio (686) (gcc version 3.4.6) #9 Wed Apr 4 13:48:08 CEST 2007"
1516240       0x1722D0        CRC32 polynomial table, little endian
1517535       0x1727DF        Copyright string: "Copyright 1995-1998 Mark Adler "
1549488       0x17A4B0        Unix path: /usr/gnemul/irix/
1550920       0x17AA48        Unix path: /usr/lib/libc.so.1
1618031       0x18B06F        Neighborly text, "neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)(%s)"
1966080       0x1E0000        gzip compressed data, maximum compression, from Unix, last modified: 2007-04-04 11:45:13

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$

因此Linux内核从1509632开始,到1516240结束。 Linux内核(01509632)前面存储了哪些数据?我使用dd提取了内核和那段未知数据。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ dd if=kernel.decompressed of=unknown.data bs=1 count=1509632
1509632+0 records in
1509632+0 records out
1509632 bytes (1.5 MB) copied, 1.62137 s, 931 kB/s
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ dd if=kernel.decompressed of=kernel bs=1 skip=1509632 count=6608
6608+0 records in
6608+0 records out
6608 bytes (6.6 kB) copied, 0.0072771 s, 908 kB/s
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$

我需要再次询问:kernel是什么类型的文件?如何从Linux内核源生成类似的文件?我使用xxdstrings来更仔细地查看文件。

ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ xxd -l 100 kernel
0000000: 4c69 6e75 7820 7665 7273 696f 6e20 322e  Linux version 2.
0000010: 362e 3133 2e31 2d6f 6869 6f20 2836 3836  6.13.1-ohio (686
0000020: 2920 2867 6363 2076 6572 7369 6f6e 2033  ) (gcc version 3
0000030: 2e34 2e36 2920 2339 2057 6564 2041 7072  .4.6) #9 Wed Apr
0000040: 2034 2031 333a 3438 3a30 3820 4345 5354   4 13:48:08 CEST
0000050: 2032 3030 370a 0000 0000 0000 0000 0000   2007...........
0000060: 0000 0000                                ....
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$ strings kernel
Linux version 2.6.13.1-ohio (686) (gcc version 3.4.6) #9 Wed Apr 4 13:48:08 CEST 2007
do_be
do_bp
do_tr
do_ri
do_cpu
nmi_exception_handler
do_ade
emulate_load_store_insn
do_page_fault
context_switch
__put_task_struct
do_exit
local_bh_enable
run_workqueue
2.6.13.1-ohio gcc-3.4
enable_irq
__free_pages_ok
free_hot_cold_page
prep_new_page
kmem_cache_destroy
kmem_cache_create
pageout
vunmap_pte_range
vmap_pte_range
__vunmap
__brelse
sync_dirty_buffer
bio_endio
queue_kicked_iocb
proc_get_inode
remove_proc_entry
sysfs_get
sysfs_fill_super
kref_get
kref_put
0123456789abcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
vsnprintf
{zt^f
pw0Gm
0cIZ-
68BG+
QC]S%
v,;Zk
ubuntu@ip-172-31-23-210:~/reverse/var/tmp$

此Github repository包含用于进一步分析的提取文件。

0 个答案:

没有答案