Android逆向分析源码中资源代码还原小工具
一般情况下,我们采用apktool(xml资源)+dex2jar+JDGui(jar to java)反编译android apk之后的代码中,涉及到资源索引的信息全部替换成了十进制的数字。
如何将这些数字还原成为原始的资源索引形式呢?
public g(Context paramContext) { super(paramContext); b(2130903088); this.b = ((FirModule)this.k.N().a("fir_module")); int[] arrayOfInt = new int[2]; arrayOfInt[0] = 2131427902; arrayOfInt[1] = 2131427901; a(arrayOfInt); f(1); f(2); }我们希望得到如下形式的代码:
public g(Context paramContext) { super(paramContext); b(R.layout.fir_info_page); this.b = ((FirModule)this.k.N().a("fir_module")); int[] arrayOfInt = new int[2]; arrayOfInt[0] = R.string.commended_apps; arrayOfInt[1] = R.string.person_info; a(arrayOfInt); f(1); f(2); }
可读性就非常高了。
下面讲述如何做到这个功能:
b(2130903088);中的数字转换为16进制以后,是0x7f030030,通过手工在R.java中搜索我们可以找到:
public static final int fir_info_page=0x7f030030;
因此在相应的地方替换为对应的资源索引就可以了,处于layout class之下,因此是 R.layout.fir_info_page 。
好了,原理很简单,接下来我们编写一个perl脚本来批量做这个事情,具体代码如下:
#!/usr/bin/perl#注意事项:#复制一份 R.java在该文件所在目录#第一个参数为:需要处理的源代码目录路径use strict;use File::Find;my $from_str;my $to_str;my $resource;my $init_folder = $ARGV[0];if (not -d $init_folder){ print "目录:$init_folder不存在.\n";print "$0 <source_folder>\n"; exit;}#读取R.java中的所有文本my $k_file = "R.java";open my $k ,"< $k_file" or die "couldn't open $k_file\n";my @keywords = <$k> ;close $k;#遍历每行数据for my $line (@keywords){ #print "$line"; #先解析内部class类型:id/style/xml/arrays等 #public static final class style { if ($line =~ /public\sstatic\sfinal\sclass\s(\w+)\s\{/) { $resource = $1; } else { #如果格式如下,则解析出来 #public static final int MarketPanelTheme=0x7f0c0076; if ($line =~ /public\sstatic\sfinal\sint\s(\w+)=(\w+)\;/) { #print "keywords:$1 <-- $2\n"; $from_str = oct $2; #16进制转化为10进制 $to_str = "R\.$resource\.$1"; print "$from_str --> $to_str\n\n"; find(\&CallBackMe, $init_folder ); } }}print "Well Done.\n";sub CallBackMe{ my $fullpath = $File::Find::name; if(-d $fullpath) { print "[Dir] $fullpath\n"; } else { print "[File] $fullpath\n"; if($fullpath =~ /\.java$/i) { if($fullpath =~ /$k_file/i) { #ignore it print "Ignored $k_file\n"; } else { #replace text print "Replacing $from_str with $to_str in $fullpath\n"; ReplaceString($fullpath, $from_str,$to_str); } } }}#Replacing $from with $to in $filesub ReplaceString{ my $file = shift @_; my $from = shift @_; my $to = shift @_; open my $fh ,"< $file" or die "couldn't open $file\n"; my @lines=<$fh>; close $fh; foreach my $l (@lines) { $l=~s/$from/$to/g; } #print "@lines\n"; #write back open my $out , "> $file" or die "couldn't write $file"; foreach my $l (@lines) { print $out $l; } close $out;}