开发者社区> 浪途> 正文

iOS App 的逆向工程: Hacking on Lyft

简介: About the Speaker: Conrad Kramer 2010 年,Conrad Kramer 开发了他的第一个越狱 App Graviboard,从那以后便开始了他的 iOS 开发生涯。他做一些常规的 iOS 开发,同时也在 Cocoa 社区的多个开源项目上活跃,比如:AFOAuth2Client 和 WFNotificationCenter。 Co
+关注继续查看


About the Speaker: Conrad Kramer

2010 年,Conrad Kramer 开发了他的第一个越狱 App Graviboard,从那以后便开始了他的 iOS 开发生涯。他做一些常规的 iOS 开发,同时也在 Cocoa 社区的多个开源项目上活跃,比如:AFOAuth2Client 和 WFNotificationCenter。 Conrad 现在把全部的精力投入到了 Workflow 上,Workflow 是一个 iOS 自动工具,从后台到 UI 都是他一个人在做。


介绍 (0:00)

我是 Conrad Kramer,工作在 Workflow 的一枚 iOS 工程师,今天要跟大家聊聊 iOS Apps 逆向工程那些事儿。通常来说,逆向工程就是试图只通过最终产物来了解它背后工作原理的过程。在 iOS app 的世界里,这意味着你在没有源代码的前提下,只通过从 App Store 下载的 .app 来发现你想要的信息。

在做逆向工程的时候,会遇到两个痛点:

  1. 使用的工具 通常很难用,因为这些工具本身就缺乏文档,而且很不出名。他们总是崩溃出错,而且没人去修复这些错误。另外,花时间找到他们以及用好他们都很难。
  2. 一旦你开始用这些工具了,清楚自己的目标也很重要,因为有太多事情可以干了。此外,你还能用工具去逆向苹果自己的框架,尽管他是闭源的。我们可以用这些技术来探索 UIKit 的某个 bug,或者某个 app 里的 bug。

所以逆向的第一步是像自己发问:“为什么这个 bug 会发生?他们在 UI 里用了哪些组件?” 比如,如果你很好奇一个 app 里是否用了 collection view 或者 table view”,你其实很容易回答这个问题,看一眼就好了。但是如果你问:“他们的 REST API 是什么结构的?”,这个时候逆向工程就能帮你一探究竟。

逆向 Lyft (1:44)

我决定通过一个项目来开始这个主题,目标是:Lyft’s iOS app,它整个都是用 Swift 完成的。首先要做的事是我们了解我们感兴趣的点。假设我对 REST API 很感兴趣,比如我想要在另一个平台或者在 web 上写一个 Lyft 客户端,我可以看看他们的 API 然后产生好奇:“他们的 URL scheme 是什么样子的?”,当你想对 Lyft 做深度链接的时候,你就不得不解决这个问题。对 Workflow 来说,相关性就更高了,因为 Workflow 就是一个自动工具,我们集成了很多不同的 app。我总是需要做些类似的事情,来发现一些不公开的私有 URL scheme。

窥视 Lyft (2:48)

从 iTunes 下载下来的 Lyft 是一个 .IPA 文件(其实就是 zip 格式的)。它有很多的元数据,像 Info.plist 文件,资源文件,图片,本地化的字符串以及很多类似的文件。这里面也包含一些可执行文件,那些被编译了的代码就在里面。另外,因为 Lyft 是用 swift 写的,所以还包含很多附加的框架。

Lyft 现在看来是一个完完全全的黑盒子。我们不能直接的看透它,但我们依然有能力从特定的一些角度窥视到。一种方法就是通过监测网络流量来观察他的 API, 同时还能看到有哪些信息被它发送到了 Lyft 的服务器,这些通常对 App 而言是没有什么伤害的。

然后,我们还能 注入代码,真的非常爽。当 app 运行的时候,你可以打探打探这些 app 里被实例化而且存活的对象。当停止运行的时候,我们可以尝试去研究下 .app 是如何被组织的,同时通过特定的视角来看这些代码。

探测网络流量 - Charles 演示 (4:08)

Charles 是一个 HTTPS 代理工具,它可以让流量在发往服务器前拦截网络流量。我们可以用这个工具来观察所有从 Lyft app 流向服务器的请求。

Lyft 事实上通过 SSL 加密了它的所有流量。但这些都很好破,通过中间人攻击的方法来解决这个问题。其实就是替换了加密证书。

当你在用 Lyft 的时候,Lyft 不断的把你的地理位置发给 Lyft 的服务器。 对车辆的请求和取消等操作会以格式化后的 JSON 在 Charles 中呈现出来。用 Charles,你会看到 app 里和网络交互的所有内容。

向 Lyft 里注入代码 - Cycript 演示 (7:44)

