美文网首页
使用python脚本来实现AndResGuard框架的反资源混淆

使用python脚本来实现AndResGuard框架的反资源混淆

作者: 文武锅 | 来源:发表于2018-12-17 16:40 被阅读0次

    前言

    最近反编译其他人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 <init>()V
        .locals 0
    
        .prologue
        .line 12
        invoke-direct {p0}, Landroid/app/Activity;-><init>()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 <init>()V
        .locals 0
    
        .prologue
        .line 12
        invoke-direct {p0}, Landroid/app/Activity;-><init>()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语法值得更加深入学习

    相关文章

      网友评论

          本文标题:使用python脚本来实现AndResGuard框架的反资源混淆

          本文链接:https://www.haomeiwen.com/subject/iwsqkqtx.html