舍得英语魔法学苑

 找回密码
 注册
查看: 318|回复: 1

折腾无罪:提取驾考宝典数据库

[复制链接]
  • TA的每日心情
    开心
    2011-10-10 00:27
  • 签到天数: 68 天

    [LV.6]常住居民II

    舍得 发表于 2016-11-20 14:22:44 | 显示全部楼层 |阅读模式
    接到朋友的一个任务,把《驾考宝典》的数据库取出来,做成SuperMemo的课程。理由很简单,用SuperMemo的复习机制,学起来更快、更轻松。
    本以为很简单,无论是PC版还是Android版的《驾考宝典》,数据库很容易找到,PC版下是一个叫“question”的文件,Android的就有点奇葩了,文件命名为”question.mp3”……
    随手写了几行代码测试了一下,一开始很顺利,大部分文本内容都能提取出来,媒体文件也能顺利取出,但碰到“问题”和“解析”这两个时段就卡壳了,尼玛,怎么都没法顺利转换成文字。
    这时脑子里模模糊糊感觉到,应该是软件的作者在这两个字段的内容里加了混淆,算是一种加密的手段吧。
    找了个IDA Pro,打算看看PC版的程序代码,一看差点吓尿,转出的是汇编语言,没学过,不会看……
    只有知道作者怎么加密的,才能顺利将问题和解析的内容取出来。嗯,从Android版的《驾考宝典》下手可能是个不错的方法。
    于是舍得开始了生平第一次反编译Android App的操作。
    在度娘帮助下,花了十分钟恶补了一下反编译Android App的知识,下载好两款叫dex2jar和jd-gui的工具,就此动手开反。
    • 把《驾考宝典》的apk扩展名改为zip,然后解压;
    • 找到解压出的classesx.dex,一共4个,x是序号,从“无”开始,然后2、3、4一直排下去;
    • 在dos命令提示符下,输入“dex2jar.bat classes.dex”,解出jar文件,4个文件依次操作;
    • 用jd-gui打开classes_dex2jar.jar,二话不说直接从“File”菜单中执行“Save All Sources”(储存全部源代码);
    • jd-gui转换出的源代码是压缩过的,把4个jar文件转换好后,解压到一个文件夹下;
    好了,源代码已经搞到手了,怎么快速找到作者加密的地方呢?他肯定要读取数据库中的加密过的这两个字段,用字段名question和explain或许能很快帮我找到相关的代码。
    这时该PowerGrep上场了,把检索范围设置成刚才解压文件存放的文件夹,开始搜索question。
    3-4秒后,PowerGrep从17000多个文件中找到含有“question”的文件,共139个,从查询结果页直接一个个看下去,不到一分钟的时间,便发现了一行貌似符合要求的代码:
    String str2 = decodeString(paramCursor.getBlob(paramCursor.getColumnIndex("question")));
    虽然没学过Java,但基本上也能看出,程序在用getBlob取出question字段后,再用decodeString将它转成字符串,看到我要找的东西就在这个叫decodeString的方法中了。果然,在这方法下找到这段代码:
    byte[] arrayOfByte = "_jiakaobaodian.com_".getBytes("utf8");
    for (int i = 0; i < paramArrayOfByte.length; i++)
      paramArrayOfByte = ((byte)(paramArrayOfByte ^ arrayOfByte[(i % arrayOfByte.length)]));
    String str = new String(paramArrayOfByte, "utf8");
    return str;
    原来这货把“"_jiakaobaodian.com_”这串文字混进去了,怪不得怎么都转换不了。
    这就好办了,回到我擅长的Python下,依样画葫芦地写了一段代码:
    paramArrayOfByte = bytearray(blob)
    arrayOfByte  = bytearray('_jiakaobaodian.com_'.encode('utf-8'))
    for i in range(len(paramArrayOfByte)):
        paramArrayOfByte = paramArrayOfByte ^ arrayOfByte [(i % len(arrayOfByte ))]
    str = paramArrayOfByte.decode()
    blob是我从数据库中取出的question字段的值,先用bytearray将它转成byte数组。
    然后也将’_jiakaoparamArrayOfByteodian.com_’转成utf-8编码后,同样转成byte数组。
    一个for循环,对paramArrayOfByte进行解密处理,解密完成后,直接转换成”utf-8”编码,这时就能够输出正确的文字了。
    其实舍得对Android的反编译和Java的代码都不熟悉,感谢万能的网络,在网络的帮助下,一通折腾,终于把这《驾考宝典》中加密的数据(最最简单的加密的手段)取出来了。
    折腾无罪,以后可以抱着学习的心态,把心仪的Android App一个个反编译出来。对我来说,看书学习还真是没有直接看代码来得快。




    本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
    作者:舍得
    首发:舍得新浪博客

  • TA的每日心情
    慵懒
    昨天 08:14
  • 签到天数: 378 天

    [LV.9]以坛为家II

    feng850113 发表于 2016-11-21 12:00:12 | 显示全部楼层
    ,前个星期,我也尝试反编译了supermemo ux for pc的程序,.net的源代码,现在正在梳理,看能不能再次编译成功。主要是想看看它生成网页的源码。
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    小黑屋|手机版|Archiver|官方微博|官方QQ群|舍得英语魔法学苑 ( 冀ICP备11024081号-1 )

    GMT+8, 2017-8-22 22:52 , Processed in 0.271966 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

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