下一个工具真的很赞,叫 Cycript。使用这个工具的时候需要一个越狱设备,注入代码到 app 里。Cycript 可以让你看到别人的代码,当然你自己写的 app 也逃不过。这个工具是 Objective-C 和 Javascript 的混合 app,只用输入 Objective-C 的代码到控制台里,就能在 app 运行这些代码。它的交互编程环境(REPL)比 LLDB 的要好很多。尽管它不能中断,设置断点等等,但他对运行时代码非常友好。你可以直接输入下面的代码,基本上都是 Objective-C :

var application = [UIApplication sharedApplication];
[application openURL:[NSURL URLWithString:@"https://google.com"]];

我 SSH 进入我的破解过的 iPhone 6 以后,打开 Lyft,运行 Cycript,我可以通过选择功能来获取一个运行时的类实例,比如 view controller 的,或者统计类的实例。作为开发者,要确定设置 ACL 来防止特定 api key 的权限问题。如果 app 能拿到这些 key,那 Cycript 也一定能拿到。

你也可以修改 app 里的 views。比如,用 UIApp.keyWindow.recursiveDescription 通过内存寻址,把 “呼叫车辆” 的按钮变成绿色。

var b = new Instance (ADDRESS)
b.backgroundColor = [UIColor greenColor]

Cycript 甚至还支持 tab 智能提示。这个功能不但对于逆向很有用,你还可以来测试你自己的 app,比如快速换个颜色测试测试效果什么的。

Q: 用 Crcript 测试自己的 app 的时候,设备一定需要越狱么?

Conrad: 对你自己的 app 的话,并不需要。在 cycript.org 官网上,提供了一些如何把这个工具嵌入到你自己的 app 的文档。

解密可执行文件 - dumpdecrypted 演示 (11:28)

接下来,我们就要来感受下 app 运行时真正的代码了。这个稍微有些复杂,而且需要设备越狱,我们的演示会比较简单。因为有能力重签名我们的设备,所以苹果会加密商店里所有的 app,防止 app 被大家共享。然而,对于一个越狱设备来说,所有的这些加密的 app 都是可以被解密的。我从其他人那里 fork 了一个 repo,叫 dumpdecrypted,原作者写这个是为了导出一个 app 的资源,我 fork 了一份,是为了让它能够支持所有的框架,毕竟现在很多 app 都含有 frameworks。

用它的时候,你只要简单的 clone 到本地,然后执行 make,再在你越狱后的设备上对 app 执行一下。我对 Lyft 的 app 执行了这个,很快就解密了所有的文件。你看这些文件的时候,会发现所有的 framework 都以 .decrypted 后缀结尾。比较有意思的一些模块是 Lyft,LyftKit 和 LyftSDK,但是我们还发现了它还用了 SocketRocket,Stripe,Pusher,Mixpanel 等等的库。

分析可执行文件 - IDA 演示 (13:47)

要分析我们导出的文件,查看源代码,我们要到 IDA,和 Hopper 及 class-dump 类似的一个工具。当在编译一个 app 的时候,XCode 会创建一个由汇编组成的可执行文件。IDA 能很漂亮的输出这些可执行文件里的汇编代码,并且相互连接起来,你因此会看到一个由汇编代码组成的图。尽管 IDA 很贵,但是它的免费版本 已经够用了。除了 64 位以外,基本都有。

要找到 Lyft 的 URL scheme,我们可以在 IDA 里执行一个简单的搜索,关键字是 openURL ,在类似的反编译工具中,Objective-C 是相对友好和容易的,因为它对于工作原理是相对透明的,Swift 就相对较差,很多工具还没有很好的支持 Swift,Swift 的汇编代码也更混乱,它的类信息很难被提取出来,不过,多练习练习,看看这些汇编,你会发现一些技巧来捕获你所想找的信息。

使用 IDA 的图表视野,我们发现了_TZFV4Lyft15DeepLinkManager13handleOpenURLfMS0_FCSo5NSURLSb,看起来是个很乱的字符串,然而我们依然可以发现 LyftDeepLinkManagerhandleOpenURL, 和 NSURL 这几个关键词。这些看似随机的字符串其实是有解释的,虽然没有文档来说明。如果想要了解这些字符串的含义,可以看看 Mike Ash 的博客里一篇叫做 Friday Q&A 的文章,这些模糊的东西都有解释。比如_T 意思是这是一个 Swift 的符号,F 意思是这是一个函数,4Lyft 是一个模块名称,等等。

寻找 Lyft 的 URL Scheme (18:23)

想要从我们所见之中发现 URL scheme,我们就要用开发者的思维来思考。

一个 URL scheme 结构大概是这样的:

lyft://action?parameter=value

我们现在要去找到 action 是什么,parameter 可能会是哪些。我首先找到了 DeepLinkAbleSwift 协议,了解了深度链接的工作原理。通过搜索 DeepLinkAble 关键字,我在一个类里发现了诸如 ridehelpinviteprofile 的请求对象。

