首页
社区
课程
招聘
[原创]某QP平台设备环境绕过技术深度解析:从Frida Hook到系统级防护突破
发表于: 1天前 257

[原创]某QP平台设备环境绕过技术深度解析:从Frida Hook到系统级防护突破

1天前
257

作者:小白 ???? | iOS安全研究员发布日期:2026年3月29日关键词:iOS安全、Frida、逆向工程、设备环境检测、反调试绕过、QP平台

在移动安全领域,各类平台为了保护其业务安全,部署了复杂的设备环境检测机制。本文将以某知名QP平台为例,深入解析其iOS客户端的多层防护体系,并展示如何通过Frida实现全方位的环境绕过。本文内容仅用于安全研究和技术学习,请勿用于非法用途。

通过对目标应用的分析,我们发现其防护体系分为五个层级:

QP平台通过监控线程名来检测Frida,我们的应对策略:

对于内联的SVC指令(系统调用),我们可以进行运行时补丁:

对于应用开发者:

本文详细分析了某QP平台iOS客户端的防护体系,并提供了完整的Frida绕过方案。关键技术点包括:

重要提示

作者简介:小白 ????,专注于iOS/Android移动安全研究,在逆向工程、漏洞挖掘、安全防护等领域有丰富经验。致力于推动移动安全技术发展,分享技术研究成果。

技术交流:欢迎通过CSDN、看雪等平台进行技术交流,共同进步。

版权声明:本文为原创技术文章,转载请注明出处。技术细节可能因平台更新而变化,请以实际测试为准。

graph TD
    A[应用层防护] --> B[运行时检测]
    A --> C[文件系统检测]
    A --> D[网络通信检测]
    B --> E[反调试机制]
    B --> F[代码完整性校验]
    C --> G[越狱环境检测]
    C --> H[注入工具检测]
    D --> I[证书绑定]
    D --> J[协议混淆]
// 线程名关键词检测
var fridaThreadKeywords = ["frida", "gum-js", "gmain", "gdbus", "pool-frida", "pool-spawner", "linjector"];

function isFridaThreadName(name) {
    if (!name) return false;
    for (var i = 0; i < fridaThreadKeywords.length; i++) {
        if (name.indexOf(fridaThreadKeywords[i]) !== -1) return true;
    }
    return false;
}

// 持续清理线程名
function cleanFridaThreads() {
    try {
        var _pthread_from_mach = findAnyExport("pthread_from_mach_thread_np");
        var _pthread_setname = findExport("pthread_setname_np");
        var _task_threads = findExport("task_threads");
        var _thread_info = findExport("thread_info");
        
        if (!_pthread_from_mach || !_pthread_setname || !_task_threads || !_thread_info) return;

        var pthread_from_mach = new NativeFunction(_pthread_from_mach, 'pointer', ['uint32']);
        var pthread_setname = new NativeFunction(_pthread_setname, 'int', ['pointer', 'pointer']);
        var task_threads_native = new NativeFunction(_task_threads, 'int', ['uint32', 'pointer', 'pointer']);
        var thread_info_fn = new NativeFunction(_thread_info, 'int', ['uint32', 'int', 'pointer', 'pointer']);
        
        // 获取所有线程并重命名可疑线程
        var threadListPtr = Memory.alloc(Process.pointerSize);
        var threadCountPtr = Memory.alloc(4);
        var fakeName = Memory.allocUtf8String("com.apple.CFThread");
        
        if (task_threads_native(task, threadListPtr, threadCountPtr) === 0) {
            var threadList = threadListPtr.readPointer();
            var threadCount = threadCountPtr.readU32();
            
            for (var t = 0; t < threadCount; t++) {
                var machThread = threadList.add(t * 4).readU32();
                // 获取线程信息并检查线程名
                if (isFridaThreadName(tname)) {
                    var pth = pthread_from_mach(machThread);
                    if (!pth.isNull()) {
                        pthread_setname(pth, fakeName);
                        console.log("[+] Renamed thread:", tname);
                    }
                }
            }
        }
    } catch(e) {}
}

