iOS安全之三攻三防

作者: Qinz | 来源:发表于2019-03-19 17:28 被阅读82次
Qinz

互联网世界每分钟都在上演黑客攻击,由此导致的财产损失不计其数。金融行业在安全方面的重视不断加深,而传统互联网行业在安全方面并没有足够重视,这样导致开发的APP在逆向开发人员面前等同于裸奔,甚至有些小厂前后台在账号密码处理上采取明文传送,本地存储,这等同于将账号密码直接暴露无疑。当然即使采用加密传送,逆向APP后依然可以获取到账号密码,让你在神不知鬼不觉的情况下将账号密码发送到了黑客邮箱,所以攻防终究是一个相互博弈的过程。本文主要分析常见的几种攻击和防护手段,通过攻击你可以看到你的APP是如何被一步一步被攻破的。有了攻击,我们针对相应的攻击就是见招拆招了。

一、攻击原理
  1. 从APPStore下载正式版本版本应用,进行一键砸壳,绝大部分应用均可以脱壳成功。
  2. 使用脚本或第三方工具MonkeyDev对应用实现重签名。
  3. 利用动态调试(LLDB,Cycript,Reveal)和静态分析(反汇编),找到关键函数进行破解。
  4. Theos编写插件,让使用更加方便。
二、攻守第一回合
1. 第一攻武器:代码注入+method_exchangeImplementations

shell脚本实现iOS包重签名及代码注入的最后,我们成功使用method_exchange截获微信点击按钮,代码如下:

+(void)load
    {
        Method oldMethod = class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), @selector(onFirstViewRegester));
        
        Method newMethod = class_getInstanceMethod(self, @selector(test));
        
        method_exchangeImplementations(oldMethod, newMethod);
    }
    
-(void)test{
    NSLog(@"----截获到微信注册按钮点击------");
}
2. 第一防护盾:framwork+fishHook

关于为什么使用framwork而不是直接在代码中创建一个类,并在类的load方法中编写防护代码,原因是自己创建framwork的加载要早于代码注入的framwork,代码注入的framwork的执行要早于自己类load的加载,具体原理请看dyld加载应用启动原理详解。防护代码如下:

防exchange

注意:当我们检查到hook代码时,比较好的处理方式是将该手机的UDID,账号等信息发送给后台服务器,让后台服务器进行封号禁设备处理,而不是直接exit(0)让程序强制退出,因为这样的好处是让黑客很难定位。

三、攻守第二回合
1. 第二攻武器:MonkeyDev

MonkeyDev可以帮助我们更加方便的实现代码重签名和hook,底层是使用了方法交换的SET和GET方法进行hook,关于MoneyDev的使用在逆向iOS系统桌面实现一键清空徽标有讲。同样以截获微信注册按钮为例,hook代码示例如下:

%hook WCAccountLoginControlLogic
- (void)onFirstViewRegester:(id)arg{
    NSLog(@"---hook-----");
}

%end
2. 第二防护盾:依然framwork+fishHook
+(void)load{
    //setIMP
    struct rebinding gt;
    gt.name = "method_getImplementation";
    gt.replacement = my_getIMP;
    gt.replaced = (void *)&getIMP;
      //getIMP
    struct rebinding st;
    st.name = "method_setImplementation";
    st.replacement = my_setIMP;
    st.replaced = (void *)&setIMP;
    
    struct rebinding rebs[2] = {gt,st};
    rebind_symbols(rebs, 2);
    
}

//保存原来的交换函数
IMP  (*getIMP)(Method _Nonnull m);
IMP  (*setIMP)(Method _Nonnull m, IMP _Nonnull imp);


IMP  my_getIMP(Method _Nonnull m){
    NSLog(@"🍺----检查到了HOOk-----🍺");
    return nil;
}
IMP  my_setIMP(Method _Nonnull m, IMP _Nonnull imp){
    
    NSLog(@"🍺----检查到了HOOk-----🍺");
    return nil;
}

三、攻守第三回合

上面的两次攻击都是通过代码注入来实现hook目的,我们能不能防止第三方代码进行注入呢?答案当然是可以,接下来我们来防止第三方代码注入。

