从手机或其他设备中提取和解压boot.img与recovery.img

 

转自:http://blog.csdn.net/darkengine/article/details/7558711 

 

boot.img与recovery.img的结构很相似,都是kernel加上一个根文件系统。所以是可以用同一个工具(脚本)来分解,下面以分解boot.img为例分析如下:


1, cat /dev/block/mtdblock0 > /sdcard/boot.img    
    【上行就是提取boot.img的方式】不同的机型可能对应着不同的分区,需要先核实。

2, split_bootimg.pl boot.img
    这个脚本是高手写的,可以用来解包boot.img或recovery.img,输出为kernel和ramdisk
 
3, gunzip -c boot.img-ramdisk.gz | cpio -i
     将解包出来的ramdisk部分再解出整个根文件系统

其中split_bootimg.pl的源码如下,能够分解出来是因为recovery.img的header有足够的信息,保证分解过程可以逆向的把它的根文件系统正确的解压出来。

  1. #!/usr/bin/perl  
  2. ###################################################################### 
  3. #  
  4. #   File          : split_bootimg.pl  
  5. #   Author(s)     : William Enck <enck@cse.psu.edu> 
  6. #   Description   : Split appart an Android boot image created  
  7. #                   with mkbootimg. The format can be found in 
  8. #                   android-src/system/core/mkbootimg/bootimg.h 
  9. #  
  10. #                   Thanks to alansj on xda-developers.com for  
  11. #                   identifying the format in bootimg.h and  
  12. #                   describing initial instructions for splitting 
  13. #                   the boot.img file. 
  14. #  
  15. #   Last Modified : Tue Dec  2 23:36:25 EST 2008 
  16. #   By            : William Enck <enck@cse.psu.edu> 
  17. #  
  18. #   Copyright (c) 2008 William Enck  
  19. #  
  20. ######################################################################  
  21.   
  22. use strict;  
  23. use warnings;  
  24.  
  25. # Turn on print flushing   
  26. $|++;  
  27.  
  28. ###################################################################### 
  29. ## Global Variables and Constants  
  30.   
  31. my $SCRIPT = __FILE__;  
  32. my $IMAGE_FN = undef;  
  33.  
  34. # Constants (from bootimg.h)   
  35. use constant BOOT_MAGIC => 'ANDROID!';  
  36. use constant BOOT_MAGIC_SIZE => 8;  
  37. use constant BOOT_NAME_SIZE => 16;  
  38. use constant BOOT_ARGS_SIZE => 512;  
  39.  
  40. # Unsigned integers are 4 bytes   
  41. use constant UNSIGNED_SIZE => 4;  
  42.  
  43. # Parsed Values   
  44. my $PAGE_SIZE = undef;  
  45. my $KERNEL_SIZE = undef;  
  46. my $RAMDISK_SIZE = undef;  
  47. my $SECOND_SIZE = undef;  
  48.  
  49. ###################################################################### 
  50. ## Main Code   
  51.   
  52. &parse_cmdline();  
  53. &parse_header($IMAGE_FN);  
  54.   
  55. =format (from bootimg.h)  
  56. ** +-----------------+  
  57. ** | boot header     | 1 page  
  58. ** +-----------------+  
  59. ** | kernel          | n pages  
  60. ** +-----------------+  
  61. ** | ramdisk         | m pages  
  62. ** +-----------------+  
  63. ** | second stage    | o pages  
  64. ** +-----------------+  
  65. **  
  66. ** n = (kernel_size + page_size - 1) / page_size  
  67. ** m = (ramdisk_size + page_size - 1) / page_size  
  68. ** o = (second_size + page_size - 1) / page_size  
  69. =cut  
  70.   
  71. my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);  
  72. my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);  
  73. my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);  
  74.   
  75. my $k_offset = $PAGE_SIZE;  
  76. my $r_offset = $k_offset + ($n * $PAGE_SIZE);  
  77. my $s_offset = $r_offset + ($m * $PAGE_SIZE);  
  78.   
  79. (my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;  
  80. my $k_file = $base . "-kernel";  
  81. my $r_file = $base . "-ramdisk.gz";  
  82. my $s_file = $base . "-second.gz"; 
  83.  
  84. # The kernel is always there   
  85. print "Writing $k_file ...";  
  86. &dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);  
  87. print " complete.\n"; 
  88.  
  89. # The ramdisk is always there   
  90. print "Writing $r_file ...";  
  91. &dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);  
  92. print " complete.\n";  
  93.  
  94. # The Second stage bootloader is optional   
  95. unless ($SECOND_SIZE == 0) {  
  96.     print "Writing $s_file ...";  
  97.     &dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);  
  98.     print " complete.\n";  
  99. }  
  100.      
  101. ###################################################################### 
  102. ## Supporting Subroutines   
  103.   
  104. =header_format (from bootimg.h)  
  105. struct boot_img_hdr  
  106. {  
  107.     unsigned char magic[BOOT_MAGIC_SIZE];  
  108.   
  109.     unsigned kernel_size;  /* size in bytes */  
  110.     unsigned kernel_addr;  /* physical load addr */  
  111.   
  112.     unsigned ramdisk_size; /* size in bytes */  
  113.     unsigned ramdisk_addr; /* physical load addr */  
  114.   
  115.     unsigned second_size;  /* size in bytes */  
  116.     unsigned second_addr;  /* physical load addr */  
  117.   
  118.     unsigned tags_addr;    /* physical addr for kernel tags */  
  119.     unsigned page_size;    /* flash page size we assume */  
  120.     unsigned unused[2];    /* future expansion: should be 0 */  
  121.   
  122.     unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */  
  123.   
  124.     unsigned char cmdline[BOOT_ARGS_SIZE];  
  125.   
  126.     unsigned id[8]; /* timestamp / checksum / sha1 / etc */  
  127. };  
  128. =cut  
  129. sub parse_header {  
  130.     my ($fn) = @_;  
  131.     my $buf = undef;  
  132.   
  133.     open INF, $fn or die "Could not open $fn: $!\n";  
  134.     binmode INF;  
  135.  
  136.     # Read the Magic   
  137.     read(INF, $buf, BOOT_MAGIC_SIZE);  
  138.     unless ($buf eq BOOT_MAGIC) {  
  139.     die "Android Magic not found in $fn. Giving up.\n";  
  140.     }  
  141.  
  142.     # Read kernel size and address (assume little-endian)  
  143.     read(INF, $buf, UNSIGNED_SIZE * 2);  
  144.     my ($k_size, $k_addr) = unpack("VV", $buf); 
  145.  
  146.     # Read ramdisk size and address (assume little-endian)  
  147.     read(INF, $buf, UNSIGNED_SIZE * 2);  
  148.     my ($r_size, $r_addr) = unpack("VV", $buf); 
  149.  
  150.     # Read second size and address (assume little-endian)  
  151.     read(INF, $buf, UNSIGNED_SIZE * 2);  
  152.     my ($s_size, $s_addr) = unpack("VV", $buf); 
  153.  
  154.     # Ignore tags_addr   
  155.     read(INF, $buf, UNSIGNED_SIZE);  
  156.  
  157.     # get the page size (assume little-endian)  
  158.     read(INF, $buf, UNSIGNED_SIZE);  
  159.     my ($p_size) = unpack("V", $buf); 
  160.  
  161.     # Ignore unused   
  162.     read(INF, $buf, UNSIGNED_SIZE * 2);  
  163.  
  164.     # Read the name (board name)   
  165.     read(INF, $buf, BOOT_NAME_SIZE);  
  166.     my $name = $buf;  
  167.  
  168.     # Read the command line   
  169.     read(INF, $buf, BOOT_ARGS_SIZE);  
  170.     my $cmdline = $buf;  
  171.  
  172.     # Ignore the id   
  173.     read(INF, $buf, UNSIGNED_SIZE * 8);  
  174.  
  175.     # Close the file   
  176.     close INF;  
  177.  
  178.     # Print important values   
  179.     printf "Page size: %d (0x%08x)\n", $p_size, $p_size;  
  180.     printf "Kernel size: %d (0x%08x)\n", $k_size, $k_size;  
  181.     printf "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;  
  182.     printf "Second size: %d (0x%08x)\n", $s_size, $s_size;  
  183.     printf "Board name: $name\n";  
  184.     printf "Command line: $cmdline\n"; 
  185.  
  186.     # Save the values   
  187.     $PAGE_SIZE = $p_size;  
  188.     $KERNEL_SIZE = $k_size;  
  189.     $RAMDISK_SIZE = $r_size;  
  190.     $SECOND_SIZE = $s_size;  
  191. }  
  192.   
  193. sub dump_file {  
  194.     my ($infn, $outfn, $offset, $size) = @_;  
  195.     my $buf = undef;  
  196.   
  197.     open INF, $infn or die "Could not open $infn: $!\n";  
  198.     open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";  
  199.   
  200.     binmode INF;  
  201.     binmode OUTF;  
  202.   
  203.     seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";  
  204.     read(INF, $buf, $size) or die "Could not read $infn: $!\n";  
  205.     print OUTF $buf or die "Could not write $outfn: $!\n";  
  206.   
  207.     close INF;  
  208.     close OUTF;  
  209. }  
  210.  
  211. ###################################################################### 
  212. ## Configuration Subroutines   
  213.   
  214. sub parse_cmdline {  
  215.     unless ($#ARGV == 0) {  
  216.     die "Usage: $SCRIPT boot.img\n";  
  217.     }  
  218.     $IMAGE_FN = $ARGV[0];  
  219. }  
