必赢亚洲手机app下载


国外程序员爱用苹果Mac电脑的十娄底由

的基本采用

反汇编的利器

初稿出处:
N.Y.(@__NY__)   

前言

近年来实战了二回 IDA + Hopper
逆向破解。讲真,第一回体会了一次把人家“服装”扒光了的快感~几乎 High
翻~所以,特此,利用 Alipay沃尔et 计算分享一下 IDA 和 Hopper
的中坚接纳。希望对我们有援助。

先想起一下,在此之前两篇小说已经学习的剧情:

  • 赢得1台越狱设备
  • 行使 SSH 连接待上访问越狱设备
  • 采用 Clutch 解密砸壳
  • 使用 class-dump 导出应用头文件
  • 选拔 Cycript 实行利用运维时的动态解析与修改

如此那般1看真正学了诸多技艺,而接下去那篇文章,会简单介绍多个反编写翻译的利器
IDA 和 Hopper 的应用。

注,这一次试验应用的并不是最新版本的开支宝 Mach-O
文件,因而或者这次试验中涉及的函数方法在新型版本中无法找到,但鉴于本文章只作为学习,所以,只提供具体的章程。假诺有亟待,可自动砸壳获得。

动态解析与静态分析

动态解析

我们前两篇学习的 Cycript ,便是数1数2的动态解析工具。Cycript
能够在动用举办运营时办法分析,视图层级分析等操作。而动态解析除了 Cycript
以外,常用的工具还有 lldb & debugserver 远程断点调节和测试,logify
追踪等,未来共同慢慢学习这几个技术方法。

静态分析

Static program analysis is the analysis of computer software that is
performed without actually executing programs (analysis performed on
executing programs is known as dynamic analysis).[1] In most cases the
analysis is performed on some version of the source code, and in the
other cases, some form of the object code.

上述是 Wikipedia 对静态分析的英文介绍,汉语翻译如下。

静态程序分析是指,未有实际施行顺序的应用程式分析方法(与之相对的是,被大千世界所知的其实履行软件的动态解析)。在多边的例子中,分析是运维在源代码的少数版本,而其他则是运作在目的代码中。

事先学习的 class-dump 工具导出 Mach-O
头文件,就是对软件应用进行静态分析。而明日我们要读书的多个工具,IDA 和
Hopper 反汇编2进制文件1律也是静态分析的法子。

IDA 的基本选取

什么是 IDA

IDA is the Interactive DisAssembler: the world’s smartest and most
feature-full disassembler, which many software security specialists are
familiar with.

IDA
是社会风气上最高效和多职能的反编写翻译工具,被许多软件安全我们所熟知的互动的反汇编工具。

安装 IDA

IDA 的官方网址是 https://www.hex-rays.com/ 。在网页上能够看出 IDA
的插件、SDK 等剧情。IDA 会在官网提供 德姆o 版的下载
https://www.hex-rays.com/products/ida/support/download_demo.shtml
。但是, 德姆o 版未有 IDA 最强劲的反汇编功效,神器
F5~!如若协调上学生运动用正版,很难负担大批量的证书开支,所以1般意况是在网上找破解版(囧。。并不引入,土豪仍旧提议买证书)。很倒霉的是
IDA Pro 的 Mac 版相当难找(小编是没找到)。所以,本文是在 Windows 下找破解
IDA Pro 来学习。

IDA Pro 的使用

打开 IDA 会出现 AboutSupport message 等唤醒对话框,点击
OK 继续后弹出 Quick Start
对话框,在这几个对话框里能够看来前面打开过的 IDA
反汇编二进制文件,也能够新建2个新的反汇编文件。那里大家点击 New
新建3个反汇编,这一次以支付宝为例。

图片 1

准备 Mach-O

忆起在此以前的剧情,先进行 Clutch 砸壳,然后 scp Alipay沃尔et 到 Mac
目录下,再接纳 class-dump 导出头文件。

导入 IDA

那里能够直接将 Mach-O 文件拖拽进 IDA
的工作区,也得以点击打开文件夹的图标将 Mach-O 导入。检查实验到 Objective-C
二.0 代码时会提醒,点击 OK 继续即可。
随后就是由来已久的等候~~~(Hopper 相对于 IDA
等待的日子会短1些,不过反编写翻译结果尚未 IDA 更近乎真实的 C
语言代码,会蕴藏众多寄存器变量)

认识 IDA 工作区

当 IDA 对 Mach-O 解析实现后,会暗中同意出现 伍个挑选卡视图,分别是汇编视图,1六进制字节视图,结构体视图,枚举类型视图,导入的函数视图,导出的函数视图
除此以外,红框标注的是工具栏,蓝框标注的是贰进制文件分析的快慢,在蓝框上面,用分化颜色区分库函数、数据、常规函数等分歧类其他分析数据。

图片 2

静态分析:还原源代码

利用 IDA
反汇编2进制文件的指标是,利用工具获得反汇编之后的伪代码,还原出真正的主次源码。比如,大家只要要看一下记名方法是如何写的,能够在曾经导出的
阿里pay沃尔et.h 中查询 login 关键字,并寻找有关代码,大家发现会有
LoginProtocol 协议和 LoginAdapter 类的连带代码,那我们无妨就拿
LoginAdapter 那一个类作为实战商讨对象。

