如何实现PT_DENY_ATTACH(iOS中的反调试)

如何实现PT_DENY_ATTACH(iOS中的反调试),ios,ibm-mobilefirst,Ios,Ibm Mobilefirst,PT_DENY_ATTACH是一种反调试功能,有助于防止调试器连接到应用程序。以下代码可以在main()中实现,以防止GDB附加到应用程序: #import <dlfcn.h> #import <sys/types.h> typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data); #define PT_DENY_ATTACH 31 void disable_gdb() {

PT_DENY_ATTACH是一种反调试功能,有助于防止调试器连接到应用程序。以下代码可以在main()中实现,以防止GDB附加到应用程序:

#import <dlfcn.h>
#import <sys/types.h>
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#define PT_DENY_ATTACH 31
void disable_gdb() {
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
}
int main(int argc, char *argv[]) {
@autoreleasepool {
#ifdef DEBUG
//do nothing
#else
disable_gdb();
#endif
}}
#导入
#进口
typedef int(*ptrace_ptr_t)(int请求、pid_t_pid、caddr_t_addr、int数据);
#定义PT_DENY_ATTACH 31
void disable_gdb(){
void*handle=dlopen(0,RTLD_全局| RTLD_现在);
ptrace_ptr_t ptrace_ptr=dlsym(手柄,“ptrace”);
ptrace_ptr(PT_DENY_ATTACH,0,0,0);
dlclose(手柄);
}
int main(int argc,char*argv[]){
@自动释放池{
#ifdef调试
//无所事事
#否则
禁用_gdb();
#恩迪夫
}}

注意:根据此工具的wiki页面,它已被禁用,不得使用:

重要提示:这个把戏已经被海盗利用过了。不要依赖它

假设您指的是在MobileFirst Studio 7.1中创建的混合应用程序,那么这与任何其他iOS应用程序都没有什么不同


混合应用程序的最终结果仍然是一个Xcode项目,您可以在Xcode中打开它来构建应用程序。这意味着您需要将代码放在Xcode项目中的同一位置,就像这是一个常规的Xcode项目一样(事实上是这样)。正如@Idan Adar所指出的那样。