#!/usr/bin/perl
######################################################################
#
#   File          : split_bootimg.pl
#   Author(s)     : William Enck <enck@cse.psu.edu>
#   Description   : Split appart an Android boot image created 
#                   with mkbootimg. The format can be found in
#                   android-src/system/core/mkbootimg/bootimg.h
#
#                   Thanks to alansj on xda-developers.com for 
#                   identifying the format in bootimg.h and 
#                   describing initial instructions for splitting
#                   the boot.img file.
#
#   Last Modified : Tue Dec  2 23:36:25 EST 2008
#   By            : William Enck <enck@cse.psu.edu>
#
#   Copyright (c) 2008 William Enck
#
######################################################################

use strict;
use warnings;

# Turn on print flushing
$|++;

######################################################################
## Global Variables and Constants

my $SCRIPT = __FILE__;
my $IMAGE_FN = undef;

# Constants (from bootimg.h)
use constant BOOT_MAGIC => 'ANDROID!';
use constant BOOT_MAGIC_SIZE => 8;
use constant BOOT_NAME_SIZE => 16;
use constant BOOT_ARGS_SIZE => 512;

# Unsigned integers are 4 bytes
use constant UNSIGNED_SIZE => 4;

# Parsed Values
my $PAGE_SIZE = undef;
my $KERNEL_SIZE = undef;
my $RAMDISK_SIZE = undef;
my $SECOND_SIZE = undef;