1. 第三防护盾:在编译设置阶段增加字段"-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null",如下图: 防止第三方代码注入
  • 1.1 增加该字段后在MachO文件就会增加_RESTRICT,__restrict段,如下图: image.png
  • 1.2 为什么增加这个字段就可以了呢?这里我们就要回归到dyld的源码了,在dyld加载过程中有一个函数hasRestrictedSegment就是用来判断是否存在__RESTRICT,__RESTRICT中是否是__restrict名称,如果是,则会禁止加载第三方注入的库文件,源码如下:

#if __MAC_OS_X_VERSION_MIN_REQUIRED
static bool hasRestrictedSegment(const macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
                
                //dyld::log("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0) 
                            return true;
                    }
                }
            }
            break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }
        
    return false;
}
#endif
2. 第三攻击武器:直接修改MachO二进制文件
  • 通过Synalyze It!工具更改MachO二进制文件字段,然后重新签名打包即可破坏该防护过程: 修改二进制
3. 第三防护2级护盾:代码过滤,增加白名单。
  • 3.1 既然禁止第三方注入代码都很容易被攻破,接下来我们就从代码入手,过滤第三方库注入库,增加白名单,代码如下:
@implementation ViewController
+(void)load
{
   
    const struct mach_header_64 * header = _dyld_get_image_header(0);
    if (hasRestrictedSegment(header)) {
        NSLog(@"---- 防止状态 ------");
    }else{
        NSLog(@"--- 防护字段被修改了 -----");
    }
    
}

static bool hasRestrictedSegment(const struct macho_header* mh)
{
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(struct macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND:
            {
                const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
                
                printf("seg name: %s\n", seg->segname);
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
                    const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict") == 0)
                            return true;
                    }
                }
            }
                break;
        }
        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
    }
    
    return false;
}
  • 3.2 原理就是使用系统的函数帮我们检测自己设定的__RESTRICT是否被更改,如果被更改说明我们被Hook了,接下来在被hook的字段中增加自己的处理逻辑即可。
总结:对最后一个防护代码也很容易进行攻击,比如找到hasRestrictedSegment函数,让其直接返回YES。所以建议将该函数进行封装,尽量不要使用Bool作为返回值。综上: 攻和守本来就是一个博弈的过程,没有绝对安全的城墙。
最后附上过滤白名单源码下载,直接拖入工程即可使用,达到较好的代码防护目的。如果觉得好用请给一个Star。

我是Qinz,希望我的文章对你有帮助。

相关文章

  • iOS安全之三攻三防

    互联网世界每分钟都在上演黑客攻击,由此导致的财产损失不计其数。金融行业在安全方面的重视不断加深,而传统互联网行业在...

  • iOS安全攻与防(总篇)

    iOS安全攻与防 本地数据攻与防 https UIWebview 第三方sdk与xcode 反编译与代码混淆 越狱...

  • fir.im Weekly - 让 iOS 应用更加安全

    攻易防难,关于 iOS 应用安全也许有些神秘。iOS Security , 源于@吴发伟_则平博客翻译的关于iOS...

  • Ios应用安全学习

    iOS应用安全 攻易防难,唯有缜密、多层的防护网络才能可靠的保护我们iOS应用程序的安全。那么,一个完善的iOS应...

  • iOS应用安全防护框架概述

    本文采集于 念茜攻易防难,唯有缜密、多层的防护网络才能可靠的保护我们iOS应用程序的安全。那么,一个完善的iOS应...

  • iOS攻防——(三)Cycript攻·防

    date: 2016-07-19 14:09:36 简介 Cycript允许开发人员探讨和修改iOS和Mac OS...

  • 三攻三防,高配8倍,顺丰快递

  • iOS App 攻与防

    签名 作为一个 iOS 开发者,在你开发使用的机器上应该已经有一个证书,一个公钥,以及一个私钥。这些是代码签名机制...

  • 黑客防攻与无线安全

    《黑客防攻与无线安全》在剖析用户进行黑客防御中迫切需要用到或迫切想要用到的技术时,力求对其进行“傻瓜”式的讲解,使...

  • iOS安全攻防: GDB依附的攻与防

    一 、GDB动态调试: 1、首先在越狱机中打开你要调试的app。 2、通过ssh远程连接到iOS设备。$ yuey...

网友评论

    本文标题:iOS安全之三攻三防

    本文链接:https://www.haomeiwen.com/subject/pvngmqtx.html