http://t.cn/RxZz7SU

前言

最近我居然反破解了IDA+Hopper。说实话,第一次体验到剥别人“衣服”的快感~差不多高了~所以,在此用支付宝钱包来总结分享一下IDA和Hopper的基本用法。希望对大家有帮助。

让我们回顾一下我们在前面两篇文章中学到的内容:

获取越狱装置

通过SSH连接访问越狱设备

用离合器解密外壳

使用类转储导出应用程序头文件

Cycript对应用运行时的动态分析和修改

我通过这种方式学到了很多技巧,下面的文章将简单介绍两个反编译工具IDA和Hopper的使用。

注意:本实验不使用支付宝Mach-O文件的最新版本,所以本实验涉及的功能方法可能在最新版本中找不到。但是,由于本文仅用于学习,因此仅提供具体方法。如有必要,可通过砸壳获得。

动态分析和静态分析

动态分析

我们在前两篇文章中学到的Cycript是一个典型的动态分析工具。Cycript可以在应用程序中执行运行时方法分析和视图级分析。除了Cycript,常用的动态分析工具还有lldb &: Debugserver远程断点调试、logify跟踪等。,以后慢慢一起学习这些技巧和方法。

静态分析

静态程序分析是在没有实际执行程序的情况下对计算机软件进行的分析(对执行程序进行的分析称为动态分析)。[1]在大多数情况下,分析是在源代码的某个版本上执行的,而在其他情况下,分析是在目标代码的某个形式上执行的。

以上是维基百科对英语静态分析的介绍,中文翻译如下。

静态程序分析是指不实际执行程序的计算机软件分析方法(相对于已知的实际执行软件的动态分析)。在大多数情况下,分析在源代码的某些版本中运行,而其余的在目标代码中运行。

Mach-O头文件是通过之前学过的类转储工具导出的,是对软件应用进行静态分析。今天我们要学习两个工具,IDA和Hopper反汇编二进制文件,也是静态分析方法。

国际开发协会的基本用途

什么是伊达

IDA是交互式反汇编器:世界上最聪明、功能最全的反汇编器,许多软件安全专家都很熟悉。

IDA是世界上最敏捷、最多功能的反编译工具,作为一种交互式反汇编工具,被很多软件安全专家所熟知。

安装IDA

IDA的官网是https://www.hex-rays.com/.你可以在网页上看到IDA插件,SDK等内容。IDA将在官网提供下载https://www.hex-rays.com/products/IDA/support/download _ Demo . shtml的Demo版本。但是Demo版没有IDA最强大的反汇编功能,神器F5 ~!如果自己学用正版,很难承担巨额的证书费用,所以一般情况是在网上找破解版。。不建议,土豪还是建议买证。可惜IDA Pro的Mac版很难找(没找到)。所以本文寻找Windows下破解IDA Pro来学习。

使用IDA Pro

打开IDA后,会出现“关于”和“支持”消息等提示对话框。点击确定继续,弹出快速启动对话框。在此对话框中,您可以查看以前打开的IDA反汇编二进制文件或创建新的反汇编文件。这里我们点击New创建一个新的反汇编,这次以支付宝为例。

准备马赫-欧

回头看前面的内容,先离合外壳,再scp AlipayWallet到Mac目录,然后用类转储导出头文件。

导入IDA

在这里可以直接将Mach-O文件拖放到IDA的工作空间,或者点击打开文件夹的图标导入Mach-O,当检测到Objective-C 2.0代码时,系统会提示,点击确定继续。

之后就是漫长的等待~ ~ ~ (Hopper会比IDA等的更短,但是反编译结果比IDA更接近真实的C语言代码,会包含很多寄存器变量)

了解IDA工作空间

IDA解析完Mach-O后,默认会出现六个选项卡视图,分别是汇编视图、十六进制字节视图、结构视图、枚举类型视图、导入函数视图和导出函数视图。

另外,红框标记工具栏,蓝框标记二进制文件解析的进度。蓝框下,库函数、数据、常规函数等不同类型的解析数据用不同的颜色区分。

静态分析:恢复源代码

IDA反汇编二进制文件的目的是利用工具获取反汇编的伪代码,还原真实的程序源代码。比如我们想看登录方式是怎么写的,可以在导出的AlipayWallet.h中查询登录关键字,找到相关代码。我们发现会有与LoginProtocol协议和loginadater类相关的代码,所以不妨以loginadater类作为实际的研究对象。

