iOS逆向工程-0x01-工具篇-Cycript

对于初开始学习iOS逆向工程的人来说,实现一个tweak可以算是入门逆向工程了。

当然了,可能你现在还不知道tweak是什么。简单来说,你可以把一个tweak当作某一个app的一个插件(类似于浏览器广告屏蔽插件)。在app运行的时候,tweak会hook住某个函数,然后在hook的函数里面,你可以插入你的代码。

比如用户在登陆微信账号的时候,tweak可以hook住登录函数,dump出用户的账号密码

那问题来了,我们要如何知道哪个函数是账号登录函数咧?这就涉及到我们如何去分析一个iOS app

分析 iOS app 的两种方法

  • 运行时分析

    • GDB/LLDB
    • Cycript
    • Logify
    • weak_classdump
    • InspectiveC
  • 可执行代码分析

    • dumpdecrpted
    • class_dump,class_dump_z,classdump_dyld
    • Disassemblers
      • IDA
      • Hopper
      • otool
    • strings
    • nm

先不要被这么多的工具多吓到,我们一样一样来。相比对汇编代码的分析,动态分析要简单,容易上手很多,对新手而言,也更加容易获取到乐趣。所以我们先从最好玩的Cycript开始。

###Cycript

Cycript最重要的特性是,它可以hook住 iOS/macosx 上面正在运行的进程,并通过终端使用objective_c或javascript语法去打印和修改该应用的运行时信息。我们可以把它当作一个可以debug没有源代码程序的工具。

以下是 Cycript 的用途:

  • 能够hook正在运行的进程,并打印相关信息,如 appdelegate,rootViewController
  • 对程序中的类,可以获取到它用过的方法名称
  • 可以获取到类的实例变量名称,以及打印出实例变量的值,当然也可以修改实例变量的值
  • 能够执行 method swizzling, 替换某个指定的函数
  • 可以在运行时调用其他方法

安装 cycript

首先利用 Cydia 下载 mobilesubstrate adv-mds;从官网上面下载最新的包,并通过 scp 把文件拷贝到 iOS 设备上去,利用 dpkg 进行安装:

dpkg -i cycript cycript_0.9.102-1_iphoneos-arm.deb

安装完成之后,执行 cycript 看是否工作:

用Cycript进行实时修改

本文将使用支付宝来进行测试。

  • 让支付宝钱包在前台运行,并找出它的进程id,然后用 cycript -p hook 进程
chengpeide-iPhone:~ root# ps aux | grep AlipayWallet
mobile     629   0.0  9.3   815836  47792   ??  Ss    9:45PM   0:34.79 /var/mobile/Containers/Bundle/Application/FB2E1466-0D87-4FF9-9616-BD4269D61BCF/AlipayWallet.app/AlipayWallet
root       678   0.0  0.1   536256    412 s000  U+    9:49PM   0:00.01 grep AlipayWallet

-rwxr-xr-x 1 root admin 906 Jan 12  2015 cycript
chengpeide-iPhone:/cp/Cycript_0.9.502 root# cycript -p 629

