吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 31479|回复: 64
收起左侧

[Android 原创] Dexguard分析&钛备份破解

  [复制链接]
Ericky 发表于 2014-12-10 17:50
本帖最后由 PoJie_小雨 于 2014-12-10 17:55 编辑

钛备份,貌似是备份方向很火的一个软件(可能类似于win下的super recovery)。Claud说是加的Dexguard壳,由于本人是初学者,也没见过什么世面,更不懂得Dexguard是个什么东西了,就一股子蛮劲,结果不小心把钛备份干掉了,看来功夫不负有心人啊。以下写出心得和大家分享,互相学习进步。
菜鸟第一次分析,请大牛勿喷,会打击小菜的积极性的!
一、APKtools反编译
可能是Dexguard壳子利用了apktoolsbug吧,反正我是没有反编译成功。AndroidManifest.xml里所有不在<intent-filter></intent-filter>的元素key值都没有反编译出来。
如图所示:
图片1.png
修复后如下:

图片2.png
但是还是无法打包。用apktools还是打包失败:
图片3.png
既然无法打包,很多方法就行不通了,log的方法也失效了,不过不要紧,反编译失败导致无法正常打包,那就用点原始的方法吧。不管那么多,先分析分析这个程序再说,程序分析透了,至少也算是对自身的一种提高,说干就干。(这个问题现在还没有解决,希望会的大牛告知一下,在下感激不尽。)
一、逆向分析

虽然说打包是没搞定,但主要是因为xml文件apktools分析出错的原因,还好不影响我们亲爱的smali文件的反编译。JEB载入,(这里要感谢SCZ大神的无私奉献,虽然说好像保存功能用不了,但是已经非常感谢了)随便翻了一下,看见一个这个:
图片13.png

我本来准备吐槽作者了,但是往后一翻,我觉得这个也不必怎么大惊小怪。因为对于第一次分析APK,发现如下的东西,我开始有点不淡定了。类名和函数的名称被加密成这样:
图片4.png 图片5.png
不过不管它多么花,也要干掉它!
那就要开始定位关键地方,进行破解了。
2.1.关键定位
我目前知道的一共有2种方法可以成功定位到关键地方。
第一种方法:搜Strings.
如图:
图片6.png
这是一种方法,当然可能搜到的不止一处,这就需要自己去甄别了。
第二种方法:这种方法在我之前的一篇学习笔记里也有讲到,地址:http://bbs.pediy.com/showthread.php?t=195202。里面的第四种方法,所谓的“遗留下的宝藏”。用到了DDMS 如图:

图片7.png
OK,真幸运,直接定位到了fs中。Nice

2.2log分析
既然发现了验证的类,那就不能放过。发现大部分字符串都被加密过了,我们就从log开始着手吧。找了几个log如下:
图片8.png
发现了解密函数,把它Rename:
图片9.png

解密函数如下:
图片10.png
找到了解密函数,这就好办了,先把strings解密了再说,我写了一个python脚本来解密encryptStringsPython脚本如下:
[Asm] 纯文本查看 复制代码
#Author Ericky
import sys
import os
import time
from jeb.api import IScript
from jeb.api import EngineOption
from jeb.api.ui import View
from jeb.api.dex import Dex
from jeb.api.ast import Class, Field, Method, Call, Constant, StaticField, NewArray
encbytes = [69, 21, -111, -111, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -36, 
                -45, -4, -1, -4, 4, -5, 83, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 25, 14, -30, 
                5, -3, -10, -6, 9, -6, 6, 9, 60, -55, -12, -12, 2, 4, 2, -20, 10, -6, 6, 70, -71, -13, 
                2, 1, 76, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 68, -15, -1, -1, 14, -30, 5, -3, -10, 
                -6, 9, -6, 6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -74, -11, 82, -79, -2, -6, 
                83, -87, 20, -12, 2, 4, 67, -66, -14, -12, 11, -3, -4, 12, 54, 14, -30, 5, -3, -10, 
                -6, 9, -6, 6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -88, 13, -4, -1, 75, -84, -2, 
                10, -4, -1, 75, -83, 12, -9, 11, -9, -6, 77, -87, 20, -12, 2, 4, 67, -71, -10, -4, 81, 
                14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -74, -11, 
                82, -84, -2, 10, -4, -1, 75, -87, 16, -14, -8, 88, -71, -13, 12, -15, 10, 57, 14, -30, 
                5, -3, -10, -6, 9, -6, 6, 9, 60, -52, -15, -22, 12, -6, 6, 70, -68, 1, -3, -6, 2, 68, 
                -71, -4, -4, 6, 42, 25, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -36, -31, -3, -6, 
                2, 68, -87, 20, -12, 2, 4, 36, 30, -30, 28, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, 
                -51, -20, -15, 2, 0, 0, -6, 13, 68, -88, 13, -4, -1, 75, -67, -4, 68, -83, 12, -2, -13, 
                12, -15, 10, 2, 0, 67, -67, -4, 1, 1, -21, 1, 13, 68, -80, -8, 16, -14, 81, -18, 1, 
                -5, 0, 17, -80, 8, 69, -74, -12, 0, 82, -87, 20, -12, 2, 4, -6, -12, -6, 88, -69, -18, 
                2, 16, -20, 10, -7, 0, 77, -74, -11, 82, -70, -8, 10, -16, -4, 13, 0, 53, 14, -30, 5, 
                -3, -10, -6, 9, -6, 6, 9, 60, -47, -34, 78, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 
                25, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -37, -34, -8, 6, -16, 10, -6, 6, 70, -79, 
                -2, 0, 64, -74, 20, -12, 2, 4, 67, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 25]


