Android 下通过触发 SIGTRAP 信号实现反调试

ops/2024/10/19 4:38:18/

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

详细的 Linux 信号列表

Linux 信号是一种用于进程间通信(IPC)和异常处理的机制。以下是详细的 Linux 信号列表,包含信号名称、默认行为及用途

信号编号信号名称默认行为说明
1SIGHUP终止进程终止控制终端或配置文件发生变化时发出。
2SIGINT终止进程来自用户输入(通常是 Ctrl+C)。
3SIGQUIT终止进程并生成core文件来自用户输入(通常是 Ctrl+\)。
4SIGILL终止进程并生成core文件非法指令执行。
5SIGTRAP终止进程并生成core文件调试陷阱。
6SIGABRT终止进程并生成core文件调用 abort 函数时发出。
7SIGBUS终止进程并生成core文件总线错误(内存访问不对齐)。
8SIGFPE终止进程并生成core文件浮点运算错误。
9SIGKILL终止进程强制终止进程,无法被捕获或忽略。
10SIGUSR1终止进程用户自定义信号 1。
11SIGSEGV终止进程并生成core文件无效的内存访问。
12SIGUSR2终止进程用户自定义信号 2。
13SIGPIPE终止进程向没有读取端的管道写入数据时发出。
14SIGALRM终止进程由 alarm 函数发出的定时器信号。
15SIGTERM终止进程请求终止进程,可以被捕获和忽略。
16SIGSTKFLT终止进程协处理器栈错误。
17SIGCHLD忽略子进程停止或终止时发出。
18SIGCONT继续执行让停止的进程继续运行。
19SIGSTOP停止进程停止进程,无法被捕获或忽略。
20SIGTSTP停止进程来自用户输入的停止信号(通常是 Ctrl+Z)。
21SIGTTIN停止进程后台进程尝试从终端读取输入时发出。
22SIGTTOU停止进程后台进程尝试向终端写入输出时发出。
23SIGURG忽略套接字有紧急数据到达时发出。
24SIGXCPU终止进程超出 CPU 时间限制。
25SIGXFSZ终止进程超出文件大小限制。
26SIGVTALRM终止进程虚拟时钟信号,由
27SIGPROF终止进程定时器到期,由
28SIGWINCH忽略终端窗口大小改变时发出。
29SIGIO忽略I/O 事件发生时发出。
30SIGPWR终止进程电源故障时发出。
31SIGSYS终止进程并生成core文件非法的系统调用。

此外,Linux 还支持实时信号(Real-Time Signals),编号从 32 开始,通常是用于用户自定义的信号,应用程序可根据需要使用这些信号。

利用 SIGTRAP 检测调试器

SIGTRAP 是一个陷阱信号,通常由调试器在调试被调试程序时触发。

如果一个程序主动触发 SIGTRAP 信号,并且信号处理函数被成功调用,则意味着没有调试器存在,因为信号并未被拦截。

反之,如果信号处理函数没有被调用,则意味着调试器捕获并处理了该信号,从而可以推测出程序正处于被调试状态。

Android下反调试的流程

1. 我们通过 JNI 调用 C 代码来设置一个 SIGTRAP 信号处理器。

2. 当触发 SIGTRAP 时,信号处理器将会捕获信号。如果信号处理器成功处理了信号,则表明没有调试器。

3. 如果调试器存在,SIGTRAP 信号不会到达我们的信号处理器,程序将检测到这一情况并在 3 秒后退出。

Android下反调试实现

1. 定义信号处理器并检测调试器

首先,我们在 C 代码中编写反调试逻辑,核心是通过 raise(SIGTRAP) 触发 SIGTRAP 信号,并判断信号是否被捕获。

#include <jni.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <android/log.h>#define LOG_TAG "AntiDebug"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)// 标志变量,判断 SIGTRAP 是否被捕获
volatile int sigtrap_caught = 0;// SIGTRAP 信号处理函数
void sigtrap_handler(int sig) {LOGI("Caught SIGTRAP. No debugger present.");sigtrap_caught = 1; // 标记 SIGTRAP 被捕获
}// JNI 方法,触发 SIGTRAP 信号并检测调试器
JNIEXPORT jboolean JNICALL
Java_com_cyrus_example_antidebug_AntiDebug_detectDebugger(JNIEnv *env, jobject instance) {// 注册 SIGTRAP 处理器signal(SIGTRAP, sigtrap_handler);// 触发 SIGTRAP 信号raise(SIGTRAP);// 检查信号是否被捕获if (sigtrap_caught) {LOGI("No debugger detected.");return JNI_FALSE; // 没有检测到调试器} else {// 如果信号未被捕获,说明有调试器LOGI("Debugger detected! The program will exit in 3 seconds...");sleep(3); // 等待 3 秒exit(EXIT_FAILURE); // 退出程序return JNI_TRUE; // 返回 true,表示检测到调试器}
}

配置 CMakeLists.txt 文件