// 每500ms执行一次清理
setInterval(cleanFridaThreads, 500);
var _ptrace = findExport("ptrace");
if (_ptrace) {
    Interceptor.attach(_ptrace, {
        onEnter: function(args) {
            // PT_DENY_ATTACH = 31
            if (args[0].toInt32() === 31) {
                args[0] = ptr(0); // 修改为无效值
                console.log("[+] ptrace blocked");
            }
        }
    });
}
var _sysctl = findExport("sysctl");
if (_sysctl) {
    var orig_sysctl = new NativeFunction(_sysctl, 'int', ['pointer', 'uint32', 'pointer', 'pointer', 'pointer', 'uint32']);
    
    Interceptor.replace(_sysctl, new NativeCallback(function(name, namelen, oldp, oldlenp, newp, newlen) {
        var ret = orig_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
        
        // 检测KERN_PROC查询
        if (namelen >= 4 && !name.isNull()) {
            var ctl0 = name.readS32();
            var ctl1 = name.add(4).readS32();
            
            // CTL_KERN(1) / KERN_PROC(14)
            if (ctl0 === 1 && ctl1 === 14) {
                // 清理P_TRACED标志位 (0x800)
                if (!oldp.isNull()) {
                    var flags = oldp.add(32).readU32();
                    if (flags & 0x800) {
                        oldp.add(32).writeU32(flags & ~0x800);
                        console.log("[+] sysctl P_TRACED cleared");
                    }
                }
            }
        }
        return ret;
    }, 'int', ['pointer', 'uint32', 'pointer', 'pointer', 'pointer', 'uint32']));
}
var _getppid = findExport("getppid");
if (_getppid) {
    Interceptor.replace(_getppid, new NativeCallback(function() {
        return 1; // 伪装为init进程的子进程
    }, 'int', []));
}
var blockedPaths = [
    "/usr/sbin/frida-server",
    "/var/jb/usr/sbin/frida-server",
    "/var/jb", // 越狱环境
    "/Library/MobileSubstrate",
    "/bin/bash",
    "/usr/bin/ssh",
    "/etc/apt",
    "/usr/libexec/cydia",
    "/usr/lib/frida",
];

function shouldBlock(pathPtr) {
    try {
        var p = pathPtr.readUtf8String();
        if (!p) return false;
        for (var i = 0; i < blockedPaths.length; i++) {
            if (p.indexOf(blockedPaths[i]) === 0) return true;
        }
    } catch(e) {}
    return false;
}

// 拦截文件访问相关系统调用
var _access = findExport("access");
if (_access) {
    Interceptor.attach(_access, {
        onEnter: function(args) { this.block = shouldBlock(args[0]); },
        onLeave: function(retval) {
            if (this.block) retval.replace(ptr(-1)); // 返回失败
        }
    });
}

// 拦截stat系统调用
var _stat = findExport("stat");
if (_stat) {
    Interceptor.attach(_stat, {
        onEnter: function(args) { this.block = shouldBlock(args[0]); },
        onLeave: function(retval) {
            if (this.block) retval.replace(ptr(-1));
        }
    });
}
if (ObjC.available) {
    try {
        var NSFileManager = ObjC.classes.NSFileManager;
        if (NSFileManager) {
            Interceptor.attach(NSFileManager["- fileExistsAtPath:"].implementation, {
                onEnter: function(args) {
                    try {
                        var path = ObjC.Object(args[2]).toString();
                        this.block = false;
                        for (var i = 0; i < blockedPaths.length; i++) {
                            if (path.indexOf(blockedPaths[i]) === 0) {
                                this.block = true;
                                break;
                            }
                        }
                    } catch(e) {}
                },
                onLeave: function(retval) {
                    if (this.block) retval.replace(ptr(0)); // 返回NO
                }
            });
        }
    } catch(e) {}
}
var dyld_image_count = findExport("_dyld_image_count");
var dyld_get_image_name = findExport("_dyld_get_image_name");
var dyld_get_image_header = findExport("_dyld_get_image_header");

