如何通过针对iOS的动态分析技术绕过反调试机制

在这篇文章中,我们将跟大家介绍和分析一种针对iOS的新型安全研究技术,该技术能够让iOS应用程序的调试过程更加轻松,并解决那些可能会延缓我们步伐的阻碍。

如果你要对一个采用了反调试技术的iOS应用程序或二进制文件进行调试的话,可能你会感觉困难重重。作为一名安全研究人员,你可能也需要经常面对黑盒测试的场景,而且大多数还会故意对代码进行混淆处理。这样一来,想要简化分析流程就会非常困难,而且很多调试工具和技术都会失效,将本应简单的任务变成了复杂的难题。

在这篇文章中,我们将给大家演示并详细介绍Corellium团队开发的一种新技术,这种技术可以加快iOS应用程序的代码动态分析工作,并解决代码调试过程中可能遇到的各种难题。

什么是反调试技术?

OWASP移动应用程序安全验证标准(MASVS)是一个用于确保移动应用程序安全性的综合标准框架,该标准框架由开放式Web应用程序安全项目(OWASP)设计研发,由各种级别的安全要求和建议组成,提供了移动应用程序安全的基线。在其指导标准中,MASVS解决了移动应用程序实现反逆向工程和调试措施的需要,并强调了这些活动是对应用程序安全和用户隐私的潜在威胁。

尤其是,它强调了整合调试检查机制的重要性。其中包括部署检测和响应调试器,以确保代码和敏感数据在调试会话期间不会暴露,并防止调试工具修改或篡改应用程序。通过实现这些安全实践建议,开发人员可以更好地保护其应用程序免受未经授权的分析和利用,这对于维护应用程序及其用户数据的完整性和机密性至关重要。

下面给出的是目前社区广泛采用的一些反调试技术:

1、使用sysctl检测是否设置了ptrace标志,该标志可能会导致应用程序在内省(在程序运行时确定对象类型的一种能力)状态下终止运行或表现有差异;

2、直接使用ptrace设置PTRACE_DENY_ATTACH,并防止父进程对其进行调试;

3、使用getppid()确定应用程序是否由launchd(pid 1)启动执行;

iOSSecuritySuite库就以非常简洁直接的形式实现了这些检查,并且可以轻松地将其应用到iOS应用程序中。在演示过程中,我们会将其中一个检查以简单二进制文件的形式重新编码实现,并且可以直接从iOS控制台运行。该应用程序也非常简单,其运行流程如下:

1、给一个NSString设置一个随机8字节标记;

2、打印关于用户空间进程的某些有用的调试信息,例如可执行程序的基地址和标记地址;

3、等待用户输入(主要是暂停并绑定调试器);

4、退出;

首先,我们直接运行该应用程序,并且没有启用任何调试保护机制:

iphone:/ root# ./main-allow  2024-01-24 08:50:08.234 main-allow[736:32888] Flag value: aX1ZWAec2024-01-24 08:50:08.234 main-allow[736:32888] PID: 7362024-01-24 08:50:08.234 main-allow[736:32888] Base Address of Main: 0x10000423c2024-01-24 08:50:08.234 main-allow[736:32888] Address of NSString: 0x16fdff2f82024-01-24 08:50:08.235 main-allow[736:32888] Address of actual NSString contents: 0x9142043a0 <--- save this for later2024-01-24 08:50:08.235 main-allow[736:32888] Pausing for user input...

然后,直接给进程绑定一个debugserver,并给需要交互的远程lldb客户端打开一个端口:

iphone:/ root# ./debugserver16-3 0.0.0.0:3333 -a 736debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-1400.2.13.2for arm64.Attaching to process 736...Listening to port 3333 for a connection from 0.0.0.0...

通过使用二进制代码提供的调试信息,我们可以打印出标志的内容:

(lldb) process connect connect://10.11.0.12:3333                                                                                                                                                                 Process 736 stopped* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOPframe #0: 0x00000001c5fe8e84 libsystem_kernel.dylib`__read_nocancel + 8libsystem_kernel.dylib`:->  0x1c5fe8e84 <+8>:  b.lo   0x1c5fe8ea4               ; <+40>0x1c5fe8e88 <+12>: pacibsp  0x1c5fe8e8c <+16>: stp    x29, x30, [sp, #-0x10]!0x1c5fe8e90 <+20>: mov    x29, spTarget 0: (main-allow) stopped.(lldb) x 0x9142043a00x9142043a0: 61 58 31 5a 57 41 65 63 00 00 00 00 00 00 00 00  aX1ZWAec........0x9142043b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................(lldb)  

