前言
最近反编译其他人APP的时候发现其他人使用了微信的资源混淆,所以记录一下如何使用python脚本解决AndResGuard框架反混淆资源
1.首先我们写一个小例子
public class MyActivity extends Activity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int color=getResources().getColor(R.color.colorPrimary);
String str=getResources().getString(R.string.app_name);
Drawable drawable=getResources().getDrawable(R.mipmap.ic_launcher);
}
}
这个是我们的例子,我们先使用AndResGuard混淆一下,看看我们的结果
public class MyActivity
extends Activity
{
protected void onCreate(@Nullable Bundle paramBundle)
{
super.onCreate(paramBundle);
getResources().getColor(2130771969);
getResources().getString(2131099648);
getResources().getDrawable(2131034112);
}
}
可以看到资源变成了一堆数字,然后我们再看看apktool反编译出来的资源
屏幕快照 2018-12-17 下午2.24.02.png
屏幕快照 2018-12-17 下午2.24.25.png
而混淆资源对应的参照表就在混淆的res/values/public.xml里,规则为代码资源int转16进制查找public.xml里对应的name,然后去找string、layout、mipmap、drawable、id、style、color
比如上面的getDrawable(2131034112)转为16进制是0x7f050000,public.xml里对应的
屏幕快照 2018-12-17 下午2.28.35.png
图片对应a,那么资源文件里就是上面的a.png了
分析smali语法
.class public Lcom/hw/mytestdemo/MyActivity; #类路径
.super Landroid/app/Activity; #超类
.source "MyActivity.java" #类名
# direct methods #表示该类的不带参数的构造方法
.method public constructor ()V
.locals 0
.prologue
.line 12
invoke-direct {p0}, Landroid/app/Activity;->()V
return-void
.end method
# virtual methods #虚方法 简单的理解就是@override方法就是虚方法
.method protected onCreate(Landroid/os/Bundle;)V #void 方法onCreate入口
.locals 5 #2个参数,Bundle和Nullable 对应5个寄存器(v0~v4)
.param p1, "savedInstanceState" # Landroid/os/Bundle; #参数1,Bundle类型的param savedInstanceState
.annotation build Landroid/support/annotation/Nullable; #参数2,Nullable注解
.end annotation
.end param #参数完毕
.prologue #代码开始
.line 15 #行数
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V //对应 super.onCreate(savedInstanceState);
.line 16 #16行对应invoke-virtual调用虚方法getResources()
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3 #移动上一次方法调用的返回值,move-result-object返回的是一个object,所以返回的是Resource对象
const v4, 0x7f010001 #对应参数R.color.colorPrimary public.xml 里为0x7f010001
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getColor(I)I 调用虚方法getColor(),I表示是int
move-result v0 move-result-object返回的是一个对象,move-result返回的则是基本数据类型
#下面的基本都和上面分析的是一样的了,这里就不多分析了
.line 17
.local v0, "color":I
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3
const/high16 v4, 0x7f060000
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
move-result-object v2
.line 18
.local v2, "str":Ljava/lang/String;
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3
const/high16 v4, 0x7f050000
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getDrawable(I)Landroid/graphics/drawable/Drawable;
move-result-object v1
.line 19
.local v1, "drawable":Landroid/graphics/drawable/Drawable;
return-void
.end method #onCreate方法结束
可以看到资源ID都是以16进制存在的,我们可以根据这个规律来替换这些16进制int来更方便的让我们理解smali,下面开始编写python脚本
import os
import xml.dom.minidom as xmldom
public='public.xml'
target='MyActivity.smali'
class replaceHex():
def __init__(self):
self.target = target
self.public=public
def traverseXml(self):
domobj=xmldom.parse(self.public)
elementobj = domobj.documentElement
subElementObj = elementobj.getElementsByTagName("public")
for i in range(len(subElementObj)):
yield {
'type': subElementObj[i].getAttribute("type"),
'name': subElementObj[i].getAttribute("name"),
'id':subElementObj[i].getAttribute("id")
}
def replace(self):
xml=self.traverseXml()
with open(self.target,'r',encoding="utf-8") as f1,open("%s.bak" % self.target, "w", encoding="utf-8") as f2:
content=str(f1.read())
for i in xml:
content=content.replace(i.get('id'),i.get('type')+'/'+i.get('name')+'['+i.get('id')+']')
f2.write(content)
os.remove(self.target)
os.rename("%s.bak" % self.target, self.target)
r=replaceHex()
r.replace()
首先读取出public.xml,然后根据id替换smali文件,这里只提供一个思路,具体替换反编译的.java还是smali还是集体替换大家自由发挥,反编译结果如下
.class public Lcom/hw/mytestdemo/MyActivity; #类路径
.super Landroid/app/Activity; #超类
.source "MyActivity.java" #类名
# direct methods #表示该类的不带参数的构造方法
.method public constructor ()V
.locals 0
.prologue
.line 12
invoke-direct {p0}, Landroid/app/Activity;->()V
return-void
.end method
# virtual methods #虚方法 简单的理解就是@override方法就是虚方法
.method protected onCreate(Landroid/os/Bundle;)V #void 方法onCreate入口
.locals 5 #2个参数,Bundle和Nullable 对应5个寄存器(v0~v4)
.param p1, "savedInstanceState" # Landroid/os/Bundle; #参数1,Bundle类型的param savedInstanceState
.annotation build Landroid/support/annotation/Nullable; #参数2,Nullable注解
.end annotation
.end param #参数完毕
.prologue #代码开始
.line 15 #行数
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V //对应 super.onCreate(savedInstanceState);
.line 16 #16行对应invoke-virtual调用虚方法getResources()
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3 #移动上一次方法调用的返回值,move-result-object返回的是一个object,所以返回的是Resource对象
const v4, color/b[0x7f010001] #对应参数R.color.colorPrimary public.xml 里为color/b[0x7f010001]
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getColor(I)I 调用虚方法getColor(),I表示是int
move-result v0 move-result-object返回的是一个对象,move-result返回的则是基本数据类型
#下面的基本都和上面分析的是一样的了,这里就不多分析了
.line 17
.local v0, "color":I
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3
const/high16 v4, string/a[0x7f060000]
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
move-result-object v2
.line 18
.local v2, "str":Ljava/lang/String;
invoke-virtual {p0}, Lcom/hw/mytestdemo/MyActivity;->getResources()Landroid/content/res/Resources;
move-result-object v3
const/high16 v4, mipmap/a[0x7f050000]
invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getDrawable(I)Landroid/graphics/drawable/Drawable;
move-result-object v1
.line 19
.local v1, "drawable":Landroid/graphics/drawable/Drawable;
return-void
.end method #onCreate方法结束
总结
smali语法值得更加深入学习