【iOS逆向与安全】越狱检测与过检测附ida伪代码

这篇具有很好参考价值的文章主要介绍了【iOS逆向与安全】越狱检测与过检测附ida伪代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先在网上查找一些检测代码

放入项目运行,用 ida 打开后 F5 得到下面的

__int64 __usercall sub_10001B3F0@<X0>(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, __int64 a8, __int64 a9, __int64 a10, __int64 a11, __int64 a12, ...)
{
  __int64 v12; // x0
  __int64 v13; // x21
  int v14; // w20
  __int64 v15; // x0
  __int64 v16; // x21
  int v17; // w22
  BOOL v18; // w23
  BOOL v19; // w24
  BOOL v20; // w25
  int v21; // w22
  char *v22; // x21
  __int64 v23; // x0
  __int64 v24; // x20
  __int64 result; // x0
  __int64 v26; // x0
  __int64 v27; // x21
  __int64 v28; // x0
  __int64 v29; // x22
  __int64 v30; // x0
  __int64 v31; // x20
  __int64 v32; // x0
  __int64 v33; // x20
  const char *v34; // [xsp+1C0h] [xbp+70h]
  va_list va; // [xsp+1C0h] [xbp+70h]
  __int64 v36; // [xsp+1C8h] [xbp+78h]
  __int64 v37; // [xsp+1D0h] [xbp+80h]
  __int64 v38; // [xsp+1D8h] [xbp+88h]
  va_list va1; // [xsp+1E0h] [xbp+90h]

  va_start(va1, a12);
  va_start(va, a12);
  v34 = va_arg(va1, const char *);
  v36 = va_arg(va1, _QWORD);
  v37 = va_arg(va1, _QWORD);
  v38 = va_arg(va1, _QWORD);
  v12 = ((__int64 (__fastcall *)(void *))sub_104BFCC20)(&OBJC_CLASS___NSFileManager);
  v13 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v12);
  v14 = sub_104C07D60();
  ((void (__fastcall *)(__int64))objc_release)(v13);
  v15 = ((__int64 (__fastcall *)(void *))sub_104BFCC20)(&OBJC_CLASS___NSFileManager);
  v16 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v15);
  v17 = sub_104C07D60();
  ((void (__fastcall *)(__int64))objc_release)(v16);
  v18 = stat("/Library/MobileSubstrate/MobileSubstrate.dylib", (struct stat *)va1) == 0;
  v19 = stat("/Applications/Cydia.app", (struct stat *)va1) == 0;
  v20 = stat("/var/lib/cydia/", (struct stat *)va1) == 0;
  v21 = (stat("/var/cache/apt", (struct stat *)va1) == 0 || v20 || v19 || v18) | v17 | v14;
  if ( dladdr(&_stat, (Dl_info *)va) )
    v21 |= strcmp(v34, "/usr/lib/system/libsystem_kernel.dylib") != 0;
  v22 = getenv("DYLD_INSERT_LIBRARIES");
  v23 = ((__int64 (__fastcall *)(void *))sub_104C831E0)(&unk_1063357B0);
  v24 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v23);
  if ( v22 || v21 )
  {
    sub_104C65B80();
    ((void (__fastcall *)(__int64))objc_release)(v24);
    v26 = ((__int64 (__fastcall *)(void *))sub_104C2B780)(&unk_1063457C8);
    v27 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v26);
    v28 = sub_104C031E0();
    v29 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v28);
    v30 = ((__int64 (__fastcall *)(void *))sub_104C8B4A0)(&OBJC_CLASS___NSString);
    v31 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v30);
    ((void (__fastcall *)(void *))sub_104C96DA0)(&unk_106361810);
    ((void (__fastcall *)(__int64))objc_release)(v31);
    ((void (__fastcall *)(__int64))objc_release)(v29);
    ((void (__fastcall *)(__int64))objc_release)(v27);
    v32 = ((__int64 (__fastcall *)(void *))sub_104BDFEA0)(&unk_10633F200);
    v33 = ((__int64 (__fastcall *)(__int64))objc_retainAutoreleasedReturnValue)(v32);
    ((void (__fastcall *)(void *))sub_104C86300)(&unk_10633F250);
    result = ((__int64 (__fastcall *)(__int64))objc_release)(v33);
  }
  else
  {
    sub_104C05A80();
    ((void (__fastcall *)(__int64))objc_release)(v24);
    result = ((__int64 (__fastcall *)(void *))sub_104BE4C00)(&OBJC_CLASS___UIView);
  }
  return result;
}

用 frida hook


frida-trace -UF -i "stat" -f xxx
frida-trace -UF -i "dladdr" -f xxxx


log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');



hook stat