@ ProtocolLoginProtocolNonsObject & gt;

+(id)shared instance;

-(ns dictionary *)current session;

-(void)loginwithloginoption:(int)arg1extrainfo:(nsdictionary*)arg2completionhandler:(void(^)(bool,nsdictionary*))arg3cancelationhandler:(void(^)(void))arg4;

-(void)loginwithloginoption:(int)arg1completionhandler:(void(^)(bool,nsdictionary*))arg2cancelationhandler:(void(^)(void))arg3;

-(BOOL)isvalidlog in;

@可选

- (void)注销;

-(void)markinvalidlinglog in;

-(BOOL)is processing log in;

@end

@ InterfaceLoginAdapter:NSoObjectloginProtocol & gt;

{

int _ is _ login _ doing

int _ is _ processing _ pending

id _ network _ config

id _ login _ service

NSMutableArray * _ loginPendingRequests;

NSRecursiveLock * _ pending _ lock

}

+(id)shared instance;

@property(retain,nonatomic)NSRecursiveLock * pending _ lock;//@ synthese pending _ lock = _ pending _ lock;

@property(retain,nonatomic)nsmutatlearray * loginPendingRequests;//@ synthese loginPendingRequests = _ loginPendingRequests;

@property(retain,nonatomic)id log in _ service;//@ synthetic log in _ service = _ log in _ service;

@property(retain,nonatomic)idnetwork _ config;//@ synthese network _ config = _ network _ config;

-(无效)。cxx _ destruct

-(void)storeSessionWithLoginResult:(id)arg 1;

-(id)CurrentUserid;

-(void)NotifyNetwOrk Dk:(id)arg 1;

- (void)注销:(id)arg 1;

-(void)logined:(id)arg 1;

-(void)loadAlu:(Class)arg 1;

-(void)loadLoginModule;

-(void)loadNetworSDKConfig;

-(void)failed endingloginrequests;

- (void)重做日志请求;

-(void)pendingLoginRequest:(id)arg 1;

-(void)release pending lock;

-(void)accquired pending lock;

-(void)release loginlock;

-(BOOL)accrequired loginlock;

-(int)try log in:(id)arg1 force:(BOOL)arg 2;

-(int)try log in:(id)arg 1;

- (void)注销;

-(id)CurrentSession;

-(int)loginWithLoginOption:(int)arg1 force:(BOOL)arg2 ext info:(id)arg3completionHandler:(cdunknownerblocktype)arg4 cancelationhandler:(cdunknownerblocktype)arg5 request:(id)arg6;

-(void)loginWithLoginOption:(int)arg1 extracinfo:(id)arg2 completionhandler:(cdunknown blocktype)arg3cancellationhandler:(cdunknown blocktype)arg4;

-(void)loginWithLoginOption:(int)arg 1 completionhandler:(cdunknownerblocktype)arg 2 cancelationhandler:(cdunknownerblocktype)arg 3;

-(BOOL)isvalidlog in;

-(BOOL)is processing log in;

-(void)markinvalidlinglog in;

-(id)SetcustomloginModule:(id)arg 1;

-(void)deal loc;

-(id)init;

//剩余属性

@property(readonly,copy)NSString * DebugDeion;

@property(readonly,copy)NSString * deion;

@ property(readonly)unsignedinstash;

@ property(readonly)class super class;

@end

你可以在头文件中搜索得到上面的结果,以LoginAdapter为例。在函数窗口,我们可以按Ctrl+F找到LoginAdapter的相关函数。

双击【登录适配器共享即时】到达该函数在二进制文件中的内存地址,按F5查看反编译后的伪代码。

这里可以看到支付宝的登录方式是怎么写的。双击[登录适配器登录操作:is force:Extra Info:CompletionHandler:cancelation Handler:Request:],按F5查看该方法的反编译伪代码。伪代码如下。

//LoginAdapter-(int)loginWithLoginOption:(int)is force:(char)ext info:(id)completionHandler:(id)cancelationHandler:(id)request:(id)

int _ _ cdecl-[LoginAdapterloginWithLoginOption:is force:ext info:completionHandler:cancellatihandler:request:](Structureloginadater * self,SELa2,inta3,chara4,ida5,ida6,ida7,ida8)