######################################################################
## Main Code

&parse_cmdline();
&parse_header($IMAGE_FN);

=format (from bootimg.h)
** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel          | n pages
** +-----------------+
** | ramdisk         | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
=cut

my $n = int(($KERNEL_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $m = int(($RAMDISK_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);
my $o = int(($SECOND_SIZE + $PAGE_SIZE - 1) / $PAGE_SIZE);

my $k_offset = $PAGE_SIZE;
my $r_offset = $k_offset + ($n * $PAGE_SIZE);
my $s_offset = $r_offset + ($m * $PAGE_SIZE);

(my $base = $IMAGE_FN) =~ s/.*\/(.*)$/$1/;
my $k_file = $base . "-kernel";
my $r_file = $base . "-ramdisk.gz";
my $s_file = $base . "-second.gz";

# The kernel is always there
print "Writing $k_file ...";
&dump_file($IMAGE_FN, $k_file, $k_offset, $KERNEL_SIZE);
print " complete.\n";

# The ramdisk is always there
print "Writing $r_file ...";
&dump_file($IMAGE_FN, $r_file, $r_offset, $RAMDISK_SIZE);
print " complete.\n";

# The Second stage bootloader is optional
unless ($SECOND_SIZE == 0) {
    print "Writing $s_file ...";
    &dump_file($IMAGE_FN, $s_file, $s_offset, $SECOND_SIZE);
    print " complete.\n";
}
    
######################################################################
## Supporting Subroutines

=header_format (from bootimg.h)
struct boot_img_hdr
{
    unsigned char magic[BOOT_MAGIC_SIZE];

    unsigned kernel_size;  /* size in bytes */
    unsigned kernel_addr;  /* physical load addr */

    unsigned ramdisk_size; /* size in bytes */
    unsigned ramdisk_addr; /* physical load addr */

    unsigned second_size;  /* size in bytes */
    unsigned second_addr;  /* physical load addr */

    unsigned tags_addr;    /* physical addr for kernel tags */
    unsigned page_size;    /* flash page size we assume */
    unsigned unused[2];    /* future expansion: should be 0 */

    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

    unsigned char cmdline[BOOT_ARGS_SIZE];

    unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
=cut
sub parse_header {
    my ($fn) = @_;
    my $buf = undef;

    open INF, $fn or die "Could not open $fn: $!\n";
    binmode INF;

    # Read the Magic
    read(INF, $buf, BOOT_MAGIC_SIZE);
    unless ($buf eq BOOT_MAGIC) {
	die "Android Magic not found in $fn. Giving up.\n";
    }

    # Read kernel size and address (assume little-endian)
    read(INF, $buf, UNSIGNED_SIZE * 2);
    my ($k_size, $k_addr) = unpack("VV", $buf);

    # Read ramdisk size and address (assume little-endian)
    read(INF, $buf, UNSIGNED_SIZE * 2);
    my ($r_size, $r_addr) = unpack("VV", $buf);

    # Read second size and address (assume little-endian)
    read(INF, $buf, UNSIGNED_SIZE * 2);
    my ($s_size, $s_addr) = unpack("VV", $buf);

    # Ignore tags_addr
    read(INF, $buf, UNSIGNED_SIZE);

    # get the page size (assume little-endian)
    read(INF, $buf, UNSIGNED_SIZE);
    my ($p_size) = unpack("V", $buf);

    # Ignore unused
    read(INF, $buf, UNSIGNED_SIZE * 2);

    # Read the name (board name)
    read(INF, $buf, BOOT_NAME_SIZE);
    my $name = $buf;

    # Read the command line
    read(INF, $buf, BOOT_ARGS_SIZE);
    my $cmdline = $buf;

    # Ignore the id
    read(INF, $buf, UNSIGNED_SIZE * 8);

    # Close the file
    close INF;

    # Print important values
    printf "Page size: %d (0x%08x)\n", $p_size, $p_size;
    printf "Kernel size: %d (0x%08x)\n", $k_size, $k_size;
    printf "Ramdisk size: %d (0x%08x)\n", $r_size, $r_size;
    printf "Second size: %d (0x%08x)\n", $s_size, $s_size;
    printf "Board name: $name\n";
    printf "Command line: $cmdline\n";

    # Save the values
    $PAGE_SIZE = $p_size;
    $KERNEL_SIZE = $k_size;
    $RAMDISK_SIZE = $r_size;
    $SECOND_SIZE = $s_size;
}

sub dump_file {
    my ($infn, $outfn, $offset, $size) = @_;
    my $buf = undef;

    open INF, $infn or die "Could not open $infn: $!\n";
    open OUTF, ">$outfn" or die "Could not open $outfn: $!\n";

    binmode INF;
    binmode OUTF;

    seek(INF, $offset, 0) or die "Could not seek in $infn: $!\n";
    read(INF, $buf, $size) or die "Could not read $infn: $!\n";
    print OUTF $buf or die "Could not write $outfn: $!\n";

    close INF;
    close OUTF;
}

######################################################################
## Configuration Subroutines

sub parse_cmdline {
    unless ($#ARGV == 0) {
	die "Usage: $SCRIPT boot.img\n";
    }
    $IMAGE_FN = $ARGV[0];
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值