Android 渗透测试学习笔记(一):基础指北

查看 91|回复 9
作者:AugustTheodor   
搬一下本人的学习笔记,新手勿喷{:1_919:}
图太多了,一个一个重传应该不行,先传md过来看看会不会被夹图

0 adb常见命令
一般模拟器(非真机模拟器)的安装目录下会有一个adb.exe。如果安装了Android Studio的话也会附带一个adb。如果两种情况都没有则需要去自己下载一个。调试远端的设备(本机上的模拟器一般不用,如雷电模拟器)需要先使用adb connect进行连接再shell。
  • adb shell 进入shell,也就是获取一个手机命令行
  • adb push 电脑地址 手机地址 将电脑文件导入到手机指定位置
  • adb install 电脑地址 安装电脑地址上的apk
  • adb connect ip port 链接指定位置的手机(适用于远程调试)
  • adb devices 查看当前设备列表
  • adb forward agree:port agree:port 转发端口
  • adb shell pm uninstall -k --user 0 包名 卸载apk
    1 代{过}{滤}理
    1.1 挂代{过}{滤}理步骤
    (这个方法真机模拟器无法使用,真机挂代{过}{滤}理方式请看下文第二节)
    使用burpsuite、mitmproxy、lamda。
    lamda github页面:https://github.com/rev1si0n/lamda/
    首先需要准备一个root权限的手机。下载lamda的安装脚本adb中使用sh运行安装(详细步骤请自行查看lamda的ReadMe)。主机中使用pip安装lamda的客户端。
    手机如果是模拟器,配置到与主机同一个网段则需要使用桥接模式。使用桥接模式后互相能ping通就可以了。
    启动lamda的命令:

    sh /data/local/tmp/x86/bin/launch.sh


    先启动手机上的lamda。使用lamda是为了挂代{过}{滤}理+安装证书。
    mitmproxy使用pip命令即可安装(它是一个python module):

    pip install mitmproxy

    安装mitmproxy的证书(运行mitmdump挂起服务器,浏览器走mitm的代{过}{滤}理访问mitm.it即可安装证书)并挂上mitmproxy的代{过}{滤}理如下:
    #启动代{过}{滤}理
    # sh /data/local/tmp/x86/bin/launch.sh
    from lamda.client import *
    d=Device("192.168.3.31")
    profile = GproxyProfile()
    profile.type = GproxyType.HTTP_CONNECT
    # 此选项请根据实际情况选择你是否需要
    profile.drop_udp = True
    profile.host = "192.168.3.82"
    profile.port = 8899
    #d.install_ca_certificate("mitmproxy-ca-cert.cer")
    d.start_gproxy(profile)
    #d.stop_gproxy()
    #d.uninstall_ca_certificate("cacert.der")
    d.beep()
    这个脚本在手机端lamda启动后运行一次,听到beep声表示运行成功。
    install_ca_certificate就是安装证书的命令,只需要运行一次。
    手机端的配置结束,接下来pip安装mitmproxy,使用upstram模式转发流量到上流代{过}{滤}理服务器(即BP)即可。
    命令为:

    mitmdump --mode upstream:127.0.0.1:8080 --listen-port 8899 --ssl-insecure

    上面的mitmweb也可以改成mitmproxy 或mitmdump 主要是中间流量的表现形式不同。
    1.2 虚拟机、手机逃避代{过}{滤}理检测
    有时候直接使用系统的代{过}{滤}理会被APK检测到。有些APK的包使用了参数NO_PROXY,会绕过系统代{过}{滤}理发送,有些则会在检测到代{过}{滤}理的时候停止发包。
    目前知道的能够绕过代{过}{滤}理的工具有两个,HTTPDroid和lamda。lamda挂代{过}{滤}理参考上面的脚本,这个我测试过是可以绕过代{过}{滤}理检测的。HTTPDroid及其他基于iptables的工具据称在原理上是可以绕过的。
    但是HTTPDroid不能在夜神模拟器上安装。我的建议是普通模拟器上使用lamda,真机模拟器上使用HTTPDroid(因为lamda不能在真机模拟器上使用)或者真机宿主机安装小黄鸟(HTTPCanary)。
    1.3 真机虚拟机逃避代{过}{滤}理检测(真机虚拟机)
    有时候APK会校验用户所处的环境是否是真机,这个时候建议直接使用真机或在真机上安装虚拟机。这个原理跟反反爬虫是一样的:再多的掩饰都是虚的,程序员总能从你想不到的角度进行检测,所以最好直接在真机里做操作。比如安装真机虚拟机如VMOS。
    但是真机虚拟机是无法使用lamda的(实际的真机可以),用VMOS抓包的一个方式是代{过}{滤}理到宿主机的小黄鸟(HTTPCanary),导出.0证书,小黄鸟设置目标应用,虚拟机安装证书。
    也可以通过转换过的.0证书+模拟器挂代{过}{滤}理代{过}{滤}理到mitmproxy然后中转到burpsuite。一样的。
    3 证书与双向认证
    3.1 安装证书的小TIPS
    由于虚拟机可能不能直接装证书,即使有ROOT(具体为什么我不知道),只能将证书导出为.0格式然后复制到/system/etc/security/cacerts/下。
    cer、pem等格式的证书可以通过openssl转换为.0格式之后手动安装。
    命令为(pem与cer都是这个):

    openssl x509 -inform PEM -subject_hash_old -in mitmproxy-ca-cert.pem -out out.0

    3.2 证书校验绕过
    有时候,APK会这样:

    校验通信中证书的签发HOST。这种情况需要用户反编译找到hostname然后自行制作一个此hostname的证书。证书可以通过openssl生成。
    3.3 双向认证(双签)绕过
    双向认证,指的是APK与服务器各自有一个私钥,每次通信时,通信包会经过两次加密。或者换句话说,就是APK发送到服务器的包要被客户端证书签名,服务器发送到APK的包要被服务器证书签名(如果APK本身还设置了)。这就导致BP等使用的自签名证书不会被服务器端接受。
    SSL双向认证体系中,客户端与服务端各拥有一对证书和密钥,在通信过程中:
    (1)客户端建立通信,发送SSL版本等信息给服务端
    (2)服务端发送服务端证书给客户端,客户端会校验服务端的证书是否在许可范围内
    (3)客户端校验通过后,发送客户端证书给服务端,服务端也会校验客户端证书是否在许可范围内
    综上所述,要成功抓到经过双向签名的包,需要同时绕过客户端和服务端双端的认证。客户端的认证可以通过Xposed模块SSLUnpinning或者JustTrustMe绕过,而服务端认证则需要获得APK文件中的证书。
    反编译APK,找到APK中保存的客户端证书,还有它的密码。公私钥一般作为单独文件存储(也有APK直接写死在代码里,不过证书是有过期时间的,所以应该没什么APK会这么做),密钥则会写在代码里,需要反编译查找。

    如果代码未经混淆,直接搜索ClientKeyStore.load即可找到打开bks证书的语句,第二个参数即为密码,第一个参数为证书文件名。
    由于Android证书端的证书格式为bks,而BP需要的证书格式为p12,所以我们还需要转换证书的格式。下载portecle后转换证书的格式,然后在BP中导入即可抓到包:

    4 使用Drozer扫描Android本地漏洞
    drozer主要 用来查找androidAPK本身的漏洞,而非对应后端的漏洞。
    4.1 安装与启动
    下载地址:
    https://github.com/WithSecureLabs/drozer/releases
    需要先额外安装一个python2.7,再运行安装程序。如果环境中已经有其他版本的python了,请先看下节。
    在运行drozer.bat文件无报错后,我们开始配置手机端的agent和依赖。搜索python2文件夹下的apk文件,找到standard-agent.apk,将其装在手机上,然后打开APK,点击右下角的开启打开agent。adb方面转发端口,使用命令:

    .\adb.exe forward tcp:31415 tcp:31415

    然后电脑处使用命令:

    .\drozer.bat console connect

    运行成功应该如下:

    4.2 额外安装py2下的各种问题
    现在基本没人会使用py2编程了,所以很多人会先装py3。
    在4.1安装python2时,如果想将py2不冲突的放进环境变量里,可以将py2文件夹里的python.exe更名为python2.exe然后将路径放在PATH下(不像放在PATH也可以,后面的python2替换为绝对路径)。
    点击安装,选择之前安装的python2文件夹,进入\Scripts文件夹下,将drozer.bat文件中的python替换为python2再运行即可启动dozer。
    然后我们开始配置依赖。移动到pip2.exe所在的文件夹使用与平时使用pip相同的命令安装service_identity、twisted、pyopenssl、pyyaml、protobuf即可。
    有时候下载的py2里没有pip文件,需要在这里获取get-pip.py:
    https://bootstrap.pypa.io/pip/2.7/get-pip.py
    全文复制后保存为python文件,然后使用py2运行就行了。但是这样获取的pip有个问题就是没有能访问的镜像源,所以每次安装时带上选项,使用国内的镜像源即可:

    -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

    4.3 常见命令(dz控制台下)
    查看APK列表:

    run app.package.list

    -f 选项可以按照关键词查找APK。
    查看APK暴露的activity列表:

    run app.activity.info -a 包名

    拉起Activity:

    run app.activity.start --component 包名 活动名(activity)

    枚举Provider:

    run app.provider.info -a 包名

    SQL注入扫描:

    run scanner.provider.injection -a 包名

    5 插件框架
    这两个框架的模块安装方式都是一样的:模块本身就是一个APK,直接安装APK即会被识别。
    5.1 安装使用Magisk
    电脑端模拟器安装Magisk可以参照此文章:https://www.52pojie.cn/thread-1583586-1-1.html
    使用Magisk而不使用XPOSED的原因是Magisk对文件系统的破坏性小,且不需要事先ROOT,适用范围广一些。并且Magisk上可以集成Xposed。
    对于真机模拟器而言,已知光速模拟器可以安装Magisk,但是一般情况下需要付费VIP。VMOS据说安装之后并不好用,可能还是要用其自带的XPOSED。
    可以使用Magisk Manager 安装Magisk。安装后,如果Manager提示更新但一直下载失败,请打开设置换源为https://qianyegroup.gitee.io/magiskbuilds/updates/custom_md2.json。
    5.2 安装使用Xposed
    这是真机模拟器的不得已之选。使用VMOS PRO的虚拟机会自带一个XPOSED。
    6 使用Frida
    由于lamda中自带了frida,本节分为使用lamda与不使用lamda两种方式讲解(可惜不能兼容真机模拟器,不然是想默认使用lamda讲解的)
    6.1 安装
    Frida与Drozer一样,也是基于python的分布式框架。分为服务端与客户端两个。客户端(本机)使用pip安装:

    pip install frida
    pip install frida-tools
    pip install objection

    服务端(安装过lamda的手机不需要安装,也就是可以跳过下面的内容直接到使用部分)访问github页面选择下载:https://github.com/frida/frida/
    服务端和客户端的版本要一致,由于pip安装时会自动选择版本,我们这里以客户端版本为准。
    使用

    pip list | findstr frida

    查看frida的版本,adb命令行中使用

    getprop ro.product.cpu.abi

    获取架构,然后选择对应的frida-server,如:



    解压文件,adb push到/data/local/tmp,对frida-server-xxx文件chmod 777然后执行即可。
    6.1.1 lamda使用frida的适配
    以当前最新的lamda版本(3.150)为例。首先,需要运行命令:
    pip3 install -U --force-reinstall lamda[full]
    然后,确定frida版本为15.X,frida-tools为12.1.X。
    否则将会出现frida命令执行反复横跳,一会成功一会提示版本不匹配的问题。
    6.2 基础使用
    使用lamda中的frida与普通情况相似,但是需要在每一条frida命令下添加参数:-H 192.168.0.2:65000(ip请改成手机ip),而原生frida需要让adb转发frida端口出来:

    adb forward tcp:27043 tcp:27043
    adb forward tcp:27042 tcp:27042

    在已经连接adb的情况下,cmd使用:

    frida-ps -U

    来进行一个热身。这个命令显示的是手机进程列表。

    使用命令(如果程序太多,考虑使用frida-ps -Ua,它只会显示运行中APK)

    frida-ps -Uai

    获取当前运行所有APK的包名:

    进入frida-shell:

    frida -H 192.168.3.61:65000 -f com.busuu.android.enc


    6.2.1 lamda中frida的另一种使用方式
    即在python脚本中进行。我给一个示例代码:
    import lamda
    from lamda.client import *
    device=Device("192.168.3.61")
    fridar=device.frida
    #以下使用frida命令
    fridar.enumerate_processes() #一个示例,枚举进程
    如果追求动态使用的话,可以在python自己的shell中运行这些代码。
    7 使用Jadx进行反编译
    这个东西很容易安装,就不讲了。
    安装后直接将要反编译的apk文件拖进程序即可:

    对于APK中的dex文件,有些能反编译出来,有些不能。
    不过根据使用经验,还有一些额外的设置推荐赠送:
  • 首选项里打开反混淆,方便追踪方法
  • 如果要搜索被混淆过的、被编码的,反正很长的文件,最好复制出来在第三方编辑器中查找,不然很容易卡死
    7.1 先谈谈APK本身
    安卓应用说来说去其实就是基于google android框架下的一类代码打包成的可运行包。与web应用不同,这些包一般都经过了编译才能在目标平台运行(想象一下jar包,里面的代码就是从.java文件编译成了.class字节码,APK可以看做大号带资源的jar包),我们是没办法直接看到源代码的。
    用解压缩文件打开一个apk包可以看到其结构如下:

    如果读者做过android开发,可以发现apk的结构和它作为源代码的结构基本类似,只是明文代码变成了编译后的文件。
    我拿一个android工程的目录做例子,进行对比:

    assets文件、res文件、AndroidManifest.xml保持不变,java文件夹中的源代码包被放在主目录,META-INF文件夹为签名。多出来的文件为.dex文件与.arsc文件(如果此APK使用NPK开发,也就是调用了CPP代码,还会出现lib文件夹,下面放的是CPP的二进制文件.so)。前者为Android原生的可执行文件(当作安卓上的exe),后者为资源映射文件。
    7.2. Jadx+Frida 进行Hook
    最新版本中,可以右键选择函数,然后复制为frida片段(在反混淆开启时此选项生成的代码是错误的):

    不过我更推荐自己写。
    我们以函数getLevels为例(获取用户等级):

    先找到其类名和函数名。然后对照原函数写原始Hook(熟悉前端Hook的人不会陌生,因为原始Hook代码为JS):
    Java.perform(function(){ //当作主函数
    var Course=Java.use('com.busuu.android.api.course.model.ApiCourse'); //这句获取类
    Course.getLevels.implementation=function(){ //这里开始是Hook函数,前面的getLevels为要Hook的函数名
        console.log("Hook start");
        var level=this.getLevels(); //获取下返回值
        console.log(level.toString());
        return level; //返回函数执行结果,否则这就不是一个纯正的Hook了
    }
    })
    然后我们再写一个python脚本,使frida挂上Hook:
    import frida,sys

    appPacknName = "com.busuu.android.enc" #请填写对应要调试APK的包名
    scriptFile = "1.js" #JS文件名
    HOST="192.168.3.61:65000" #frida 位置
    输出日志的回调方法
    def on_message(message, data):
    if message['type'] == 'send':
    print(" {0}".format(message['payload']))
    else:
    print(message)
    manager = frida.get_device_manager()
    device = manager.add_remote_device(HOST)
    spawn模式,找到目标包名并重启,在启动前注入脚本
    pid = device.spawn([appPacknName])
    session = device.attach(pid)
    device.resume(pid) #以上两行的顺序不能错
    with open(scriptFile, encoding='UTF-8') as f :
    script = session.create_script(f.read())
    script.on("message", on_message)
    script.load()   #把js代码注入到目标应用中
    设置一直监听
    sys.stdin.read()
    运行此脚本,frida会自动重启APK并挂上Hook。执行效果如下:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681206175077-fd94df56-8b0e-4b30-b0c4-382f35650258.png#averageHue=%23010101&clientId=u1f85cc59-315a-4&from=paste&height=99&id=u7017dc6e&originHeight=99&originWidth=485&originalType=binary&ratio=1&rotation=0&showTitle=false&size=2399&status=done&style=none&taskId=ua0237936-ac94-400e-9344-61741f73f12&title=&width=485)
    ## 7.3 Jadx远程调试
    由于我这里用的夜神模拟器有个一直占用端口的adb,Jadx基于adb的远程动态调试暂时不可用。
    # 8 使用apktool解包、修改、重新打包、签名APK
    在进行动态调试之前,我们要先判断APK是否允许调试。如果APK不允许调试,我们就需要反编译解包APK,修改其中的AndroidManifest.xml文件并重新打包签名。
    另外一些情况中,我们也需要通过修改APK的代码达到绕过校验等目的。
    我们以第一种情况为例,下载apktool,这是Android官方的工具,下载方式应该很简单。
    ## 8.1 解包修改文件并重新打包
    使用命令
    > java -jar .\apktool_2.7.0.jar d -f C:\Users\HONOR\Desktop\bosuu2501.apk
    对APK进行反编译:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681284423897-8ec91aa7-cdee-4c20-af6c-60cb8ce6f0c3.png#averageHue=%23010101&clientId=u1f85cc59-315a-4&from=paste&height=302&id=ub999c1d9&originHeight=302&originWidth=983&originalType=binary&ratio=1&rotation=0&showTitle=false&size=14337&status=done&style=none&taskId=u90b4768c-2a91-42c5-9e8d-75eacac73de&title=&width=983)
    编译完成后,切入文件夹,找到AndroidManifest.xml,修改:
    在application标签里(理论上只会有一个这种标签)加上android:debuggable=“true”,然后保存:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681284821824-ebcab80f-36eb-42e3-88b3-1b8c1b481203.png#averageHue=%238c684a&clientId=u1f85cc59-315a-4&from=paste&height=1048&id=u768c7553&originHeight=1048&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=415710&status=done&style=none&taskId=u3d458213-fde2-419a-9e99-74fa22b63dd&title=&width=1920)
    然后继续使用apktool
    > java -jar .\apktool_2.7.0.jar b .\bosuu2501\
    将APK文件夹进行打包:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681285181692-75766e4b-0f81-4d1b-a7d8-5f3b46a600f3.png#averageHue=%23000000&clientId=u1f85cc59-315a-4&from=paste&height=340&id=ua0f30776&originHeight=340&originWidth=749&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13795&status=done&style=none&taskId=uf088aba8-e0de-4656-bc95-ab8f492f40e&title=&width=749)
    ## 8.2 签名
    之前我们说过,APK包里会有一个META-INF文件夹用于签名。APK在运行时,安卓会先对APK的签名进行校验,所以我们需要将修改过的APK重新签名使其通过校验。
    签名的话,方式有很多种,可以使用Android官方的工具jarsigner,也可以使用MT管理器等APK。
    考虑到使用jarsigner的传统艺能是打一大段命令行,这里就直接使用MT管理器进行签名。adb push打包后的apk文件到手机中,打开MT管理器,切到目录下,长按文件,选择签名即可:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681286438244-9b0afdc3-b343-48d7-8c7f-e2ba80dfc329.png#averageHue=%23d9d8d8&clientId=u1f85cc59-315a-4&from=paste&height=1020&id=u134152ae&originHeight=1020&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=146594&status=done&style=none&taskId=u0c730ba6-6bbe-4d59-9b3d-b060cc7fe16&title=&width=596)
    签名后,会出现一个相同名字后缀为_sign的apk文件,直接安装此文件,成功。
    # 9 使用JEB进行反编译与远程调试
    不推荐单独使用JEB进行反编译,因为它初始给出的代码为Smali。
    同时,JEB也挺容易卡的,可以在它的根目录下创建jvmopt.txt文件并输入参数-Xmx8G以提高其运行内存。
    ## 9.1 使用JEB对照查看Java代码与Smali代码
    直接使用JEB打开APK文件,在文件树中选择要查看的JAVA类,右键选择解析:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681268832407-3b0458a0-3c61-4922-a22f-45b746e537f4.png#averageHue=%23f0eeed&clientId=u1f85cc59-315a-4&from=paste&height=752&id=ud15f2f4a&originHeight=752&originWidth=600&originalType=binary&ratio=1&rotation=0&showTitle=false&size=82400&status=done&style=none&taskId=u11fd2233-6109-4886-81a6-768453f98d8&title=&width=600)
    以打开Java代码。然后在选中行中右键再次点击解析,会定位到其Smali代码:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681268943333-72f7bede-4474-479a-a8f5-d59d56ea319c.png#averageHue=%23f4f2f1&clientId=u1f85cc59-315a-4&from=paste&height=1048&id=ua69c570d&originHeight=1048&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=233720&status=done&style=none&taskId=uff097eed-229a-4622-b387-e9db62d8c4b&title=&width=1920)
    ## 9.2 使用JEB对APK进行动态调试
    使用动态调试之前,需要确保以下几点:
    - adb已经连接上手机
    - 手机打开了USB调试
    - 手机的USB调试中指定调试APK为目标,并打开“等待调试程序”
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681287071550-7a3db90e-75ff-4c6e-926a-eff7f4a837be.png#averageHue=%23f3efef&clientId=u1f85cc59-315a-4&from=paste&height=662&id=u70383d24&originHeight=662&originWidth=575&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84114&status=done&style=none&taskId=uaf13d323-4269-4eeb-8a7a-162bca33ab5&title=&width=575)
    如果在选择调试应用中没有调试目标,需要考虑APK没有打开允许调试的选项。
    如果APK附加进程后直接闪退,请使用最后修改打包签名后的APK进行反编译(也就是说,最后你在手机上运行的是什么APK就要用什么APK进行反编译)。
    如果附加进程后一直卡在链接窗口,关闭USB调试试试。
    将待调试的Smali语句Ctrl+B打上断点,然后按右上角小BUG打开调试窗口,手机打开目标APK,JEB选择设备和进程,点击附加开始动态调试。
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681291155791-9cf89076-6e46-42a4-ba48-cd9bfa85e209.png#averageHue=%23f3efee&clientId=u1f85cc59-315a-4&from=paste&height=935&id=u8c0edf15&originHeight=935&originWidth=1186&originalType=binary&ratio=1&rotation=0&showTitle=false&size=135915&status=done&style=none&taskId=uc3a34e08-6730-4f2a-8445-4ce4037c438&title=&width=1186)
    调试成功,可以看到已经在断点处停下:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681350194091-bbb42951-3624-4690-a998-8eea84a07da0.png#averageHue=%23b1b685&clientId=ua02b84a8-af5e-4&from=paste&height=1048&id=u3f9f55d8&originHeight=1048&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=221179&status=done&style=none&taskId=ue3d00c9a-9a16-4fd3-8f16-4f907a64972&title=&width=1920)
    # 10 脱壳
    本章节涉及具体技术原理请参考:
    - [https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458457914&idx=1&sn=1d505597b47089cbd8bdc1e6e0a2b068&chksm=b18e27b086f9aea63d4404f118b0dc4c0b87c5986f20e556a5a85c967834df0d7f3e8e6d98d6&scene=27](https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458457914&idx=1&sn=1d505597b47089cbd8bdc1e6e0a2b068&chksm=b18e27b086f9aea63d4404f118b0dc4c0b87c5986f20e556a5a85c967834df0d7f3e8e6d98d6&scene=27)
    APK壳的原理其实不难理解,我们可以理解为另一种对源代码的混淆和加密。
    具体的来说,就是通过替换APK运行过程中的dex文件加载器为自定义的加载器以读取dex文件,这样做开发者就可以额外对dex文件进行加密。目前APK加壳技术有dex整体加密、函数抽取、VMP加壳等类型。有些壳每次都会读取整个dex文件,这种比较容易脱壳;有些壳是分段读取的,或者使用了更复杂的技术,就需要进一步的调试。
    ## 10.1 识别APK是否加壳
    有些壳可以直接通过工具识别出来,有些自定义壳需要自己看代码识别。
    ### 10.1.1 工具识别APK是否加壳
    使用APK Messenger或者在线平台摸瓜、南明离火,手机端的MT管理器可以识别出一些壳来。直接用工具打开即可。
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681353691653-e4f8276f-bf7e-4ee2-9bc4-eee27c0e0b97.png#averageHue=%23cfcfcf&clientId=ua02b84a8-af5e-4&from=paste&height=228&id=u92140c1a&originHeight=228&originWidth=503&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12313&status=done&style=none&taskId=ud0c111df-d64c-45ba-83a2-ccd878d4080&title=&width=503)
    ### 10.1.2 查看反编译代码判断APK是否加壳
    下面给出一些可以用来识别APK是否加壳的TIPS,不一定准确。
    - 如果dex文件中的自定义函数(非ANDROID自带)不是JAVA函数而是Native函数,这个APK可能使用了VMP/Dex2C加壳
    - 如果dex文件并不完整,关键类和函数的代码是空的(函数return null,查看smali代码一片nop),这个APK可能使用了函数抽取加壳
    - 可以查看资源文件->lib中的so文件文件名是否是已知的加壳读取器文件名
    - 如果APK看上去不像需要使用NPK技术(调用CPP,大多数情况下是调用底层方法),却带有.so文件,大概率使用了壳
    ## 10.2 ⭐腾讯乐固(御安全)简单脱壳修复并重新打包
    以下文章里有八中常见壳的脱修教程,本节的乐固脱壳步骤参考的就是此文:[https://www.52pojie.cn/thread-1453091-1-1.html](https://www.52pojie.cn/thread-1453091-1-1.html)
    Dex整体加固脱壳修复打包示范,以安全家3.8.9为例,使用GDA检测可以看到为乐固:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681440642402-6b182abd-683a-4532-aa1f-6f379b683cb9.png#averageHue=%23f5fafd&clientId=u59f98cda-4554-4&from=paste&height=474&id=ud284369a&originHeight=474&originWidth=671&originalType=binary&ratio=1&rotation=0&showTitle=false&size=49104&status=done&style=none&taskId=ue764104d-e879-4546-909f-f889bc73d12&title=&width=671)
    已知壳如果能脱下来,那么详细的脱壳步骤就是**使用工具脱壳->替换、删除dex文件->用脱下来dex文件的入口修改AndroidManifest.xml文件->修复dex->重新打包->签名**。
    ### 10.2.1 脱出dex文件并删改、修复
    使用工具为BlackDex,请注意此APK分位数版本,需要按照手机位数下载32位或64位。
    打开工具,直接选择APK自动脱壳:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681375222324-a54570aa-3831-46ab-a1db-29f46ece905a.png#averageHue=%237c7c7c&clientId=ua02b84a8-af5e-4&from=paste&height=1020&id=u5976c8dd&originHeight=1020&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=85250&status=done&style=none&taskId=ufaf14536-b848-4307-a3f6-f9e0b0741ad&title=&width=596)
    脱出来了四个dex文件:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681440838646-36b6810a-7c52-4210-a5dc-b4d0ce7e3225.png#averageHue=%232a2928&clientId=u59f98cda-4554-4&from=paste&height=167&id=u1675aafe&originHeight=167&originWidth=697&originalType=binary&ratio=1&rotation=0&showTitle=false&size=20264&status=done&style=none&taskId=ub1e22faa-4f55-4408-b8c6-9c46898f3af&title=&width=697)
    将APK用解压缩软件打开,对比两边的dex文件大小:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681440880345-2e465cdc-3a8c-42b0-9294-679175164517.png#averageHue=%23787776&clientId=u59f98cda-4554-4&from=paste&height=668&id=ud4f293e3&originHeight=668&originWidth=1904&originalType=binary&ratio=1&rotation=0&showTitle=false&size=171942&status=done&style=none&taskId=uea423b9a-3ad3-4955-ad8c-4c7817149a3&title=&width=1904)
    可以看到有两个dex文件与原始dex大小相同,删去这两个dex。
    剩下的dex留个备份,然后用NP管理器打开进行dex文件修复,选择全部修复:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681436996892-68726ccb-39f8-4749-8fca-7c512932429a.png#averageHue=%23888888&clientId=u59f98cda-4554-4&from=paste&height=1020&id=EIS5C&originHeight=1020&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=112433&status=done&style=none&taskId=u414e1f4b-513f-4456-8722-2bdd2ca9326&title=&width=596)
    ### 10.2.2 查找真实入口并进行替换
    gda打开或使用baksmali(前者是国人写的软件,后者貌似是什么官方工具,都很容易下载)反编译dex文件**(指的是原dex文件,不是脱下来的)**,然后查找真实appname。
    这里使用backsmali,命令为 java -jar .\baksmali-2.5.2.jar d .\cookie_3561024.dex。
    全局搜索.field static className:Ljava/lang/String;找到对应的字段(这个需要搜索的字段每个加固是不一样的,毕竟加固相当于自定义读取器,每个厂家代码不同):
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681435267476-129e267b-37df-4246-8a6e-ef0d58112d5e.png#averageHue=%2395724c&clientId=u59f98cda-4554-4&from=paste&height=398&id=acitn&originHeight=398&originWidth=1907&originalType=binary&ratio=1&rotation=0&showTitle=false&size=91926&status=done&style=none&taskId=u405beb53-e611-420d-8563-929191aa3f8&title=&width=1907)
    向下看,找到赋值部分:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681439911517-dd6eb7a0-4f9b-414b-aec0-8bdabc538b52.png#averageHue=%23201e1e&clientId=u59f98cda-4554-4&from=paste&height=635&id=ZYVrO&originHeight=635&originWidth=1252&originalType=binary&ratio=1&rotation=0&showTitle=false&size=60980&status=done&style=none&taskId=u4f3b3bf5-614f-40ec-a5b9-c2b7ee86ef8&title=&width=1252)
    可以看到值为com.nursinghome.monitor.base.MyApp,这就是APK的真实入口名。
    电脑端使用apktool对apk进行反编译(命令参考上面章节),得到smali源码文件夹。
    在文件夹中找到AndroidManifest.xml文件,找到application元素的android:name字段,替换为刚才找到的值:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681437934210-6b751fc6-0bbd-4c61-a712-ecdea17224db.png#averageHue=%23262221&clientId=u59f98cda-4554-4&from=paste&height=144&id=u9c9d7a0a&originHeight=144&originWidth=1431&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42918&status=done&style=none&taskId=ub36f71a4-19af-4be4-819c-afed9893a19&title=&width=1431)
    ### 10.2.3 重新编译APK并删除加固文件、替换dex
    替换完成后,保存文件,使用apktool重新编译:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681441280037-63b8469a-cfeb-4b0e-bc93-a8b871d2ed7e.png#averageHue=%23000000&clientId=u59f98cda-4554-4&from=paste&height=149&id=ub25a9b34&originHeight=149&originWidth=618&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5712&status=done&style=none&taskId=uc1a07510-088a-4ad8-beb9-5ebaf4859e4&title=&width=618)
    然后用解压缩软件打开编译后的APK文件,查找并删除以下文件:
    - 0O等类似开头长得很混乱的文件,如0OO00l111l1l
    - tencent_stub
    - tosversion
    - 其他名字中带有shell的文件(主要是so文件)
    然后,删除根目录下的classes{n}.dex文件,放入第一步中修复好的dex文件并将它们重命名为classes{n}.dex。
    ### 10.2.4 重新签名,安装
    跟第八节中的步骤一样。打开NP管理器,选择APK文件,可以看到加固已经没有了,但是显示校验不通过。
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681441579974-921b0fd3-6f1f-4c94-a7e3-bd72ad2b34ef.png#averageHue=%23d5d4d3&clientId=u59f98cda-4554-4&from=paste&height=422&id=u4e691af3&originHeight=422&originWidth=545&originalType=binary&ratio=1&rotation=0&showTitle=false&size=49320&status=done&style=none&taskId=uc906d2f5-f6f3-4567-85cb-8abc3d9b86a&title=&width=545)
    点击功能,选择签名然后安装签名后的APK即可:
    ![image.png](https://cdn.nlark.com/yuque/0/2023/png/32358243/1681440439215-021f7549-0f70-479e-a83a-1d783bc4eecb.png#averageHue=%237b7876&clientId=u59f98cda-4554-4&from=paste&height=1020&id=ub3124c75&originHeight=1020&originWidth=596&originalType=binary&ratio=1&rotation=0&showTitle=false&size=129866&status=done&style=none&taskId=ue4fbcae5-7b2d-4e23-9e08-b321950d9b0&title=&width=596)

    文件, 证书

  • WXjzc   

    图片盗链无法显示,上传论坛本地吧,还有不要用分页影响阅读,最后文章底部的内容格式好像也搞错了。
    Appoint   

    倒是希望论坛能出一个和博客园一样的提取图片的功能,不然编辑一个图片多的文档太麻烦了
    bindat   

    开眼l,感谢分享!
    janken   

    有的图不显示,感觉像看打码作品!!!
    lxyi   

    过来看看
    beautiful008   

    先保存一下,谢谢分享
    evill   

    第一篇看完,期待第二篇ing
    www12x2   

    感谢分享,就是图片应该是防盗链加载不出来
    ArEmper   

    先mark,最近正好在学逆向,先收藏一手
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部