{

structLoginAdapter * v8//r8 & lt;a href = ' http://www . job bole . com/members/Yao Wei 729 ' & gt;@ 1 & lt/a>。

//一些变量

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->;_登录_服务)

{

v18 = 0;

v19 = v39

gotoLABEL _ 27

}

v40 = v11

if(v15)

objc_msgSend(v8,“accquirePendingLock”);

if((unsignedint)objc _ MSgsend(V8,“accquireroginLock”)& amp;0xFF)

{

if(v9||!((unsignedint)objc_msgSend(v8,“ISvalidLogon”)& amp;0xFF))

{

v36 = v13

if(v15)

objc_msgSend(v8," pendingLoginRequest:",v15);

v 20 = objc _ MSgsend(& amp;OBJC_CLASS___LogAdapter," GetInstance ");

v 21 =(void *)objc _ retainautoreLealedreturnVaLue(v 20);

v38 = v8

v22= objc_msgSend(v15,“GetPiname”);

v 23 = objc _ retainaurelatedreturn value(v 22);

v24= objc_msgSend(v15,“GetaPiVersion”);

v 25 = objc _ retainaurelatedreturn value(v 24);

v26 = v25

v27= objc_msgSend(

& ampOBJC _ CLASS _ _ _ NSString,

字符串格式:“,

CFSTR("[LoginAdapter]ApiName:% & lt;a href = ' http://www . job bole . com/members/名家_神' & gt@,& lt/a>。apiVersion: %@ pull登录模块"),

v23,

v 25);

v 28 = objc _ retainaurelatedreturn value(v 27);

objc_msgSend(v21," warn:",v 28);

objc _ release(v 28);

objc _ release(v 26);

objc _ release(v 23);

objc _ release(v 21);

v29= v38->。_ login _ service

v48 = & amp_ NSConcreteStackBlock

v 49 =-1040187392;

v50 = 0;

v51 = sub _ 2AAF082

v52 = & ampunk _ 3164640

v30= objc_retain(v38,sub _ 2aaf 082);

v53 = v30

v54= objc_retain(v40,v31);

v41 = & amp_ NSConcreteStackBlock

v 42 =-1040187392;

v43 = 0;

v44 = sub _ 2AAF1AC

v45 = & ampunk _ 3164660

v13 = v36

v46= objc_retain(v30,ampunk _ 3164660);

v19 = v39

v47= objc_retain(v36,v 32);

objc_msgSend(v29,“loginWithLoginOption:Extrainfo:CompletionHandler:CancelAThandler:“,v37,v39,& ampv48,amp。v41);

objc _ release(v47);

objc _ release(v46);

objc _ release(v54);

objc _ release(v53);

v18 = 2;

gotoLABEL _ 24

}

objc_msgSend(v8,“release loginLock”);

if(v11)

{

v38 = v8

v16= objc_msgSend(v8->;_login_service," CurrentSession ");

v17 = objc _ retainaureleatedreturnvalue(v16);

(*(void(_ fastcall * *)(int,signedint,int))(v11+ 12))(v11,1,v 17);

objc _ release(v17);

}

其他

{

v38 = v8

}

v18 = 3;

}

其他

{

if(v15)

{

if((unsignedint)objc _ MSgsend((void *)V8->_loginPendingRequests," count ")>;0xFF)

{

v38 = v8

v18 = 0;

}

其他

{

v38 = v8

objc_msgSend(v8," pendingLoginRequest:",v15);

v18 = 1;

}

}

其他

{

v38 = v8

v18 = 0;

}

if(v11)

{

v 33 = objc _ MSgsend(& amp;OBJC _ CLASS _ _ _ NSDictionary,“dictionary”);

v 34 = objc _ retainaureleatedreturnvalue(v 33);

v40 = v11

(*(void(_ fastcall * *)(int,_DWORD,int))(v11+ 12))(v11,0,v 34);

objc _ release(v 34);

}

其他

{

v40 = 0;

}

}

v19 = v39

LABEL_24:

if(v15)

objc_msgSend(v38," release pending lock ");

v11 = v40

LABEL_27:

objc _ release(v15);

objc _ release(V13);

objc _ release(v11);

objc _ release(v19);

returnv18

}