/*
 * Auto-generated by Frida. Please modify to match the signature of stat.
 * This stub is currently auto-generated from manpages when available.
 *
 * For full API reference, see: https://frida.re/docs/javascript-api/
 */

{
  /**
   * Called synchronously when about to call stat.
   *
   * @this {object} - Object allowing you to store state for use in onLeave.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {array} args - Function arguments represented as an array of NativePointer objects.
   * For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
   * It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
   * @param {object} state - Object allowing you to keep state across function calls.
   * Only one JavaScript function will execute at a time, so do not worry about race-conditions.
   * However, do not use this to store function arguments across onEnter/onLeave, but instead
   * use "this" which is an object for keeping state local to an invocation.
   */
  onEnter(log, args, state) {
    log(`stat(fildes=${args[0]}, buf=${args[1]})`);
    log(`stat(fildes=${(args[0].readUtf8String())}]`);

    this.args0 = args[0]; // 入参
    this.args2 = args[1]; // 返回值指针

   

  },

  /**
   * Called synchronously when about to return from stat.
   *
   * See onEnter for details.
   *
   * @this {object} - Object allowing you to access state stored in onEnter.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {NativePointer} retval - Return value represented as a NativePointer object.
   * @param {object} state - Object allowing you to keep state across function calls.
   */
  onLeave(log, retval, state) {
    log(`before:=${retval}`);
    var newstr = this.args0 .readUtf8String();//oldNSStr.toString();
    if(newstr.search("Cydia")>0
||  newstr.search("MobileSubstrate")>0
||  newstr.search("private---")>0
||  newstr.search("cydia")>0
||  newstr.search("Applications")>0
||  newstr.search("apt")>0
      ){
      log("=========checkJB=hook===========" );
      //var str = ObjC.classes.NSString.stringWithString_('{"ret":0,"msg":null,"data":{"c":3,"t":6,"w":60,"fc":1}}');  // 对应的oc语法:NSString *str = [NSString stringWithString:@"hi with!"];
      //args[2] = str;

    retval.replace(0xf1)  // 修改返回值 0xffffffffffffffff
    log(`before:=${retval}`);
    log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');
    }


  }
}

hook md5

frida-trace -UF -i "CC_MD5" -f xxxxxxx.xxx.xxxx

/*
 * Auto-generated by Frida. Please modify to match the signature of CC_MD5.
 * This stub is currently auto-generated from manpages when available.
 *
 * For full API reference, see: https://frida.re/docs/javascript-api/
 */

{
  /**
   * Called synchronously when about to call CC_MD5.
   *
   * @this {object} - Object allowing you to store state for use in onLeave.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {array} args - Function arguments represented as an array of NativePointer objects.
   * For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
   * It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
   * @param {object} state - Object allowing you to keep state across function calls.
   * Only one JavaScript function will execute at a time, so do not worry about race-conditions.
   * However, do not use this to store function arguments across onEnter/onLeave, but instead
   * use "this" which is an object for keeping state local to an invocation.
   */
  onEnter(log, args, state) {
    log('CC_MD5()');
    this.args0 = args[0]; // 入参
    this.args2 = args[2]; // 返回值指针
  },

  /**
   * Called synchronously when about to return from CC_MD5.
   *
   * See onEnter for details.
   *
   * @this {object} - Object allowing you to access state stored in onEnter.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {NativePointer} retval - Return value represented as a NativePointer object.
   * @param {object} state - Object allowing you to keep state across function calls.
   */
  onLeave(log, retval, state) {
    var ByteArray = Memory.readByteArray(this.args2, 16);
    var uint8Array = new Uint8Array(ByteArray);

    var str = "";
    for(var i = 0; i < uint8Array.length; i++) {
        var hextemp = (uint8Array[i].toString(16))
        if(hextemp.length == 1){
            hextemp = "0" + hextemp
        }
        str += hextemp;
    }
    log(`CC_MD5(${this.args0.readUtf8String()})`);    // 入参
    log(`CC_MD5()=${str}=`);  
  }
}

fishhook


    rebind_symbols((struct rebinding[1]){{"stat", my_stat, (void *)&orig_stat}}, 1);
    rebind_symbols((struct rebinding[1]){{"strcmp", my_strcmp, (void *)&orig_strcmp}}, 1);
    
//***********************abort********************************
//void     abort(void) __dead2;
 void abort_hook(void) {
}
static void (*abort_old)(void);