我们对如何开始一次打车很好奇,我们可以看一下 Lyft 的 DeepLinkToRide 类,看看他是如何工作的。想要看这些,你甚至不需要了解汇编,你只需知道如何搜索和扫描汇编中你需要的信息即可。就好比你即使不会法语,却经常看见到法语,看的足够多次后,你总是能悟出些东西来。很多时候 IDA 展示给我们的完全就是一种外语,其实我第一次尝试逆向 Swift 的时候,就是这样一种感受。

通过大致浏览 DeepLinkToRide 的图。我发现了一些不同的字符串,比如 “pickup”,“[latitude]”,“[longtitude]”,“destination” 等等。IDA 还展显示了 ”ridetype“,后面经过测试发现这是个 action,通过查看 “ridetype”,我们发现了 “lyft”, “lyft_line”, “lyft_plus”, 和 “access”,这些都是出行方式。

构造这些不同的 URL 部分,然后测试请求。我发现请求一个出行的 scheme 方式如下:

lyft://ridetype
      ?id=lyft_line
      &pickup[latitude]=0
      &pickup[longitude]=0
      &destination[latitude]=0
      &destination[longitude]=0

现在,我明白了 Lyft 是如何工作的了,我可以集成到 Workflow 里了。这个过程其实就是二进制分析。尽管这些看起来很复杂,但事实上,只要像个开发者一样思考,其实也那么的难。

Q&A (22:50)

Q: 证书绑定(pinning certificates)能否防止中间人攻击?

Conrad:证书绑定是一个用来防止中间人攻击的方法,在实践中确实很有用,前提是你的手机未越狱。比如 Twitter 就在用证书绑定技术。然而,用逆向工具 Cycript 能够轻松破解。AFNetworking 支持证书绑定,只要设置一下 SSLPinningMode 这个属性。然而… 我们可以用 Cycript,再把它修改成 none,如果你的 iPhone 越狱了,或者被人控制了。所以,并没有一种方案能够彻底防止你的流量被检测,如果没有越狱,倒是一种很好的保护方法。

Q: 是否推荐类似 cocoapods-keys 这样的工具来混淆字符串?

Conrad: 字符串混淆有以下的好处:

- 如果你用苹果框架里的私有 API,能很容易的躲避过苹果审查的自动扫描工具。
- 如果那个人并没有一部越狱的 iPhone,或者它不知道如何解析混淆,他可能很难找到 app 里的字符串。

然而,你无法永远的把字符串藏起来。比如,在 Cycript 中,你可以轻易地解开混淆。所以字符串混淆也不是没法破的保护方案。

Q: class-dump 和 dumpdecryped 的区别是啥?

Conrad: 他们事实上是不同的工具。dumpecrypted 能将一个 App Store 加密的工具解密。而 class-dump 能将一个解密后得二进制文件去除他的 Objective-C 接口文件,跟 IDA 有点像,不过很遗憾的是:它不支持 Swift。

Q: 导出 Apple framework 的库,比如:this one,是不是也是用的 class-dump?

Conrad: 是的,苹果的框架没有加密,可以被轻易地导出所有的class。这意味着那些把苹果的私有interface 放到GitHub上的,你可以轻易地搞定他们。

Q: 逆向工程是否存在法律问题?Lyft 会不会不同意调用他们的私有代码和 api?

Conrad: 从法律上讲,我觉得没有太多问题。我们通常会跟所有的合作伙伴去聊到我们在做的事情。比如:我刚刚发现的这些东西我都会和 Lyft 讨论一下,在他们允许后集成到 Workflow 里。这些技术其实也有很多道德上的考虑。不过话说回来,这些技术也能阻止开发者们胡乱搞,就比如之前逆向 Twitter 发现他们上传用户手机里装的 App 列表到他们的服务器上。所以凡事总有两面,逆向工程只是个工具,善用就好了。

Q: 如何查看苹果框架的反汇编代码?

Conrad: 这个的过程跟我之前展示的一个很像,只不过你不再需要一个越狱后的设备。当你把线插到设备上的时候,iTunes 实际上获取到了设备的符号,你可以在 Xcode 里找到一个大概叫 “device symbol” 文件夹,在 IDA 或者 class-dump 里打开 Apple 的 frameworks,然后展开分析。这些都是没加密的,而且可以直接拿来用。在修复一些 beta 版本的 UIKit 的 bug 的时候很好使。



https://realm.io/cn/news/conrad-kramer-reverse-engineering-ios-apps-lyft/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
9601 0
使用SSH远程登录阿里云ECS服务器
远程连接服务器以及配置环境
13319 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
20275 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
13841 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18555 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
33244 0
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
35036 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
18965 0
+关注
浪途
到2016年10月,4年的iOS开发了,一边一边学习Java后台开发
149
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载