前言
前几天在网上无意间看到了class-dump这个词语,出于好奇就查了下,没想到挺有意思的:简单来说,就是可以将objc编译后程序中的声明信息导出查看,有点类似于源程序的.h头文件。
这个有什么用呢?国内搜索class-dump能看到一些使用class-dump导出Apple Framework私有API的教程。我对这个没什么兴趣。既然class-dump是根据objc语言特性来实现的,那么在理论上应该也可以对ios的app使用吧。之前对Appstore的一款App实现方式感兴趣,这次可以试试看个究竟了。
那么,我们的目标分析是一款唱歌软件,具体名字就不公布了,这里就以sing代替吧。
下面我们需要一台iOS系统的已越狱真机一台(例如itouch、iphone),mac系统主机一台。软件若干(稍后会介绍)
一、Frist try
我的思路很简单:尝试直接调用class-dump程序对sing app导出头文件。那么我们得做三件事:
- 安装class-dump。
- 获得sing app的程序文件。
- 执行命令class-dump singapp,导出头文件。
先安装class-dump吧。class-dump大概有三个版本(它们之间的区别和详细介绍在此),我们直接下载class-dump-z 0.2a,解压后将mac_x86目录中的class-dump-z程序文件拷贝至/usr/local/bin目录。这样就算安装完成啦。
然后找到Sing app的主程序文件。确保我们的真机已经安装了Sing app后。直接使用iExploer(或iFunbox)打开真机的应用程序目录,打开ktv.app子目录,按照Size(文件大小)排序,你会看到一个与父目录同名的程序文件ktv,这个就是编译后的主程序了(如下图),将它导出到桌面吧。
激动人心时刻到啦!使用命令class-dump-z ktv,what?!这都是神马东西……
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/**
* This header is generated by class-dump-z 0.2a.
* class-dump-z is Copyright (C) 2009 by KennyTM~, licensed under GPLv3.
*
* Source: (null)
*/
@protocol
XXEncryptedProtocol_6cb0f0
-
(
?
)
XXEncryptedMethod_56bb35
;
-
(
?
)
XXEncryptedMethod_56bb29
;
-
(
?
)
XXEncryptedMethod_56bb1d
;
-
(
?
)
XXEncryptedMethod_56bb15
;
-
(
?
)
XXEncryptedMethod_56bb0e
;
-
(
?
)
XXEncryptedMethod_56bafa
;
-
(
?
)
XXEncryptedMethod_56bae6
;
-
(
?
)
XXEncryptedMethod_56bad5
;
-
(
?
)
XXEncryptedMethod_569e54
;
-
(
?
)
XXEncryptedMethod_56bacd
;
-
(
?
)
XXEncryptedMethod_56baa6
;
-
(
?
)
XXEncryptedMethod_56ba8a
;
-
(
?
)
XXEncryptedMethod_56ba79
;
-
(
?
)
XXEncryptedMethod_56ba74
;
-
(
?
)
XXEncryptedMethod_56ba6f
;
-
(
?
)
XXEncryptedMethod_569e4e
;
-
(
?
)
XXEncryptedMethod_56ba64
;
-
(
?
)
XXEncryptedMethod_56ba5f
;
-
(
?
)
XXEncryptedMethod_56ba56
;
@
optional
-
(
?
)
XXEncryptedMethod_56bb41
;
@end
//...
|
想想也觉得不会这么一帆风顺。看上去这些类名和属性名都被加密了。网上搜索后才知道从AppStore下载到本地的App是做了加密处理的。所以我们直接想要直接获得程序信息是不行滴~
那么——有解决办法吗?
二、Try again
老外的牛牛们已经写好解密工具了,它就是Clutch!这个工具只能在iOS上运行,并且需要真机越狱。
恩,首先越狱机器已经准备好了,使用Cydia搜索并安装Clutch(注:现在Cydia已经下载不到了,需要我们自己下载程序后通过sftp复制到真机,Clutch下载地址)。安装完后怎么使用呢?这是一个命令行工具,所以我们得用bash之类的工具才行。
再使用Cydia安装Openssh,然后电脑端使用ssh连接真机(默认密码是alpine),输入命令Clutch后会看到一个App列表,找到sing在列表中的序号是3,执行命令Clutch 3,这时它就真的开始运行了,运行后的结果是将原Appstore App转换为ipa文件(文件保存位置如下图);最重要的是,它被解密了~
关于中文名App问题:我在最近的使用过程中发现一个小问题,真机的ssh无法输入中文,这导致我们无法使用Clutch解密中文App。我的临时解决办法是在我的电脑本地用vim创建一个decrypt.sh脚本文件(默认使用utf-8编码),其中写入要执行的命令(例如”Clutch 中文App名”),保存后使用sftp传入真机运行即可。
我在使用Clutch-1.4.5-git2版本的过程中,遇到了破解完成后到/User/Documents/Cracked/目录下却未找到破解文件的问题,这是由于未安装zip造成的(使用which zip命令检查),解决方法是使用Cydia安装zip后使用Clutch再次破解即可。(官方Issue在此)
使用iExplorer将ipa文件下载到电脑端,修改后缀名为zip解压,找到其中的主程序文件,再次使用命令class-dump-z ktv,是不是看到头文件信息啦~
简单摘录一小部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/**
* This header is generated by class-dump-z 0.2a.
* class-dump-z is Copyright (C) 2009 by KennyTM~, licensed under GPLv3.
*
* Source: (null)
*/
typedef
struct
_NSZone
NSZone
;
typedef
struct
CGPoint
{
float
x
;
float
y
;
}
CGPoint
;
typedef
struct
CGSize
{
float
width
;
float
height
;
}
CGSize
;
//...
typedef
struct
AQRecorder
{
unsigned
long
long
_field1
;
unsigned
char
_field2
;
OpaqueAudioComponentInstance
*
_field3
;
AURenderCallbackStruct
_field4
;
CAStreamBasicDescription
_field5
;
unsigned
char
_field6
;
ReverbEffect32
_field7
;
Freeverb
_field8
;
bool
_field9
;
BandpassFilter
_field10
;
BandpassFilter
_field11
;
queue
<
short
,
std
::
deque
<
short
,
std
::
allocator
<short>
>
>
_field12
;
queue
<
short
,
std
::
deque
<
short
,
std
::
allocator
<short>
>
>
_field13
;
queue
<
short
,
std
::
deque
<
short
,
std
::
allocator
<short>
>
>
_field14
;
CFStringRef
_field15
;
OpaqueAudioQueue
*
_field16
;
AudioQueueBuffer
*
_field17
[
3
]
;
OpaqueAudioFileID
*
_field18
;
long
long
_field19
;
CAStreamBasicDescription
_field20
;
unsigned
char
_field21
;
id
_field22
;
}
AQRecorder
;
//...
typedef
struct
_Crashlytics__Session_
_
User
{
ProtobufCMessage
_field1
;
char
*
_field2
;
char
*
_field3
;
char
*
_field4
;
unsigned
_field5
;
Crashlytics__CustomAttribute
*
*
_field6
;
}
Crashlytics__Session__User
;
//...
@protocol
EGOImageLoaderObserver
<NSObject>
@
optional
-
(
void
)
imageLoaderDidFailToLoad
:
(
id
)
imageLoader
;
-
(
void
)
imageLoaderDidLoad
:
(
id
)
imageLoader
;
@end
//...
|
通过这些代码我们已经了解到一些信息了:
- 录音部分使用的是AudioQueue相关技术。
- 项目使用了Crashlytics服务保存并分析Crash信息。
- 图片加载使用了EGOImage第三方开源库。
这只是分析文件的很小一部分,以此可以说明这种方式是有效的。
后记
在写本文的时候,我看到最近关于支付宝插件分析的文章中,Allen兄也使用到了class-dump,不妨看看。传送门
突然发现将文章写的过于过程、步骤化,不带一丝的情感的文章看上去会感觉很生硬,所以以后我会在写文的时候加入一些自己的思考,虽然没什么文采,但可以慢慢锻炼嘛。