Objective-C

@protocol LoginProtocol NSObject> + (id)sharedInstantce; –
(NSDictionary *)currentSession; – (void)loginWithLoginOption:(int)arg1
extraInfo:(NSDictionary *)arg2 completionHandler:(void (^)(BOOL,
NSDictionary *))arg3 cancelationHandler:(void (^)(void))arg4; –
(void)loginWithLoginOption:(int)arg1 completionHandler:(void (^)(BOOL,
NSDictionary *))arg2 cancelationHandler:(void (^)(void))arg3; –
(BOOL)isValidLogin;   @optional – (void)logout; –
(void)markInvalidLogin; – (BOOL)isProcessingLogin; @end   @interface
LoginAdapter : NSObject LoginProtocol> { int _is_login_doing; int
_is_processing_pending; id _network_config; id _login_service;
NSMutableArray *_loginPendingRequests; NSRecursiveLock
*_pending_lock; }   + (id)sharedInstantce; @property(retain,
nonatomic) NSRecursiveLock *pending_lock; // @synthesize
pending_lock=_pending_lock; @property(retain, nonatomic)
NSMutableArray *loginPendingRequests; // @synthesize
loginPendingRequests=_loginPendingRequests; @property(retain,
nonatomic) id login_service; // @synthesize
login_service=_login_service; @property(retain, nonatomic) id
network_config; // @synthesize network_config=_network_config; –
(void).cxx_destruct; – (void)storeSessionWithLoginResult:(id)arg1; –
(id)currentUserId; – (void)notifyNetworkSDK:(id)arg1; –
(void)logout:(id)arg1; – (void)logined:(id)arg1; –
(void)loadAlu:(Class)arg1; – (void)loadLoginModule; –
(void)loadNetworSDKConfig; – (void)failedPendingLoginRequests; –
(void)redoPendingLoginRequests; – (void)pendingLoginRequest:(id)arg1; –
(void)releasePendingLock; – (void)accquirePendingLock; –
(void)releaseLoginLock; – (BOOL)accquireLoginLock; –
(int)tryLogin:(id)arg1 isForce:(BOOL)arg2; – (int)tryLogin:(id)arg1; –
(void)logout; – (id)currentSession; –
(int)loginWithLoginOption:(int)arg1 isForce:(BOOL)arg2
extraInfo:(id)arg3 completionHandler:(CDUnknownBlockType)arg4
cancelationHandler:(CDUnknownBlockType)arg5 request:(id)arg6; –
(void)loginWithLoginOption:(int)arg1 extraInfo:(id)arg2
completionHandler:(CDUnknownBlockType)arg3
cancelationHandler:(CDUnknownBlockType)arg4; –
(void)loginWithLoginOption:(int)arg1
completionHandler:(CDUnknownBlockType)arg2
cancelationHandler:(CDUnknownBlockType)arg3; – (BOOL)isValidLogin; –
(BOOL)isProcessingLogin; – (void)markInvalidLogin; –
(id)setCustomLoginModule:(id)arg1; – (void)dealloc; – (id)init;   //
Remaining properties @property(readonly, copy) NSString
*debugDescription; @property(readonly, copy) NSString *description;
@property(readonly) unsigned int hash; @property(readonly) Class
superclass;   @end

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
@protocol LoginProtocol NSObject>
+ (id)sharedInstantce;
– (NSDictionary *)currentSession;
– (void)loginWithLoginOption:(int)arg1 extraInfo:(NSDictionary *)arg2 completionHandler:(void (^)(BOOL, NSDictionary *))arg3 cancelationHandler:(void (^)(void))arg4;
– (void)loginWithLoginOption:(int)arg1 completionHandler:(void (^)(BOOL, NSDictionary *))arg2 cancelationHandler:(void (^)(void))arg3;
– (BOOL)isValidLogin;
 
@optional
– (void)logout;
– (void)markInvalidLogin;
– (BOOL)isProcessingLogin;
@end
 
@interface LoginAdapter : NSObject LoginProtocol>
{
int _is_login_doing;
int _is_processing_pending;
id _network_config;
id _login_service;
NSMutableArray *_loginPendingRequests;
NSRecursiveLock *_pending_lock;
}
 