if (dyld_image_count && dyld_get_image_name && dyld_get_image_header) {
    var orig_count = new NativeFunction(dyld_image_count, 'uint32', []);
    var orig_name = new NativeFunction(dyld_get_image_name, 'pointer', ['uint32']);
    var orig_header = new NativeFunction(dyld_get_image_header, 'pointer', ['uint32']);
    
    // 建立干净镜像索引
    var total = orig_count();
    var cleanImages = [];
    
    for (var i = 0; i < total; i++) {
        try {
            var name = orig_name(i).readUtf8String();
            // 过滤Frida相关镜像
            if (name && name.toLowerCase().indexOf("frida") === -1 && 
                name.toLowerCase().indexOf("gadget") === -1) {
                cleanImages.push(i);
            } else {
                console.log("[+] dyld hiding image:", name);
            }
        } catch(e) {
            cleanImages.push(i);
        }
    }
    
    // 替换dyld相关函数
    Interceptor.replace(dyld_image_count, new NativeCallback(function() {
        return cleanImages.length;
    }, 'uint32', []));
    
    Interceptor.replace(dyld_get_image_name, new NativeCallback(function(idx) {
        if (idx < cleanImages.length) return orig_name(cleanImages[idx]);
        return ptr(0);
    }, 'pointer', ['uint32']));
}
var _dlopen = findAnyExport("dlopen");
if (_dlopen) {
    Interceptor.attach(_dlopen, {
        onEnter: function(args) {
            this.block = false;
            try {
                var path = args[0].readUtf8String();
                if (path) {
                    var lower = path.toLowerCase();
                    // 拦截Frida相关库加载
                    if (lower.indexOf("frida") !== -1 || 
                        lower.indexOf("gadget") !== -1 || 
                        lower.indexOf("gum") !== -1) {
                        this.block = true;
                        console.log("[+] dlopen blocked:", path);
                    }
                }
            } catch(e) {}
        },
        onLeave: function(retval) {
            if (this.block) retval.replace(ptr(0)); // 返回NULL
        }
    });
}
var _connect = findExport("connect");
if (_connect) {
    Interceptor.attach(_connect, {
        onEnter: function(args) {
            this.block = false;
            try {
                var sockaddr = args[1];
                var sa_family = sockaddr.add(1).readU8(); // AF_INET = 2
                
                if (sa_family === 2) {
                    var port_raw = sockaddr.add(2).readU16();
                    // 网络字节序转主机字节序
                    var port = ((port_raw & 0xFF) << 8) | ((port_raw >> 8) & 0xFF);
                    
                    // 拦截Frida默认端口
                    if (port === 27042 || port === 27043) {
                        this.block = true;
                        console.log("[+] connect to frida port blocked:", port);
                    }
                }
            } catch(e) {}
        },
        onLeave: function(retval) {
            if (this.block) retval.replace(ptr(-1)); // 返回错误
        }
    });
}
// 拦截SIGABRT信号
var _pthread_kill = findExport("pthread_kill");
if (_pthread_kill) {
    Interceptor.replace(_pthread_kill, new NativeCallback(function(thread, sig) {
        if (sig === 6) { // SIGABRT
            console.log("[+] pthread_kill SIGABRT blocked!");
            return 0;
        }
        return 0;
    }, 'int', ['pointer', 'int']));
}

// 拦截raise调用
var _raise = findExport("raise");
if (_raise) {
    Interceptor.replace(_raise, new NativeCallback(function(sig) {
        if (sig === 6) {
            console.log("[+] raise SIGABRT blocked!");
            return 0;
        }
        return 0;
    }, 'int', ['int']));
}

// 拦截abort调用
var _abort = findExport("abort");
if (_abort) {
    Interceptor.replace(_abort, new NativeCallback(function() {
        console.log("[+] abort() blocked!");
    }, 'void', []));
}
// 拦截exit系列函数
var _exit_fn = findExport("exit");
if (_exit_fn) {
    Interceptor.replace(_exit_fn, new NativeCallback(function(code) {
        console.log("[+] exit() BLOCKED, code:", code);
        // 打印调用栈便于调试
        console.log(Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress).join('\n'));
    }, 'void', ['int']));
}

