【iOS逆向】- 脱壳

苹果手机的应用市场分为App Store和非App StorePP助手爱思助手)。

我们平时编写的代码最后发布到App Store的时候苹果会对包进行一个加密,生成一个壳程序,防止被篡改。也就是说在App Store上下载的程序都是被加过壳,其他越狱市场下载的一般是没有加过壳的。有很多方式可以看是否已经加过壳了,下面简单介绍一下。

class-dump方式

class-dump通过传入一个可执行文件,可以导出该文件的所有类的头文件,下载地址,下载后的文件建议放到/usr/local/bin目录下,就不用改环境变量了,也可以放到你的环境变量的目录下,通过下面的命令查看自己电脑的的环境变量

echo $PATH

【iOS逆向】- 脱壳_第1张图片
15425400351609.jpg

我手机上有上面几个应用,除了网易严选其他都是从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 

@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

很可能这个项目是ocswift混编的,请参照这篇文章解决

使用MachOView工具

MachOView是专门用来查看MachO文件的工具,官网的下载地址安装会有闪退,这里我自己修改了下并重新生成点击下载安装,分别拖进工具中查看load commands中的LC_ENCRYPTION_INFO中的Crypt ID这个值为1就是加过壳了,为0就是没有加壳

【iOS逆向】- 脱壳_第2张图片
15425419163089.jpg

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:   京东-好物好玩上京东 
2:   淘宝 - 双11全球狂欢节 
3:   SuperVPN - 超好用的VPN 
4:   网易云音乐 
5:   腾讯课堂 
6:   优酷视频-火星情报局第四季全网独播 
7:   爱思加强版 
8:   抖音短视频 
9:   微博 
10:  腾讯视频-风味人间独播 
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文件

【iOS逆向】- 脱壳_第3张图片
15425447415453.jpg

重新再使用之前介绍的方式看看发现都已经脱壳成功了。

你可能感兴趣的:(【iOS逆向】- 脱壳)