追踪iOS某APP的验证签名过程

利用反汇编追踪iOS某APP的验证签名过程


环境需求

  • 越狱iOS设备一台,

  • Openssh

  • Cycript

  • Hopper Disassembler v4*

  • iProxy

对iOS APP进行砸壳

首先用USB连接越狱手机,使用USB进行端口映射到本机

iproxy 2222 22

新开终端

ssh [email protected] -p 2222

开始砸壳

DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/1999C8D2-58C1-43C0-A717-A44B55CC1FEA/***.app/***

得到砸壳后的文件

Testerde-iPhone:~/decrypted root# ls
cf.decrypted
Testerde-iPhone:~/decrypted root#

使用Hopper载入砸壳后的文件同时使用class-dump导出头文件

class-dump -H ./cf.decrypted -o ./header --arch arm64

注意在砸壳手机上运行的是什么CPU架构的,我们这里是arm64

在使用charles抓包时发现URL中使用auth_key参数传递了验证签名,所以在hopper 中搜索auth_key
得到以下片段

00000001011436a9         db         "WSOpenMemberViewController", 0             ; DATA XREF=cfstring_WSOpenMemberViewController
00000001011436c4         db         "loadedTimeRanges", 0                       ; DATA XREF=cfstring_loadedTimeRanges
00000001011436d5         db         "v32@?0{?=qiIq}8", 0
00000001011436e5         db         "mm:ss", 0                                  ; DATA XREF=cfstring_mm_ss
00000001011436eb         db         "%@-%.f-0-0-%@", 0                          ; DATA XREF=cfstring______f_0_0___
00000001011436f9         db         "%@?auth_key=%.f-0-0-%@", 0                 ; DATA XREF=cfstring____auth_key___f_0_0___
0000000101143710         db         "player", 0                                 ; DATA XREF=0x10138cc60, 0x1013d6b60, 0x1013e1218, 0x101484138, 0x1014e82c8, 0x1014f6400, 0x10155c500, 0x101592bb8, 0x101593f18
0000000101143717         db         "T@\"AVPlayer\",&,N,V_player", 0            ; DATA XREF=0x10138cc60, 0x1013d6b60, 0x101484138, 0x1014f6400, 0x101592bb8, 0x101593f18
0000000101143731         db         "playerItem", 0                             ; DATA XREF=0x10138cc70, 0x1013d6b70
000000010114373c         db         "T@\"AVPlayerItem\",&,N,V_playerItem", 0    ; DATA XREF=0x10138cc70, 0x1013d6b70
000000010114375e         db         "playerLayer", 0                            ; DATA XREF=0x10138cc80, 0x1013d6b80, 0x1013e1228, 0x1014f6410, 0x10155c510
000000010114376a         db         "T@\"AVPlayerLayer\",&,N,V_playerLayer", 0  ; DATA XREF=0x10138cc80, 0x1013d6b80, 0x1014f6410

双击

00000001011436f9         db         "%@?auth_key=%.f-0-0-%@", 0                 ; DATA XREF=cfstring____auth_key___f_0_0___

查看到

 cfstring____auth_key___f_0_0___:
00000001012e7760         dq         ___CFConstantStringClassReference, 0x7c8, 0x1011436f9, 0x16 ; "%@?auth_key=%.f-0-0-%@", DATA XREF=-[WSAVPlayerView encryptionUrl:andVideoKey:]+368, -[WSSpecialColumPlayerView encryptionUrl:andVideoKey:]+368

这可以可以得出auth_key这个字符串在

  • [WSAVPlayerView encryptionUrl:andVideoKey:]+368
  • [WSSpecialColumPlayerView encryptionUrl:andVideoKey:]+368

这两个地方使用过,这查看使用class_dump导出的头文件
WSAVPlayerView.h

//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

#import "UIView.h"

@class AVPlayer, AVPlayerItem, AVPlayerLayer, NSString, NSTimer, UIButton, UIImageView, UILabel, UIProgressView, UISlider, UITapGestureRecognizer;

@interface WSAVPlayerView : UIView
{
    _Bool _isPortraitShow;
    _Bool _isVIP;
    _Bool _isNetWorkWiFi;
    _Bool _isSeeking;
    _Bool _isShowingTool;
    NSString *_currentUrlString;
    NSString *_videoKey;
    double _time;
    id  _delegate;
    AVPlayer *_player;
    AVPlayerItem *_playerItem;
    AVPlayerLayer *_playerLayer;
    UISlider *_progressSlider;
    UIView *_topToolView;
    UIView *_bottomToolView;
    UIView *_vipView;
    UILabel *_vipLabel;
    UIButton *_vipButton;
    UIButton *_continueButton;
    UIImageView *_vipBgImageView;
    UIButton *_backButton;
    UIButton *_lockButton;
    UIButton *_playButton;
    UILabel *_progressTimeLabel;
    UILabel *_restTimeLabel;
    UIButton *_expandOrShrinkButton;
    AVPlayerItem *_currentPlayerItem;
    NSTimer *_progressTimer;
    UIProgressView *_progressView;
    UITapGestureRecognizer *_tapGesture;
    NSTimer *_toolControlTimer;
}

+ (Class)layerClass;
@property(nonatomic) _Bool isShowingTool; // @synthesize isShowingTool=_isShowingTool;
@property(nonatomic) _Bool isSeeking; // @synthesize isSeeking=_isSeeking;
@property(retain, nonatomic) NSTimer *toolControlTimer; // @synthesize toolControlTimer=_toolControlTimer;
@property(retain, nonatomic) UITapGestureRecognizer *tapGesture; // @synthesize tapGesture=_tapGesture;
@property(retain, nonatomic) UIProgressView *progressView; // @synthesize progressView=_progressView;
@property(retain, nonatomic) NSTimer *progressTimer; // @synthesize progressTimer=_progressTimer;
@property(retain, nonatomic) AVPlayerItem *currentPlayerItem; // @synthesize currentPlayerItem=_currentPlayerItem;
@property(retain, nonatomic) UIButton *expandOrShrinkButton; // @synthesize expandOrShrinkButton=_expandOrShrinkButton;
@property(retain, nonatomic) UILabel *restTimeLabel; // @synthesize restTimeLabel=_restTimeLabel;
@property(retain, nonatomic) UILabel *progressTimeLabel; // @synthesize progressTimeLabel=_progressTimeLabel;
@property(retain, nonatomic) UIButton *playButton; // @synthesize playButton=_playButton;
@property(retain, nonatomic) UIButton *lockButton; // @synthesize lockButton=_lockButton;
@property(retain, nonatomic) UIButton *backButton; // @synthesize backButton=_backButton;
@property(retain, nonatomic) UIImageView *vipBgImageView; // @synthesize vipBgImageView=_vipBgImageView;
@property(retain, nonatomic) UIButton *continueButton; // @synthesize continueButton=_continueButton;
@property(retain, nonatomic) UIButton *vipButton; // @synthesize vipButton=_vipButton;
@property(retain, nonatomic) UILabel *vipLabel; // @synthesize vipLabel=_vipLabel;
@property(retain, nonatomic) UIView *vipView; // @synthesize vipView=_vipView;
@property(retain, nonatomic) UIView *bottomToolView; // @synthesize bottomToolView=_bottomToolView;
@property(retain, nonatomic) UIView *topToolView; // @synthesize topToolView=_topToolView;
@property(retain, nonatomic) UISlider *progressSlider; // @synthesize progressSlider=_progressSlider;
@property(retain, nonatomic) AVPlayerLayer *playerLayer; // @synthesize playerLayer=_playerLayer;
@property(retain, nonatomic) AVPlayerItem *playerItem; // @synthesize playerItem=_playerItem;
@property(retain, nonatomic) AVPlayer *player; // @synthesize player=_player;
@property(nonatomic) _Bool isNetWorkWiFi; // @synthesize isNetWorkWiFi=_isNetWorkWiFi;
@property(nonatomic) _Bool isVIP; // @synthesize isVIP=_isVIP;
@property(nonatomic) _Bool isPortraitShow; // @synthesize isPortraitShow=_isPortraitShow;
@property(nonatomic) __weak id  delegate; // @synthesize delegate=_delegate;
@property(readonly, nonatomic) double time; // @synthesize time=_time;
@property(retain, nonatomic) NSString *videoKey; // @synthesize videoKey=_videoKey;
@property(readonly, copy, nonatomic) NSString *currentUrlString; // @synthesize currentUrlString=_currentUrlString;
- (void).cxx_destruct;
- (void)layoutSubviews;
- (void)dealloc;
- (id)getPrivateKey:(id)arg1;
- (id)encryptionUrl:(id)arg1 andVideoKey:(id)arg2;
- (void)seekTime:(double)arg1;
- (id)convertTime:(double)arg1;
- (double)availableDuration;
- (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4;
- (void)playerDidFinishPlaying:(id)arg1;
- (void)prepareToPlay;
- (void)removeSystemNotifications;
- (void)addSystemNotifications;
- (void)removeTimeObserver;
- (void)addTimeObserver;
- (void)removePlayerItemStatusObserver;
- (void)addPlayerItemStatusObserver;
- (void)refreshProgessUI;
- (void)showVIPView:(_Bool)arg1;
- (void)hideVIPView;
- (void)hideToolView;
- (void)showToolView;
- (void)continuePlayVideo;
- (void)openVIPAction;
- (void)expandOrShrinkAction:(id)arg1;
- (void)playAction:(id)arg1;
- (void)lockAction:(id)arg1;
- (void)backAction:(id)arg1;
- (void)resumeRefreshing;
- (void)pauseRefreshing;
- (void)seek:(id)arg1;
- (void)addExternToolView;
- (void)playWithUrlString:(id)arg1;
- (void)clean;
- (void)pause;
- (void)play;
@property(readonly, nonatomic) _Bool isPlaying;
- (void)initializeAVPlayer;
- (id)initWithFrame:(struct CGRect)arg1;
- (id)initWithFrame:(struct CGRect)arg1 playUrl:(id)arg2;

@end

通过查看头文件可以看到
[WSAVPlayerView encryptionUrl:andVideoKey:]
方法中的VideoKey会保存在view的属性里面,我们来看看这个VideoKey是什么?

在终端查看进程id

 ps -e

 5507 ??         0:14.64 /var/mobile/Containers/Bundle/Application/3912B0D8-705D-42E0-A087-D7A9711CB464/QQ.app/QQ
 5703 ??         0:05.17 /var/mobile/Containers/Bundle/Application/30C91D48-B9A6-4CA2-9669-A76073893084/WeChat.app/WeChat
 5830 ??         0:00.30 /usr/libexec/rtcreportingd
 5976 ??         0:00.64 /System/Library/Frameworks/SystemConfiguration.framework/SCHelper
 6030 ??         1:01.96 /var/mobile/Containers/Bundle/Application/1999C8D2-58C1-43C0-A717-A44B55CC1FEA/***.app/***

这时使用cycript附加上去

cycript -p 6030
cy#

我们先让这个播放器初始化完成并传入数据,这时需要在手机上进入到响应页面点击播放按钮

查看当前的视图层次

UIApp.keyWindow.recursiveDescription().toString()

发现 WSAVPlayerView的内存地址为0x12688de50
这时为了方便下次的调用我们声明一个变量

cy# var pv = #0x12688de50
#"

查看属性VideoKey

cy# pv.videoKey
@"NnVpU1VEc2drMTIzQVB4dDY="

通过对比发现NnVpU1VEc2drMTIzQVB4dDY=的值是在请求视频资料中传入的

我们把输入带入[WSAVPlayerView encryptionUrl:andVideoKey:]
这个方法需要传入两个参数,第一个为url,第二个为key

cy# [pv encryptionUrl:@"http://www.baidu.com/class/18007651/454eae93a1963d7c31b1076b7c5a6e58_18007651_480.mp4" andVideoKey:@"NnVpU1VEc2drMTIzQVB4dDY="]
@"http://www.baidu.com/class/18007651/454eae93a1963d7c31b1076b7c5a6e58_18007651_480.mp4?auth_key=1503547268-0-0-077178daad75b10032af437b1d5d4cfb"

这里返回了正确的auth_key说明我们找的函数对了

那么我们来看看hopper这个函数大致做了一些什么

00000001000ee4b4         mov        x23, x0
00000001000ee4b8         adrp       x8, #0x101615000                            ; @selector(setStarImage:highlightedStarImage:)
00000001000ee4bc         ldr        x1, [x8, #0x948]                            ; "timeIntervalSince1970",@selector(timeIntervalSince1970)
00000001000ee4c0         bl         imp___stubs__objc_msgSend
00000001000ee4c4         mov        v8, v0
00000001000ee4c8         adrp       x28, #0x101643000                           ; @selector(wifiReachability)
00000001000ee4cc         ldr        x0, [x28, #0x9d0]                           ; objc_cls_ref_WOWSUtils,__objc_class_WOWSUtils_class
00000001000ee4d0         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee4d4         ldr        x1, [x8, #0x660]                            ; "base64Decode:",@selector(base64Decode:)
00000001000ee4d8         mov        x2, x20
00000001000ee4dc         bl         imp___stubs__objc_msgSend
00000001000ee4e0         mov        x29, x29
00000001000ee4e4         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee4e8         mov        x25, x0
00000001000ee4ec         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee4f0         ldr        x1, [x8, #0x668]                            ; "getPrivateKey:",@selector(getPrivateKey:)
00000001000ee4f4         mov        x0, x24
00000001000ee4f8         mov        x2, x25
00000001000ee4fc         bl         imp___stubs__objc_msgSend
00000001000ee500         mov        x29, x29
00000001000ee504         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee508         mov        x24, x0
00000001000ee50c         adrp       x21, #0x101643000                           ; @selector(wifiReachability)
00000001000ee510         ldr        x0, [x21, #0xab0]                           ; objc_cls_ref_NSString,_OBJC_CLASS_$_NSString
00000001000ee514         adrp       x8, #0x101612000
00000001000ee518         ldr        x26, [x8, #0xad0]                           ; "stringWithFormat:",@selector(stringWithFormat:)
00000001000ee51c         str        x24, [sp, #0x10]
00000001000ee520         str        d8, [sp, #0x8]
00000001000ee524         str        x22, sp
00000001000ee528         adrp       x2, #0x1012e7000
00000001000ee52c         add        x2, x2, #0x740                              ; @"%@-%.f-0-0-%@"
00000001000ee530         mov        x1, x26
00000001000ee534         bl         imp___stubs__objc_msgSend
00000001000ee538         mov        x29, x29
00000001000ee53c         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee540         mov        x27, x0
00000001000ee544         ldr        x0, [x28, #0x9d0]                           ; objc_cls_ref_WOWSUtils,__objc_class_WOWSUtils_class
00000001000ee548         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee54c         ldr        x1, [x8, #0x670]                            ; "getMD5String:",@selector(getMD5String:)
00000001000ee550         mov        x2, x27
00000001000ee554         bl         imp___stubs__objc_msgSend
00000001000ee558         mov        x29, x29
00000001000ee55c         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee560         mov        x28, x0
00000001000ee564         ldr        x0, [x21, #0xab0]                           ; objc_cls_ref_NSString,_OBJC_CLASS_$_NSString
00000001000ee568         str        x28, [sp, #0x10]
00000001000ee56c         str        d8, [sp, #0x8]
00000001000ee570         str        x19, sp
00000001000ee574         adrp       x2, #0x1012e7000
00000001000ee578         add        x2, x2, #0x760                              ; @"%@?auth_key=%.f-0-0-%@"
00000001000ee57c         mov        x1, x26
00000001000ee580         bl         imp___stubs__objc_msgSend
00000001000ee584         mov        x29, x29
00000001000ee588         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee58c         mov        x26, x0
00000001000ee590         mov        x0, x28
00000001000ee594         bl         imp___stubs__objc_release
00000001000ee598         mov        x0, x27
00000001000ee59c         bl         imp___stubs__objc_release
00000001000ee5a0         mov        x0, x24
00000001000ee5a4         bl         imp___stubs__objc_release
00000001000ee5a8         mov        x0, x25
00000001000ee5ac         bl         imp___stubs__objc_release
00000001000ee5b0         mov        x0, x23
00000001000ee5b4         bl         imp___stubs__objc_release
00000001000ee5b8         mov        x0, x22
00000001000ee5bc         bl         imp___stubs__objc_release
00000001000ee5c0         ldr        x0, [sp, #0x18]
00000001000ee5c4         bl         imp___stubs__objc_release
00000001000ee5c8         b          loc_1000ee5d8

                     loc_1000ee5cc:
00000001000ee5cc         mov        x0, x19                                     ; CODE XREF=-[WSAVPlayerView encryptionUrl:andVideoKey:]+68, -[WSAVPlayerView encryptionUrl:andVideoKey:]+72
00000001000ee5d0         bl         imp___stubs__objc_retain
00000001000ee5d4         mov        x26, x0

                     loc_1000ee5d8:
00000001000ee5d8         mov        x0, x20                                     ; CODE XREF=-[WSAVPlayerView encryptionUrl:andVideoKey:]+448
00000001000ee5dc         bl         imp___stubs__objc_release
00000001000ee5e0         mov        x0, x19
00000001000ee5e4         bl         imp___stubs__objc_release
00000001000ee5e8         mov        x0, x26
00000001000ee5ec         ldp        x29, x30, [sp, #0x80]
00000001000ee5f0         ldp        x20, x19, [sp, #0x70]
00000001000ee5f4         ldp        x22, x21, [sp, #0x60]
00000001000ee5f8         ldp        x24, x23, [sp, #0x50]
00000001000ee5fc         ldp        x26, x25, [sp, #0x40]
00000001000ee600         ldp        x28, x27, [sp, #0x30]
00000001000ee604         ldp        d9, d8, [sp, #0x20]
00000001000ee608         add        sp, sp, #0x90
00000001000ee60c         b          imp___stubs__objc_autoreleaseReturnValue
                        ; endp

用hopper查看得出大致流程

  • 解密base64的VideoKey
  • 格式化需要签名的字符串
  • 生成效验字符串MD5
  • 格式化成最终URL,也就是上面返回值

解密base64的VideoKey


那现在我们来看看怎么解密VideoKey的
服务器传下来的
VideoKey是NnVpU1VEc2drMTIzQVB4dDY=
base64解码以后的字符为
6uiSUDsgk123APxt6

00000001000ee4cc         ldr        x0, [x28, #0x9d0]                           ; objc_cls_ref_WOWSUtils,__objc_class_WOWSUtils_class
00000001000ee4d0         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee4d4         ldr        x1, [x8, #0x660]                            ; "base64Decode:",@selector(base64Decode:)
00000001000ee4d8         mov        x2, x20
00000001000ee4dc         bl         imp___stubs__objc_msgSend
00000001000ee4e0         mov        x29, x29
00000001000ee4e4         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee4e8         mov        x25, x0
00000001000ee4ec         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee4f0         ldr        x1, [x8, #0x668]                            ; "getPrivateKey:",@selector(getPrivateKey:)

在反汇编中可以看到解码以后调用了getPrivateKey方法
那么我们这里在cycript中带入看看

cy# [pv getPrivateKey:@"6uiSUDsgk123APxt6"]
@"sgk123"

发现这个结果是正确的

这是在hopper中查看[WSAVPlayerView getPrivateKey:]方法

00000001000ee610         stp        x24, x23, [sp, #-0x40]!                     ; Objective C Implementation defined at 0x10138c348 (instance method), DATA XREF=0x10138c348
00000001000ee614         stp        x22, x21, [sp, #0x10]
00000001000ee618         stp        x20, x19, [sp, #0x20]
00000001000ee61c         stp        x29, x30, [sp, #0x30]
00000001000ee620         add        x29, sp, #0x30
00000001000ee624         mov        x20, x2
00000001000ee628         adrp       x8, #0x101615000                            ; @selector(setStarImage:highlightedStarImage:)
00000001000ee62c         ldr        x21, [x8, #0x1c8]                           ; "substringToIndex:",@selector(substringToIndex:)
00000001000ee630         mov        x0, x20
00000001000ee634         bl         imp___stubs__objc_retain
00000001000ee638         mov        x19, x0
00000001000ee63c         orr        w2, wzr, #0x1
00000001000ee640         mov        x0, x20
00000001000ee644         mov        x1, x21
00000001000ee648         bl         imp___stubs__objc_msgSend
00000001000ee64c         mov        x29, x29
00000001000ee650         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee654         mov        x21, x0
00000001000ee658         adrp       x8, #0x101612000
00000001000ee65c         ldr        x22, [x8, #0x8c8]                           ; "integerValue",@selector(integerValue)
00000001000ee660         mov        x1, x22
00000001000ee664         bl         imp___stubs__objc_msgSend
00000001000ee668         mov        x23, x0
00000001000ee66c         mov        x0, x21
00000001000ee670         bl         imp___stubs__objc_release
00000001000ee674         adrp       x8, #0x101612000
00000001000ee678         ldr        x1, [x8, #0xa98]                            ; "length",@selector(length)
00000001000ee67c         mov        x0, x20
00000001000ee680         bl         imp___stubs__objc_msgSend
00000001000ee684         sub        x2, x0, #0x1
00000001000ee688         adrp       x8, #0x101614000                            ; @selector(setReturnKeyType:)
00000001000ee68c         ldr        x1, [x8, #0x460]                            ; "substringFromIndex:",@selector(substringFromIndex:)
00000001000ee690         mov        x0, x20
00000001000ee694         bl         imp___stubs__objc_msgSend
00000001000ee698         mov        x29, x29
00000001000ee69c         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee6a0         mov        x21, x0
00000001000ee6a4         mov        x1, x22
00000001000ee6a8         bl         imp___stubs__objc_msgSend
00000001000ee6ac         mov        x22, x0
00000001000ee6b0         mov        x0, x21
00000001000ee6b4         bl         imp___stubs__objc_release
00000001000ee6b8         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee6bc         ldr        x1, [x8, #0x678]                            ; "substringWithRange:",@selector(substringWithRange:)
00000001000ee6c0         mov        x0, x20
00000001000ee6c4         mov        x2, x23
00000001000ee6c8         mov        x3, x22
00000001000ee6cc         bl         imp___stubs__objc_msgSend
00000001000ee6d0         mov        x20, x0
00000001000ee6d4         mov        x0, x19
00000001000ee6d8         bl         imp___stubs__objc_release
00000001000ee6dc         mov        x0, x20
00000001000ee6e0         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee6e4         ldp        x29, x30, [sp, #0x30]
00000001000ee6e8         ldp        x20, x19, [sp, #0x20]
00000001000ee6ec         ldp        x22, x21, [sp, #0x10]
00000001000ee6f0         ldp        x24, x23, [sp]!, #0x40
00000001000ee6f4         b          imp___stubs__objc_autoreleaseReturnValue
                        ; endp

字符串6uiSUDsgk123APxt6得出sgk123的过程为
第一个字符和最后一个字符为字符串需要截取的开始和结尾
比如

6uiSUDsgk123APxt6 => 6uiSUD sgk123 APxt6
9TFQUz4wN sgk123 7ltDvfB6 => 9TFQUz4wN sgk123 7ltDvfB6

格式化需要签名的字符串

00000001000ee508         mov        x24, x0
00000001000ee50c         adrp       x21, #0x101643000                           ; @selector(wifiReachability)
00000001000ee510         ldr        x0, [x21, #0xab0]                           ; objc_cls_ref_NSString,_OBJC_CLASS_$_NSString
00000001000ee514         adrp       x8, #0x101612000
00000001000ee518         ldr        x26, [x8, #0xad0]                           ; "stringWithFormat:",@selector(stringWithFormat:)
00000001000ee51c         str        x24, [sp, #0x10]
00000001000ee520         str        d8, [sp, #0x8]
00000001000ee524         str        x22, sp
00000001000ee528         adrp       x2, #0x1012e7000
00000001000ee52c         add        x2, x2, #0x740                              ; @"%@-%.f-0-0-%@"
00000001000ee530         mov        x1, x26
00000001000ee534         bl         imp___stubs__objc_msgSend
00000001000ee538         mov        x29, x29
00000001000ee53c         bl         imp___stubs__objc_retainAutoreleasedReturnValue
00000001000ee540         mov        x27, x0
00000001000ee544         ldr        x0, [x28, #0x9d0]                           ; objc_cls_ref_WOWSUtils,__objc_class_WOWSUtils_class
00000001000ee548         adrp       x8, #0x101617000                            ; @selector(defaultManager)
00000001000ee54c         ldr        x1, [x8, #0x670]                            ; "getMD5String:",@selector(getMD5String:)

[WSAVPlayerView encryptionUrl:andVideoKey:]方法反汇编中可以看到

format的格式为%@-%.f-0-0-%@,这里有三个参数,怎么取获取这三个参数的值?

格式化完成以后传入getMD5String:方法
直接在getMD5String中查看传入的值就好了,这里使用lldb 的debugserver查看

debugserver默认没有task_for_pid权限
我们先把越狱手机/Developer/usr/bin/debugserver复制到mac

先创建一个ent.xml
然后保存一下内容

  
  
  
        com.apple.springboard.debugapplications  
          
        get-task-allow  
          
        task_for_pid-allow  
          
        run-unsigned-code  
          
  
  

执行签名

ldid -Sent.xml debugserver

然后复制到越狱设备的/usr/bin/
开启调试***为进程名称

Testerde-iPhone:~/ root# debugserver *:1234 -a "***"
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-320.2.89
 for arm64.
Attaching to process ***...
Listening to port 1234 for a connection from *..

这时调试服务器已经监听开启了1234端口等候处理
这里我们再使用iProxy映射一个端口

iproxy 1234 1234

新开一个终端
启动lldb建立和debugserver的连接

➜  ~ lldb
(lldb) process connect connect://127.0.0.1:1234
Process 6254 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x00000001965d4e7c libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x1965d4e7c <+8>: ret

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x1965d4e80 <+0>: mov    x16, #-0x20
    0x1965d4e84 <+4>: svc    #0x80
    0x1965d4e88 <+8>: ret
(lldb)

查看基址

(lldb) image list -o -f
[  0] 0x0000000000084000 /private/var/mobile/Containers/Bundle/Application/1999C8D2-58C1-43C0-A717-A44B55CC1FEA/***.app/***(0x0000000100084000)
[  1] 0x0000000000094000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/usr/lib/dyld
[  2] 0x000000010182c000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x000000010182c000)
[  3] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/usr/lib/libc++.1.dylib
[  4] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
[  5] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/Foundation.framework/Foundation
[  6] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/ImageIO.framework/ImageIO
[  7] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices
[  8] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/QuartzCore.framework/QuartzCore
[  9] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/Security.framework/Security
[ 10] 0x0000000003aac000 /Users/charley/Library/Developer/Xcode/iOS DeviceSupport/8.1.3 (12B466)/Symbols/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration

这里可以看到基址为0x0000000000084000

[  0] 0x0000000000084000 /private/var/mobile/Containers/Bundle/Application/1999C8D2-58C1-43C0-A717-A44B55CC1FEA/***.app/***(0x0000000100084000)

lldb命令c让程序继续运行

(lldb) c
Process 6254 resuming
(lldb)

我们在getMD5String这个方法的第一行下断点,也就是
下面的第一行

0000000100493b48         sub        sp, sp, #0x60                               ; Objective C Implementation defined at 0x10143f320 (class method), DATA XREF=0x10143f320
0000000100493b4c         stp        x24, x23, [sp, #0x20]
0000000100493b50         stp        x22, x21, [sp, #0x30]
0000000100493b54         stp        x20, x19, [sp, #0x40]
0000000100493b58         stp        x29, x30, [sp, #0x50]
0000000100493b5c         add        x29, sp, #0x50
0000000100493b60         mov        x19, x2

那么程序在手机内存中的地址怎么计算?
其实就是上面查看到的基址0x0000000000084000 +第一行的偏移量0000000100493b48 = 0x100517B48
那么我就在0x100517B48下断点

(lldb) br s -a 0x100517B48
Breakpoint 6: where = *** `_mh_execute_header + 4772212, address = 0x0000000100517b48

手机点击界面进行播放,lldb会断下来执行po $x2查看传入的参数

Process 6254 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
    frame #0: 0x0000000100517b48 ***`_mh_execute_header + 4799304
***`_mh_execute_header:
->  0x100517b48 <+4799304>: sub    sp, sp, #0x60             ; =0x60
    0x100517b4c <+4799308>: stp    x24, x23, [sp, #0x20]
    0x100517b50 <+4799312>: stp    x22, x21, [sp, #0x30]
    0x100517b54 <+4799316>: stp    x20, x19, [sp, #0x40]
(lldb)po $x2
/class/17426404/2dbe0a6c9077e5aa969196faf047be2b_17426404_480.mp4-1503551940-0-0-sgk123
(lldb)

是不是很清楚了
%@-%.f-0-0-%@格式化的三个参数

  • url路径
  • 时间戳
  • PrivateKey

后面的就比较容易了


生成效验字符串MD5


使用格式化的字符做MD5结果
f62b7278787782d900497c498d7271b2

格式化成最终URL

格式

@"%@?auth_key=%.f-0-0-%@"

参数如下

  • url地址
  • 时间戳
  • md5签名

格式化的结果

http://www.baidu.com/class/18007651/454eae93a1963d7c31b1076b7c5a6e58_18007651_480.mp4?auth_key=1503552405-0-0-f62b7278787782d900497c498d7271b2

参考文章


  • Cycript
  • Cycript基本语法与使用-iOS逆向工程
  • iOS逆向工程之Hopper+LLDB调试第三方App

你可能感兴趣的:(追踪iOS某APP的验证签名过程)