+ (id)sharedInstantce;
@property(retain, nonatomic) NSRecursiveLock *pending_lock; // @synthesize pending_lock=_pending_lock;
@property(retain, nonatomic) NSMutableArray *loginPendingRequests; // @synthesize loginPendingRequests=_loginPendingRequests;
@property(retain, nonatomic) id login_service; // @synthesize login_service=_login_service;
@property(retain, nonatomic) id network_config; // @synthesize network_config=_network_config;
– (void).cxx_destruct;
– (void)storeSessionWithLoginResult:(id)arg1;
– (id)currentUserId;
– (void)notifyNetworkSDK:(id)arg1;
– (void)logout:(id)arg1;
– (void)logined:(id)arg1;
– (void)loadAlu:(Class)arg1;
– (void)loadLoginModule;
– (void)loadNetworSDKConfig;
– (void)failedPendingLoginRequests;
– (void)redoPendingLoginRequests;
– (void)pendingLoginRequest:(id)arg1;
– (void)releasePendingLock;
– (void)accquirePendingLock;
– (void)releaseLoginLock;
– (BOOL)accquireLoginLock;
– (int)tryLogin:(id)arg1 isForce:(BOOL)arg2;
– (int)tryLogin:(id)arg1;
– (void)logout;
– (id)currentSession;
– (int)loginWithLoginOption:(int)arg1 isForce:(BOOL)arg2 extraInfo:(id)arg3 completionHandler:(CDUnknownBlockType)arg4 cancelationHandler:(CDUnknownBlockType)arg5 request:(id)arg6;
– (void)loginWithLoginOption:(int)arg1 extraInfo:(id)arg2 completionHandler:(CDUnknownBlockType)arg3 cancelationHandler:(CDUnknownBlockType)arg4;
– (void)loginWithLoginOption:(int)arg1 completionHandler:(CDUnknownBlockType)arg2 cancelationHandler:(CDUnknownBlockType)arg3;
– (BOOL)isValidLogin;
– (BOOL)isProcessingLogin;
– (void)markInvalidLogin;
– (id)setCustomLoginModule:(id)arg1;
– (void)dealloc;
– (id)init;
 
// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned int hash;
@property(readonly) Class superclass;
 
@end

在头文件里搜寻能够得到地点结果,以 LoginAdapter 为例。大家得以在
function 窗口中按住 Ctrl+F 键查找 LoginAdapter 的连锁函数。

图片 3

双击 [LoginAdapter sharedInstan]
到达那几个函数在二进制文件中的内部存款和储蓄器地址,按 F5
能够就翻开这一个反编写翻译的伪码。
那边能够看一下登录方法 Alipay 是什么写的,双击 [LoginAdapter
loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:]

,按 F5 键查看那些办法的反编写翻译伪代码。伪代码如下。

Objective-C

