安卓逆向学习2-APP攻防01

查看 132|回复 10
作者:Juana111   
2.1APK结构
apk本质是一个zip压缩文件,可以通过打开压缩包的形式打开apk文件。


1.PNG (41.39 KB, 下载次数: 2)
下载附件
2024-8-8 10:05 上传

.dex文件
除了源文件与资源文件之外,可以发现.dex文件,是逆向分析的核心文件。
Tip: .dex文件是Android系统虚拟机的可执行文件,是Java文件夹中所有Java类编译的二进制文件,存储apk整体业务逻辑的核心。一般是将.dex文件反编译为smali语言【Android虚拟机的汇编语言】的文件。
其他文件
其他文件一把梭!
assets文件夹:配置文件,包含非xml的静态资源文件,音频、字体、html这些文件;
lib文件夹:应用程序的本地链接库目录(.so文件),存放与特定硬件架构相关的本地库文件,下图文件包括armeabi-v7a【通用所有Android设备】和x86【Android模拟器】,一般会存在,下图lib文件在assets文件夹中;


2.PNG (8.38 KB, 下载次数: 2)
下载附件
2024-8-8 10:05 上传

kotlin文件夹:kotlin编程语言开发的源文件,Android官方开发语言,与Java兼容;
META-INF文件夹:存储apk程序的签名信息,用做校验计算存储计算结果,保证包的文件不被替换;
okhttps3文件夹:处理网络请求的框架,使用Get\Post请求,上传下载文件等功能;
org文件夹:不了解,查看文件有关于Antlr的,百度了下是一个语法分析器生成器。嗯,暂时不重要;
res/raw文件夹:xml、json、txt、图片文件这些文件的存储。
AndroidManifest.xml文件:配置清单文件,编译自动生成的文件,在安装时会读取该文件确定应用的基本信息和权限要求。文件中包括包名、应用名、权限、安卓四大组件、版本等信息的声明。学到的方法是通过资源文件中的AndroidManifest.xml文件中的四大组件标签【activity/service/receiver/provider】标识来找到app包名(进程的唯一标志)。通过标签内容定位app入口类。
[XML] 纯文本查看 复制代码
               
               

resources.arsc文件:资源索引表,用来描述具有ID值的资源的配置信息。再使用反编译工具查看,主要是源代码与资源文件两种。


3.PNG (13.13 KB, 下载次数: 2)
下载附件
2024-8-8 10:05 上传

