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{//setIMPstruct rebinding gt;gt.name = "method_getImplementation";gt.replacement = my_getIMP;gt.replaced = (void *)&getIMP;//getIMPstruct 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(@"---- 防止状态 ------");//如果__RESTRICT字段被绕过,开始开名单检测CheckWhitelist()}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;
}#pragma mark -- 白名单监测
bool CheckWhitelist(){int count = _dyld_image_count();//加载了多少数量for (int i = 0; i < count; i++) {//遍历拿到库名称!const char * imageName = _dyld_get_image_name(i);if (!strstr(libraries, imageName)&&!strstr(imageName, "/var/mobile/Containers/Bundle/Application")) {printf("该库非白名单之内!!\n%s",imageName);return NO;}return YES;
}
  • 3.2 原理就是使用系统的函数帮我们检测自己设定的__RESTRICT是否被更改,如果被更改说明我们被Hook了,接下来在被hook的字段中增加自己的处理逻辑即可。

总结:对最后一个防护代码也很容易进行攻击,比如找到hasRestrictedSegment函数,让其直接返回YES。所以建议将该函数进行封装,尽量不要使用Bool作为返回值。综上: 攻和守本来就是一个博弈的过程,没有绝对安全的城墙。

最后附上过滤白名单源码下载,直接拖入工程即可使用,达到较好的代码防护目的。如果帮助到你请给一个Star。

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

作者:Qinz
链接:https://www.jianshu.com/p/655c91b61f8a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

iOS安全之三攻三防相关推荐

  1. iOS应用开发攻略 pdf电子书

    尊敬的用户您好,由于该iOS应用开发攻略pdf书受百度网盘影响无法做公共分享,只能私密分享,有不到之处请多多谅解! 百度链接: http://pan.baidu.com/s/1xPovn   密码: ...

  2. 印尼玩lol注册哪个服务器,《LOL手游》印尼服怎么注册 安卓IOS注册流程攻略

    导 读 LOL手游印尼服终于上线咯.相信大家都想去尝试一波,印尼服作为国际外服,想要体验就需要注册账号哦,下面九游小编就带来详细注册方法,快来看看吧~ 云顶之弈手游安卓ios注册流程详解 国服英雄联盟 ...

  3. Flash开发iOS应用全攻略(四)——如何为iTunes Connect准备应用

    在上周我介绍了如何在Flash里发布iOS应用,以及如何申请成为合法的iOS开发者.如何使用iOS开发者授权和申请证书.今天我会给大家介绍一下如果你打算将应用发布到 Apple应用程序商店,都应该做些 ...

  4. Flash开发iOS应用全攻略(三)——如何使用iOS开发者授权以及如何申请证书

    上一篇我介绍了如何申请成为合法的iOS开发者,这篇文章会详细介绍如何使用授权文件(.mobileprovision)和签名证书文件(.cer) 在缴费成功后会收到一份来自Apple Developer ...

  5. Flash发布iOS应用全攻略(二)——如何成为一个合法的iOS开发者

    上一篇文章里,我们介绍了如何在Flash里发布iOS应用.但是在发布设置中需要用到几个文件使得发布流程无法继续进行.这篇文章我会具体介绍一下如何成为一个合法的iOS开发者. iOS开发者的申请流程 如 ...

  6. Flash发布iOS应用全攻略(一)——如何在Flash里发布iOS应用

    这个系列的文章会给大家介绍一下如何在Flash Professional CS5里发布一个iOS应用,以及如何最终上传到Apple App Store.主要知识点如下: 使用Flash Profess ...

  7. 为什么我花了三个半月准备的面试还是砸了?附 iOS 开发者求职攻略

    最近我被一家公司拒了. 为了申请这家公司我花了三个半月的心血.我事先研究了这个公司的一切,对它了如指掌.他们的创始人在网上公开发表过的任何东西我都可以倒背如流. 不过我还是想的太美了. 就像在博客上写 ...

  8. iOS开发面试攻略(KVO、KVC、多线程、锁、runloop、计时器)

    KVO & KVC KVO用法和底层原理 使用方法:添加观察者,然后怎样实现监听的代理 KVO底层使用了 isa-swizling的技术. OC中每个对象/类都有isa指针, isa 表示这个 ...

  9. jdk1.8 官网下载 必须注册_英雄联盟手游内测资格申请流程(安卓,IOS,下载攻略大全)...

    预约网站:https://wildrift.leagueoflegends.com/zh-tw/ 如果你还没有下载预约成功,一定一定要认真看这篇文章,全网最全最详细的英雄联盟手游下载教程了,如果在公测 ...

最新文章

  1. cocos2d-x 弹出对话框
  2. React开发(113):git 操作记录
  3. IOS6 新特性之UIRefreshControl
  4. 分段线性变换与直方图修正
  5. python-往对象中添加属性值
  6. 纪念我2014.1.4 中国银行广东分行面试
  7. 蚂蚁集团回应两地暂缓上市;​iPhone 有望采用侧面指纹识别;Pyston v2 发布|极客头条
  8. 慕课软件质量保证与测试(习题集)
  9. 使用函数 imnoise 对图像添加噪声
  10. 【系统分析师之路】系统分析师历年真题大汇总
  11. 做支付行业这些支付方式你需要知道!
  12. github添加设置ssh key
  13. 玩苹果为什么要越狱?
  14. 网卡设置不当造成断线
  15. qml+QQuickPaintedItem数学公式编辑器的实现
  16. SAP那些事-生产订单结算规则修改
  17. 免校准的电量计量芯片_技术 | 免校准电能计量芯片,让家电智能化更简单
  18. 等我装完B 我再收拾你 Wating me to fuck you
  19. SpringBoot项目启动 错误: 找不到或无法加载主类 com.abc.demo.DemoApplication
  20. 为什么打开wps文字背景是绿色的?怎么变成白色的呢?

热门文章

  1. xshell突然卡住不动了怎么回事?
  2. 景联文科技|两种常见的视频标注方法
  3. CCF CSP 201812-2 小明放学 解题思路及经验总结
  4. 让python飞:形象理解python 全局变量、局部变量、内部函数、外部函数、ascii码、内置函数
  5. 【2023下半年】软考报名考试时间 软考报名入口
  6. C++将数据写入文件
  7. 2021.1.20--备战信息系统项目管理师学习笔记
  8. 第1条:了解Objective-C语言的起源
  9. 电路驱动LED数码管时,喇叭有电流声
  10. spring5下载安装(等于向IDE中导入模块)