//int     stat(const char *, struct stat *) __DARWIN_INODE64(stat);
static int     (*orig_stat)(const char *age1, struct stat * age2) ;
static int my_stat(const char *age1, struct stat *age2){
    
    //NSLog(@"[orig_stat =================]");
    printf("[orig_stat =hook================]\n my_stat  age1=%s ,Cydia=%s\n ",age1,strstr(age1, "Cydia"));
     int isfind = 0;
    if(strstr(age1, "Cydia") != NULL){
        isfind = 1;
    }else if (strstr(age1, "cydia") != NULL){
        isfind = 1;
    }else if (strstr(age1, "MobileSubstrate") != NULL){
        isfind = 1;
    }else if (strstr(age1, "Applications") != NULL){
        isfind = 1;
    }else if (strstr(age1, "apt") != NULL){
        isfind = 1;
    }
     if(isfind == 1){
         NSLog(@" ========hook=stat===%s\n ",age1);
         return 1;//返回不存在
     }
    return orig_stat(age1,age2);
}

//strcmp
//如果返回值 < 0,则表示 str1 小于 str2。
//如果返回值 > 0,则表示 str2 小于 str1。
//如果返回值 = 0,则表示 str1 等于 str2。
//int     strcmp(const char *__s1, const char *__s2);
static int (*orig_strcmp)(const char *__s1, const char *__s2);
static int my_strcmp(const char *__s1, const char *__s2){
    
    if(strstr(__s2, "libsystem_kernel") != NULL){
        NSLog(@" ========hook=strcmp===%s %s\n ",__s1,__s2);
        return 0;//返回相等
    }
    return orig_strcmp(__s1,__s2);
}

下面是网上找的源码文章来源地址https://www.toymoban.com/news/detail-768322.html


//这里都是一些越狱后的手机带的一些框架和工具,未越狱的手机是装不上的。
- (void)isOk0 {
    NSString *cydiaPath = @"/Applications/Cydia.app";
    NSString *aptPath = @"/private/var/lib/apt/";
    NSString *applications = @"/User/Applications/";
    NSString *Mobile = @"/Library/MobileSubstrate/MobileSubstrate.dylib";
    NSString *bash = @"/bin/bash";
    NSString *sshd =@"/usr/sbin/sshd";
    NSString *sd = @"/etc/apt";
    if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {
        exit(0);
    }
    if([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {
        exit(0);
    }
    if([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:applications]){
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:Mobile]){
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:bash]){
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:sshd]){
        exit(0);
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:sd]){
        exit(0);
    }
}

