dump分析工具_iOS逆向分析和注入微信防撤回

微信公众号:passerbycrk-weixin
如有问题或建议,请公众号留言

复习iOS逆向知识,以微信消息防撤回为例,一步一步分析调试,到完成插件注入。


环境配置

越狱iPhone 5s (iOS 10.1.1) 并安装了以下软件:

OpenSSH: 实现在越狱手机上远程进行 ssh 服务,通过 ssh,即可以通过终端连接 iPhone 进行控制。dumpdecrypted: 砸壳工具。Cycript: 脚本语言工具,用于 hook 正在运行的进程,并实时注入代码。debugserver: 用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可在iPhone目录的 /Developer/usr/bin/ 中生成。

苹果电脑 (macOS High Sierra 10.13.3) 并安装了以下软件:

frida-ios-dump: 砸壳利器。class_dump: dump 目标对象的 class 信息的工具。Hopper_Disassembler: 静态分析工具。usbmuxd: 端口转发,可以让我们通过 usb 连接手机进行 ssh、lldb 调试等。lldb: 调试神器,用过的都说好 (/Applications/Xcode.app/Contents/Developer/usr/bin/lldb)。theos: 插件编写IDE。


流程概述

  • 砸壳: frida-ios-dumpdumpdecryptedClutch

  • 分析调试:

    • 静态分析: class-dumpHopper Disassembler

    • 动态分析: CycriptLogifylldb+debugserver

  • 编写插件并注入: theos


砸壳

推荐使用frida-ios-dump,下面会分别以frida-ios-dumpdumpdecrypted为例进行砸壳,实际情况任选一个使用即可。

frida-ios-dump

1.获取app信息 frida-ios-dump -l

# frida-ios-dump -l
 PID  Name            Identifier
-----  --------------  -------------------------------
92311  微信              com.tencent.xin
   -  App Store       com.apple.AppStore
   -  Cydia           com.saurik.Cydia
   -  FaceTime        com.apple.facetime
   -  Safari          com.apple.mobilesafari
   ...

2.根据app信息进行砸壳 frida-ios-dump [bundle id|name]

# frida-ios-dump com.tencent.xin
Start the target app com.tencent.xin
Dumping 微信 to /var/folders/7b/c3cyxy3j0t7_tgnt0dh5wc240000gn/T
start dump /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat
WeChat.fid: 100%|█████████████████████████████████████████████████| 71.8M/71.8M [00:06<00:00, 11.1MB/s]
start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/WCDB.framework/WCDB
WCDB.fid: 100%|███████████████████████████████████████████████████| 2.49M/2.49M [00:00<00:00, 9.10MB/s]
start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/MMCommon.framework/MMCommon
MMCommon.fid: 100%|█████████████████████████████████████████████████| 979k/979k [00:00<00:00, 7.56MB/s]
start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/MultiMedia.framework/MultiMedia
MultiMedia.fid: 100%|█████████████████████████████████████████████| 6.61M/6.61M [00:00<00:00, 10.8MB/s]
start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/mars.framework/mars
mars.fid: 100%|███████████████████████████████████████████████████| 8.49M/8.49M [00:00<00:00, 11.2MB/s]
network_setting.html: 139MB [00:25, 5.62MB/s]
0.00B [00:00, ?B/s]
Generating "微信.ipa"

砸壳成功后会在当前目录下生成去壳后的安装包微信.ipa

dumpdecrypted

1.获取app安装路径 ps -e | grep /var/

# ps -e | grep /var/
92817 ??         0:16.99 /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat
92867 ??         0:00.20 /private/var/containers/Bundle/Application/FD3685C9-80D5-419E-B106-DF466545003E/News.app/PlugIns/NewsNotificationServiceExtension.appex/NewsNotificationServiceExtension
93182 ttys000    0:00.02 grep /var/

2.根据app安装路径进行砸壳 DYLD_INSERT_LIBRARIES=/path/to/dumpdecrypted.dylib /path/to/app/executablename