反编译的伪代码会保留原函数的逻辑和函数的符号名。然后,我们可以尝试恢复这段代码的Objective-C源代码。

创建项目

创建一个空项目,创建LoginAdapter类的头文件和实现文件,然后将class-dump导出的头文件的属性和常用方法复制到新创建的头文件中,然后根据反汇编代码还原原始代码。

请注意,在本例中,CDUnknownBlockType是一种块类型,但不能导出特定的块类型,即类转储。如果你想得到这个街区,你可以参考一下

hook https://github . com/IOs re/SMSNinja/blob/master/libsmsninja/hook . XM # L754

不推荐使用的https://github . com/IOs re/SMSNINJA/blob/master/libsmSNINJA/不推荐使用的. xm#L139

方法名称和参数

我们知道,Objective-C中的objc_msgSend方法是向消息接收者(实例对象)发送消息。Apple文档如下。

**objc_msgSend**

向类的实例发送带有简单返回值的samessage。

id objc _ MSgsend(id SEL,SEL op,...);

参数

自我

指向接收消息的类实例的接口。

外科手术

处理消息的方法的选择器。

...

包含方法参数的可变参数列表。

从文档中可以得出结论,第一个参数是接受的消息类型实例的指针,第二个参数是方法选择器,然后是实例方法传递的参数。

反编译得到的伪代码中,第一行是Objective-C方法和实际C函数的参数对应,如下图。

int _ _ cdecl-[LoginAdapter loginWithLoginOption:is force:Extrainfo:CompletionHandler:CancelAThandler:request:](Structureloginadapter * self,SEL a2,inta3,chara4,id a5,id a6,id a7,id a8)

因此,我们可以得出结论:

Self为当前实例指针,a2对应方法选择器,a3对应方法参数选项;A4对应方法参数isForcea5对应的方法参数extraInfoA6对应方法参数completionHandlerA7对应于方法参数cancelationHandlerA8对应于方法参数请求。定义好方法名和参数的对应关系后,我们就开始恢复函数体。

方法功能体

恢复函数体的基本思路很简单,就是利用伪代码的方法名和变量,按照应用正向开发的经验方法,恢复函数体的具体逻辑。

函数体涉及的其他类和相关协议,比如mtopextrequest tbsdkrequest日志适配器,也可以通过IDA和头文件获取,这里不重复具体的恢复过程,恢复函数体代码如下。

#导入“LoginAdapter.h”

#导入“LogAdapter.h”

#导入“MtopExtRequest.h”

@implementationLoginAdapter

-(n整数)登录不登录:(int)选项

isForce:(BOOL)isForce

ext info:(NSDictionary *)ext info

完成处理程序:(支付宝完成处理程序)完成处理程序

取消处理程序:(支付宝取消处理程序)取消处理程序

请求:(MtopExtRequest*)请求{

// self为当前实例指针,a2对应方法选择器,a3对应方法参数选项;A4对应方法参数isForcea5对应的方法参数extraInfo

// a6对应方法参数completionHandlerA7对应于方法参数cancelationHandlerA8对应于方法参数请求

NSIntegerreturnValue = 0;// v18

if(!self.login_service){

return value = 0;

}

if(request){

[SelfacacquirePending Lock];

}

if([SelfaceQuorlogInLock]){

if(extraInfo||![selisvalidlog in]){

if(request){

[自助登录请求:请求];

}

LogAdapter * LogAdapter =[LogAdapterGetInstance];

nsStrIng * ApiName =[request GetAppName];

nsString * apiVersion =[request GetaPiversion];

NSString * LogString =[NSStringStringWithformat:@ "[LoginAdapter]ApiName:% & lt;a href = ' http://www . job bole . com/members/名家_神' & gt@,& lt/a>。apiVersion: %@ pull login module ",apiName,apiVersion];

[LogDapterWarn:LogString];

[self . log in _ ServiceloginWithloginoption:选项

ext info:ext info

完成处理程序:完成处理程序

取消处理程序:取消处理程序];

}// extraInfo ||![self isValidLogin]结束

[SelfReleaseloginLock];

if(completionHandler){

NSDictionary * current session =[self . log in _ service current session];

completionHandler(1,CurrentSession);

}else{

// v38 = v8,也就是说,self被保留而没有被翻译成oc代码

}

return value = 3;

}else{

if(request){

if(self . loginpendingrequests . count){

return value = 0;

}else{

[自助登录请求:请求];

return value = 1;

}

}else{

return value = 0;

}

if(completionHandler){

completionHandler(0,[nsdictionary dictionary]);

}else{

completionHandler = nil

}

}

if(request){

[SelfReleaseloginLock];

}

return返回值;

}