// LoginAdapter – (int)loginWithLoginOption:(int) isForce:(char)
extraInfo:(id) completionHandler:(id) cancelationHandler:(id)
request:(id) int __cdecl -[LoginAdapter
loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](struct
LoginAdapter *self, SEL a2, int a3, char a4, id a5, id a6, id a7, id
a8) { struct LoginAdapter *v8; // r8<a
href=’http://www.jobbole.com/members/yaowei729'&gt;@1&lt;/a&gt; // some
variarble   v8 = self; v9 = a4; v37 = a3; v39 = objc_retain(a5, a2);
v11 = objc_retain(a6, v10); v13 = objc_retain(a7, v12); v15 = (void
*)objc_retain(a8, v14); if ( !v8->_login_service ) { v18 = 0; v19
= v39; goto LABEL_27; } v40 = v11; if ( v15 ) objc_msgSend(v8,
“accquirePendingLock”); if ( (unsigned int)objc_msgSend(v8,
“accquireLoginLock”) & 0xFF ) { if ( v9 || !((unsigned
int)objc_msgSend(v8, “isValidLogin”) & 0xFF) ) { v36 = v13; if ( v15 )
objc_msgSend(v8, “pendingLoginRequest:”, v15); v20 =
objc_msgSend(&OBJC_CLASS___LogAdapter, “getInstance”); v21 = (void
*)objc_retainAutoreleasedReturnValue(v20); v38 = v8; v22 =
objc_msgSend(v15, “getApiName”); v23 =
objc_retainAutoreleasedReturnValue(v22); v24 = objc_msgSend(v15,
“getApiVersion”); v25 = objc_retainAutoreleasedReturnValue(v24); v26 =
v25; v27 = objc_msgSend( &OBJC_CLASS___NSString,
“stringWithFormat:”, CFSTR(“[LoginAdapter] apiName: %<a
href=’http://www.jobbole.com/members/Famous\_god'&gt;@,&lt;/a&gt;
apiVersion: %@ pull login module”), v23, v25); v28 =
objc_retainAutoreleasedReturnValue(v27); objc_msgSend(v21, “warn:”,
v28); objc_release(v28); objc_release(v26); objc_release(v23);
objc_release(v21); v29 = v38->_login_service; v48 =
&_NSConcreteStackBlock; v49 = -1040187392; v50 = 0; v51 = sub_2AAF082;
v52 = &unk_3164640; v30 = objc_retain(v38, sub_2AAF082); v53 = v30;
v54 = objc_retain(v40, v31); v41 = &_NSConcreteStackBlock; v42 =
-1040187392; v43 = 0; v44 = sub_2AAF1AC; v45 = &unk_3164660; v13 =
v36; v46 = objc_retain(v30, &unk_3164660); v19 = v39; v47 =
objc_retain(v36, v32); objc_msgSend(v29,
“loginWithLoginOption:extraInfo:completionHandler:cancelationHandler:”,
v37, v39, &v48, &v41); objc_release(v47); objc_release(v46);
objc_release(v54); objc_release(v53); v18 = 2; goto LABEL_24; }
objc_msgSend(v8, “releaseLoginLock”); if ( v11 ) { v38 = v8; v16 =
objc_msgSend(v8->_login_service, “currentSession”); v17 =
objc_retainAutoreleasedReturnValue(v16); (*(void (__fastcall
**)(int, signed int, int))(v11 + 12))(v11, 1, v17);
objc_release(v17); } else { v38 = v8; } v18 = 3; } else { if ( v15 ) {
if ( (unsigned int)objc_msgSend((void *)v8->_loginPendingRequests,
“count”) > 0xFF ) { v38 = v8; v18 = 0; } else { v38 = v8;
objc_msgSend(v8, “pendingLoginRequest:”, v15); v18 = 1; } } else { v38
= v8; v18 = 0; } if ( v11 ) { v33 =
objc_msgSend(&OBJC_CLASS___NSDictionary, “dictionary”); v34 =
objc_retainAutoreleasedReturnValue(v33); v40 = v11; (*(void
(__fastcall **)(int, _DWORD, int))(v11 + 12))(v11, 0, v34);
objc_release(v34); } else { v40 = 0; } } v19 = v39; LABEL_24: if ( v15
) objc_msgSend(v38, “releasePendingLock”); v11 = v40; LABEL_27:
objc_release(v15); objc_release(v13); objc_release(v11);
objc_release(v19); return v18; }

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// LoginAdapter – (int)loginWithLoginOption:(int) isForce:(char) extraInfo:(id) completionHandler:(id) cancelationHandler:(id) request:(id)
int __cdecl -[LoginAdapter loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](struct LoginAdapter *self, SEL a2, int a3, char a4, id a5, id a6, id a7, id a8)
{
struct LoginAdapter *v8; // r8<a href=’http://www.jobbole.com/members/yaowei729′>@1</a>
// some variarble
 
v8 = self;
v9 = a4;
v37 = a3;
v39 = objc_retain(a5, a2);
v11 = objc_retain(a6, v10);
v13 = objc_retain(a7, v12);
v15 = (void *)objc_retain(a8, v14);
if ( !v8->_login_service )
{
v18 = 0;
v19 = v39;
goto LABEL_27;
}
v40 = v11;
if ( v15 )
objc_msgSend(v8, "accquirePendingLock");
if ( (unsigned int)objc_msgSend(v8, "accquireLoginLock") & 0xFF )
{
if ( v9 || !((unsigned int)objc_msgSend(v8, "isValidLogin") & 0xFF) )
{
v36 = v13;
if ( v15 )
objc_msgSend(v8, "pendingLoginRequest:", v15);
v20 = objc_msgSend(&OBJC_CLASS___LogAdapter, "getInstance");
v21 = (void *)objc_retainAutoreleasedReturnValue(v20);
v38 = v8;
v22 = objc_msgSend(v15, "getApiName");
v23 = objc_retainAutoreleasedReturnValue(v22);
v24 = objc_msgSend(v15, "getApiVersion");
v25 = objc_retainAutoreleasedReturnValue(v24);
v26 = v25;
v27 = objc_msgSend(
&OBJC_CLASS___NSString,
"stringWithFormat:",
CFSTR("[LoginAdapter] apiName: %<a href=’http://www.jobbole.com/members/Famous_god’>@,</a> apiVersion: %@ pull login module"),
v23,
v25);
v28 = objc_retainAutoreleasedReturnValue(v27);
objc_msgSend(v21, "warn:", v28);
objc_release(v28);
objc_release(v26);
objc_release(v23);
objc_release(v21);
v29 = v38->_login_service;
v48 = &_NSConcreteStackBlock;
v49 = -1040187392;
v50 = 0;
v51 = sub_2AAF082;
v52 = &unk_3164640;
v30 = objc_retain(v38, sub_2AAF082);
v53 = v30;
v54 = objc_retain(v40, v31);
v41 = &_NSConcreteStackBlock;
v42 = -1040187392;
v43 = 0;
v44 = sub_2AAF1AC;
v45 = &unk_3164660;
v13 = v36;
v46 = objc_retain(v30, &unk_3164660);
v19 = v39;
v47 = objc_retain(v36, v32);
objc_msgSend(v29, "loginWithLoginOption:extraInfo:completionHandler:cancelationHandler:", v37, v39, &v48, &v41);
objc_release(v47);
objc_release(v46);
objc_release(v54);
objc_release(v53);
v18 = 2;
goto LABEL_24;
}
objc_msgSend(v8, "releaseLoginLock");
if ( v11 )
{
v38 = v8;
v16 = objc_msgSend(v8->_login_service, "currentSession");
v17 = objc_retainAutoreleasedReturnValue(v16);
(*(void (__fastcall **)(int, signed int, int))(v11 + 12))(v11, 1, v17);
objc_release(v17);
}
else
{
v38 = v8;
}
v18 = 3;
}
else
{
if ( v15 )
{
if ( (unsigned int)objc_msgSend((void *)v8->_loginPendingRequests, "count") > 0xFF )
{
v38 = v8;
v18 = 0;
}
else
{
v38 = v8;
objc_msgSend(v8, "pendingLoginRequest:", v15);
v18 = 1;
}
}
else
{
v38 = v8;
v18 = 0;
}
if ( v11 )
{
v33 = objc_msgSend(&OBJC_CLASS___NSDictionary, "dictionary");
v34 = objc_retainAutoreleasedReturnValue(v33);
v40 = v11;
(*(void (__fastcall **)(int, _DWORD, int))(v11 + 12))(v11, 0, v34);
objc_release(v34);
}
else
{
v40 = 0;
}
}
v19 = v39;
LABEL_24:
if ( v15 )
objc_msgSend(v38, "releasePendingLock");
v11 = v40;
LABEL_27:
objc_release(v15);
objc_release(v13);
objc_release(v11);
objc_release(v19);
return v18;
}

