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

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

详细的 Linux 信号列表

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

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

arduino 复制代码
#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 文件

perl 复制代码
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 函数,以检测是否存在调试器。根据结果,程序可以作出不同的响应。

kotlin 复制代码
package com.cyrus.example.antidebug

import android.util.Log

object AntiDebug {

    init {
        // 加载 native 库
        System.loadLibrary("antidebug")
    }

    external fun detectDebugger(): Boolean

    fun isDebuggerDetected(): Boolean {
        val detected = detectDebugger()
        if (detected) {
            Log.i("AntiDebug", "Debugger detected!")
        } else {
            Log.i("AntiDebug", "No debugger detected.")
        }
        return detected
    }
}

3. 调用反调试功能

kotlin 复制代码
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 反调试" 按钮调用反调试功能,未检测到调试器,程序正常运行。

2. 调试状态下

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

App 中点击 "SIGTRAP 反调试" 按钮调用反调试功能,SIGTRAP 信号 被 IDA Pro 调试器捕获。

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

源码

完整源码:github.com/CYRUS-STUDI...

相关推荐
别动我齐刘海6 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
Lsetea6 小时前
OpenSSL报certificate chain too long:error 22与verify_depth深度排查
linux·https·ssl证书·openssl·证书链
不像程序员的程序媛7 小时前
linux常见文本操作命令
linux·运维·服务器
wangbing11258 小时前
开发指南149-IotDB-常用命令
linux·运维·iotdb
看着博客敲代码8 小时前
WorkBuddy 接上 Kali MCP 做自动化渗透:信息收集到初步验证的落地记录
linux·人工智能·安全·网络安全·自动化
geovindu8 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
小HANN9 小时前
华为云企业网站上云实战|从零搭建高可用WordPress全站架构(ECS+RDS+ELB+弹性伸缩+云监控闭环)
linux·运维·服务器·经验分享
星恒随风10 小时前
Linux库的底层原理:ELF文件格式、静态链接、程序加载、虚拟地址空间与GOT/PLT详解
linux·运维·笔记·学习·状态模式
知之则吱吱10 小时前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
GeW10 小时前
2026新质生产力路线图:Linux、数据库与智能算力融合报告
linux