@end

如果想看具体代码,可以去GitHub看看:

仓库地址https://github.com/niyaoyao/reverse-learning

料斗的基本用途

对于Hopper的研究,文件AlipayWallet还是用来分析的,和IDA比较。

霍普是什么

Hopper反汇编器,反向工程工具,让你反汇编,反编译和调试你的应用程序。

Hopper反汇编工具是一个逆向工程工具,它允许您反汇编、反编译和调试您的应用程序。

安装料斗

Hopper的官网是https://www.hopperapp.com/,,和IDA一样。官网也提供了Demo的试用版。试用版也可以拆开,但是*。无法保存跃点文件。所以Hopper的Demo版已经足够学习了。

料斗的使用

进口料斗

与IDA不同,Hopper不能直接将马赫-O文件导入工作空间,而是需要下载应用程序的*。ipa文件,并将文件后缀改为*.,解压文件后,可以看到Payload文件目录,里面存储着对应应用的package package文件。右键单击要出现在菜单中的包,并选择“显示包内容”选项以查看包内容。

了解霍普的工作空间

和IDA类似,Hopper也有一个进度条,用于解析二进制文件。左边是符号Label等区域,中间是ARM的汇编代码,右边是相关信息栏。

静态分析:Hopper拆解的伪码

如图,在最左边一列的搜索字段输入关键字loginWithLoginOption,双击选择方法【登录适配器loginWithLoginOption:is force:Extra info:CompletionHandler:cancel Handler:Request:】。在中间的汇编代码区,光标会跳转到这个方法的内存地址。

int-[LoginAdapter loginWithLoginOption:is force:Extrainfo:CompletionHandler:CancelationHandler:request:](void * self,void* _cmd,intarg2,chararg3,void* arg4,void* arg5,void* arg6,void* arg7){

stack[2048]= arg 4;

r7 =(sp-0x 14)+0xc;

sp = sp-0x 74;

r8=自我;

r5 = arg3

stack[2051]= arg 2;

stack[2053]=[arg 4 retain];

r6= [arg5保留];

r11= [arg6保留];

r10= [arg7保留];

if(r8->;_ log in _ service = = 0x 0)goto loc _ 2aa e0a;

loc_2aaed6c:

stack[2054]= R6;

if(r10!= 0x0){

[r8 accquirePendingLock];

}

if(([r8 accquiloginlock]& amp;0xff)= = 0x 0)goto loc _ 2 aaefa 8;

loc_2aaeda0:

if(((r5 & amp;0xff)!= 0x0)|| (([r8是有效登录]& amp;0xff)= = 0x 0))goto loc _ 2aae 10;

loc_2aaedbe:

[r8 release loginLock];

R6 = stack[2054];

if(r6!= 0x0){

stack[2052]= r8;

r5= [[r8->;_ log in _ service CurrentSession]保留];

(*(r6+ 0xc))(r6,0x1,r5,*(R6+0xc));

[r5发布];

}

else{

stack[2052]= r8;

}

r5 = 0x3

gotoloc _ 2aaf044

loc_2aaf044:

R4 = stack[2053];

gotoloc _ 2aaf046

loc_2aaf046:

if(r10!= 0x0){

[stack[2052]release pending lock];

}

R6 = stack[2054];

gotoloc _ 2aaf060

loc_2aaf060:

[r10释放];

[r11版本];

[r6发布];

[r4释放];

r0 = r5

returnr0

loc _ 2aaee10:

stack[2050]= r11;

if(r10!= 0x0){

[r8 pendingLoginRequest:r10];

}

R6 =[[LogAdapter GetInstance]保留];

stack[2052]= r8;

r8 =[[r10 GetPiname]保留];

r11 =[[r10 GetaPiversion]保留];

r5 =[[NSString StringWithformat:@ "[LoginAdapter]ApiName:% & lt;a href = ' http://www . job bole . com/members/名家_神' & gt@,& lt/a>。apiVersion: %@ pull login module ",r8,r11]retain];

[R6 warn:r5];

[r5发布];

[r11版本];

[r8发布];

[r6发布];

r5 =[stack[2052]retain];

stack[2068]=[stack[2054]retain];

r11 = stack[2050];

stack[2060]= [r5保留];

R4 = stack[2053];

stack[2061]= [r11保留];

[stack[2052]->_ log in _ 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,0x 0];

[stack[2061]发布];

[stack[2060]发布];

【栈[2068]发布】;

[r5发布];

r5 = 0x2

gotoloc _ 2aaf046

loc_2aaefa8:

if(r10!= 0x0){

R6 = stack[2054];

if([r8->;_loginPendingRequests计数]

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),堆栈[2048]);

[r4释放];

}