反编写翻译后的伪代码会保持原来函数的逻辑和函数的标志名,接下去,我们就能够品尝还原那段代码的
Objective-C 源代码。

成立工程

成立1个空项目,并创立 LoginAdapter 类的头文件和落到实处文件,然后把
class-dump 导出的头文件的 property
和共有的艺术复制在新创制的头文件中,然后依照反汇编码还原原代码。

瞩目,在这么些事例中, CDUnknownBlockType 是一个 block
类型,可是实际的 block 类型,class-dump 不能够导出,如若想赢得那一个 block
可参照

方法名和参数

笔者们知晓, Objective-C 中的 objc_msgSend
方法是向新闻接受者(实例对象)发送一条新闻,苹果文书档案如下。

**objc_msgSend** Sends a message with a simple return value to an
instance of a class.   id objc_msgSend(id self, SEL op, …);  
Parameters self A pointer that points to the instance of the class that
is to receive the message.   op The selector of the method that handles
the message.   … A variable argument list containing the arguments to
the method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
**objc_msgSend**
Sends a message with a simple return value to an instance of a class.
 
id objc_msgSend(id self, SEL op, …);
 
Parameters
self
A pointer that points to the instance of the class that is to receive the message.
 
op
The selector of the method that handles the message.
 
A variable argument list containing the arguments to the method.

从文书档案能够汲取,第一个参数是该接受新闻类型实例的指针,首个参数是办法选择器(selector),之后是实例方法传递的参数。

而在反编写翻译获得的伪码中,第一行正是 Objective-C 方法和实在 C
函数的参数对应,如下所示。

int __cdecl -[LoginAdapter
loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](struct
LoginAdapter *self, SEL a2, int a3, char a4, id a5, id a6, id a7, id
a8)

1
int __cdecl -[LoginAdapter loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](struct LoginAdapter *self, SEL a2, int a3, char a4, id a5, id a6, id a7, id a8)

故而,大家能够得出:
self 是时下实例指针,a二 对应方法选用器,a3 对应方法参数 option; a4对应方法参数 isForce; a5 对应方法参数 extraInfo; a六 对应方法参数
completionHandler; a7 对应方法参数 cancelationHandler; a八 对应方法参数
request
。分明方法名和参数对应提到随后,大家接下去就开头还原函数体。

方法函数体

还原函数体的基本思路很不难,正是选择伪代码的方法名和变量,依照使用正向开发的经验方法,还原函数体的切实逻辑。

对此函数体中涉及的其他类及连锁协议协议,如,MtopExtRequest
TBSDKRequest LogAdapter 等也足以选取 IDA
和头文件获得,具体恢复生机进度那里就不再赘述,还原函数体代码如下。

Objective-C

#import “LoginAdapter.h” #import “LogAdapter.h” #import
“MtopExtRequest.h”   @implementation LoginAdapter   –
(NSInteger)loginWithLoginOption:(int)option isForce:(BOOL)isForce
extraInfo:(NSDictionary *)extraInfo
completionHandler:(AlipayCompletionHandler)completionHandler
cancelationHandler:(AlipayCancelationHandler)cancelationHandler
request:(MtopExtRequest *)request { // self 是近来实例指针,a2对应方法选拔器,a叁 对应方法参数 option; a4 对应方法参数 isForce; a5对应方法参数 extraInfo; // a六 对应方法参数 completionHandler; a7对应方法参数 cancelationHandler; a8 对应方法参数 request NSInteger
returnValue = 0; // v1八   if (!self.login_service) { returnValue = 0; }
  if (request) { [self accquirePendingLock]; }   if ([self
accquireLoginLock]) {   if (extraInfo || ![self isValidLogin]) { if
(request) { [self pendingLoginRequest:request]; }   LogAdapter
*logAdapter = [LogAdapter getInstance]; NSString *apiName =
[request getApiName]; NSString *apiVersion = [request
getApiVersion]; NSString *logString = [NSString
stringWithFormat:@”[LoginAdapter] apiName: %<a
href=’http://www.jobbole.com/members/Famous\_god'&gt;@,&lt;/a&gt;
apiVersion: %@ pull login module”, apiName, apiVersion]; [logAdapter
warn:logString];   [self.login_service loginWithLoginOption:option
extraInfo:extraInfo completionHandler:completionHandler
cancelationHandler:cancelationHandler];   } // extraInfo || ![self
isValidLogin] end   [self releaseLoginLock];   if (completionHandler)
{ NSDictionary *currentSession = [self.login_service
currentSession]; completionHandler(1, currentSession); } else { // v3八= v八 即,对 self 进行 retain 操作,无需翻译成 oc 代码 }   returnValue =
三;   } else { if (request) {   if (self.loginPendingRequests.count) {
returnValue = 0; } else { [self pendingLoginRequest:request];
returnValue = 1; }   } else { returnValue = 0; }   if
(completionHandler) { completionHandler(0, [NSDictionary dictionary]);
} else { completionHandler = nil; } }   if (request) { [self
releaseLoginLock]; }   return returnValue; }   @end

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#import "LoginAdapter.h"
#import "LogAdapter.h"
#import "MtopExtRequest.h"
 
