Mac OSX 之自己动手初步学习破解软件入门

96
代码行者
0.7 2016.12.31 20:50* 字数 1765
本软件破解学习教程,仅用于学习软件原理知识,还请各位童鞋(尤其是软件开发的童鞋)养成知识产权的保护意识,拒绝盗版,尊重他人.本篇通过手动创建一个Mac osx应用,然后进行破解学习,一步一步分析,到最后完成破解目标,通篇没有高深的理论术语,因此仅用来作为初步学习的一个引子,供各位童鞋或爱好者在软件运行原理的学习中提供一个微薄的参考而已...

0. 学前准备:

1. Mac OSX下的反汇编工具: Hopper Disassembler (本示例使用v4.0.8)

2. 基本的汇编指令(比如mov ,xor ,jmp,je 等)

3. 没有其他啦,马上开始动手吧

1. 先手动创建一个简单的Mac OSX应用

关于如何具体创建简单的Mac OSX 应用,请移步我之前翻译的三篇系列入门一步一步,开始上手Mac开发

或者可以从这里下载示例中的应用demo工程:github.com/Alexiuce/Tip-for-day/tree/master/CrackDemo

我们创建的这个简单应用,是模仿注册码验证的一个逻辑判断(其实你也可以把这个当作是登录验证,道理是相同的),如果用户输入1234,我们认为是正确的结果,显示验证通过,否则都会显示验证码错误这样的提示信息

应用的界面大致如下图:

示例界面

从Xcode工程中提取应用

运行工程后,会在Products中,生成一个 "项目名称.app"的应用,这个就是我们的目标应用,然后在finder中找到它,并拷贝到桌面备用(我们后续的破解都是针对这个来进行的~)


提取项目工程中的应用程序

先来运行一下破解前的程序,它的样子差不多跟下面图片相似

破解前的运行情况

开启破解之旅

1 打开Hopper Disassembler

Hopper Disassembler工具的默认启动界面

2. 将需要破解的应用(就是demo.app)拖入到Hopper中

拖入我们的demo.app到Hopper中

确认选择界面

确认

加载后的界面,入下图

加载后的界面

这个界面的布局和Xcode非常相似,大家不要被一些看不懂的内容界面和工具栏迷惑而感到微微的手足无措(笔者第一次看到这个界面,也是茫然的~),我们下面把基本上常用的会一一介绍,其他的的功能按钮,先当作不存在(催眠式提升信心法~~),好,我们先来看一下工具栏下面的左侧Labels窗口:

Labels窗口

这个Labels窗口中列出的是应用被反编译后可以识别出来Objective-c方法,看到这些熟悉的方法名,小伙伴们是不是一下子感觉又回到Xcode代码中啦,让我们先忘记掉我们之前写过的工程代码,从这个列表里,我们根据方面名称,大致可以推断(破解的一个要素就是要有根据的猜测)出这几个方法的用途:

[ViewController viewDidLoad] ====>  视图生命周期方法,加载视图的时候调用

[ViewController checkCode:] ====>  从名字可以看着,这个方法是用来做验证检查的(后面会进一步分析)

[ViewController textField] : ====>  get方法,获取文本输入控件

[ViewController setTextField: ] ====> set方法,设置文本输入控件

[ViewController tintLable]  ==== >  get方法,获取提示文本控件

[ViewController setTintLabel:]   ====> set方法,设置提示文本控件

3.查看checkCode:方法

我们根据方法名列表,最值得怀疑的就是checkCode:(就像如果破解一个软件的vip身份,那么如果看到isVip就应该给予特别注意一样)

查看checkCode:的逻辑(右侧显示的部分很重要)

从这个图里的右侧流程部分,我们可以看出checkCode这个方法的执行逻辑是这样的:

checkCode方法入口---> 执行一些代码(我们先不管这些代码在做什么)--->选择两个分支代码段中的一个执行---> 再执行一些代码后,checkCode方法结束

checkCode:方法的逻辑流程图

4.假设阶段

查看汇编代码

这三行汇编代码是:

mov al,byte [rbp+var_29]     ====> 这句汇编的含义相当于我们使用高级语言里的赋值语句,例如 al = 123(这里是为了理解写al = 123来举例,程序运行真实的al值并不是123),我们先把al当作一个变量来看,不去想al寄存器的事情

cmp al,0x0    ====> 这个汇编的含义是进行两个值的比较 ,我们可以把它想象成一个高级语言的比较函数,后面是两个参数,例如cmp(a,b), 执行后返回比较的结果,汇编执行比较,其实是做减法运算,因此两个数相减会有三种情况,分别是大于零,等于零,小于零,这三种结果,有可以简单分为两个:相等,或不相等

je loc_10001054  ====> 这个汇编的含义,我们可以认为是 相等(equality), 不相等是jne, 在汇编中,一般cmp后面都会根上类似的判断跳转语句. 因此这行代码下面会有两个分支(参考方法的流程图),如果cmp的比较结果是相等,就执行 loc_10001054 这个分支,否则就执行另外的那个分支(方法流程图中红色线条指向的那个分支)

从这个代码逻辑,我们可以简单的猜测出来应用里判断验证码的逻辑是这样的:

if (输入的内容 == 验证码) {显示正确结果(分支1)}else{显示错误结果分支2)}

5.求证阶段

现在我们面临的问题是,哪个分支才是正确结果的那个部分呢?

我们不必去读懂两个分支的汇编代码(如果你有兴趣另说),只需要修改逻辑并根据执行结果来验证就好了,比如,我们去除掉je loc_10001054 这个相等就执行的汇编代码,这样,checkCode的执行逻辑就被我们修改为没有分支loc_10001054的直线流程了.好,先动手试试

切换工具栏按钮

替换掉je loc_10001054这条汇编指令(就是去掉条件判断,不管比较结果如何,都会执行固定的分支)

替换空指令
替换后的结果

保存修改后的结果,生成新的可执行文件

保存修改结果,生成新的可执行文件

保存的路径一定不能与demo.app相同!

保存的路径一定不能与demo.app相同!!

保存的路径一定不能与demo.app相同!!!

保存新的可执行文件

使用新的可执行文件,替换掉破解前的可执行文件:

在demo.app上点击右键,显示包内容
用破解的文件替换原来的
替换后示例

运行破解后的demo.app

破解的运行结果

小结与讨论

到这里我们貌似已经完成了破解工作,但其实是有很大的运气成分(我们只选了一个分支就碰巧是验证通过的那个代码分支),大家可以考虑如果我们这个分支是无论怎么输入都是显示错误的那个分支,应该怎么办呢?其实很简单,就是把je换成jne就可以了,有兴趣的可是试试,我这里就不再详细描述了(点选Modify菜单->Assemble Instruction 可以手动输入新的汇编指令,把je 替换成jne就可以哦)

最后,给有兴趣的童鞋留个疑问,如果找到原来正确的验证码呢? 大家自己动手看看吧

日记本
Web note ad 1