Android逆向入门流程

0.写在前面

本文是笔者自学笔记,以破解某目标apk的方式进行学习,中间辅以原理性知识,方便面试需求。
参考文章的原文链接会附在相应流程位置,方便阅读学习。

逆向分析流程.jpg

1.获取目标apk

第一步是拿到目标安装包文件,这一步很简单,可以在主流的第三方市场内获取,但是主流的第三方市场都要求应用加固,为了之后方便,笔者常常去app的官网下载,或者去一些小市场下载,运气好的话能下载到他们的未加固版本。

2.确定逆向目标

这个就看各自需求,比如有破解内购,分析反逆向逻辑,crackme题目,查看竞品实现方式,确定好目标再下手。

3.拖动目标文件到集成工具

直接拖apk到集成工具,如改之理,比如jadx,这里是为了检查有没有加固。
附上一些必要的开发工具下载地址
//www.greatytc.com/p/b33eb2f5efa0

4.加固

这里判断很好判断,形如有StubShell的包,都是被加固了的。
那接下来就是要脱壳了。

4.1加固原理

脱壳之前,了解壳是什么(加固原理)。
//www.greatytc.com/p/cec7ef861ace

加壳
https://mp.weixin.qq.com/s/KELi6e6x4-svGP6Ef6r4jQ

壳的加载
https://mp.weixin.qq.com/s/AYZ7k75IlKLDbAIJZ2BelA

so的加载
https://mp.weixin.qq.com/s/BhGxnJrRnrYAEWJ7zDZKmQ

还可能涉及到,so指令膨胀(加花),指令抽取等防护。

4.2脱壳

接下来才是脱壳
脱壳还可能涉及到指令修复

壳的指令修复
https://mp.weixin.qq.com/s/-vrDvp3rbTKNIX-pAlamVw

4.2.1手脱

手脱的麻烦点就在于过各种检测,过完所有的检测最终就是找到dex的内存地址,最后运行代码进行dump

链接是收集各种手工脱壳的帖子
//www.greatytc.com/p/3f6bcf364197

4.2.2机脱

实际上就是各种脱壳机,原理就是
无论什么壳,最终都是要加载到内存中,等apk已经加载到内存后,脱壳机把dex dump出来就行了,也就省去了手工脱壳的麻烦。

这里的原理可参考
Android中apk加固完善篇之内存加载dex方案实现原理(不落地方式加载)
http://www.520monkey.com/archives/629

原理主要讨论了两个问题
如果解密后有一个未加密的apk做中间产物,那就是落地方式,这个方式已经被淘汰了,因为不安全。
如果不落地则可能出现加载两次到内存的效率问题。

这里不深研,只提供一个脱壳机,fdex2
看雪原帖(也说了原理)
https://bbs.pediy.com/thread-224105.htm
52破解帖
https://www.52pojie.cn/forum.php?mod=viewthread&tid=758726&fromguid=hot
推荐另一个机脱dumpDex
https://github.com/WrBug/dumpDex