class Mydecypt(IScript):

  def run(self, jeb):
    self.jeb = jeb
    self.dex = self.jeb.getDex()
    self.cstbuilder = Constant.Builder(jeb)

    self.csig = 'fs'
    self.encbytes = encbytes
    self.mname_decrypt = None

    r = jeb.decompileClass(self.csig)
    decrypted_string = self.decrypt(66, 26, 0) #Here enter your encrypt strings
    print '  Decrypted string: %s' % repr(decrypted_string)
  def decrypt(self, length, curChar, pos):
    length = 93 - length
    pos = pos * 2 + 91
    curChar = 378 - curChar
    r = ''
    for i in range(length):
      curChar +=1
      r += chr(pos & 0xFF)
      if i >= len(self.encbytes):
        break
      curEncodedChar = self.encbytes[curChar]
      pos = pos - curEncodedChar -1
    return r   
把字符串解密了,那就事半功倍了。具体的分析就比较简单了。分析解密后如下:
[Asm] 纯文本查看 复制代码
private static final BigInteger 大整数;
    private static final byte[] 加密字符串;
    public static boolean 普通版开关;
    public static boolean 专业版开关;
    public static hG HG类;
    private static final String 字符串常量;
    private static int 常数;
    private static boolean modaco隐藏版本开关;

    static {
        fs.加密字符串 = new byte[]{69, 21, -111, -111, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -36, -45, -4, 
                -1, -4, 4, -5, 83, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 25, 14, -30, 5, -3, -10, 
                -6, 9, -6, 6, 9, 60, -55, -12, -12, 2, 4, 2, -20, 10, -6, 6, 70, -71, -13, 2, 1, 76, 
                -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 68, -15, -1, -1, 14, -30, 5, -3, -10, -6, 9, 
                -6, 6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -74, -11, 82, -79, -2, -6, 83, -87, 
                20, -12, 2, 4, 67, -66, -14, -12, 11, -3, -4, 12, 54, 14, -30, 5, -3, -10, -6, 9, -6, 
                6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -88, 13, -4, -1, 75, -84, -2, 10, -4, 
                -1, 75, -83, 12, -9, 11, -9, -6, 77, -87, 20, -12, 2, 4, 67, -71, -10, -4, 81, 14, -30, 
                5, -3, -10, -6, 9, -6, 6, 9, 60, -51, -20, -15, 2, 0, 0, -6, 13, 68, -74, -11, 82, -84, 
                -2, 10, -4, -1, 75, -87, 16, -14, -8, 88, -71, -13, 12, -15, 10, 57, 14, -30, 5, -3, 
                -10, -6, 9, -6, 6, 9, 60, -52, -15, -22, 12, -6, 6, 70, -68, 1, -3, -6, 2, 68, -71, 
                -4, -4, 6, 42, 25, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -36, -31, -3, -6, 2, 68, 
                -87, 20, -12, 2, 4, 36, 30, -30, 28, 14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -51, 
                -20, -15, 2, 0, 0, -6, 13, 68, -88, 13, -4, -1, 75, -67, -4, 68, -83, 12, -2, -13, 12, 
                -15, 10, 2, 0, 67, -67, -4, 1, 1, -21, 1, 13, 68, -80, -8, 16, -14, 81, -18, 1, -5, 
                0, 17, -80, 8, 69, -74, -12, 0, 82, -87, 20, -12, 2, 4, -6, -12, -6, 88, -69, -18, 2, 
                16, -20, 10, -7, 0, 77, -74, -11, 82, -70, -8, 10, -16, -4, 13, 0, 53, 14, -30, 5, -3, 
                -10, -6, 9, -6, 6, 9, 60, -47, -34, 78, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 25, 
                14, -30, 5, -3, -10, -6, 9, -6, 6, 9, 60, -37, -34, -8, 6, -16, 10, -6, 6, 70, -79, 
                -2, 0, 64, -74, 20, -12, 2, 4, 67, -68, 1, -3, -6, 2, 68, -71, -4, -4, 6, 42, 25};
        fs.常数 = 245;
        boolean v0 = !fs.class.desiredAssertionStatus() ? true : false;
        fs.&#700; = v0;
        fs.字符串常量 = fs.class.getName();
        fs.普通版开关 = false;
        fs.专业版开关 = false;
        fs.HG类 = null;
        fs.modaco隐藏版本开关 = false;
        fs.大整数 = BigInteger.ONE.shiftLeft(16).add(BigInteger.ONE);

值得注意的地方是这个函数:
[Asm] 纯文本查看 复制代码
private static void 关键函数(Runnable arg3, boolean arg4) {
        if(arg4) {
            fs.ˊ(true);
            fs.专业版开关 = true;
            fs.HG类 = new hG();
        }
        else {
            fs.ˊ(fs.ˊ(MainApplication.&#702;));
            boolean v0 = !fs.modaco隐藏版本开关 || !"95116f196c3b".equals(fs.HG类.get("keyId")) ? false : true;
            fs.普通版开关 = v0;
        }

        arg3.run();//很明显了吧  
}
分析好的fs类我会打包在附件中。
三、破解

3个开关,事情就变得很简单了,改几个字节就行了。找到类中的开关,打开交叉引用:
图片11.png
找到每一个地方,稍微分析一下,把需要改的置真即可。当然你不怕麻烦的话,可以每一处都置“1”,也是一样的。
看了吾爱的一篇文章说修改之后,会弹出版本不正确。打开APK中的so,你会看到一个mprotect的函数,根据名字我猜的话应该是so里面的MD5完整性校验,但是奇怪的是,由于我更改的是几个“开关”,貌似dexguard对开关,或者说是声明函数里的东西是不检查的,因此这种方法直接避过了dexguard 6.0anti-tampering check.不仅省去了逆SO的时间和精力,动态加载也不用去担心,因为找到的这块是风水宝地啊,直接避开了dexguard的检测,当然也有可能是我直接改的dex文件里的opcode,可能dexguarddex的检测只是依赖与dex自身的SHA-1值和签名值。
刚才说了打包不了,怎么办呢?我的方法是直接解压apk,用IDA load dex,然后在IDA中定位到具体的offset,然后用16进制工具直接找到offset直接修改dexopcode即可。还是很期待有人指点下过dexguard反编译方法啦,我自己当然也会继续研究的。如图:
图片12.png

四、总结


11.22号开始看丰生强的那本入门书,这个程序3天分析得差不多了,也算是对最近20天自己的一个交代。这个程序真的很有意思,除了表面上的2个版本之外后来还发现有一个隐藏的版本,真的是耐人寻味啊。从中加强了自己的逆向分析,同时也了解到了作者的一些验证思路。本来找到了keygen算法(第一个函数)想分析算法,patch之后做一个keygen出来,但是因为实力有限吧,最后还是放弃了。因为JEB不能保存的缘故,这一次fs里面分析的东西是临时做的,难免有疏漏,还望各位见谅。
在这里衷心谢谢非虫的书,越反复看觉得越写得好,虽然有的地方有一些冗长。也感谢论坛上的一些文章,认真读了,很有收获。接下来还是要继续学习吧,不过基础还是一定要打牢!
总的来说,收获还是挺大的,学到了很多东西。欢迎大家和我一起交流,一起进步。新手难免没有纰漏,失敬之处还望各位大侠多多指点。
(*^__^*)
By Ericky
2014.12.9

fs analysis.zip (7.33 KB, 下载次数: 34) Cracked by Ericky.haozip01.zip (2.5 MB, 下载次数: 116) Cracked by Ericky.haozip02.zip (1.91 MB, 下载次数: 91)

点评

会编程简直是逆向的一大利器啊  发表于 2014-12-13 08:31
你还会py。。  发表于 2014-12-10 20:15

免费评分

参与人数 7热心值 +7 收起 理由
610100 + 1 谢谢@Thanks!
蜡笔小新爱蜡笔 + 1 谢谢@Thanks!
XhyEax + 1 谢谢@Thanks!
无名低调me + 1 谢谢@Thanks!
感恩心 + 1 我很赞同!
william2568 + 1 谢谢@Thanks!
sndncel + 1 谢谢@Thanks!不得不说,你很牛X呀。。。。

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2014-12-11 00:02
赞一个。
 楼主| Ericky 发表于 2014-12-13 12:31
神小白 发表于 2014-12-10 18:01
 楼主| Ericky 发表于 2014-12-10 18:07

现在感觉也没什么~
头像被屏蔽
yyz219 发表于 2014-12-10 19:16
非常的深奥的
Some 发表于 2014-12-10 19:32
精。。。这是必须的。
 楼主| Ericky 发表于 2014-12-10 19:50

仔细看看  比较好学
 楼主| Ericky 发表于 2014-12-10 19:51
Some 发表于 2014-12-10 19:32
精。。。这是必须的。

谢谢~~~~
924410377 发表于 2014-12-10 20:00 来自手机
不错的分析
sndncel 发表于 2014-12-10 20:09
虽然很多感觉看不太懂,不过还是看完了呀。。。谢谢分享呀。。。
GA゛木子 发表于 2014-12-10 20:22 来自手机
完全看不懂,而且没看完。。。不要在意,我就是个门外汉,破解什么的完全不会,当我打酱油的就行。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-19 04:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表