@implementation LoginAdapter
 
– (NSInteger)loginWithLoginOption:(int)option
isForce:(BOOL)isForce
extraInfo:(NSDictionary *)extraInfo
completionHandler:(AlipayCompletionHandler)completionHandler
cancelationHandler:(AlipayCancelationHandler)cancelationHandler
request:(MtopExtRequest *)request {
// self 是当前实例指针,a2 对应方法选择器,a3 对应方法参数 option; a4 对应方法参数 isForce; a5 对应方法参数 extraInfo;
// a6 对应方法参数 completionHandler; a7 对应方法参数 cancelationHandler; a8 对应方法参数 request
NSInteger returnValue = 0; // v18
 
if (!self.login_service) {
returnValue = 0;
}
 
if (request) {
[self accquirePendingLock];
}
 
if ([self accquireLoginLock]) {
 
if (extraInfo || ![self isValidLogin]) {
if (request) {
[self pendingLoginRequest:request];
}
 
LogAdapter *logAdapter = [LogAdapter getInstance];
NSString *apiName = [request getApiName];
NSString *apiVersion = [request getApiVersion];
NSString *logString = [NSString stringWithFormat:@"[LoginAdapter] apiName: %<a href=’http://www.jobbole.com/members/Famous_god’>@,</a> apiVersion: %@ pull login module", apiName, apiVersion];
[logAdapter warn:logString];
 
[self.login_service loginWithLoginOption:option
extraInfo:extraInfo
completionHandler:completionHandler
cancelationHandler:cancelationHandler];
 
} // extraInfo || ![self isValidLogin] end
 
[self releaseLoginLock];
 
if (completionHandler) {
NSDictionary *currentSession = [self.login_service currentSession];
completionHandler(1, currentSession);
} else {
// v38 = v8 即,对 self 进行 retain 操作,无需翻译成 oc 代码
}
 
returnValue = 3;
 
} else {
if (request) {
 
if (self.loginPendingRequests.count) {
returnValue = 0;
} else {
[self pendingLoginRequest:request];
returnValue = 1;
}
 
} else {
returnValue = 0;
}
 
if (completionHandler) {
completionHandler(0, [NSDictionary dictionary]);
} else {
completionHandler = nil;
}
}
 
if (request) {
[self releaseLoginLock];
}
 
return returnValue;
}
 
@end

假使想查看具体代码,可到 GitHub 查看:
库房地址 https://github.com/niyaoyao/reverse-learning

Hopper 的为主选用

对此 Hopper 的上学,依旧接纳 Alipay沃尔et 这些文件举行剖析,与 IDA
做相比,类比举行。

什么是 Hopper

Hopper Disassembler, the reverse engineering tool that lets you
disassemble, decompile and debug your applications.

Hopper
反汇编工具,是逆向工程的工具,能够让您进行反汇编、反编写翻译并且调节和测试你的使用。

安装 Hopper

Hopper 的官网是 https://www.hopperapp.com/ ,与 IDA 相同,官网也提供了
德姆o 的试用版。试用版也足以开始展览反汇编,不过不可能保存 *.hop
文件。所以,用于学习的话 Hopper 的 德姆o 版就丰富了。

Hopper 的使用

导入 Hopper

与 IDA 差别, Hopper 不可能直接将 Mach-O 文件导入工作区,供给下载使用的
*.ipa 文件,并将文件后缀改为 *.zip,解压该 zip 文件后就可看出 Payload
文件目录,在该目录下就具备对应应用的 package 包文件。右击该 package
出现菜单,选取 Show Package Contents 选项,就可知到包内容。

图片 4

认识 Hopper 工作区

与 IDA 类似, Hopper 也有二进制文件的解析进度条,左侧是符号 Label
等区域,中间是 A宝马X3M 的汇编代码,左边是连锁新闻栏。

图片 5

静态分析:Hopper 反汇编的伪代码

如图,在最左列的搜索栏中输入 loginWithLoginOption 关键字,双击选用
[LoginAdapter
loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:]

方法,在中游的汇编代码区域,光标就会跳到该措施的内部存款和储蓄器地址处。

图片 6

当 Hopper 分析完全数二进制后,按住 Option + Enter 键,就可看出
Hopper 反编写翻译后的伪代码,如下所示。

