一些APP渗透测试时的小tips

举报
亿人安全 发表于 2024/07/30 19:04:07 2024/07/30
【摘要】 朋友们现在只对常读和星标的公众号才展示大图推送,建议大家把“亿人安全“设为星标”,否则可能就看不到了啦原文首发在先知社区https://xz.aliyun.com/t/14648绕过APP强制更新我们在拿到一些APP老版本的时候,可能会要求我们进行更新,有时候我们不更新,它的接口也是可以使用的,但是它会弹出更新框,盖住了APP,使我们无法进行操作,所以我们这时候需要绕过APP的强制更新如何绕...

朋友们现在只对常读和星标的公众号才展示大图推送,建议大家把“亿人安全设为星标”,否则可能就看不到了啦


原文首发在先知社区

https://xz.aliyun.com/t/14648


绕过APP强制更新
我们在拿到一些APP老版本的时候,可能会要求我们进行更新,有时候我们不更新,它的接口也是可以使用的,但是它会弹出更新框,盖住了APP,使我们无法进行操作,所以我们这时候需要绕过APP的强制更新

图片


如何绕过强制更新
一般绕过强制更新有两种方法:
1、某些app启动向后端发送请求,获取APP的最新版本号,跟本地版本号做笔记,如果两个版本差距过大就会强制弹出窗,要求用户进行更新,但是他的弹窗代码在首页,只要切换到别的页面,这个弹窗就没了。对于这种形式的弹窗只需断开WiFi,进入app,然后连接WiFi,就可以绕过了。
2、第二种就是断网也绕不过的,只要联网,在任意一个界面都会弹出,这是我们可以通过反编译,找到弹窗位置进行hook

  • 通过hook进行绕过
    反编译APP

图片

搜索:最新版本,只搜索到一个结果,双击进入,可以看出如果后端查到的版本高,就会弹出窗强制要求更新,只要执行updateDialog.show();就会弹窗,所以我们需要去hook这个方法,让他不运行

图片


后面就要启动frida,然后进行端口转发

adb shell
su
cd /data/local/tmp/
ls
./frida-server-16.1.7-an

import subprocess 
subprocess.getoutput("adb forward tcp:27042 tcp:27042")
subprocess.getoutput("adb forward tcp:27043 tcp:27043")

使用spawn方案

图片


但是这时会发现只要运行hook脚本,APP就闪退了,这是因为做了frida反调试,那我们此时就要绕过frida反调试了,这就是下面要介绍的如何绕过frida反调试。


绕过frida反调试


  • 方案一
    有些公司,安全部门的人员,会通过编写 so文件,检测frida是否在运行,如果运行,就自动终止app,安全人员写的so,是单独的,不会跟app的业务功能关联,我们可以通过删除这些so文件,实现绕过。
    我们在尝试删除操作时,要测试app是否能正常使用,如果能正常使用,说明这个so跟业务无关,如果app不能使用了,说明这个so跟业务有关,我们不能删除。
    通过hook安卓底层,依次打印运行app时加载的so文件,一个个打印出so文件,当打印到某个so文件时,如果app退出了,这个so文件,就是在检测frida是否运行

import frida
import sys

rdev = frida.get_remote_device()
pid = rdev.spawn(["com.xxxx.xxxx"])
session = rdev.attach(pid)

scr = """
Java.perform(function () {

    var dlopen = Module.findExportByName(null, "dlopen");
    var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");

    Interceptor.attach(dlopen, {
        onEnter: function (args) {
            var path_ptr = args[0];
            var path = ptr(path_ptr).readCString();
            console.log("[dlopen:]", path);
        },
        onLeave: function (retval) {

        }
    });

    Interceptor.attach(android_dlopen_ext, {
        onEnter: function (args) {
            var path_ptr = args[0];
            var path = ptr(path_ptr).readCString();
            console.log("[dlopen_ext:]", path);
        },
        onLeave: function (retval) {

        }
    });
});
"""
script = session.create_script(scr)


def on_message(message, data):
    print(message, data)


script.on("message", on_message)
script.load()
rdev.resume(pid)
sys.stdin.read()

运行hook脚本后,会发现加载到/lib/arm64/libmsaoaidsec.so时程序崩了,删除该文件即可

图片

  • 方案二
    在面对检测frida的APP的时候,我们可以使用frida的增强版(strongR-frida-android),就是把frida的名字改掉,运行的时候没有frida的特征。
    项目地址:https://github.com/hzzheyang/strongR-frida-android/releases
    strongR-frida-android 它的本质就是frida-server,只是改了名字
    它的版本跟frida-server是一一对应的
    将下载好的文件推送到手机上运行测试即可
    绕过APP代理检测
    当我们尝试进行抓包分析时,发现抓到的包全是乱码形式,没有想要的包,这时可以发现该APP做了代理的检测

图片


这时我们需要绕过代理的检测,抓更底层的包,不抓https的包,抓socket的包,需要使用APP进行,这里我们使用SocksDroid.apk,使用之前关闭手机系统代理

  • 打开开关


    图片

  • 配置电脑IP地址


    图片

  • 配置端口,这里的端口和Charles中的socket端口一致



  • =图片

  • 进行抓包,此时可以成功抓到包


  • 图片