2.2安卓加固
预告:安卓安全相关手段
代码混淆手段:更改类名、函数名、变量名,实现两种结果。一是符号混淆:将有意义的类名或者函数名改为a,b,c这种没有意义的名称,破解人员看不懂,增加破解难度;二是压缩文件大小。代码混淆中又包括了字符串加密、花指令和资源加密等。
动态加载方案:将保护的代码单独编译,加密后保存在外部二进制文件中,常见的是将程序的业务逻辑放置在.so文件中。使用动态分析的手段破解程序,在加载后的函数中设置断点dump内存,找到真实的dex文件,具体是通过注入将指令代码和数据注入到目标进程,对目标进程进行调试和内存监控。
正片:安卓加固手段
  • DEX加固:对dex整体加固,将dex整体加密后动态加载。-->先解密文件并在解密完成后写入到另一个文件,解密完调用加载函数来加载解密后文件。-->加密的dex文件在内存中解密并直接在内存中加载。
  • 代码抽取保护:利用私有函数,通过对进程的hook拦截函数调用路径,在函数真实调用前使用nop代码数据填充。-->存在兼容性和性能损耗问题。
  • VMP和DEX2C:VMP-->java代码变成Native层代码,找到与系统解释器的映射关系;DEX2C-->java代码转为Native层代码,native的二进制编码(C/C++)比Java字节码更难。
  • OLLVM保护native层:编写PASS控制中间代码混淆,实现平坦化。
    2.3app分析与破解
    2.3.1未加固app进行分析破解
    目的:使用Objection对未加固应用包中的弹窗进行快速定位操作,并去掉弹窗
    实验工具:
    "
    具体操作:第一步:先在adb中安装apk文件:
    [Shell] 纯文本查看 复制代码adb install XXX.apk
    这里遇到问题有两个
  • adb.exe: more than one device/emulator

      Xxxx offline 检查是不是开了多个设备或者模拟器使用命令:

    [Shell] 纯文本查看 复制代码adb devices
    ##解决方式
    ##adb -s emulator-5554 shell
    ##adb kill-server
    ##adb start-server
  • adb: failed to install zhibo.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install com.hd.zhibo without first uninstalling.]

    安装apk之前,设备上已经安装过了一个版本,再次安装会安装失败。

    [Shell] 纯文本查看 复制代码##解决方式 -r覆盖安装
    adb install -r XXX.apk
    第二步:在adb启动frida-server,执行命令如下
    [Shell] 纯文本查看 复制代码D:\CTF_Tools\APK_Tools\adb>adb shell
    aosp:/ # su
    aosp:/ # cd /data/local/tmp/
    aosp:/data/local/tmp # ./fs
    另外起一个cmd,objection注入
    [Shell] 纯文本查看 复制代码D:\CTF_Tools\APK_Tools\adb>objection -g com.hd.zhibo explore


    4.png (80.31 KB, 下载次数: 2)
    下载附件
    2024-8-8 10:05 上传

    成功之后就像图中这样,这里尝试了用不同机型来启动,发现只有xiaomi不报错,牛批!这里遇到的问题比较多
  • 电脑重新安装过,之前的frida版本乱乱的,总体还是遗留了之前和朋友打比赛复现的环境,重新将frida-server push到adb中

    [Shell] 纯文本查看 复制代码adb.exe push frida-server /data/local/tmp
    ##push 文件名 文件位置
  • objection安装

      直接在python中安装frida和objection的包,直接使用cmd会发现报错,就直接在pycharm中进行了package的安装,一种蛮快捷的方式!
    对反编译之后的apk进行文本的搜索,找到弹窗调用的类名,使用命令
    [Shell] 纯文本查看 复制代码android heap search instances android.app.AlertDialog


    5.png (21.77 KB, 下载次数: 2)
    下载附件
    2024-8-8 10:05 上传

    跑出来的效果太亏贼了,需要进一步了解弹窗类的类型,大概先了解操作,笔者又使用了ubuntu和真机测试,发现又出现了一系列问题,等到后面重新解决。这里还推荐了一个插件Wallbreaker,在github可以搜到,等后面换设备再重新搭建。
    使用命令对AlterDialog类进行hook来去欸的那个调用弹窗的函数。
    [Shell] 纯文本查看 复制代码objection -g com.hd.zhibo explore -s "android hooking watch class android.app.AlertDialog"


    6.png (643.59 KB, 下载次数: 1)
    下载附件
    2024-8-8 10:05 上传

    确定被调用函数后,选取其中一个再进行hook来确定提示弹窗中在app下的函数,这里选定activity启动调用的第一个函数OnCreat()进行hook并打印调用栈。
    手动关闭app之后输入命令:
    [Shell] 纯文本查看 复制代码objection -g com.hd.zhibo explore -s "android hooking watch class_method android.app.AlertDialog.OnCreate --dump-args --dump-backtrace --dump-return"
    确定app弹窗的创建函数com.zhibo.media.channel_main.update_show(),用jadx具体查看函数的内容。
    [Shell] 纯文本查看 复制代码public void update_show(Bundle bundle) {
            if (bundle != null && bundle.containsKey("ver") && bundle.containsKey("info") && bundle.containsKey("path")) {
                new AlertDialog.Builder(this).setTitle("发现新版本 " + bundle.getString("ver") + " 是否升级").setMessage(bundle.getString("info")).setPositiveButton("立刻升级", new DialogInterface$OnClickListenerC0971o(this, bundle)).show();
            }
        }
    根据外面的if条件判断,不再弹出弹窗就需要修改对应的判断语句重新打包app。使用apktool命令对app进行反编译
    [Shell] 纯文本查看 复制代码apktool_2.8.0.jar d D:\CTF_Tools\APK_Tools\adb\zhibo.apk
    新获得一个同名的文件夹,使用android stdio打开文件夹。找到channel_main类中对应的smali文件以及update_show()函数在的文件中的位置。【对代码进行注释解释】
    [Shell] 纯文本查看 复制代码.method public update_show(Landroid/os/Bundle;)V
    ##.method定义updata_show这个方法
        .locals 3
        ##本地寄存器的个数
        if-eqz p1, :cond_0
        ##p1寄存器 p开头--->参数寄存器
        ##equals zero,p1寄存器等于0则跳转到:cond_0处
        ##nez not equals zero
        const-string v0, "ver"
        ##v0寄存器 v开头--->本地寄存器
       
        invoke-virtual {p1, v0}, Landroid/os/Bundle;->containsKey(Ljava/lang/String;)Z
        ##方法调用 {参数},方法所属类的包路径->方法名(参数类型)方法返回值类型【Z:boolean】
       
        move-result v0
        ##将上一个方法调用的结果值移到v0
       
        if-eqz v0, :cond_0
        const-string v0, "info"
        invoke-virtual {p1, v0}, Landroid/os/Bundle;->containsKey(Ljava/lang/String;)Z
        move-result v0
       
        if-eqz v0, :cond_0
        const-string v0, "path"
        invoke-virtual {p1, v0}, Landroid/os/Bundle;->containsKey(Ljava/lang/String;)Z
        move-result v0
        if-eqz v0, :cond_0
        new-instance v0, Landroid/app/AlertDialog$Builder;
        invoke-direct {v0, p0}, Landroid/app/AlertDialog$Builder;->(Landroid/content/Context;)V
        ##方法构造【V:void】
       
        new-instance v1, Ljava/lang/StringBuilder;
        const-string v2, "\u53d1\u73b0\u65b0\u7248\u672c "
        invoke-direct {v1, v2}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V
        const-string v2, "ver"
        invoke-virtual {p1, v2}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
        ##【Lpackage/name/ObjectName格式-->Ljava/lang/String:String-->对象数组】
       
        move-result-object v2
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
        move-result-object v1
        const-string v2, " \u662f\u5426\u5347\u7ea7"
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
        move-result-object v1
        invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
        move-result-object v1
        invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;->setTitle(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;
        move-result-object v0
        const-string v1, "info"
        invoke-virtual {p1, v1}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
        move-result-object v1
        invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;->setMessage(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;
        move-result-object v0
        const-string v1, "\u7acb\u523b\u5347\u7ea7"
        new-instance v2, Lcom/zhibo/media/o;
        invoke-direct {v2, p0, p1}, Lcom/zhibo/media/o;->(Lcom/zhibo/media/channel_main;Landroid/os/Bundle;)V
        invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;->setPositiveButton(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;
        move-result-object v0
        invoke-virtual {v0}, Landroid/app/AlertDialog$Builder;->show()Landroid/app/AlertDialog;
        :cond_0
        return-void
    .end method
    ##定义方法结束
    这里是直接在第一个if判断那里的eqz(等于0跳转),改为nez(不等于0跳转)。使用打包命令对修改后的app重新打包,在dist文件下生成一个未作签名的out.apk文件。
    [Shell] 纯文本查看 复制代码apktool_2.8.0.jar b zhibo


    7.png (111.78 KB, 下载次数: 2)
    下载附件
    2024-8-8 10:05 上传

    最后生成的apk是在目录的dist文件下,由于修改后缺少对应的app签名,这里需要使用签名工具生成签名文件对新打包的apk进行签名。这里使用的是自带的签名工具,也可以选择其他的工具。使用的两条命令:[Shell] 纯文本查看 复制代码keytool -genkey -alias new_zhibo.keystore -keyalg RSA -validity 2000 -keystore /home/juana-2u/Software/zhibo/dist/new_zhibo.key
    ##生成签名文件
    ##-genkey 生成证书
    ##-alias 证书别名,包名
    ##-keyalg RSA 签名文件使用的加密类型
    ##-validity 签名有效期2000days
    ##-keystore 签名文件生成的路径


    8、.png (127.19 KB, 下载次数: 1)
    下载附件
    2024-8-8 10:05 上传

    [Shell] 纯文本查看 复制代码jarsigner -verbose -keystore new_zhibo.key -signedjar zhibo_patch.apk out.apk new_zhibo.keystore
    ##生成patch之后的apk文件
    ##jarsigner -verbose -keystore [签名秘钥文件路径] -signerjar [签名后apk的文件路径] [未签名apk的文件路径] [证书别名]


    9.png (207.32 KB, 下载次数: 1)
    下载附件
    2024-8-8 10:05 上传

    2.3.2对加固app进行分析破解
    目的:使用Objection对加固后应用包中的弹窗进行快速定位操作,并去掉弹窗
    实验工具:
    "
    具体操作:
    apk启动不了,直接反编译来看了,与上面的未加固app的分析步骤类似。对弹窗类进行hook判断具体实现的弹窗类名,使用watch class的方式hook弹窗类,根据函数的被调用记录判断类是否被使用。前面都是差不多的,点击对应的弹窗位置或者操作,objection都会返回被调用的函数,与下图类似。


    10.png (44.41 KB, 下载次数: 2)
    下载附件
    2024-8-8 10:05 上传

    确定样本中升级提示弹窗的实现类对setCancelate(boolean)函数进行hook,根据调用栈发现app中发起弹窗的函数这样。
    重点是加固的部分的处理。总结如下两点
  • 对加固的dex进行脱壳处理,app的dex要替换壳的dex
  • 修改app的入口点:加固后的入口点只是壳的入口点,即在重打包时要在配置AndroidManifest.xml文件中修改入口类。
    第一步:对dex脱壳
    用jadx打开apk文件,与上面的非加固的apk不一样,加固之后的apk只显示了外部壳的类信息。


    11.png (41.78 KB, 下载次数: 1)
    下载附件
    2024-8-8 10:05 上传

    使用frida-dexdump,github地址:https://github.com/hluwa/frida-dexdump,需要在frida-server调试的同时进行脱壳。
    这里的插件安装存在问题,windows上直接安装不了,使用pip安装出现一排? 安装失败ubuntu安装好了,看资料需要在apk运行的条件下进行dexdump【?】准备再研究一下继续复现这一块。
    彩蛋:来填上期留下的Objection的坑!
    2.4Objection简单介绍
    1. objection是什么
    Objection是基于Firda的一个工具。利用Frida(安卓逆向的一种Hook框架)提供各种api实现安卓逆向分析的具体功能,Objection是集合体,同时支持android和IOS两大平台。完成任务:内存搜索、类和模块搜索、方法Hook、打印参数、打印返回值、调用栈等功能(内存漫游+逆向分析),依托Frida完成对应用注入和对函数的hook模板使用:填充具体的类完成Hook测试
    2.objection三大组成部分:
  • Objection重打包的组件:完成Frida无root调试,重打包Frida运行需要的firda-gadget.so文件
  • Objection本身的pypi包:和包含firda-gadget.so文件的app交互,运行hook脚本,分析hook结果
  • Objection编译的agent.js文件:【TypeScript】项目,在app运行中插入了Frida的运行库

    参考资料:
    《安卓Frida逆向与抓包实战》陈佳林
    附件地址:https://github.com/r0ysue/AndroidFridaBeginnersBook
    笔者复现附件地址:https://github.com/Juana-2u/Android_Study_demo

    文件, 代码

  • ltgb   

    xiaomi?牛批!
    Juana111
    OP
      


    h1989 发表于 2024-8-15 11:13
    请问大佬,某软件查题,不论mt什么反混淆,都无法查到兑换码、会员、vip等字眼,这是什么原因呢?

    会不会是进行了类似加密的方式将文本格式转成了其他格式 试试触发带有这些字眼的操作进行抓包呢
    acg7878   

    好有用,学习了
    wenmingziyou   

    感谢分享,学习了
    luohuhai688   

    学习了,感谢分享!
    shimeiyangwei   

    介绍详细,回头学学
    wangyuyan   

    感谢 学习了
    amwquhwqas128   

    非常感谢详细内容的文章
    kennygui   

    刚从ios切换到安卓,正好对这块内容感兴趣,感谢分享
    您需要登录后才可以回帖 登录 | 立即注册