cy# var app = [UIApplication sharedApplication]
#"<DFApplication: 0x14df44d0>"
cy# app.delegate
#"<DFClientDelegate: 0x14ed2d40>"
cy# app.keyWindow.rootViewController
#"<DFNavigationController: 0x15ac9a00>"
cy# var nav = new Instance(0x15ac9a00)
#"<DFNavigationController: 0x15ac9a00>"
cy# nav.topViewController.childViewControllers
@[#"<HPHomeWidgetGroup: 0x160a03d0>",#"<O2OIndexViewController: 0x15ad6600>",#"<APContactRecentViewController: 0x15afb600>",#"<WWAssetsViewController: 0x160a9da0>"]
cy# var assetsViewController = new Instance(0x160a9da0)
#"<WWAssetsViewController: 0x160a9da0>"
cy# [assetsViewController.view subviews]
@[#"<UIView: 0x162d8000; frame = (0 0; 0 0); layer = <CALayer: 0x162c85d0>>",#"<UITableView: 0x15433800; frame = (0 0; 320 519); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x1623d1f0>; layer = <CALayer: 0x162c3b10>; contentOffset: {0, -64}; contentSize: {320, 800}>"]
cy# var tableView = new Instance (0x15433800)
#"<UITableView: 0x15433800; frame = (0 0; 320 519); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x1623d1f0>; layer = <CALayer: 0x162c3b10>; contentOffset: {0, -42}; contentSize: {320, 800}>"
cy# tableView.backgroundColor = [UIColor redColor]
#"UIDeviceRGBColorSpace 1 0 0 1"

[tableView visibleCells]
@[#"<HeadInfoCell: 0x16160a40; baseClass = UITableViewCell; frame = (0 220; 320 80); autoresize = W; layer = <CALayer: 0x16160e80>>",#"<DoubleInfoCell: 0x1569e800; baseClass = UITableViewCell; frame = (0 300; 320 80); autoresize = W; layer = <CALayer: 0x16486e80>>",#"<DoubleInfoCell: 0x15452e00; baseClass = UITableViewCell; frame = (0 380; 320 80); autoresize = W; layer = <CALayer: 0x16491a50>>"]
cy# var headCell = new Instance (0x16160a40)
#"<HeadInfoCell: 0x16160a40; baseClass = UITableViewCell; frame = (0 220; 320 80); autoresize = W; layer = <CALayer: 0x16160e80>>"
cy# headCell.backgroundColor = [UIColor redColor]
#"UIDeviceRGBColorSpace 1 0 0 1"
cy# headCell.contentView.backgroundColor = [UIColor redColor]
#"UIDeviceRGBColorSpace 1 0 0 1"

我们可以看到,界面上 tableViewCell 的背景颜色变成了红色。

shortcut2

以上操作的思路大致就是, appdelegate => keyWindow => rootViewController => viewControllers => view

当然你也可以骗骗自己,把余额这个label的text改成巨款,过过眼瘾

cy# [tableView subviews]
@[#"<UIRefreshControl: 0x16482c90; frame = (0 0; 320 60); hidden = YES; autoresize = W; layer = <CALayer: 0x16256370>>",#"<UITableViewWrapperView: 0x1624cce0; frame = (0 0; 320 519); gestureRecognizers = <NSArray: 0x16098960>; layer = <CALayer: 0x14e12cf0>; contentOffset: {0, 0}; contentSize: {320, 519}>",#"<UIView: 0x16216d10; frame = (0 780; 320 20); layer = <CALayer: 0x162562c0>>",#"<WHAccountHeaderView: 0x16217c10; frame = (0 0; 320 180); layer = <CALayer: 0x1637edd0>>",#"<UIView: 0x17635b80; frame = (0 180; 320 40); autoresize = W; layer = <CALayer: 0x1620d670>>",#"<UIImageView: 0x161f4740; frame = (0 452.5; 320 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x161f47c0>>"]
cy# var header = new Instance(0x16217c10)
#"<WHAccountHeaderView: 0x16217c10; frame = (0 0; 320 180); layer = <CALayer: 0x1637edd0>>"
cy# [header subviews]
@[#"<UIView: 0x161c6530; frame = (0 0; 320 117); layer = <CALayer: 0x1638a780>>",#"<UIView: 0x16142d70; frame = (0 117.5; 106.667 62.5); layer = <CALayer: 0x161f6350>>",#"<UIView: 0x16142de0; frame = (106.667 117.5; 106.667 62.5); layer = <CALayer: 0x16109ed0>>",#"<UIView: 0x1610a4b0; frame = (213.333 117.5; 106.667 62.5); layer = <CALayer: 0x163771b0>>",#"<UILabel: 0x161082c0; frame = (122 28; 76 41); text = '0.00'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x14f73520>>",#"<UIImageView: 0x1610a520; frame = (246 42; 9 13); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x161025c0>>",#"<UIImageView: 0x161692b0; frame = (56.5 83; 13 13); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x16169330>>",#"<UILabel: 0x16169380; frame = (74.5 83; 189 13); text = '\xe7\x82\xb9\xe6\xad\xa4\xe5\xbc\x80\xe5\x90\xaf\xe8\xb4\xa6\xe6\x88\xb7\xe5\xae\x89\xe5\x85\xa8\xe9\x99\xa9\xef\xbc\x8c\xe4\xba\xab100\xe4\xb8\x87\xe4\xbf\x9d\xe9\x9a\x9c'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16169230>>",#"<UILabel: 0x16169570; frame = (36.8333 154.25; 33 12); text = '\xe9\x93\xb6\xe8\xa1\x8c\xe5\x8d\xa1'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16169630>>",#"<UILabel: 0x16169810; frame = (48.3333 131.25; 10 17); text = '2'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x161698d0>>",#"<UIImageView: 0x16169ab0; frame = (42.3333 127.25; 22 22); hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x16169b30>>",#"<UILabel: 0x16381200; frame = (149 154.25; 22 12); text = '\xe4\xbd\x99\xe9\xa2\x9d'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16381160>>",#"<UILabel: 0x16380280; frame = (144 131.25; 32 17); text = '0.00'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x16380340>>",#"<UILabel: 0x16380520; frame = (255.667 154.25; 22 12); text = '\xe5\x8d\xa1\xe5\x8c\x85'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x163805e0>>",#"<UILabel: 0x1638d640; frame = (261.667 131.25; 10 17); text = '0'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1638d700>>",#"<UIView: 0x16151570; frame = (0 117; 320 0.5); layer = <CALayer: 0x161515e0>>",#"<UIView: 0x16151670; frame = (0 179.5; 320 0.5); layer = <CALayer: 0x161516e0>>"]
cy# var label2= new Instance(0x161082c0)
#"<UILabel: 0x161082c0; frame = (122 28; 76 41); text = '0.00'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x14f73520>>"
cy# label2.text=@"10000000000000"
@"10000000000000"

shortcut2

很好玩,也很有用的工具,cycript。当然cycript还有一些高级用法,后面会介绍。