简体   繁体   English

检测Cycript / Substrate或gdb是否附加到iOS应用程序的进程?

[英]Detect if Cycript/Substrate or gdb is attached to an iOS app's process?

I am building an iOS app that transmits sensitive data to my server, and I'm signing my API requests as an additional measure. 我正在构建一个将敏感数据传输到我的服务器的iOS应用程序,我正在签署我的API请求作为一项额外措施。 I want to make reverse engineering as hard as possible, and having used Cycript to find signing keys of some real-world apps, I know it's not hard to find these keys by attaching to a process. 我想尽可能地进行逆向工程,并且使用Cycript查找某些真实应用程序的签名密钥,我知道通过附加到流程来找到这些密钥并不困难。 I am absolutely aware that if someone is really skilled and tries hard enough , they eventually will exploit, but I'm trying to make it as hard as possible, while still being convenient for myself and users. 我完全清楚,如果有人真的很熟练并且努力尝试,他们最终利用,但我想尽可能地努力,同时仍然方便自己和用户。

I can check for jailbroken status and take additional measures, or I can do SSL pinning, but both are still easy to bypass by attaching to the process and modifying the memory. 我可以检查越狱状态并采取其他措施,或者我可以执行SSL固定,但通过附加到进程并修改内存,两者仍然很容易绕过。

Is there any way to detect if something (whether it be Cycript, gdb, or any similar tool that can be used for cracking the process) is attached to the process, while not being rejected from App Store? 有没有办法检测是否有某些东西 (无论是Cycript,gdb,还是任何可用于破解流程的类似工具)附加到流程中,而不是被App Store拒绝?

EDIT: This is not a duplicate of Detecting if iOS app is run in debugger . 编辑:这不是检测iOS应用程序是否在调试器中运行的重复。 That question is more related to outputting and it checks an output stream to identify if there's an output stream attached to a logger, while my question is not related to that (and that check doesn't cover my condition). 该问题与输出更相关,它检查输出流以确定是否有输出流附加到记录器,而我的问题与此无关(并且该检查不包括我的条件)。

gdb detection is doable via the linked stackoverflow question - it uses the kstat to determine if the process is being debugged. gdb检测可以通过链接的stackoverflow问题来实现 - 它使用kstat来确定进程是否正在被调试。 This will detect if a debugger is currently attached to the process. 这将检测调试器当前是否附加到进程。

There is also a piece of code - Using the Macro SEC_IS_BEING_DEBUGGED_RETURN_NIL in iOS app - which allows you to throw in a macro that performs the debugger attached check in a variety of locations in your code (it's C/Objective-C). 还有一段代码 - 在iOS应用程序中使用宏SEC_IS_BEING_DEBUGGED_RETURN_NIL - 它允许您在代码中的各个位置(它是C / Objective-C)引入一个执行调试器附加检查的宏。

As for detecting Cycript, when it is run against a process, it injects a dylib into the process to deal with communications between the cycript command line and the process - the library has part of the name looking like cynject . 至于检测Cycript,当它针对一个进程运行时,它会在进程中注入一个dylib来处理cycript命令行和进程之间的通信 - 该库的部分名称看起来像cynject That name doesn't look similar to any libraries that are present on a typical iOS app. 该名称与典型iOS应用程序中存在的任何库类似。 This should be detectable with a little loop like ( C ): 这应该可以通过像( C )这样的小循环来检测:

BOOL hasCynject() {
    int max = _dyld_image_count();
    for (int i = 0; i < max; i++) {
        const char *name = _dyld_get_image_name(i);
        if (name != NULL) {
            if (strstr(name, "cynject") == 0) return YES;
        }
    }
}

Again, giving it a better name than this would be advisable, as well as obfuscating the string that you're testing. 同样,给它一个比这更好的名称是可取的,以及混淆你正在测试的字符串。

These are only approaches that can be taken - unfortunately these would only protect you in some ways at run-time, if someone chooses to point IDA or some other disassembler at it then you would not be protected. 这些只是可以采取的方法 - 不幸的是,这些只会在运行时以某种方式保护您,如果有人选择指向IDA或其他一些反汇编程序,那么您就不会受到保护。

The reason that the check for debugger is implemented as a macro is that you would be placing the code in a variety of places in the code, and as a result someone trying to fix it would have to patch the app in a variety of places. 将调试器检查作为宏实现的原因是您将代码放在代码中的各个位置,因此有人试图修复它必须在各种地方修补应用程序。

Based on @petesh's answer, I found the below code achieved what I wanted on a jailbroken phone with Cycript. 基于@ petesh的回答,我发现下面的代码在带有Cycript的越狱手机上达到了我想要的效果。 The existence of printf strings is gold to a reverse engineer, so this code is only suitable for demo / crack-me apps. printf字符串的存在是反向工程师的黄金,所以这段代码只适用于demo / crack-me应用程序。

#include <stdio.h>
#include <string.h>
#include <mach-o/dyld.h>

int main ()
{
        int max = _dyld_image_count();
        for (int i = 0; i < max; i++) {
            const char *name = _dyld_get_image_name(i);
            const char needle[11] = "libcycript";
            char *ret;

            if ((ret = strstr(name, needle)) != NULL){
                printf("%s\nThe substring is: %s\n", name, ret);
            }
        }

    return 0;
}

As far as I know, Cycript process injection is made possible by debug symbols. 据我所知,Cycript过程注入可以通过调试符号实现。 So, if you strip out debug symbols for the App Store release (the default build setting for the Release configuration), that would help. 因此,如果您删除App Store版本的调试符号(Release配置的默认构建设置),那将有所帮助。

Another action you could take, which would have no impact on the usability of the App, would be to use an obfuscator. 您可以采取的另一个操作,即对App的可用性没有影响,将使用混淆器。 However, this would render any crash reports useless, since you wouldn't be able to make sense of the symbols, even if the crash report was symbolicated. 但是,这会导致任何崩溃报告无效,因为即使崩溃报告符号化,您也无法理解符号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM