必赢亚洲手机app下载


反汇编的利器

看那3下面

的基本采用

原来的文章出处:
N.Y.(@__NY__)   

前言

近些年实战了壹遍 IDA + Hopper
逆向破解。讲真,第叁次体会了一遍把外人“服装”扒光了的快感~差不多 High
翻~所以,特此,利用 Alipay沃尔et 总括分享一下 IDA 和 Hopper
的基本选拔。希望对大家有帮带。

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

  • 得到壹台越狱设备
  • 应用 SSH 连接待上访问越狱设备
  • 接纳 Clutch 解密砸壳
  • 行使 class-dump 导出应用头文件
  • 采用 Cycript 举行应用运行时的动态解析与修改

这么一看真正学了不少技术,而接下去那篇小说,会简单介绍多个反编写翻译的利器
IDA 和 Hopper 的行使。

注,这一次试验应用的并不是最新版本的开发宝 Mach-O
文件,由此可能此番试验中涉及的函数方法在新型版本中不可能找到,但由于本文章只作为学习,所以,只提供具体的法子。如若有亟待,可自动砸壳获得。

动态解析与静态分析

动态解析

大家前两篇学习的 Cycript ,就是卓绝群伦的动态解析工具。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 反汇编二进制文件壹律也是静态分析的艺术。

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 最精锐的反汇编效用,神器
F五~!假设本人学习运用正版,很难负担巨大的证书费用,所以一般情状是在网上找破解版(囧。。并不推荐,土豪恐怕提议买证书)。很消沉的是
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
等待的时日会短一些,不过反编译结果尚未 IDA 更近乎真实的 C
语言代码,会含有众多寄存器变量)

认识 IDA 工作区

当 IDA 对 Mach-O 解析实现后,会暗中认可现身 陆个选项卡视图,分别是汇编视图,16进制字节视图,结构体视图,枚举类型视图,导入的函数视图,导出的函数视图
除此以外,红框标注的是工具栏,蓝框标注的是二进制文件分析的快慢,在蓝框下边,用分裂颜色区分库函数、数据、常规函数等不等类其他剖析数据。

电脑软件 2

静态分析:还原源代码

运用 IDA
反汇编二进制文件的目标是,利用工具获得反汇编之后的伪代码,还原出真正的顺序源码。比如,我们只要要看一下签到方法是何许写的,能够在早就导出的
Alipay沃尔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]
到达那些函数在2进制文件中的内部存储器地址,按 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 源代码。

始建筑工程程

开创一个空项目,并成立 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二 对应方法选取器,a三 对应方法参数 option; a4对应方法参数 isForce; a五 对应方法参数 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; a四 对应方法参数 isForce; a5对应方法参数 extraInfo; // a陆 对应方法参数 completionHandler; a7对应方法参数 cancelationHandler; a捌 对应方法参数 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(一, 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 的学习,依然选用 AlipayWallet 这一个文件进行辨析,与 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奥迪Q3M 的汇编代码,左侧是不无关系音信栏。

电脑软件 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等寄存器,阅读性相较而言差1些,不过,仍旧能够根据伪代码还原出源代码。

实际上大家得以用这些伪代码来检查大家事先还原的源代码,保障还原代码的没有错。

以上,就是 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
权限,从而实行各个操作。而后天学到的方法,也仅是略窥一斑。所以,要更为周全的求学,不光是
iOS 进攻和防守技能,操作系统内核原理、Android 进攻和防守、 Web
前端进攻和防守相关技能也应持有涉猎。

其余,互连网发展越来越强盛,消息资源也随后变得廉价。技术不是最难的,壹项技术,你会,外人也能够学会。由此,会壹门技术、一个编制程序语言,都不可能成为一位的着力竞争力。真正的竞争力是人的思考,是消除难题的能力。所以,大家不应执念于技术或工具。(讲真,看到前边某厂顶牛应该运用
Vue 还是 React 技术栈的时候,真心觉得是内容倒置。)

2 赞 6 收藏 1
评论

相关文章

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