cmake_minimum_required(VERSION 3.4.1)find_library( # 查找 log 库log-lib# 库名log )add_library( # 库名称antidebug# 库类型SHARED# 源文件anti_debug.c )target_link_libraries( # 绑定库到 log 库antidebug${log-lib} )

2. Kotlin 层调用 JNI 方法

在 Kotlin 层,我们通过 JNI 调用 detectDebugger 函数,以检测是否存在调试器。根据结果,程序可以作出不同的响应。

package com.cyrus.example.antidebugimport android.util.Logobject AntiDebug {init {// 加载 native 库System.loadLibrary("antidebug")}external fun detectDebugger(): Booleanfun isDebuggerDetected(): Boolean {val detected = detectDebugger()if (detected) {Log.i("AntiDebug", "Debugger detected!")} else {Log.i("AntiDebug", "No debugger detected.")}return detected}
}

3. 调用反调试功能

val debuggerDetected = AntiDebug.isDebuggerDetected()
if (debuggerDetected) {Toast.makeText(this, "Debugger Detected", Toast.LENGTH_SHORT).show()
} else {Toast.makeText(this, "No Debugger Detected", Toast.LENGTH_SHORT).show()
}

测试反调试

1. 无调试状态

无调式状态 App 中点击 “SIGTRAP 反调试” 按钮调用反调试功能,未检测到调试器,程序正常运行。
image.png

2. 调试状态下

通过 IDA Pro 附加到当前应用
image.png
关于如何使用 IDA Pro 动态调试 Android App 可以参考这篇文章【使用IDA Pro动态调试Android APP】

App 中点击 “SIGTRAP 反调试” 按钮调用反调试功能,SIGTRAP 信号 被 IDA Pro 调试器捕获。
image.png

触发程序反调试机制,程序在 3 秒后退出。
image.png

源码

完整源码:https://github.com/CYRUS-STUDIO/AndroidExample


http://www.ppmy.cn/ops/126635.html

相关文章

理解学习JavaScript当中的混入操作(Mixin)

介绍 混入&#xff08;Mixin&#xff09; 是一种代码复用的模式。它的主要目的是将一个对象的功能“混入”到另一个对象中&#xff0c;而不是通过继承。这种模式通常被用来在多个类之间共享功能&#xff0c;而无需使用复杂的继承层次。 在 JavaScript 中&#xff0c;混入可以…

Python网络爬虫

随着互联网的迅猛发展&#xff0c;数据成为了新的“石油”。人们对于信息的需求日益增涨&#xff0c;尤其是在市场分析、学术研究和数据挖掘等领域。网络爬虫作为一种自动提取网络数据的技术&#xff0c;因其强大的能力而备受关注。而Python&#xff0c;凭借其简洁的语法和丰富…

10.13论文阅读

通过联合学习检测和描述关键点增强可变形局部特征 摘要 局部特征提取是计算机视觉中处理图像匹配和检索等关键任务的常用方法。大多数方法的核心理念是图像经历仿射变换&#xff0c;忽略了诸如非刚性形变等更复杂的效果。此外&#xff0c;针对非刚性对应的新兴工作仍然依赖于…

Ping32运维中心工具:提升企业IT管理效率的利器

在当今数字化时代&#xff0c;信息技术的高效管理对企业的运营至关重要。Ping32运维中心工具应运而生&#xff0c;为企业提供了一整套便捷的运维解决方案&#xff0c;帮助IT团队高效管理网络与设备&#xff0c;确保业务连续性。 一体化监控平台 Ping32运维中心工具提供了一体化…

jmeter 从多个固定字符串中随机取一个值的方法

1、先新增用户参数&#xff0c;将固定值设置为不同的变量 2、使用下面的函数&#xff0c;调用这写变量 ${__RandomFromMultipleVars(noticeType1|noticeType2|noticeType3|noticeType4|noticeType5)} 3、每次请求就是随机取的值了

【C++标准模版库】unordered_map和unordered_set的介绍及使用

unordered_map和unordered_set 一.unordered_set1.unordered_set类的介绍2.unordered_set和set的使用差异 二.unordered_map1.unordered_map和map的使用差异 三.unordered_multimap/unordered_multiset四.unordered_map/unordered_set的哈希相关接口 一.unordered_set 1.unord…

Vscode 如何自动排序导入语句

前言 在日常的 React 项目开发中&#xff0c;我们经常需要导入各种模块和组件。然而&#xff0c;随着项目规模的扩大&#xff0c;import 语句容易变得混乱不堪&#xff0c;这不仅增加了代码的可读性难度&#xff0c;还可能导致不必要的冲突和错误。 幸运的是&#xff0c;VSCod…

机器学习:opencv--风格迁移

目录 前言 一、代码及步骤解释 1.图片与处理 2.加载模型 3.输出图像 前言 风格迁移&#xff08;Style Transfer&#xff09;是一种计算机视觉技术&#xff0c;旨在将一种图像的艺术风格应用到另一种图像上&#xff0c;同时保持其内容。 一、代码及步骤解释 1.图片与处理 …