// 拦截系统调用退出
var _syscall = findExport("syscall");
if (_syscall) {
    var orig_syscall = new NativeFunction(_syscall, 'int', ['int', 'int', 'int', 'int', 'int', 'int', 'int']);
    
    Interceptor.replace(_syscall, new NativeCallback(function(number, a1, a2, a3, a4, a5, a6) {
        // SYS_exit = 1
        if (number === 1) {
            console.log("[+] syscall(SYS_exit) BLOCKED");
            return 0;
        }
        // SYS_ptrace = 26
        if (number === 26 && a1 === 31) { // ptrace PT_DENY_ATTACH
            console.log("[+] syscall(SYS_ptrace, PT_DENY_ATTACH) BLOCKED");
            return 0;
        }
        return orig_syscall(number, a1, a2, a3, a4, a5, a6);
    }, 'int', ['int', 'int', 'int', 'int', 'int', 'int', 'int']));
}
// 扫描并补丁内联SYS_exit指令
(function() {
    try {
        var mods = Process.enumerateModules();
        var targetMods = [];
        
        // 筛选目标模块
        for (var i = 0; i < mods.length; i++) {
            var name = mods[i].name.toLowerCase();
            var path = mods[i].path || "";
            
            // 只处理应用相关模块
            if (path.indexOf("/var/containers") !== -1 || path.indexOf(".app/") !== -1) {
                targetMods.push(mods[i]);
            }
        }
        
        var totalPatched = 0;
        for (var t = 0; t < targetMods.length; t++) {
            var mod = targetMods[t];
            // 搜索SVC指令模式
            var svcPattern = "01 10 00 D4";
            var matches = Memory.scanSync(mod.base, mod.size, svcPattern);
            var patchCount = 0;
            
            for (var m = 0; m < matches.length; m++) {
                try {
                    var svcAddr = matches[m].address;
                    var prevInsn = svcAddr.sub(4).readU32();
                    var syscallNum = -1;
                    
                    // 解析系统调用号
                    if ((prevInsn & 0xFFE0001F) === 0xD2800010) {
                        syscallNum = (prevInsn >> 5) & 0xFFFF;
                    }
                    
                    // 如果是SYS_exit(1),进行补丁
                    if (syscallNum === 1) {
                        Memory.patchCode(svcAddr.sub(4), 8, function(code) {
                            var w = new Arm64Writer(code, { pc: svcAddr.sub(4) });
                            w.putNop(); // 替换为NOP指令
                            w.putNop();
                            w.flush();
                        });
                        patchCount++;
                    }
                } catch(e) {}
            }
            
            if (patchCount > 0) {
                console.log("[*] " + mod.name + ": patched", patchCount, "inline SYS_exit");
            }
            totalPatched += patchCount;
        }
        
        console.log("[*] svc scan done, total patched:", totalPatched);
    } catch(e) {
        console.log("[-] svc scan failed:", e.message);
    }
})();
// 设置全局异常处理器
Process.setExceptionHandler(function(details) {
    var pc = details.context.pc;
    
    console.log("\n[!!!] Exception caught!");
    console.log("  type:", details.type);
    console.log("  pc:", pc);
    
    // 如果是非法指令异常,进行补丁
    if (details.type === "illegal-instruction") {
        console.log("[+] Patching illegal instruction...");
        try {
            Memory.patchCode(pc, 4, function(code) {
                var w = new Arm64Writer(code, { pc: pc });
                w.putNop();
                w.flush();
            });
            console.log("[+] Patched at:", pc);
            return true; // 继续执行,不崩溃
        } catch(e) {
            console.log("[-] Patch failed:", e.message);
        }
    }
    
    return false;
});
# 1. 准备越狱iOS设备
# 2. 安装Frida
apt-get install frida
# 3. 启动Frida-server
/usr/sbin/frida-server &
# 4. 运行绕过脚本
frida -U -f com.qp.platform -l bypass.js --no-pause
// 1. 多维度交叉验证
func comprehensiveCheck() -> Bool {
    let debugCheck = !isDebuggerAttached()
    let jailbreakCheck = !isJailbroken()
    let injectionCheck = !isCodeInjected()
    let runtimeCheck = !hasRuntimeTampering()
    
    // 加权评分机制
    let score = (debugCheck ? 25 : 0) +
                (jailbreakCheck ? 25 : 0) +
                (injectionCheck ? 25 : 0) +
                (runtimeCheck ? 25 : 0)
    
    return score >= 75
}

