Android逆向分析源码中资源代码还原小工具


一般情况下,我们采用apktool(xml资源)+dex2jar+JDGui(jar to java)反编译Android apk之后的代码中,涉及到资源索引的信息全部替换成了十进制的数字。

如何将这些数字还原成为原始的资源索引形式呢?

  1. public g(Context paramContext)  
  2. {  
  3.   super(paramContext);  
  4.   b(2130903088);  
  5.   this.b = ((FirModule)this.k.N().a("fir_module"));  
  6.   int[] arrayOfInt = new int[2];  
  7.   arrayOfInt[0] = 2131427902;  
  8.   arrayOfInt[1] = 2131427901;  
  9.   a(arrayOfInt);  
  10.   f(1);  
  11.   f(2);  
  12. }  

我们希望得到如下形式的代码:

  1. public g(Context paramContext)  
  2. {  
  3.   super(paramContext);  
  4.   b(R.layout.fir_info_page);  
  5.   this.b = ((FirModule)this.k.N().a("fir_module"));  
  6.   int[] arrayOfInt = new int[2];  
  7.   arrayOfInt[0] = R.string.commended_apps;  
  8.   arrayOfInt[1] = R.string.person_info;  
  9.   a(arrayOfInt);  
  10.   f(1);  
  11.   f(2);  
  12. }  

可读性就非常高了。

下面讲述如何做到这个功能:

 b(2130903088);中的数字转换为16进制以后,是0x7f030030,通过手工在R.java中搜索我们可以找到:

        public static final int fir_info_page=0x7f030030;

因此在相应的地方替换为对应的资源索引就可以了,处于layout class之下,因此是 R.layout.fir_info_page 。

好了,原理很简单,接下来我们编写一个perl脚本来批量做这个事情,具体代码如下:

  1. #!/usr/bin/perl  
  2. #注意事项:  
  3. #复制一份 R.java在该文件所在目录  
  4. #第一个参数为:需要处理的源代码目录路径  
  5.   
  6. use strict;  
  7.   
  8. use File::Find;  
  9.   
  10. my $from_str;  
  11. my $to_str;  
  12. my $resource;  
  13. my $init_folder = $ARGV[0];  
  14.   
  15. if (not -d $init_folder)  
  16. {  
  17.   print "目录:$init_folder不存在.\n";  
  18. print "$0 <source_folder>\n";   
  19.   exit;  
  20. }  
  21.   
  22. #读取R.java中的所有文本  
  23. my $k_file = "R.java";  
  24. open my $k ,"< $k_file" or die "couldn't open $k_file\n";  
  25. my @keywords = <$k> ;  
  26. close $k;  
  27.   
  28.   
  29. #遍历每行数据  
  30. for my $line (@keywords)  
  31. {  
  32.   #print "$line";  
  33.   
  34.   #先解析内部class类型:id/style/xml/arrays等  
  35.   #public static final class style {  
  36.   if ($line =~ /public\sstatic\sfinal\sclass\s(\w+)\s\{/)  
  37.   {  
  38.      $resource = $1;  
  39.   }  
  40.   else  
  41.   {  
  42.     #如果格式如下,则解析出来  
  43.     #public static final int MarketPanelTheme=0x7f0c0076;  
  44.     if ($line =~ /public\sstatic\sfinal\sint\s(\w+)=(\w+)\;/)  
  45.     {  
  46.       #print "keywords:$1 <-- $2\n";  
  47.       $from_str = oct $2; #16进制转化为10进制  
  48.       $to_str = "R\.$resource\.$1";  
  49.       print "$from_str --> $to_str\n\n";  
  50.       find(\&CallBackMe, $init_folder );  
  51.     }  
  52.   }  
  53. }  
  54.   
  55. print "Well Done.\n";  
  56.   
  57. sub CallBackMe  
  58. {  
  59.  my $fullpath = $File::Find::name;  
  60.   
  61.  if(-d $fullpath)  
  62.  {  
  63.       print "[Dir] $fullpath\n";  
  64.  }  
  65.  else  
  66.  {  
  67.    print "[File] $fullpath\n";  
  68.    if($fullpath =~ /\.java$/i)  
  69.    {  
  70.      if($fullpath =~ /$k_file/i)  
  71.      {  
  72.         #ignore it  
  73.         print "Ignored $k_file\n";  
  74.      }  
  75.      else  
  76.      {  
  77.        #replace text  
  78.        print "Replacing $from_str with $to_str in $fullpath\n";  
  79.        ReplaceString($fullpath, $from_str,$to_str);  
  80.      }  
  81.    }  
  82.  }  
  83. }  
  84.   
  85. #Replacing $from with $to in $file  
  86. sub ReplaceString  
  87. {  
  88.   my $file = shift @_;  
  89.   my $from = shift @_;  
  90.   my $to = shift @_;  
  91.   
  92.   open my $fh ,"< $file" or die "couldn't open $file\n";  
  93.   my @lines=<$fh>;  
  94.   close $fh;  
  95.   foreach my $l (@lines)  
  96.   {  
  97.     $l=~s/$from/$to/g;  
  98.   }  
  99.   #print "@lines\n";  
  100.   #write back  
  101.   open my $out , "> $file" or die "couldn't write $file";  
  102.   foreach my $l (@lines)  
  103.   {  
  104.      print $out $l;  
  105.   }  
  106.   close $out;  
  107. }  

相关内容