没错,我们就可以查看到NSString对象的内容了(程序提供的地址右边)。

现在,我们需要在我们自己的应用程序中重新实现IOSSecuritySuite中的.denyDebugger()方法:

static void denyDebugger() {// Dynamic loading of ptracevoid *handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);pid_t pid = getpid();if (handle) {typedef int (*PtraceType)(int request, pid_t pid, caddr_t addr, int data);PtraceType ptraceFunction = (PtraceType)dlsym(handle, "ptrace");if (ptraceFunction) {// PT_DENY_ATTACH == 31int ptraceRet = ptraceFunction(31, 0, 0, 0);if (ptraceRet != 0) {NSLog(@"Error occurred when calling ptrace(). Denying debugger may not be reliable");}}dlclose(handle);}}

如果我们重新运行附加了额外功能函数的应用程序,我们将能够得到一次完全不一样的体验:

iphone:/ root# ./debugserver16-3 0.0.0.0:3333 -a 739debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-1400.2.13.2for arm64.Attaching to process 739...Segmentation fault: 11iphone:/ root#  

通过设置PT_DENY_ATTACH标志,debugserver/lldb将无法绑定到目标进程上。但这种技术并不是万能的,因为我们也可以通过钩子和代码修补的组合方式来绕过这种技术。然而,应用程序也可以使用一些技术方法来检测它们当前是否正在被其他工具检测,或应用程序完整性是否被破坏。

那么,我们如何在不给目标应用程序“知情”的情况下对其进行调试呢?

使用Corellium进行调试

Corellium能够提供一个内核级的gdb-stub,我们可以将其与gdb和lldb一起使用。对于想要深入了解iOS内部细节或执行安全漏洞研究的人来说,内核调试器是非常有价值的工具。如果你必须处理云环境中的潜在问题,以提供更快速的调试体验,我们也可以将其与Corellium调试加速器结合使用。

Corellium VM在service_ip:4000上会暴露公内核调试桩,我们可以使用任何适配gdb协议的东西连接到该调试桩。在下面的例子中,我们将使用lldb进行演示:

(lldb) gdb-remote 10.11.1.12:4000Kernel UUID: EE3449F0-DB47-3596-B253-084A0EBDBDC5Load Address: 0xfffffff00700c000WARNING: Unable to locate kernel binary on the debugger system.Process 1 stopped* thread #1, stop reason = signal SIGINTframe #0: 0xfffffff007d2d0f0->  0xfffffff007d2d0f0: cbz    x30, -0xff82d2f080xfffffff007d2d0f4: ret     0xfffffff007d2d0f8: mov    x0, #0x10xfffffff007d2d0fc: bl     -0xff816d978Target 0: (No executable module.) stopped.(lldb) cProcess 1 resuming

我们还可以使用内核调试器来调试用户空间进程,利用监控器过滤功能,我们可以通过进程名称、PID或TID来指定一个用户空间进程,而且还可以使用boe标志(可选)来中断正在进入用户空间的进程:

(lldb) process plugin packet monitor filter user pid:814 boe

接下来,我们将控制内核进入使用pid:标志指定的进程:

(lldb) process plugin packet monitor filter user pid:745 boepacket: qRcmd,66696c7465722075736572207069643a37343520626f65response: OKProcess 1 stopped* thread #2, stop reason = signal SIGSTOPframe #0: 0x00000001c5fe8e84->  0x1c5fe8e84: b.lo   0x1c5fe8ea40x1c5fe8e88: pacibsp  0x1c5fe8e8c: stp    x29, x30, [sp, #-0x10]!0x1c5fe8e90: mov    x29, spTarget 0: (No executable module.) stopped.

从上述代码中我们可以看到,我们已经将调试上下文从内核切换到了用户空间进程。程序也正常运行,但我们仍然在悄悄地调试它。现在,使用程序提供的调试信息,我们可以使用lldb打印用户空间NSString对象的内容:

2024-01-24 09:31:26.294 main-deny[745:40019] Flag value: k5mLCxkR 
2024-01-24 09:31:26.295 main-deny[745:40019] PID: 745 
2024-01-24 09:31:26.295 main-deny[745:40019] Base Address of Main: 0x10000423c 
2024-01-24 09:31:26.295 main-deny[745:40019] Address of NSString: 0x16fdff2f8 
2024-01-24 09:31:26.295 main-deny[745:40019] Address of actual NSString contents: 0x7c24043e0 
2024-01-24 09:31:26.296 main-deny[745:40019] Pausing for user input... 
(lldb) x 0x7c24043e0 
0x7c24043e0: 6b 35 6d 4c 43 78 6b 52 00 00 00 00 00 00 00 00  k5mLCxkR........ 
0x7c24043f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
(lldb)  

后话

当然了,你还可以使用该技术来调试Corellium的非越狱模型。如果你想在未越狱VM中调试com.apple.WebKit.WebContent的话,可以直接绑定一个内核调试器并安装上述步骤操作即可。

参考资料

Technical Q&A QA1361: Detecting the Debugger

Mac OS X Manual Page For ptrace(2)

https://github.com/securing/IOSSecuritySuite/blob/2121b32eb967a2a27c5cf54a369a92c2e36546d3/IOSSecuritySuite/DebuggerChecker.swift

How to Debug the Kernel | Corellium Support Center

Debug Accelerator | Corellium Support Center

参考链接

Defeating debug protections with Corellium

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/780170.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

民航电子数据库:CAEMigrator迁移数据库时总是卡死

目录 一、场景二、异常情况三、排查四、应急方案 一、场景 1、对接民航电子数据库 2、将mysql数据库迁移到cae数据库 3、使用CAEMigrator迁移工具进行数据库迁移时&#xff0c;该工具会卡死&#xff08;不清楚是否是部署cae服务的服务器资源导致&#xff09; 二、异常情况 …

数据结构与集合(三)

在计算机科学领域&#xff0c;哈希表是非常重要的数据结构&#xff0c;它们在数据组织和存储中扮演着重要角色。本文将介绍哈希表的的基本概念、特点以及实际应用&#xff0c;帮助读者更好地理解这种数据结构在算法设计和编程中的重要性。让我们一起深入探讨哈希表&#xff0c;…

Java的KruskaI知识点(含面试大厂题和源码)

Kruskal算法是用于在加权无向图中找到最小生成树的一种算法。与Prim算法不同&#xff0c;Kruskal算法是一种基于边的贪心算法&#xff0c;它在构建最小生成树的过程中逐步添加边。以下是Kruskal算法的一些关键知识点&#xff1a; 1. 算法概述 Kruskal算法从考虑所有边的集合开…

【python plotly库介绍】从视觉到洞见:桑基图在业务分析中的应用【保姆级教程过于详细珍藏版】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 本文结构&#xff1a;工具介绍python实现库 - 案例 - 分析思路与过程 实战专栏&#xff1a;https://blog.csdn.net/cciehl/category_12615648.html 备注说明&#xff1a; 企业…

2024软件设计师备考讲义——(7)

数据库技术 一、数据库基础 1.数据库系统 DB、DBS、DBA、DBMS 2.三级模式两级映像 内模式 物理存储 概念模式 基本表 外模式 用户使用应用程序&#xff0c;视图级别 外模式-概念模式的映像 表和视图之间的映射若表中数据变化&#xff0c;只要修改映射&#xff0c;不用改程序…

vue使用el-upload上传,上传错误文件,名称还会显示

vue使用el-upload上传&#xff0c;上传错误文件&#xff0c;名称还会显示 背景&#xff1a;上传不符合后缀的文件&#xff0c;但是还是在页面中显示&#xff0c;使用的是http-request方法 代码&#xff1a; <el-upload multiple class"avatar-uploader" action…

【八股03.29】

【八股03.29】 1.内存泄漏&#xff1f;野指针&#xff1f;悬挂指针&#xff1f; 什么是内存泄漏&#xff1f; 内存泄漏是指程序运行过程中申请的动态分配的堆内存没有被释放&#xff0c;造成系统内存浪费&#xff0c;运行速度减慢甚至崩溃等严重后果。 如何避免&#xff1f;…

DARTS-PT: RETHINKING ARCHITECTURE SELECTION IN DIFFERENTIABLE NAS

Rethinking Architecture Selection in Differentiable NAS 论文链接&#xff1a;https://arxiv.org/abs/2108.04392v1 项目链接&#xff1a;https://github.com/ruocwang/darts-pt ABSTRACT 可微架构搜索(Differentiable Neural Architecture Search, NAS)是目前最流行的网…

光耦合器电路基本概述

在当今快速发展的技术环境中&#xff0c;光耦合器电路在确保电信号跨隔离电路的无缝传输方面发挥着关键作用。这些半导体器件通常被称为光电隔离器&#xff0c;具有许多优点&#xff0c;包括电路隔离、信号传输和精确的电路控制。然而&#xff0c;如果不全面了解市场上各种光耦…

Python批量提取pdf首页并合并为一个文件

前情提要&#xff1a;python安装pypdf2包 pip install pypdf2 第一种&#xff1a;既需要每一个单独的首页&#xff0c;也需要将首页合并。 整体操作思路&#xff0c;将文件夹下面原本的每一个pdf获取第一页&#xff0c;然后再写出&#xff0c;将其放在FirstPage文件夹下。再…

Verilog语法之always语句学习

always语法是Verilog_HDL中最常用的一种语法。 always过程语句和语句块组成的&#xff0c;语法格式如下所示。 always(敏感信号1 or 敏感信号2.....) always实现组合逻辑和时序逻辑。用always实现组合逻辑要将所有的敏感信号加入敏感列表中&#xff1b;用always实现时序逻辑时…

vue 窗口内容滚动到底部

onMounted(() > {scrollToBottom() }) // 滚动到底部方法 const scrollToBottom () > {// 获取聊天窗口容器let chatRoom: any document.querySelector(".chat-content");// 滚动到容器底部chatRoom.scrollTop chatRoom.scrollHeight; } 效果 聊天窗口代码…

aeon,一个好用的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个好用的 Python 库 - aeon Github地址&#xff1a;https://github.com/aeon-toolkit/aeon 在现代计算机科学和人工智能领域&#xff0c;处理时间序列数据是一个重要而复杂的任务。Python aeon库…

npm install 报错ERESOLVE unable to resolve dependency tree

描述&#xff1a;npm install 报错ERESOLVE unable to resolve dependency tree 解决方案&#xff1a; npm install --legacy-peer-deps

深入MNN:开源深度学习框架的介绍、安装与编译指南

引言 在人工智能的世界里&#xff0c;深度学习框架的选择对于研究和应用的进展至关重要。MNN&#xff0c;作为一个轻量级、高效率的深度学习框架&#xff0c;近年来受到了众多开发者和研究人员的青睐。它由阿里巴巴集团开源&#xff0c;专为移动端设备设计&#xff0c;支持跨平…

gateway 分发时若两个服务的路由地址一样,怎么指定访问想要的服务下的地址

1.思路 在使用Spring Cloud Gateway时&#xff0c;如果两个服务的路由地址相同&#xff0c;可以通过Predicate&#xff08;断言&#xff09;和Filter&#xff08;过滤器&#xff09;的组合来实现根据请求的不同条件将请求分发到不同的服务下的地址。 使用Predicate进行路由条件…

sync包常用并发安全数据结构

sync.WaitGroup 使用 sync.WaitGroup用于等待一组goroutine完成。Add方法设置计数器&#xff0c;Done方法减少计数器&#xff0c;Wait方法阻塞直到计数器为0。 package mainimport ("fmt""sync""time" )func worker(id int, wg *sync.WaitGroup…

Hive窗口函数笔试题(面试题)

Hive笔试题实战 短视频 题目一&#xff1a;计算各个视频的平均未完播率 有用户-视频互动表tb_user_video_log&#xff1a; id uid video_id start_time end_time if_follow if_like if_retweet comment_id 1 101 2001 2021-10-01 10:00:00 2021-10-01 10:00:30…

使用mysql官网软件包安装mysql

确定你的操作系统&#xff0c;我的是Centos myqsl 所有安装包的地址&#xff1a;https://repo.mysql.com/yum/ 如果你是使用rpm安装你可以到对应的版本里面找到对应的包。 mysql 发行包的地址&#xff1a;http://repo.mysql.com/ 在这里你可以找到对应的发布包安装。 这里使用y…

TCP/IP 网络模型有哪几层?(计算机网络)

应用层 为用户提供应用功能 传输层 负责为应用层提供网络支持 使用TCP和UDP 当传输层的数据包大小超过 MSS&#xff08;TCP 最大报文段长度&#xff09; &#xff0c;就要将数据包分块&#xff0c;这样即使中途有一个分块丢失或损坏了&#xff0c;只需要重新发送这一个分块…