int -[LoginAdapter
loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](void
* self, void * _cmd, int arg2, char arg3, void * arg4, void * arg5,
void * arg6, void * arg7) { stack[2048] = arg4; r7 = (sp – 0x14) +
0xc; sp = sp – 0x74; r8 = self; r5 = arg3; stack[2051] = arg2;
stack[2053] = [arg4 retain]; r6 = [arg5 retain]; r11 = [arg6
retain]; r10 = [arg7 retain]; if (r8->_login_service == 0x0)
goto loc_2aaee0a;   loc_2aaed6c: stack[2054] = r6; if (r10 != 0x0) {
[r8 accquirePendingLock]; } if (([r8 accquireLoginLock] & 0xff) ==
0x0) goto loc_2aaefa8;   loc_2aaeda0: if (((r5 & 0xff) != 0x0) ||
(([r8 isValidLogin] & 0xff) == 0x0)) goto loc_2aaee10;  
loc_2aaedbe: [r8 releaseLoginLock]; r6 = stack[2054]; if (r6 !=
0x0) { stack[2052] = r8; r5 = [[r8->_login_service
currentSession] retain]; (*(r6 + 0xc))(r6, 0x1, r5, *(r6 + 0xc));
[r5 release]; } else { stack[2052] = r8; } r5 = 0x3; goto
loc_2aaf044;   loc_2aaf044: r4 = stack[2053]; goto loc_2aaf046;  
loc_2aaf046: if (r10 != 0x0) { [stack[2052] releasePendingLock]; }
r6 = stack[2054]; goto loc_2aaf060;   loc_2aaf060: [r10 release];
[r11 release]; [r6 release]; [r4 release]; r0 = r5; return r0;  
loc_2aaee10: stack[2050] = r11; if (r10 != 0x0) { [r8
pendingLoginRequest:r10]; } r6 = [[LogAdapter getInstance] retain];
stack[2052] = r8; r8 = [[r10 getApiName] retain]; r11 = [[r10
getApiVersion] retain]; r5 = [[NSString
stringWithFormat:@”[LoginAdapter] apiName: %<a
href=’http://www.jobbole.com/members/Famous\_god'&gt;@,&lt;/a&gt;
apiVersion: %@ pull login module”, r8, r11] retain]; [r6 warn:r5];
[r5 release]; [r11 release]; [r8 release]; [r6 release]; r5 =
[stack[2052] retain]; stack[2068] = [stack[2054] retain]; r11
= stack[2050]; stack[2060] = [r5 retain]; r4 = stack[2053];
stack[2061] = [r11 retain]; [stack[2052]->_login_service
loginWithLoginOption:stack[2051] extraInfo:r4 completionHandler:sp +
0x38 cancelationHandler:sp + 0x1c, stack[2050], stack[2051],
stack[2052], stack[2053], stack[2054], __NSConcreteStackBlock,
0xc2000000, 0x0]; [stack[2061] release]; [stack[2060] release];
[stack[2068] release]; [r5 release]; r5 = 0x2; goto loc_2aaf046;
  loc_2aaefa8: if (r10 != 0x0) { r6 = stack[2054]; if
([r8->_loginPendingRequests count] stack[2052] = r8; [r8
pendingLoginRequest:r10]; r5 = 0x1; } else { stack[2052] = r8; r5 =
0x0; } } else { stack[2052] = r8; r5 = 0x0; r6 = stack[2054]; } if
(r6 != 0x0) { r4 = [[NSDictionary dictionary] retain]; stack[2054]
= r6; (*(r6 + 0xc))(r6, 0x0, r4, *(r6 + 0xc), stack[2048]); [r4
release]; } else { stack[2054] = r6; } goto loc_2aaf044;  
loc_2aaee0a: r5 = 0x0; r4 = stack[2053]; goto loc_2aaf060; }

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
int -[LoginAdapter loginWithLoginOption:isForce:extraInfo:completionHandler:cancelationHandler:request:](void * self, void * _cmd, int arg2, char arg3, void * arg4, void * arg5, void * arg6, void * arg7) {
stack[2048] = arg4;
r7 = (sp – 0x14) + 0xc;
sp = sp – 0x74;
r8 = self;
r5 = arg3;
stack[2051] = arg2;
stack[2053] = [arg4 retain];
r6 = [arg5 retain];
r11 = [arg6 retain];
r10 = [arg7 retain];
if (r8->_login_service == 0x0) goto loc_2aaee0a;
 
loc_2aaed6c:
stack[2054] = r6;
if (r10 != 0x0) {
[r8 accquirePendingLock];
}
if (([r8 accquireLoginLock] & 0xff) == 0x0) goto loc_2aaefa8;
 
loc_2aaeda0:
if (((r5 & 0xff) != 0x0) || (([r8 isValidLogin] & 0xff) == 0x0)) goto loc_2aaee10;
 
loc_2aaedbe:
[r8 releaseLoginLock];
r6 = stack[2054];
if (r6 != 0x0) {
stack[2052] = r8;
r5 = [[r8->_login_service currentSession] retain];
(*(r6 + 0xc))(r6, 0x1, r5, *(r6 + 0xc));
[r5 release];
}
else {
stack[2052] = r8;
}
r5 = 0x3;
goto loc_2aaf044;
 
loc_2aaf044:
r4 = stack[2053];
goto loc_2aaf046;
 
loc_2aaf046:
if (r10 != 0x0) {
[stack[2052] releasePendingLock];
}
r6 = stack[2054];
goto loc_2aaf060;
 
loc_2aaf060:
[r10 release];
[r11 release];
[r6 release];
[r4 release];
r0 = r5;
return r0;
 
loc_2aaee10:
stack[2050] = r11;
if (r10 != 0x0) {
[r8 pendingLoginRequest:r10];
}
r6 = [[LogAdapter getInstance] retain];
stack[2052] = r8;
r8 = [[r10 getApiName] retain];
r11 = [[r10 getApiVersion] retain];
r5 = [[NSString stringWithFormat:@"[LoginAdapter] apiName: %<a href=’http://www.jobbole.com/members/Famous_god’>@,</a> apiVersion: %@ pull login module", r8, r11] retain];
[r6 warn:r5];
[r5 release];
[r11 release];
[r8 release];
[r6 release];
r5 = [stack[2052] retain];
stack[2068] = [stack[2054] retain];
r11 = stack[2050];
stack[2060] = [r5 retain];
r4 = stack[2053];
stack[2061] = [r11 retain];
[stack[2052]->_login_service loginWithLoginOption:stack[2051] extraInfo:r4 completionHandler:sp + 0x38 cancelationHandler:sp + 0x1c, stack[2050], stack[2051], stack[2052], stack[2053], stack[2054], __NSConcreteStackBlock, 0xc2000000, 0x0];
[stack[2061] release];
[stack[2060] release];
[stack[2068] release];
[r5 release];
r5 = 0x2;
goto loc_2aaf046;
 
loc_2aaefa8:
if (r10 != 0x0) {
r6 = stack[2054];
if ([r8->_loginPendingRequests count]
stack[2052] = r8;
[r8 pendingLoginRequest:r10];
r5 = 0x1;
}
else {
stack[2052] = r8;
r5 = 0x0;
}
}
else {
stack[2052] = r8;
r5 = 0x0;
r6 = stack[2054];
}
if (r6 != 0x0) {
r4 = [[NSDictionary dictionary] retain];
stack[2054] = r6;
(*(r6 + 0xc))(r6, 0x0, r4, *(r6 + 0xc), stack[2048]);
[r4 release];
}
else {
stack[2054] = r6;
}
goto loc_2aaf044;
 
loc_2aaee0a:
r5 = 0x0;
r4 = stack[2053];
goto loc_2aaf060;
}