# DYLD_INSERT_LIBRARIES=/path/to/dumpdecrypted.dylib /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat
mach-o decryption dumper
DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.
[+] detected 64bit ARM binary in memory.
[+] offset to cryptid found: @0x1000b4cf8(from 0x1000b4000) = cf8
[+] Found encrypted data at address 00004000 of length 59457536 bytes - type 1.
[+] Opening /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a plain MACH-O image
[+] Opening WeChat.decrypted for writing.
[+] Copying the not encrypted start of the file
[+] Dumping the decrypted data into the file
[+] Copying the not encrypted remainder of the file
[+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset cf8
[+] Closing original file
[+] Closing dump file        

成功后会在当前目录下生成WeChat.decrypted,也就是砸壳后的执行文件。

9888cfcad6ecf08b6f0379b5061e2fcb.png


分析调试

Cycript (动态分析工具)

官网: http://www.cycript.org/

Cycript允许开发人员调试和修改iOS和Mac OS X上运行的应用程序。
Cycript是一个理解Objective-C语法的javascript解释器,它能够挂钩正在运行的进程,能够在运行时修改应用的很多东西。

调试命令 cycript [-p ]
可以先通过 ps -e | grep /var命令找到对应pid

# cycript -p WeChat
cy# [[[UIWindow keyWindow] rootViewController] _printHierarchy].toString()
`<MMTabBarController 0x14606ae00>, state: appeared, view: <UILayoutContainerView 0x145da6420>
  | <MMUINavigationController 0x146179800>, state: appeared, view: <UILayoutContainerView 0x145d99460>
  |    | <NewMainFrameViewController 0x1460ff600>, state: disappeared, view: <MMUIHookView 0x145d8efa0> not in the window
  |    | <BaseMsgContentViewController 0x146983e00>, state: appeared, view: <UIView 0x145d7d440>
  | <MMUINavigationController 0x14618b000>, state: disappeared, view: <UILayoutContainerView 0x145d9dda0> not in the window
  |    | <ContactsViewController 0x146191000>, state: disappeared, view:  (view not loaded)
  | <MMUINavigationController 0x14613a800>, state: disappeared, view: <UILayoutContainerView 0x145da0ec0> not in the window
  |    | <FindFriendEntryViewController 0x146859200>, state: disappeared, view:  (view not loaded)
  | <MMUINavigationController 0x1461a4e00>, state: disappeared, view: <UILayoutContainerView 0x145da3950> not in the window
  |    | <MoreViewController 0x146172c00>, state: disappeared, view:  (view not loaded)`
Logify (静态分析工具-追踪)

介绍: http://iphonedevwiki.net/index.php/Logify

Logify是一种实用工具,可以将类的头文件(.h文件)作为输入,并生成MobileSubstrate文件(.xm文件)。
作用:能自动Hook该类所有的方法,并生成打印日志信息代码,方便开发人员看到在使用过程中调用了某些方法。

# logify.pl BaseMsgContentViewController.h > Tweak.xm
Logos 语法

介绍: http://iphonedevwiki.net/index.php/Logos

可以在MobileSubstrate文件(.xm文件)中使用的语法

Theos-NIC 

介绍: http://iphonedevwiki.net/index.php/NIC

Theos NIC templates内置了多种种Theos工程类型的模板。
用于编写iOS越狱设备的插件。

创建一个追踪logify的插件工程:

# nic.pl
NIC 2.0 - New Instance Creator
------------------------------
 [1.] iphone/activator_event
 [2.] iphone/application_modern
 [3.] iphone/cydget
 [4.] iphone/flipswitch_switch
 [5.] iphone/framework
 [6.] iphone/ios7_notification_center_widget
 [7.] iphone/library
 [8.] iphone/notification_center_widget
 [9.] iphone/preference_bundle_modern
 [10.] iphone/tool
 [11.] iphone/tweak
 [12.] iphone/xpc_service
Choose a Template (required): 11
Project Name (required): TWeak-Logify-WX
Package Name [com.yourcompany.tweak-logify-wx]: cn.theos.tweak.wx.logify
Author/Maintainer Name [dabing]: author name
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.tencent.xin
[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]:
Instantiating iphone/tweak in tweaklogifywx/...
Done.

工程文件结构如下:

# tree
.
└── tweaklogifywx
   ├── Makefile
   ├── TWeakLogifyWX.plist
   ├── Tweak.xm
   └── control

Logify生成的Tweak.xm覆盖掉工程中的Tweak.xm
用文本编辑器打开Makefile文件,在文件的开头增加iOS设备的ip地址和ssh端口等信息:

THEOS_DEVICE_IP = localhost
THEOS_DEVICE_PORT = 2333
ARCHS = arm64
TRAGET = iphone:latest:9.0
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = TWeakLogifyWX
TWeakLogifyWX_FILES = Tweak.xm
logifyWX_FRAMEWORKS = UIKit Foundation CoreGraphics
logifyWX_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
   install.exec "killall -9 SpringBoard"

编译打包安装:

# make package install
> Making all for tweak TWeakLogifyWX…
==> Preprocessing Tweak.xm…
==> Compiling Tweak.xm (arm64)…
==> Linking tweak TWeakLogifyWX (arm64)…
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of iOS 7 [-Wdeprecated]
==> Generating debug symbols for TWeakLogifyWX (arm64)…
warning: no debug symbols in executable (-arch arm64)
==> Merging tweak TWeakLogifyWX…
==> Signing TWeakLogifyWX…
> Making stage for tweak TWeakLogifyWX…
dm.pl: building package `cn.theos.tweak.wx.logify:iphoneos-arm' in `./packages/cn.theos.tweak.wx.logify_0.0.1-1+debug_iphoneos-arm.deb'
==> Installing…
Selecting previously unselected package cn.theos.tweak.wx.logify.
(Reading database ... 2279 files and directories currently installed.)
Preparing to unpack /tmp/_theos_install.deb ...
Unpacking cn.theos.tweak.wx.logify (0.0.1-1+debug) ...
Setting up cn.theos.tweak.wx.logify (0.0.1-1+debug) ...
install.exec "killall -9 SpringBoard"

注意:一般该Tweak.xm仍然无法执行,需要进行修改:
去掉 .cxx_destruct 方法
将 HBLogDebug 改为 NSLog
去掉所有的 weak 属性
将头文件(.h文件)中的@class和@protocol声明都拷贝至Tweak.xm (或去掉所有delegate并将所有参数对象类型改为id)。

安装成功后会在设备中新增以下两个文件:

/Library/MobileSubstrate/DynamicLibraries/TWeakLogifyWX.dylib
/Library/MobileSubstrate/DynamicLibraries/TWeakLogifyWX.plist

打开Cydia-已安装可以看到插件已经安装成功:

e2fc6f9b789766609317a1e6cfc13408.png

idevicesyslog (iOS日志查看工具)

介绍: https://github.com/libimobiledevice/libimobiledevice

libimobiledevice下的一个子工具,可以实时追踪iOS设备日志。

# idevicesyslog | grep "BaseMsgContentViewController"

重新运行app,执行收到消息和撤回消息的case,可以分别获取两份log:

接收消息log

b54fcc35481c5b0ebe7ff33e8746d738.png

撤回消息log

3d98ccd8990da89526e8b8218cd90f89.png

整理后log对比可以发现可疑方法调用-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:]

