苹果手机的应用市场分为App Store
和非App Store
(PP助手
、爱思助手
)。
我们平时编写的代码最后发布到App Store
的时候苹果会对包进行一个加密,生成一个壳程序,防止被篡改。也就是说在App Store
上下载的程序都是被加过壳,其他越狱市场下载的一般是没有加过壳的。有很多方式可以看是否已经加过壳了,下面简单介绍一下。
class-dump方式
class-dump
通过传入一个可执行文件,可以导出该文件的所有类的头文件,下载地址,下载后的文件建议放到/usr/local/bin
目录下,就不用改环境变量了,也可以放到你的环境变量的目录下,通过下面的命令查看自己电脑的的环境变量
echo $PATH
我手机上有上面几个应用,除了网易严选
其他都是从App Store
上下载的,就拿淘宝
和网易严选
做个对比看下这2个包分别使用class-dump
后会生成什么。在手机上分别打开2个应用后使用命令ps -A
找到安装目录,我这台手机上2个包的安装目录分别如下
网易严选
/var/mobile/Containers/Bundle/Application/A0149F19-C83C-4800-B5A4-27AF0ECCCB1B/NeteaseYanxuan.app/NeteaseYanxuan
淘宝
/var/mobile/Containers/Bundle/Application/52E9162D-FB0C-4E79-A711-D94DCD7C102A/Taobao4iPhone.app/Taobao4iPhone
找到对应的文件,复制到我们的Mac
下,自己找个目录存放着,我这里放到我的电脑的~/Desktop/jailbreak/testClassDump
,分别执行class-dump
命令
淘宝
➜ taobao class-dump -H Taobao4iPhone -o headers // -H 表示导出头文件 -o 表示导出的东西放置到headers文件夹下
此时的目录如下
➜ taobao tree
.
├── Taobao4iPhone
└── headers
└── CDStructures.h
1 directory, 2 files
➜ taobao
发现在headers
下只会生成一个CDStructures.h
,一般导出这个的就是加过壳的程序了.再来看看网易严选
➜ wangyiyanxuan tree | more
.
├── NeteaseYanxuan
└── headers
├── A2BlockInvocation.h
├── A2DynamicBKURLConnectionInformalDelegate.h
├── A2DynamicClassDelegate.h
├── A2DynamicDelegate.h
├── A2DynamicMFMailComposeViewControllerDelegate.h
├── A2DynamicMFMessageComposeViewControllerDelegate.h
├── A2DynamicNSCacheDelegate.h
├── A2DynamicNSURLConnectionDelegate.h
├── A2DynamicUIActionSheetDelegate.h
├── A2DynamicUIAlertViewDelegate.h
├── A2DynamicUIImagePickerControllerDelegate.h
├── A2DynamicUIPopoverControllerDelegate.h
├── A2DynamicUIWebViewDelegate.h
├── AFActivityIndicatorViewNotificationObserver.h
├── AFAutoPurgingImageCache.h
├── AFCachedImage.h
├── AFCompoundResponseSerializer.h
├── AFHTTPBodyPart.h
├── AFHTTPRequestSerializer.h
├── AFHTTPResponseSerializer.h
├── AFHTTPSessionManager.h
├── AFImageCache-Protocol.h
├── AFImageDownloadReceipt.h
├── AFImageDownloader.h
├── AFImageDownloaderMergedTask.h
├── AFImageDownloaderResponseHandler.h
├── AFImageRequestCache-Protocol.h
├── AFImageResponseSerializer.h
├── AFJSONRequestSerializer.h
├── AFJSONResponseSerializer.h
....
有很多文件,这里就不全部列举了,像这种的能解析出很多的头文件的一般就是没有加壳的了。
随便挑一个文件看看里面的内容以_BKObserver
为例
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
#import "NSObject.h"
@class NSMutableArray;
@interface _BKObserver : NSObject
{
_Bool _isObserving;
int _context;
id _observee;
NSMutableArray *_keyPaths;
id _task;
}
@property(readonly, nonatomic) int context; // @synthesize context=_context;
@property(readonly, nonatomic) id task; // @synthesize task=_task;
@property(readonly, nonatomic) NSMutableArray *keyPaths; // @synthesize keyPaths=_keyPaths;
@property(readonly, nonatomic) id observee; // @synthesize observee=_observee;
- (void).cxx_destruct;
- (void)dealloc;
- (void)stopObserving;
- (void)_stopObservingLocked;
- (void)stopObservingKeyPath:(id)arg1;
- (void)startObservingWithOptions:(unsigned long long)arg1;
- (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4;
- (id)initWithObservee:(id)arg1 keyPaths:(id)arg2 context:(int)arg3 task:(id)arg4;
@end
可以看到有很多方法和成员变量,不由得会问是所有的方法都dump
出来了吗,我们写个demo工程测试一下
.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
@public // 共有变量
int age;
@private // 私有变量
double nums;
}
// 属性变量
@property(nonatomic, copy) NSString *name;
// 暴露的对象方法
- (void)testFunction;
@end
.m
#import "ViewController.h"
@interface ViewController ()
// 类扩展的属性
@property (nonatomic , copy) NSString *innerName;
@end
// 静态全局变量
static int innerStaticAge = 0;
// 全局变量
int globalNum = 0;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)testFunction {
}
// 内部方法
- (void)innerFunction {
}
// 静态方法
static int staticFunction () {
return 0;
}
@end
发现class-dump
以后
#import "UIViewController.h"
@class NSString;
@interface ViewController : UIViewController
{
int age;
double nums;
NSString *_name;
NSString *_innerName;
}
@property(copy, nonatomic) NSString *innerName; // @synthesize innerName=_innerName;
@property(copy, nonatomic) NSString *name; // @synthesize name=_name;
- (void).cxx_destruct;
- (void)innerFunction;
- (void)testFunction;
- (void)viewDidLoad;
@end
除了静态方法、静态变量、全局方法都dump下来了,也就是属于这个类的都dump
下来了,不禁会想有些重要的敏感数据可以考虑放到全局或者静态中去,因为就dump
来说,一般是查看不到的,达到一定的防破解的能力。
class-dump 失败
如果class-dump的时候报下面的错误
Cannot find offset for address 0xXXX in stringAtAddress
很可能这个项目是oc
和swift
混编的,请参照这篇文章解决
使用MachOView工具
MachOView
是专门用来查看MachO
文件的工具,官网的下载地址安装会有闪退,这里我自己修改了下并重新生成点击下载安装,分别拖进工具中查看load commands
中的LC_ENCRYPTION_INFO
中的Crypt ID
这个值为1
就是加过壳了,为0
就是没有加壳
otool命令
使用-l
参数就是load command
的意思。
➜ wangyiyanxuan otool -l NeteaseYanxuan | grep crypt
cryptoff 16384
cryptsize 27557888
cryptid 0
cryptoff 16384
cryptsize 30539776
cryptid 0
➜ wangyiyanxuan cd ..
➜ testClassDump ls
taobao wangyiyanxuan
➜ testClassDump cd taobao
➜ taobao otool -l Taobao4iPhone | grep crypt
cryptoff 16384
cryptsize 51838976
cryptid 1
cryptoff 16384
cryptsize 56737792
cryptid 1
➜ taobao
如果查到有2个,就是这个二进制里面有2个架构的包而已。
脱壳-Clutch
脱壳的意思就是把App Store
上加的壳程序给去掉,下面介绍2个常用的吧。
<1>. 下载:Clutch
,下载地址 ;
<2>. 安装:要想命令行能直接使用,最好放在手机的/usr/bin
目录下;
如果权限不够的话,可以增加下权限,chmod使用介绍
chmod 777 /usr/bin/Clutch
<3>. 使用:
使用i
可以查看所有需要脱壳的应用
iPhone:~ root# Clutch -I
Installed apps:
1: 京东-好物好玩上京东 <com.360buy.jdmobile>
2: 淘宝 - 双11全球狂欢节 <com.taobao.taobao4iphone>
3: SuperVPN - 超好用的VPN <com.simple.VPN>
4: 网易云音乐 <com.netease.cloudmusic>
5: 腾讯课堂 <com.tencent.edu>
6: 优酷视频-火星情报局第四季全网独播 <com.youku.YouKu>
7: 爱思加强版 <com.pd.A4Player>
8: 抖音短视频 <com.ss.iphone.ugc.Aweme>
9: 微博 <com.sina.weibo>
10: 腾讯视频-风味人间独播 <com.tencent.live4iphone>
iPhone:~ root#
使用d
可以对应用进行脱壳
Clutch -d com.taobao.taobao4iphone
脱壳成功的话在最后会有生成的路径
DONE: /private/var/mobile/Documents/Dumped/com.taobao.taobao4iphone-iOS8.0-(Clutch-2.0.4).ipa // 这个就是脱壳成功的ipa
Finished dumping com.taobao.taobao4iphone in 112.4 seconds
脱壳 - dumpdecrypted
<1>.下载
<2>.放到/var/root
目录下,其他当前用户有读写权限的目录下都可以
<3>.使用
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib 可执行文件路径
方式如下
iPhone:~ root# DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/52E9162D-FB0C-4E79-A711-D94DCD7C102A/Taobao4iPhone.app/Taobao4iPhone
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: @0x100034f20(from 0x100034000) = f20
[+] Found encrypted data at address 00004000 of length 56737792 bytes - type 1.
[+] Opening /private/var/mobile/Containers/Bundle/Application/52E9162D-FB0C-4E79-A711-D94DCD7C102A/Taobao4iPhone.app/Taobao4iPhone for reading.
[+] Reading header
[+] Detecting header type
[+] Executable is a FAT image - searching for right architecture
[+] Correct arch is at offset 73777152 in the file
[+] Opening Taobao4iPhone.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 465cf20
[+] Closing original file
[+] Closing dump file
iPhone:~ root#
脱壳成功的话会在dumpdecrypted.dylib
库的目录下生成Taobao4iPhone.decrypted
文件
重新再使用之前介绍的方式看看发现都已经脱壳成功了。