- (void)isOK1 {
    //可能存在hook了NSFileManager方法,此处用底层C stat去检测
    // /Library/MobileSubstrate/MobileSubstrate.dylib 最重要的越狱文件,几乎所有的越狱机都会安装MobileSubstrate
    // /Applications/Cydia.app/ /var/lib/cydia/绝大多数越狱机都会安装
    struct stat stat_info;
    if (0 == stat("/Library/MobileSubstrate/MobileSubstrate.dylib", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/Applications/Cydia.app", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/var/lib/cydia/", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/var/cache/apt", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/var/lib/apt", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/etc/apt", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/bin/bash", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/bin/sh", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/usr/sbin/sshd", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/usr/libexec/ssh-keysign", &stat_info)) {
        exit(0);
    }
    if (0 == stat("/etc/ssh/sshd_config", &stat_info)) {
        exit(0);
    }
}
//strcmp
//如果返回值 < 0,则表示 str1 小于 str2。
//如果返回值 > 0,则表示 str2 小于 str1。
//如果返回值 = 0,则表示 str1 等于 str2。
- (void)isOK2 {
    //可能存在stat也被hook了,可以看stat是不是出自系统库,有没有被攻击者换掉
    //这种情况出现的可能性很小
    int ret;
    Dl_info dylib_info;
    int (*func_stat)(const char *,struct stat *) = stat;
    if ((ret = dladdr(&func_stat, &dylib_info))) {
        NSLog(@"lib:%s",dylib_info.dli_fname);      //如果不是系统库,肯定被攻击了
        if (strcmp(dylib_info.dli_fname, "/usr/lib/system/libsystem_kernel.dylib")) {    //不相等,肯定被攻击了,相等为0
            exit(0);
        }
    }
}
- (void)isOK3 {
    //列出所有已链接的动态库:
    //通常情况下,会包含越狱机的输出结果会包含字符串: Library/MobileSubstrate/MobileSubstrate.dylib 。
    uint32_t count = _dyld_image_count();
    for (uint32_t i = 0 ; i < count; ++i) {
        NSString *name = [[NSString alloc]initWithUTF8String:_dyld_get_image_name(i)];
        if ([name containsString:@"Library/MobileSubstrate/MobileSubstrate.dylib"]) {
            exit(0);
        }
    }
}
- (void)isOK4 {
    //如果攻击者给MobileSubstrate改名,但是原理都是通过DYLD_INSERT_LIBRARIES注入动态库
    //那么可以,检测当前程序运行的环境变量
    char *env = getenv("DYLD_INSERT_LIBRARIES");
    if (env != NULL) {
        exit(0);
    }
}
//对于这些函数,不建议单独写方法,容易被hook掉,所以最好是写在不能被hook的函数里,比如application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions。。。
//谁TM会hook程序的初始化函数。。

到了这里,关于【iOS逆向与安全】越狱检测与过检测附ida伪代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 二进制代码反汇编逆向工具:IDA Pro(Win&Mac)v7.7 汉化版

    IDA Pro是一款交互式的、可编程的、可扩展的、多处理器的、交叉Windows或Linux WinCE MacOS平台主机来分析程序。它被公认为最好的花钱可以买到的逆向工程利器,已经成为事实上的分析敌意代码的标准并让其自身迅速成为攻击研究领域的重要工具。 功能丰富:IDA Pro提供了诸多功

    2024年02月20日
    浏览(47)
  • 《算法还原 - CTF》逆向exe程序 + ida Pro 反汇编分析伪C代码 + python算法复现

    二进制安全,能干什么 逆向分析: 负责成品软件的技术原理. 比如分析竞品软件,吸取技术上的优点,进行技术难点公关 病毒分析: 负责分析病毒样本.研究恶意代码的技术手段等工作.主要是在安全公司,尤其是在杀毒软件公司需求较多.如360 、腾讯电脑管家等. 漏洞挖掘分析: 负责

    2024年01月22日
    浏览(52)
  • IDA-逆向分析-工具教程-IDA简介-反汇编工具-功能窗口

    介绍了IDA反汇编原理分为, 线性扫描反汇编和递归下降反汇编 。比较了两者的优点和缺点。线性扫描反汇编算法采用一种非常简单的方法来确定需要反汇编的指令的位置:一条指令结束、另一条指令开始的地方。因此,确定起始位置最为困难。常用的解决办法是,假设程序

    2024年02月10日
    浏览(43)
  • 【iOS逆向与安全】iOS插件开发入门

    前言 经过之前的学习,相信你已经能熟练的使用Frida-trace、IDA Pro等逆向工具。不过,仅仅到这肯定是不够的。接下来,学会把你逆向的结果打包成插件并运行,那iOS逆向,你也就真正的入门了。 一、目标 把逆向的结果制作成插件并运行 二、工具 mac系统 Xcode:插件开发工具

    2024年02月09日
    浏览(67)
  • 【iOS逆向与安全】iOS插件开发光速入门

    经过之前的学习,相信你已经能熟练的使用Frida-trace、IDA Pro等逆向工具。不过,仅仅到这肯定是不够的。接下来,学会把你逆向的结果打包成插件并运行,那iOS逆向,你也就真正的入门了。 把逆向的结果制作成插件并运行 mac系统 Xcode:插件开发工具 已越狱iOS设备:运行deb插

    2024年02月06日
    浏览(42)
  • 【iOS逆向与安全】原生程序与WebView交互

    WKWebView 是 iOS 应用中强大的组件,但如何在逆向工程中最好地利用它呢?本文将带您了解在逆向过程中遇到webview后的相关操作。这些技术将让您能够修改 WKWebView 行为,读写关键元素,接口拦截,并揭示更多有趣的可能性。 了解如何在 iOS 逆向工程中处理 WKWebView,包括 元素

    2024年02月02日
    浏览(59)
  • 【iOS逆向与安全】sms短信转发插件开发

    经过之前的分享,相信大家已经掌握了用户级的插件开发。勤奋好学的你是否对系统级的插件也有着浓厚的性趣,本篇文章将和大家一起学习如何分析并编写一款系统级的插件。 一步步分析并编写一个短信自动转发的deb插件 mac系统 已越狱iOS设备:脱壳及frida调试 IDA Pro:静态

    2024年02月10日
    浏览(43)
  • 【iOS逆向与安全】好用的一套 TCP 类

     初始化  发送数据 源码类 配置端口

    2024年02月07日
    浏览(42)
  • 【iOS逆向与安全】使用ollvm混淆你的源码

    当你在研究别人源码的时候,是不是期望着别人代码没有进行任何的防护和混淆。这时的你,是不是应该考虑一下自己代码的安全.本篇文章将告诉你,如何使用ollvm来混淆iOS端的代码【此文为入门贴,大佬请绕道】。 编译ollvm工具,并在Xcode中来混淆你的ipa或动态库,增加别

    2023年04月19日
    浏览(85)
  • 【iOS逆向与安全】编写一个使应用保持前台运行的系统插件

    iOS越狱为用户打开了无限的可能性,其中之一是便是开发系统级插件,为了确保应用程序一直保持在前台,即使在意外情况下也是如此。 本文将向您展示如何轻松编写这样的插件,让我们开始探索iOS系统插件的世界吧! 学会创建功能强大的iOS系统插件。 mac系统 frida:动态调

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包