else{

stack[2054]= R6;

}

gotoloc _ 2aaf044

loc _ 2aaee0a:

r5 = 0x0

R4 = stack[2053];

gotoloc _ 2aaf060

}

与IDA相比,Hopper反编译伪代码的逻辑与IDA反编译伪代码类似,但r0~r8等寄存器较多,可读性较差。但是源代码还是可以按照伪代码还原的。

其实我们可以用这个伪代码来检查我们之前还原的源代码,从而保证还原代码的正确性。

以上是Hopper的简单使用。Hopper不仅可以查看汇编代码,还可以直接修改Mach-O文件,然后重新生成二进制文件(Demo版没有这个功能)。

感兴趣的同学可以阅读这篇文章,了解“如何让微信客户端的苹果版防退”http://t.cn/RxzeMIx

总结

本文主要研究了以下内容:

国际开发协会的安装和使用

料斗的安装和使用

静态分析,根据伪代码还原源代码

关于iOS安全还有很多技巧需要学习,以后还会继续学习和研究。比如TheOS,tweak,加解密,越狱应用开发等。,不过不用担心学的慢~

有志者事竟成!

永远不要忘记你的梦想!

打架!

如何防止微信客户端Mac版撤http://t.cn/RxzeMIx

IOS安全攻防(15)利用Hopper修改字符串http://www.cnblogs.com/jailbreaker/p/4183954.html

iOS逆向工程的Hopper中ARM命令的Http://www.cnblogs.com/ludashi/p/5740696.html

IDA反汇编/反编译静态分析iOS模拟器程序http://blog.csdn.net/column/details/ios-ida.html

从今天开始学习逆向:运行时分析和应用操作

今天开始学习反向:SSH访问越狱机,导出头文件https://niyaoyo . github . io/2016/11/01/learning-reverse-from-today-D1/

离题

本文主要讲IDA和Hopper的基本用法。反汇编工具可以方便我们分析应用程序的二进制文件,但是工具的使用是其次,最重要的是思考。任何方法都能及时学会。记得大神念西在微博上说“密码只是一把锁,安全是一个系统”(大意如此)。

之前爆发的支付宝漏洞也充分验证了这一点。用户和朋友可以通过忘记密码进入手机不在身边的入口。之后,选择联系人、送货地址、购买商品等信息,就可以绕过密码登录,更改密码,然后登录账号获得用户权限。密码只是一把锁,系统的整体安全性才是核心关键。换句话说,任何安全攻防中要解决的问题都是获取根权限进行各种操作。而现在学到的方法也只是一瞥。所以要学的比较全面,不仅是iOS攻防技术,还要涉及操作系统内核原理、Android攻防、Web前端攻防等相关技术。

此外,随着互联网的发展,信息资源变得廉价。技术不是最难的,一门技术,你可以,别人可以学。所以,懂一门技术或者一门编程语言,并不能成为一个人的核心竞争力。真正的竞争力是人的思维和解决问题的能力。所以,我们不应该执着于技术或者工具。(说实话,之前看到一家工厂在争论是用Vue还是React技术栈,我真的觉得是本末倒置。)

在Hopper分析完完整的二进制文件后,按住Option+Enter查看Hopper的反编译伪代码,如下所示。

觉得这篇文章对你有帮助?请与更多人分享

关注“iOS大全”

查看更多特色iOS技术文章

1.《hopper 今天开始学逆向:反汇编的利器 IDA 和 Hopper 的基本使用》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《hopper 今天开始学逆向:反汇编的利器 IDA 和 Hopper 的基本使用》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/tiyu/1635530.html