iOS安全之三攻三防

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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2219691.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

三防电子产品美军标MIL-STD-810G

MIL-STD-810标准详尽描述了环境管理和一系列工程实施过程&#xff0c;这对系统的可靠性设计和对环境的适应性设计具有重大价值。该标准包含了军方采购程序计划和工程规范&#xff0c;考虑了环境因素在设备服役周期各个环节对于设备的影响。文档中并没有要求具体的设计或测试规范…

android系统三防机,超机访问:当Android三防附体你如何看

三防手机是一种比较另类的手机。这类手机大多有这“彪悍魁梧”的机身&#xff0c;采用橡胶或者塑料材质的包裹。具有防水、防尘、防摔的特点。这类手机最主要的用途是为了满足特殊工作需求的使用者的需求&#xff0c;比如在户外采矿、勘测、户外探险等特殊专业领域。而随着现在…

小白网络安全学习手册—黑客

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟…

详解Anaconda + 如何在Anaconda上更换python版本

详解Anaconda 如何在Anaconda上更换python版本 宇内虹游 2018-10-09 16:02:26 101626 收藏 501 分类专栏&#xff1a; 研二上 每天一道编程题 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。…

Java基础:final、权限、内部类、引用类型

第一章 final关键字 1.1 概述 子类可以在父类的基础上改写父类内容&#xff0c;比如&#xff0c;方法重写。那么我们能不能随意的继承API中提供的类&#xff0c;改写其内容呢&#xff1f;显然这是不合适的。为了避免这种随意改写的情况&#xff0c;Java提供了final关键字&…

docker~全

文章目录 前言docker概念部署docker镜像操作容器常规操作运行容器列出容器删除容器:后台运行终止容器进入容器容器改名容器信息查看容器与宿主机间文件传输 docker网络容器端口暴露bridge模式自定义模式 host模式container模式None 模式 数据共享与持久化数据卷挂载主机目录 do…

python基础笔记二_面向对象

面向对象 Object Oriented 概述 面向过程 1.分析出解决问题的步骤&#xff0c;然后逐步实现。例如&#xff1a;婚礼筹办-- 发请柬&#xff08;选照片、措词、制作&#xff09;-- 宴席&#xff08;场地、找厨师、准备桌椅餐具、计划菜品、购买食材&#xff09;-- 婚礼仪式&am…

Java研发岗必问30+道高级面试题,java基础笔试面试题以及答案

引言 做了5年开发的我&#xff0c;阿里一直是我心之所向&#xff0c;如今我如愿以偿进入了国内互联网巨头——Alibaba&#xff01; 其实&#xff0c;今年下半年我面试不少互联网企业&#xff0c;像涂鸦智能&#xff0c;百度&#xff0c;京东&#xff0c;腾讯&#xff0c;字节…

(附源码)ssm失物招领系统 毕业设计 182317

失物招领系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对失物招领等问题&…

NodeJS 响应式故宫文化宣传网站计算机毕设源码61557

摘 要 21世纪时信息化的时代&#xff0c;几乎任何一个行业都离不开计算机&#xff0c;将计算机运用于景区文化宣传网站上也是十分常见的。过去使用手工的宣传管理方式对故宫文化宣传进行管理&#xff0c;造成了管理繁琐、难以维护等问题&#xff0c;如今使用计算机对故宫文化宣…

Redis高频面试题汇总(2021最新版)

本文已收录于专栏 ⭐️《Redis面试题汇总——2021最新版本》⭐️ 上千人点赞收藏&#xff0c;全套Redis高频面试题&#xff0c;大厂必备技能&#xff01; 面试官心理分析 从面试官的角度分析&#xff0c;出这道题的目的是为了考察你对缓存的认知水平&#xff0c;以及结合缓存…

测试技能提升HM-性能测试

性能测试分类 基准测试 狭义上讲&#xff1a;单用户测试&#xff08;单用户循环多次得到的数据&#xff09; 广义上讲&#xff1a;建立基准线&#xff0c;当系统的软硬件环境发生变化之后再进行一次基准测试以确定变化对性能的影响 基准测试的用途&#xff1a; 基准测试不会单…

【调试工具|mqtt-spy】mqtt客户端调试工具 mqtt-spy 详细使用教程

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

校园跑腿小程序还受欢迎不?

校园跑腿小程序是如今大学生群体中越来越受欢迎的一种服务模式。它为大学生提供了一个便捷的平台&#xff0c;使他们能够在校园内完成各类生活事务&#xff0c;如购买食品、快递取送、打印复印等。这种形式的服务在过去几年里在全球范围内迅速发展&#xff0c;并取得了巨大的成…

CTR特征建模:ContextNet MaskNet(Twitter在用的排序模型)

在之前的文章中 FiBiNet&FiBiNet模型&#xff0c;阐述了微博在CTR特征(Embedding)重要性建模方面的一些实践方向&#xff0c;今天再来学习下这个方面的两个相关研究&#xff1a;致力于特征和特征交互精炼(refine)的ContextNet和MaskNet&#xff0c;其中MaskNet也是Twitter(…

什么是粘包和拆包,Netty如何解决粘包拆包?

Netty粘包拆包 TCP 粘包拆包是指发送方发送的若干包数据到接收方接收时粘成一包或某个数据包被拆开接收。 如下图所示&#xff0c;client 发送了两个数据包 D1 和 D2&#xff0c;但是 server 端可能会收到如下几种情况的数据。 上图中演示了粘包和拆包的三种情况&#xff1a;…

tcp的拆包和粘包

tcp的拆包和粘包 简介 拆包和粘包是在socket编程中经常出现的情况&#xff0c;在socket通讯过程中&#xff0c;如果通讯的一端一次性连续发送多条数据包&#xff0c;tcp协议会将多个数据包打包成一个tcp报文发送出去&#xff0c;这就是所谓的粘包。而如果通讯的一端发送的数据…

TCP粘包和拆包

TCP粘包和拆包 &#xff08;1&#xff09;TCP是面向连接的&#xff0c;面向流的&#xff0c;提供可靠性服务。收发两端&#xff08;客户端和服务端&#xff09;都要有一一成对的socket&#xff0c;因此&#xff0c;发送端为了将多个发给接收端的包&#xff0c;更有效的发给对方…

Python拆包

Python拆包 怎么元组拆包&#xff1f;怎么字典拆包&#xff1f;怎么拆包赋值&#xff1f; 拆包&#xff1a; 对于函数中的多个返回数据, 去掉元组, 列表 或者字典直接获取里面数据的过程 &#xff08;只能对可迭代对象进行拆包&#xff09; Python拆包&#xff1a; 就是把元组…

python 拆包_python 拆包

广告关闭 腾讯云11.11云上盛惠 &#xff0c;精选热门产品助力上云&#xff0c;云服务器首年88元起&#xff0c;买的越多返的越多&#xff0c;最高返5000元&#xff01; 为了查明原因&#xff0c;我去查了 matplotlib 的源码&#xff0c;发现 plot 函数返回的是一个列表&#…