与burpsuite进行联动
通过上一步我们已经绕过了APP的代理检测,但是我们想要将包转发到burp中应该怎么做呢?


在Charles点击External Proxy Settings设置,配置burp代理

图片

图片

配置好之后,burp就可以收到转发过来的数据包了

图片


root检测和绕过方案

打开APP,由于我们的手机是root过的,所以一打开软件,会产生提示

图片


  • root检测原理
    我们在运行APP的时候,APP会用代码去固定位置进行检查,当前位置下有没有su命令,如果有,说明手机被root了
    root的手机,会有一些特征,典型的特征就是 su 命令
    只要手机root了,会在如下目录出现特殊的标识

    "/system/bin/su", # 不同root软件,生成的位置不同,面具一般在这个目录下
    "/data/local/bin/su",
    "/data/local/su",
    "/data/local/xbin/su",
    "/sbin/su",
    "/system/app/Superuser.apk",
    "/system/bin/failsafe/su",
    "/su/bin/su",
    "/system/sd/xbin/su",
    "/system/xbin/busybox",
    "/system/xbin/daemonsu",
    "/system/xbin/su",
    "/system/sbin/su",
    

    当我们想查看当前手机是否root,直接进入/system/bin 看看有没有su可执行文件

    adb shell  # 进入到手机
    su         # 获得超级用户权限
    /system/bin # 进入到目录下
    ls          # 查看当前目录下的文件或文件夹
    ls | grep su  # 查看当前目录下 名字中包含 su 的 文件或文件夹
    
  • 绕过方案一
    第一个方案是使用github上一个开源的项目,针对所有APP,借助于frida-server进行hook,这个脚本的原理就是通过hook底层,让APP去检测对应文件的时候检测不到
    项目地址:https://github.com/AshenOneYe/FridaAntiRootDetection
    使用antiroot.js这个脚本



    图片


手机端启动frida-server,然后进行端口转发
运行这个js脚本:

  • frida -U -f app包名 -l antiroot.js


图片

查看手机APP,此时以成功绕过

图片

  • 绕过方案二:
    面具+Shamiko模块方案+隐藏magisk应用,此方案的原理就是隐藏su文件,让APP检测不到。
    先将Shamiko-v0.5.2-120-release.zip推送到手机上

    adb push Shamiko-v0.5.2-120-release.zip /sdcard/Download/Shamiko-v0.5.2-120-release.zip
    

    此时我们可以在手机下载目录里看到该文件

图片

打开面具,进入模块,选择从本地安装,将zip刷入,点击重启


  • 图片

图片

  • 再次打开面具,首页,点击右上角齿轮,选择配置排除列表,将我们要绕过的APP排除,此时打开APP就没有提示了


图片

  • 有时候还会碰到一些APP,不仅做了root检测,还做了面具检测,我们手机上装了面具也不允许进入APP,这时我们就需要修改面具APP的名字,自定义名字


  • 图片



绕过方案三:
我们还可以通过反编译定位代码,通过hook进行绕过
反编译APP后,搜索"威胁您"

  • 图片



上述代码通过MiscUtil.isSimulator检测是否在模拟器中运行和 MiscUtil.isRooted()检测是否root。


  • 图片


我们先看 MiscUtil.isRooted()代码,可以看到这段代码主要是通过检查系统路径中的文件来判断是否是否被root,在"/system/xbin/", "/system/bin/", "/system/sbin/", "/sbin/", "/vendor/bin/", "/su/bin/"文件目录后进行拼接bh.y然后进行检测,我们bh.y可以发现该处的变量就是su,所以就是在上述路径后拼接su,查看这些目录下是否有su文件,如果有就返回true,没有就返回false


  • public static boolean isRooted() {
          String[] strArr = {"/system/xbin/", "/system/bin/", "/system/sbin/", "/sbin/", "/vendor/bin/", "/su/bin/"};
          for (int i2 = 0; i2 < 6; i2++) {
              try {
                  String str = strArr[i2] + bh.y;
                  if (new File(str).exists()) {
                      String exec = exec(new String[]{"ls", "-l", str});
                      String str2 = "isRooted=" + exec;
                      if (TextUtils.isEmpty(exec) || exec.indexOf("root") == exec.lastIndexOf("root")) {
                          return false;
                      }
                      return true;
                  }
              } catch (Exception e2) {
                  e2.printStackTrace();
              }
          }
          return false;
      }


接下来我们查看MiscUtil.isSimulator代码,该段代码主要是查看Build文件中,有没有一些虚拟设备的关键词,该处可以直接写hook脚本进行绕过

图片

public static boolean isSimulator(Context context) {
      return Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.toLowerCase().contains("vbox") || Build.FINGERPRINT.toLowerCase().contains("test-keys") || Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.contains("MuMu") || Build.MODEL.contains("virtual") || Build.SERIAL.equalsIgnoreCase("android") || Build.MANUFACTURER.contains("Genymotion") || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) || "google_sdk".equals(Build.PRODUCT) || ((TelephonyManager) context.getSystemService(AliyunLogCommon.TERMINAL_TYPE)).getNetworkOperatorName().toLowerCase().equals("android");
  }

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。