class-dump (静态分析工具)

介绍: http://stevenygard.com/projects/class-dump/

这是一个检查存储在Mach-O文件Objective-C运行时信息的命令行实用工具。
能生成classes、categories、protocols定义的头文件(.h文件)。(与otool -ov命令获取的信息类似,但可读性更高)

# class-dump -HA WeChat -o ./Headers

获得头文件以及方法的IMP address

例如:-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] // IMP=0x0000000102129454

Hopper Disassembler (分析工具)

介绍: https://www.hopperapp.com

是一款32位和64位的二进制反汇编器,反编译和调试。可以使用此工具拆开你想要的任何二进制。

使用方法很简单:将二进制文件拖入软件中,等待处理完成即可。
(完整解析微信app需要很长一段时间,可以前置该流程进行解析处理)

lldb+debugserver (远程调试) 

  1. 打开微信后,在连接至设备的控制台中键入debugserver *:1234 -a "WeChat"启动debugserver。
    2.从控制台打开新窗口,键入lldb进入调试,再键入debugserver *:1234 -a "WeChat"连接1234端口。

11dac476a91266608b157c65fe7c79c2.png

(此处连接需要一段时间,连接上后键入c(continue)命令后app就可以正常运行了)
连接成功后lldb窗口会出现以下内容:

(lldb) process connect connect://192.168.1.19:1234
Process 73244 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
   frame #0: 0x00000001900f5164 libsystem_kernel.dylib`__fcntl + 8
libsystem_kernel.dylib`__fcntl:
->  0x1900f5164 8>:  b.lo   0x1900f517c               ; 32>
   0x1900f5168 12>: stp    x29, x30, [sp, #-0x10]!
   0x1900f516c 16>: mov    x29, sp
   0x1900f5170 20>: bl     0x1900d9e8c               ; cerror
Target 0: (WeChat) stopped.
(lldb) c
Process 73244 resuming

获取aslroffset。(每次启动都不同)
其中第一列[X]是image的序号,不用管;第二列是aslroffset(也就是对应image的虚拟内存slide);第三列是image的全路径和slide之后的基地址,也不用管~所以第二列就是我们需要的信息。

(lldb) image list -o -f
[  0] 0x0000000000048000 /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat(0x0000000100048000)
[  1] 0x0000000104a20000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/usr/lib/dyld
[  2] 0x0000000104970000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x0000000104970000)
[  3] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/CallKit.framework/CallKit
[  4] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/Accelerate.framework/Accelerate
[  5] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/Intents.framework/Intents
[  6] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/usr/lib/libbz2.1.0.dylib
[  7] 0x0000000104aa4000 /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/WCDB.framework/WCDB(0x0000000104aa4000)
[  8] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
...

得到aslroffset0x0000000000048000 (不同的发布版本偏移量不一定相同)
再根据class-dump获得的头文件,找到对应的方法,在后面可以看到IMPoffset-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] // IMP=0x0000000102129454
通过br命令设置断点(aslr_offset + IMP_offset)

(lldb) br s -a '0x0000000000048000+0x0000000102129454'
Breakpoint 1: where = WeChat`ClearDataItem::compareTime(std::__1::shared_ptrconst&, std::__1::shared_ptrconst&) + 4373492, address = 0x0000000102171454