核心代码,有空可以看
package com.ppma.xposed;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class MainHook implements IXposedHookLoadPackage {

    XSharedPreferences xsp;
    Class Dex;
    Method Dex_getBytes;
    Method getDex;
    String packagename;


    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        xsp = new XSharedPreferences("com.ppma.appinfo", "User");
        xsp.makeWorldReadable();
        xsp.reload();
        initRefect();
        packagename = xsp.getString("packagename", null);
        XposedBridge.log("设定包名:"+packagename);
        if ((!lpparam.packageName.equals(packagename))||packagename==null) {
            XposedBridge.log("当前程序包名与设定不一致或者包名为空");
            return;
        }
        XposedBridge.log("目标包名:"+lpparam.packageName);
        String str = "java.lang.ClassLoader";
        String str2 = "loadClass";

        XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Class cls = (Class) param.getResult();
                if (cls == null) {
                    //XposedBridge.log("cls == null");
                    return;
                }
                String name = cls.getName();
                XposedBridge.log("当前类名:" + name);
                byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
                if (bArr == null) {
                    XposedBridge.log("数据为空:返回");
                    return;
                }
                XposedBridge.log("开始写数据");
                String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
                XposedBridge.log(dex_path);
                File file = new File(dex_path);
                if (file.exists()) return;
                writeByte(bArr, file.getAbsolutePath());
            }
            } );
    }

    public void initRefect() {
        try {
            Dex = Class.forName("com.android.dex.Dex");
            Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
            getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

    public  void writeByte(byte[] bArr, String str) {
        try {
            OutputStream outputStream = new FileOutputStream(str);
            outputStream.write(bArr);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            XposedBridge.log("文件写出失败");
        }
    }
}

4.3得到.dex文件

dex文件是什么
java,dex,smali,关系/区别又是什么
//www.greatytc.com/p/fb9aec070c0a
延展阅读
dex直接得到smali,插入log代码再回编译dex
https://blog.csdn.net/jiangwei0910410003/article/details/79820040

涉及到两个语句

java -jar baksmali.jar -o classes classes.dex 其中classes是反编译dex之后的smali文件夹目录

java -jar smali.jar classes -o classes.dex 其中classes是反编译的smali目录,classes.dex是回编译之后的dex

5.集成工具分析

其实就是可以把刚才拿到的.dex拖进来分析了

6.减少混淆干扰

apk在打包时会被混淆,文件名被替换成影响无意义的字母甚至汉字。
jdax通过以下设置来减少混淆干扰
https://segmentfault.com/a/1190000012180752

发散:proguard的源码阅读
//www.greatytc.com/p/734424a14eff

7.定位目标

借助第三方工具
比如adb工具
https://blog.csdn.net/halibobo1998/article/details/50623929

或者有一部已经root的机器(可以减少很多麻烦),使用layoutInspector去查布局找id

简单的就下一个第三方app 当前activity

还可以通过搜索界面里的特殊字串来定目标文件。
因为资源字串无论怎么混淆,反编译出来的public.xml一定有对应的int值

8.分析业务逻辑

9.确定逆向方法

比如想通过xposed框架去hook某个结果,还是直接nop掉某个返回值。

10.使用apktool进行反编译

执行代码

apktool d -f 目标apk路径

这里可能遇到壳利用apktool漏洞对其进行的干扰
http://www.520monkey.com/archives/808

11.得到.smali

smali语法
//www.greatytc.com/p/54e893ae28ea
空类的smali结构
//www.greatytc.com/p/758bccaaa0a6

12.源码调试

静态调试
//www.greatytc.com/p/4359598a2c9b

动态调试
//www.greatytc.com/p/90f495191a6a

动态调试so
//www.greatytc.com/p/5617220cbb02

13.回编译 app

执行命令

apktool b -d 资源路径 -o 输出.apk

可能会遇到回编译失败的情况,比如低版本的apktool不认识高Android版本的属性,可以选择升级apktool或者删除该属性值。

14.签名

执行命令

apksigner sign --ks testKey.jks --ks-key-alias testkey --ks-pass pass:123456 --key-pass pass:123456 --out output_sign.apk source.apk

参考

Android逆向分析笔记
https://lichao890427.github.io/wiki/android%20reverse%20engineering/#%E6%A6%82%E8%BF%B0

adb指令
//www.greatytc.com/p/85373d89bc81

bugly出的一篇反调总结
大部分方法都写过,少部分如文件节点,inotify,so hash检测可以加以了解(就是我没写过)
https://mp.weixin.qq.com/s/uvrkAvbfWuDYf7SWX_dJBA

todo

还有smali,baksmali没写上去,还有教我兄弟学逆向,卧槽还有好多。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容

  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,421评论 2 45
  •   Android系统由于其开源的属性,市场上针对开源代码定制的ROM参差不齐,在系统层面的安全防范和易损性都不一...
    道书简阅读 9,366评论 0 23
  • 1、网络请求——裸奔的数据 无论是网页还是APP,都不可避免与后台服务进行访问,可能从服务器获取数据或者提交数据到...
    dfqin阅读 9,938评论 0 15
  • 文/梅香 词林正韵 冰雪消融阳和煦,柳绿桃红,芳菲随风吐,彩蝶闻香翩舞赴,南归紫燕谁家顾。 倩女思亲花下驻。春意盈...
    流浪的狗尾巴草阅读 444评论 2 6
  • 姓名:庹亚军 公司:宁波贞观电器有限公司 组别:第235期 利他一组 【日精进打卡第 43天】 【知~学习】 《六...
    tyj小电工阅读 264评论 0 0