-这个技巧是可行的,但如果您想在任何教育或其他目的中尝试,您可以尝试执行以下操作:

  • 添加u'r应用程序的定义,以允许u在需要时运行和调试

    #define SOME
    
  • 在main.m中添加以下代码

    #define SOME
    
    #import <UIKit/UIKit.h>
    #import "AppDelegate.h"
    
    #ifdef SOME
    
    #import <dlfcn.h>
    #import <sys/types.h>
    
     typedef int (*ptrace_ptr_t)(int request, pid_t pid, caddr_t addr, int data);
    #if !defined(PT_DENY_ATTACH)
    #define PT_DENY_ATTACH 31
    #endif  // !defined(PT_DENY_ATTACH)
    
     void disable_gdb();
    
     int main(int argc, char *argv[])
    {
    //   disable_gdb();
    @autoreleasepool {
              return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
    }
    
     void disable_gdb()
    {
              void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
              ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
              ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
              dlclose(handle);
    }
    
     int main3(int argc, char *argv[])
    {
              return -1;
    }
    
    #else
    
     int main(int argc, char *argv[])
    {
    @autoreleasepool {
              return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
      }
    }
    
    #endif
    
    #定义一些
    #进口
    #导入“AppDelegate.h”
    #如果有的话
    #进口
    #进口
    typedef int(*ptrace_ptr_t)(int请求、pid_t pid、caddr_t addr、int数据);
    #如果!已定义(PT_DENY_ATTACH)
    #定义PT_DENY_ATTACH 31
    #endif/!已定义(PT_DENY_ATTACH)
    void disable_gdb();
    int main(int argc,char*argv[])
    {
    //禁用_gdb();
    @自动释放池{
    返回UIApplicationMain(argc、argv、nil、NSStringFromClass([AppDelegate类]);
    }
    }
    void disable_gdb()
    {
    void*handle=dlopen(0,RTLD_全局| RTLD_现在);
    ptrace_ptr_t ptrace_ptr=dlsym(手柄,“ptrace”);
    ptrace_ptr(PT_DENY_ATTACH,0,0,0);
    dlclose(手柄);
    }
    int main3(int argc,char*argv[])
    {
    返回-1;
    }
    #否则
    int main(int argc,char*argv[])
    {
    @自动释放池{
    返回UIApplicationMain(argc、argv、nil、NSStringFromClass([AppDelegate类]);
    }
    }
    #恩迪夫
    

  • -关于

    伙计们,有一些好的开始点这是真的,这个技巧已经被解决了,可以通过重写绕过,但是看看

    在这里,来自iphonedevwiki.net的家伙们展示了另一种在汇编中实现相同功能的方法,使得修补变得更加困难。因此,要绕过此程序集实现,必须对Mach-O二进制文件进行解密并覆盖函数的实现,例如,攻击者可以将函数中的所有程序集指令仅与不起任何作用的
    nop
    指令交换。但如果您混淆了组装例程,攻击者将更难识别正在发生的事情,因此只有最有经验的人才能绕过它

    对于那些不知道如何在Swift 5项目中编写汇编的人,以下是您需要做的事情:

  • 创建一个新的
    C
    文件+头
  • 让我们将它们命名为
    disable\u debuggers\u advanced.c
    disable\u debuggers\u advanced.h
  • 禁用调试器\u advanced.c
    中添加以下内容:
  • #包括“禁用调试高级.h”
    void mRiYXNnZnZmZGF2Ym(){
    //不需要对这些字符串进行编码,因为它们将被直接编译,它们不会出现在二进制文件的“数据”段中。
    __asm(
    “mov r0,#31\n”//set#定义PT#u DENY#u连接(31)到r0
    “移动r1,#0\n”//clear r1
    “移动r2,#0\n”//clear r2
    “mov r3,#0\n”//clear r3
    “mov ip,#26\n”//将指令指针设置为syscal 26
    “svc#0x80\n”//svc(以前的SWI)生成一个主管调用。主管调用通常用于从操作系统请求特权操作或访问系统资源
    );
    }
    
  • 禁用调试器\u advanced.h
    中添加以下内容:
  • 
    #ifndef禁用\u调试\u高级\u h
    #定义禁用调试高级
    #包括
    /**
    原始名称:`disable_gdb_advanced()`
    此函数使进程通过以下方式拒绝调试器的附加请求:
    模拟macOS上已有的功能:
    ptrace(PT_DENY_ATTACH,0,0,0);
    通过直接用汇编语言实现。
    这种禁用调试程序的方法为攻击者所熟知,但他们无法轻松绕过它
    因为它是内核内存空间的一部分。
    请注意,这将使XCode无法将其调试程序连接到进程,
    所以只在发布版本中运行它。
    资料来源:https://iphonedevwiki.net/index.php/Crack_prevention#PT_DENY_ATTACH
    */
    void mRiYXNnZnZmZGF2Ym(void)uuuu属性uuu((始终在线));
    #endif/*禁用调试高级*/
    
  • #包括“disable_debug_advanced.h”
    添加到桥接头中,如果您的项目还没有桥接头,则添加桥接头
  • 现在可以调用此函数来禁用调试器

    请注意,这将使XCode调试器收支平衡,因此仅在发布版本中使用它

    如果您想知道
    \uuuu属性((总是内联的))
    部分和奇怪的名称,那是因为我们希望函数尽可能隐藏。如果您不熟悉函数内联,您可以观看我关于函数内联的视频,在那里我对它进行了深入的描述,或者您可以阅读。即使这是一个速度编译器优化,它也可以给我们带来好处,因为如果您从多个位置调用它,攻击者将更难修补所有函数体
    #import "AppDelegate.h"
    #import "Application.h"
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/sysctl.h>
    #include <stdlib.h>
    
    typedef int (*PYStdWriter)(void *, const char *, int);
    static PYStdWriter _oldStdWrite;
    #define   PT_DENY_ATTACH  31
    
    int __pyStderrWrite(void *inFD, const char *buffer, int size)
    {
        if ( strncmp(buffer, "AssertMacros:", 13) == 0 ) {
            return 0;
        }
        return _oldStdWrite(inFD, buffer, size);
    }
    
    static int is_debugger_present(void)
    {
        int name[4];
        struct kinfo_proc info;
        size_t info_size = sizeof(info);
    
        info.kp_proc.p_flag = 0;
    
        name[0] = CTL_KERN;
        name[1] = KERN_PROC;
        name[2] = KERN_PROC_PID;
        name[3] = getpid();
    
        if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {
            perror("sysctl");
            exit(-1);
        }
        return ((info.kp_proc.p_flag & P_TRACED) != 0);
    }
    
    int main(int argc, char *argv[]) {
    
    
    #ifdef DEBUG
        _oldStdWrite = stderr->_write;
        stderr->_write = __pyStderrWrite;
        @autoreleasepool {
            return UIApplicationMain(argc, argv, NSStringFromClass([Application class]), NSStringFromClass([AppDelegate class]));
        }
    #else
        //Anti Debugging Code
        //https://coredump.gr/articles/ios-anti-debugging-protections-part-2/
    
        //ptrace(PT_DENY_ATTACH, 0, 0, 0);
        printf("Looping forever");
        fflush(stdout);
        while (1)
        {
            sleep(1);
            if (is_debugger_present())
            {
                //[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isAntiDebug"];
                printf("Debugger detected! Terminating...\n");
                return -1;
            }
            printf(".");
            fflush(stdout);
    
            _oldStdWrite = stderr->_write;
            stderr->_write = __pyStderrWrite;
            @autoreleasepool {
                //[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isAntiDebug"];
                int retVal = UIApplicationMain(argc, argv, NSStringFromClass([Application class]), NSStringFromClass([AppDelegate class]));
                return retVal;
            }
        }
    
    #endif
    }
    
    #if defined (__arm64__)
        __asm(
            "mov x0, #26\n" // ptrace
            "mov x1, #31\n" // PT_DENY_ATTACH
            "mov x2, #0\n"
            "mov x3, #0\n"
            "mov x16, #0\n"
            "svc #128\n"
        );