重新操作消息撤回case后,进入断点,键入bt命令:

Process 73244 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
   frame #0: 0x0000000102171454 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 4373492
WeChat`ClearDataItem::compareTime:
->  0x102171454 4373492>: stp    x24, x23, [sp, #-0x40]!
   0x102171458 4373496>: stp    x22, x21, [sp, #0x10]
   0x10217145c 4373500>: stp    x20, x19, [sp, #0x20]
   0x102171460 4373504>: stp    x29, x30, [sp, #0x30]
Target 0: (WeChat) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
 * frame #0: 0x0000000102171454 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 4373492
   frame #1: 0x0000000104d5b980 MMCommon`_callExtension + 480
   frame #2: 0x0000000102ccfaac WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 16294476
   frame #3: 0x0000000102cda958 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 16339192
   frame #4: 0x0000000102cdb60c WeChat`ClearDataItem::compareTime(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 16342444
   frame #5: 0x0000000104d5b980 MMCommon`_callExtension + 480
   frame #6: 0x0000000102f89414 WeChat`ClearSessionItem::compareVideo(std::__1::shared_ptr const&, std::__1::shared_ptr const&) + 1516048
   ...

python+Hopper Disassembler 获取调用栈

>>> hex(0x0000000102171454-0x0000000000048000)
'0x102129454' // -[BaseMsgContentViewController OnMsgRevoked:n64MsgId:]
>>> hex(0x0000000102ccfaac-0x0000000000048000)
'0x102c87aac' // -[CMessageMgr onRevokeMsg:]    
使用Hopper Disassembler可以定位调用方法名,此处我们发现可疑函数调用 -[CMessageMgr onRevokeMsg:]

编写插件并注入

创建插件工程

# nic.pl
NIC 2.0 - New Instance Creator
------------------------------
 [1.] iphone/activator_event
 [2.] iphone/application_modern
 [3.] iphone/cydget
 [4.] iphone/flipswitch_switch
 [5.] iphone/framework
 [6.] iphone/ios7_notification_center_widget
 [7.] iphone/library
 [8.] iphone/notification_center_widget
 [9.] iphone/preference_bundle_modern
 [10.] iphone/tool
 [11.] iphone/tweak
 [12.] iphone/xpc_service
Choose a Template (required): 11
Project Name (required): Tweak-crack-WX
Package Name [com.yourcompany.tweak-crack-wx]:
Author/Maintainer Name [dabing]:
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.tencent.xin
[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]:
Instantiating iphone/tweak in tweakcrackwx/...
Done.

Tweak.xm

%hook CMessageMgr
- (void)onRevokeMsg:(id)arg1 {
   // do nothing
}
%end

安装

# make package install
> Making all for tweak TweakcrackWX…
make[2]: Nothing to be done for `internal-library-compile'.
> Making stage for tweak TweakcrackWX…
dm.pl: building package `com.yourcompany.tweak-crack-wx:iphoneos-arm' in `./packages/com.yourcompany.tweak-crack-wx_0.0.1-2+debug_iphoneos-arm.deb'
==> Installing…
Selecting previously unselected package com.yourcompany.tweak-crack-wx.
(Reading database ... 2277 files and directories currently installed.)
Preparing to unpack /tmp/_theos_install.deb ...
Unpacking com.yourcompany.tweak-crack-wx (0.0.1-2+debug) ...
Setting up com.yourcompany.tweak-crack-wx (0.0.1-2+debug) ...
install.exec "killall -9 SpringBoard"

打开Cydia-已安装可以看到插件已经安装成功:

38c5c4c8b81521f1f991c286d1ff9e7d.png

接下来重新运行微信,试试消息撤回的case,发现消息撤回已经被阻止了,任务完成~

(文章特意选了个软柿子案例,实际情况可能不会这么容易找到关键函数,需要反复调试验证)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值