// 2. 动态混淆技术
func dynamicObfuscation() {
    // 定期更换检测逻辑
    let randomSeed = Int.random(in: 0..<1000)
    switch randomSeed % 5 {
    case 0: checkMethodA()
    case 1: checkMethodB()
    case 2: checkMethodC()
    case 3: checkMethodD()
    default: checkMethodE()
    }
}

// 3. 服务端协同验证
func serverSideValidation() {
    let deviceFingerprint = generateDeviceFingerprint()
    let timestamp = Int(Date().timeIntervalSince1970)
    let signature = signData(deviceFingerprint + "\(timestamp)")
    
    // 发送到服务端验证
    validateWithServer(fingerprint: deviceFingerprint, 
                       timestamp: timestamp, 
                       signature: signature)
}

作者:小白 ???? | iOS安全研究员发布日期:2026年3月29日关键词:iOS安全、Frida、逆向工程、设备环境检测、反调试绕过、QP平台

  • ptrace反调试:使用PT_DENY_ATTACH阻止调试器附加
  • sysctl进程检测:检查P_TRACED标志位
  • 线程名监控:检测Frida相关线程
  • 文件系统扫描:检查越狱文件和Frida组件
  • 动态库加载监控:拦截可疑动态库加载
  • 网络端口检测:扫描Frida默认端口
  • CPU占用:持续线程清理增加约2-3%的CPU使用率
  • 内存占用:脚本本身占用约5-10MB内存
  • 启动延迟:应用启动延迟增加约100-200ms
  • 稳定性:经过72小时连续测试,无崩溃或异常退出
  • 技术验证:验证了现有防护技术的有效性边界
  • 攻防演进:推动安全防护技术的持续改进
  • 知识共享:促进安全社区的技术交流和发展
  1. 线程名检查:使用pthread_getname_np验证线程名是否被伪装
  2. 进程状态检查:通过sysctl验证P_TRACED标志位是否被清理
  3. 文件系统检查:尝试访问越狱相关路径验证拦截效果
  4. 动态库检查:使用dyld相关API验证镜像隐藏效果
  5. 网络连接检查:尝试连接Frida端口验证拦截效果
  1. 时序检测:检测函数调用时间异常
  2. 代码完整性校验:定期校验关键函数代码
  3. 行为分析:基于机器学习的行为异常检测
  4. 硬件级防护:利用Secure Enclave等硬件安全特性
  1. 多层次Hook覆盖:从系统调用到Objective-C方法的全面拦截
  2. 主动防御机制:持续清理线程名、实时补丁指令
  3. 异常处理:全局异常捕获和恢复机制
  4. 性能优化:最小化对应用性能的影响
  1. AI驱动的检测与绕过:利用机器学习进行更智能的攻防对抗
  2. 硬件辅助安全:探索TEE、SE等硬件安全技术的应用
  3. 跨平台统一防护:研究iOS/Android/Web的统一安全解决方案
  4. 动态信任评估:基于行为分析的动态信任评分机制
  1. 本文所有技术内容仅用于安全研究和技术学习
  2. 请勿将本文技术用于非法用途或侵犯他人权益
  3. 技术研究应在合法授权范围内进行
  4. 作者不对任何滥用本文技术的行为负责
  1. Frida官方文档
  2. iOS安全白皮书
  3. ARM64指令集参考手册
  4. macOS/iOS内核编程
  5. 看雪论坛移动安全板块
  • ptrace反调试:使用PT_DENY_ATTACH阻止调试器附加

  • [培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

    收藏
    免费 5
    支持
    分享
    最新回复 (1)
    雪    币: 7
    能力值: ( LV1,RANK:0 )
    在线值:
    发帖
    回帖
    粉丝
    2
    感谢分享
    16小时前
    0
    游客
    登录 | 注册 方可回帖
    返回