与 IDA 相比较, Hopper 反编写翻译后的伪代码的逻辑与 IDA
反编写翻译获得的伪代码逻辑类似,但多了 r0~r8等寄存器,阅读性相较而言差了一点,可是,还是能够依据伪代码还原出源代码。

事实上大家得以用这么些伪代码来检查我们事先还原的源代码,保险还原代码的不利。

以上,正是 Hopper 的粗略利用。 Hopper
除了能够查阅汇编代码以外,仍是能够直接对 Mach-O
文件实行改动,然后再一次生成二进制文件(德姆o 版没有这么些成效)。

感兴趣的同室能够阅读那篇文章学习, 《怎样让 Mac
版微信客户端防撤回》http://t.cn/RxzeMIx

小结

正文重要学习了一下剧情:

  • IDA 的装置及利用
  • Hopper 的安装及采用
  • 静态分析,依照伪码还原源代码

至于 iOS 安全球还有很多技能要学习,以后还会一而再攻读钻研。比如,TheOS、
tweak、加密解密、越狱应用开发等,可是不着急稳步学~
Where there’s a will, there’s a way!
Never forget your dream!
Fighting!

参考

题外话

那篇作品,首要讲了 IDA 和 Hopper
的着力选拔,反汇编工具得以壹本万利大家解析利用的二进制文件,但工具的施用是次要,最根本的是思想。任何措施假以时日都以能够被人学会的,记得念茜大神在腾讯网上说过一句话,「密码只是道锁,而平安是个种类」(马虎是这么)。

事先爆出的支付宝的纰漏,也固然表明了那或多或少。用户朋友能够透过忘记密码,进入手机不在身边入口。之后,选用联系人、收货地址、购买的货物等音讯,就能绕过密码登录,修改密码,从而登录账户得到用户权限。密码只是一道锁,系统的完整安全才是着力重点。或然说,任何安全进攻和防守要消除的标题都以,提权得到root
权限,从而举行种种操作。而前天学到的诀窍,也仅是略窥1斑。所以,要更为完善的求学,不光是
iOS 进攻和防守技能,操作系统内核原理、Android 进攻和防守、 Web
前端进攻和防守相关技能也应具有涉猎。

除此以外,网络发展越来越兴旺发达,音信能源也随后变得廉价。技术不是最难的,一项技艺,你会,旁人也足以学会。由此,会1门技术、1个编制程序语言,都无法变成一位的着力竞争力。真正的竞争力是人的考虑,是消除难点的能力。所以,大家不应执念于技术或工具。(讲真,看到从前某厂争辩应该运用
Vue 依然 React 技术栈的时候,真心觉得是内容倒置。)

2 赞 6 收藏 1
评论

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图