吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 3539|回复: 8

[转载技术] 第十六章-序列号生成算法分析-Part1

[复制链接]
Shark恒 发表于 2015-1-20 16:15 | 显示全部楼层 |阅读模式

                    第16章-序列号生成算法分析-Part1
本章,我们分析的CrackMe与之前的不同之处在于序列号是基于名称变化的,也就是说我们将讨论序列号生成算法。
尽管分析的技巧和之前的很相似,我们还是得来看几个例子巩固一下。
我们先来分析一下CrueHead’a的CrackMe的序列号生成算法。
用OD加载它。
image002.jpg
我们停在了入口点处。
我们来看看该程序使用什么API函数来获取用户输入的序列号。
image004.jpg
我们可以看到GetDlgItemTextA这个API函数,我们给这个API函数设置断点,输入用户名和正确的序列号看看是否会中断下来。
image006.jpg
运行起来。
image008.jpg
我们单击OK按钮,断在了刚刚设置的断点处,我们来看看堆栈中的参数情况。
image010.jpg
Buffer指向的缓冲区存放用户输入的文本,起始地址为40218E,我们在Buffer参数上面单击鼠标右键选择-Follow in Dump来在数据窗口中定位到该缓冲区。
image012.jpg
由于此函数还没有执行,所有缓冲区里面是空的,我们选择主菜单中的Debug-Execute till return,我们就到了ret指令处,我们按F7键返回到主模块中。
image014.jpg
我们可以看到缓冲区中保存了我们输入的名字,程序会进行相应的处理生成正确的序列号。如果我们想编写注册机的话,我们得分析由名称生成序列号的算法,但是现在我们暂时不关心生成算法,我们只是想看看生成的序列号是多少。
image016.jpg
第二次断在了GetDlgItemTextA处,新的缓冲区保存用户输入的序列号,起始地址为40217E,我们在数据窗口中定位到
该缓冲区。
image018.jpg
同样由于函数还没有执行,缓冲区里面是空的,我们通过选择主菜单中的Debug-Execute till return执行到返回,然后按F7键返回到主模块中。
image020.jpg
好了,现在缓冲区里面存放了我们输入的错误序列号,从程序的角度出发,程序就会取用户输入的错误的序列号与根据名称生成的正确序列号进行比较,所以我们可以对错误序列号设置内存访问断点,看看程序的哪些地方使用了。
image022.jpg
我们拖选中错误的序列号,单击鼠标右键选择-Breakpoint-Memory,onaccess,然后运行起来。
image024.jpg
可以看到该程序尝试读取错误序列号的第一个字节并且将保存到BL寄存器中,我们按F7键。
image026.jpg
可以看到BL寄存器保存的值为39,是错误序列号的第一个字节,我们需要跟踪程序的处理过程,如果可能的话,记录下该程序的相关数学运算。
image028.jpg
这里判断BL的值是否为零,为零说明到了字符串结尾,如果到了字符串结尾将结束循环,我们按F7键单步。
image030.jpg
因为BL不为零,所以跳转不会发生,将执行SUB BL,30指令。
image032.jpg
BL的值减去30等于9,即错误序列号第一个字符的值。
下一条指令EDI乘以EAX。
image034.jpg
这两个寄存器被初始化为以下值:EAX寄存器循环体开始处被初始化为了0A,EDI寄存器在循环体之前被XOR EDI,EDI指令初始化为零了。
image036.jpg
按F7键,我们可以看到两个操作数相乘,并且IMUL指令会考虑符号位,并且结果被保存到第一个操作数中。
image038.jpg
相乘的结果为零,保存在EDI中。
image040.jpg
接着EDI加上EBX。
image042.jpg
EDI的结果为9,下一条指令INC ESI,ESI递增1,然后跳转到循环开始处,读取错误序列号的下一个字节。
image044.jpg
AL依然被初始化为了0A,错误序列号的下一个字节值为38,不为零,所以将减去30,然后执行IMUL指令。
image046.jpg
可以看到上次循环的结果EDI乘以EAX的值(依然是初始化为了0A),结果依然保存在EDI中。
image048.jpg
现在EDI的值为5A,下一条指令,EDI将加上EBX。
image050.jpg
以上结果依然保存到EDI中,一步步跟踪这个循环是烦的,如果略过这个过程呢?我们接下来将介绍。
image052.jpg
我们只需要在循环的下一条指令处设置一个断点,然后按F9键,就会中断下来,我们看看EDI的值为多少。
image054.jpg
我们双击EDI寄存器。
image056.jpg
EDI的值为十六进制形式,第二行显示的是有符号的十进制值,也就是我们输入的错误序列号的值,即以上循环结束EDI保存了错误序列号的十六进制值。
概括来说就是: “98989898”序列号将被转化为十进制的98989898或者十六进制的5E6774A。
image058.jpg
下一条指令,EDI异或1234。
image060.jpg
结果为5E6657E,然后保存到EBX寄存器中,接着就到了RET指令。
image062.jpg
我们可以看到RET返回以后,EAX与EBX进行比较,根据比较的结果来决定是否跳转到正确序列号部分。
image064.jpg
我们可以看到EBX与EAX进行比较,EAX的值为547B。
由于EAX的由程序计算出来的,EBX是由我们输入的错误序列号计算出来的,由于我们输入的序列号是错误的,所以这两个寄存器不相等。
如果EBX等于EAX的话,将跳转到正确的序列号提示窗口处,现在两寄存器的值不相等,我们需要分析原因。
笔记如下:
EBX(错误序列号的十六进制值) XOR 1234
我们需要的是EAX与EBX相等。
如果EAX=EBX
用EAX替换EBX
也就是说
EAX(正确序列号的十六进制值)XOR 1234
此时EAX的值为547B。我们用这个值替换EAX。
547B XOR 1234 =
异或运算的结果为:
464F
464F为十六进制值,对应的十进制值为:
image066.jpg
转化为十进制为:
image068.jpg
17999就是”narvaja”这个名称对应的正确序列号。我们删除之前设置的所有断点。
image070.jpg
单击OK按钮。
image072.jpg
这样我们就得到了我们输入名称所对应的正确序列号了。
这是一种解决方案,另一种解决方案如下:
如果我们把对错误序列号进行的一系列操作称之为函数F。
F(错误序列号) = EBX
对错误序列号进行操作的结果被存放到EBX中。
与之进行比较的EAX寄存器,我们的公式如下:
F(正确序列号) = EAX
正确序列号进行一系列操作结果保存到EAX中。
为了得到正确的序列号,我们对EAX进行反向的操作。
正确序列号 = 反向F(EAX)
当前情况下,反向操作依然是异或。
因此XOR EAX的结果就是正确序列号的十六进制值,我们将其转化为十进制值就得到了正确的序列号。
因此,我们也可以利用这种方法来获取正确的序列号,除非反向操作是不等价的,我们来看一个这样的例子。
接下来的例子是Splish,这个CrackMe的第一部分是找到硬编码序列号,现在我们来看看它的第二部分。
加载Splish,断在入口点处。
image074.jpg
看看程序使用了哪些API函数。
image076.jpg
给我们熟悉的GetWindowTextA设置断点。
image078.jpg
我们按F9键运行起来。
image080.jpg
我们随便输入一个错误的名称和序列号,然后单击Name/SerialCheck按钮。
image082.jpg
断在了GetWindowTextA这个API函数入口处,我们来看看缓冲区。
image084.jpg
我们在数据窗口中定位到该缓冲区。
image086.jpg
缓冲区里面是空的,我们选择主菜单中的Debug-Executetill return。就会停在ret指令处,接着我们按F7键返回到主程序模块中。
image088.jpg
可以看到缓冲区中保存了错误的序列号,我们对错误的序列号设置内存访问断点。
image090.jpg
运行起来。
image092.jpg
再次断在了GetWindowTextA这个API函数入口处,这里获取的是窗体的名称,我们不感兴趣,继续运行起来。
image094.jpg
断在了这个函数里面,如果我们执行这行代码的话,会发现将错误序列号的第一个字节移动到EAX中了。
image096.jpg
接下来我们看看下面的CDQ指令的解释,我们直接来看Google里面的解释,我们在谷歌中直接搜索CDQAssembler。
例如如下指令:
CDQ
IDIV ESI
CDQ指令双字扩展,把EAX中的符号位扩展到EDX中去,然后EDX:EAX对应的值除以ESI,商保存到EAX中,余数保存到EDX中。EAX符号位扩展到EDX中,EDX的值应该变为零,相当于对EDX进行XOREDX,EDX操作。现在不需要将EDX清零了,因为CDQ指令已经帮我们完成了该操作。
所以当前情况下我们不必每次循环之前将EDX赋值为零,我们只需要在IDIV指令之前加上一个CDQ指令即可。
EDX:EAX除以ECX,商存放在EAX中,余数存放到EDX中。好了,我们现在来看看具体的实现。
第一个字节为39,除以ECX(值为0A)。
image098.jpg
看看发生了什么。
image100.jpg
这里商5被保存到了EAX中,余数7被保存到了EDX中。
image102.jpg
可以看到下一行将DL的值保存到40324D指向的内存单元中。在数据窗口中定位到40324D这个内存单元。
image104.jpg
继续按F7键。
image106.jpg
7被保存到了该内存单元中。
image108.jpg
我们可以EBX的值为零,然后递增1,接着与6进行比较,如果不相等将继续循环。
image110.jpg
现在我来看看第二个字节将发生什么。
image112.jpg
通过是EDX:EAX除以0A,商保存到EAX中,余数保存到EDX中。
image114.jpg
保存余数。
image116.jpg
好了,对所有字节进行以上操作。
image118.jpg
接着JNZ指令跳转没有发生退出循环。
image120.jpg
接下里我们看到正确序列号以及错误序列号的消息框代码,说明离找到正确序列号已经不远了。
image122.jpg
接下来LEA指令分别将两个地址保存到ESI,EDI寄存器中。
image124.jpg
ESI指向了保存刚刚运行的结果,EDI指向哪里呢?嘿嘿
image126.jpg
继续
image128.jpg
可以EBX值为零,与7进行比较,如果它们相等...
image130.jpg
将跳转到正确序列号的提示框处。中间的循环体中还有另一个JNZ指令会跳转到错误序列号的消息框处。
image132.jpg
好了,我们看看比较。
image134.jpg
EAX将保存EDI指向的内存单元的第一个字节即02,ECX将保存之前计算结果的第一个字节7。
image136.jpg
如果我们计算结果的第一个字节为02的话就好了。
我们当前情况是:
39-5*0A = 7。
也就是说除法运算的结果是39/0A 商为5,余数为7。所以我们可以通过反向运算5乘以0A然后加上7得到39。
39 = 5*0A + 7
对于正确序列号的情况如下:
正确的字节 = 5*0A + 2
即正确字节 = 32 + 2 = 34 (注意是十六进制)
34这个ASCII码对应的字符’4’.
我们可以看到,
正确字节值 = 5*0A + 2
得到是一个(30 ~ 39)之间的值,如果结果超出了这个范围,我们可以做如下变换:
正确字节值 = 4*0A + 平衡值
好了,我们的第一个字符是’4’。
接下来计算剩下的字节。
image138.jpg
02已经计算过了
然后是08。
正确字节 = 5 * 0A + 8
即正确字节 = 32 + 8 (十六进制)
等于40,超过了39(‘9’的ASCII码)这个上限,我们按变换的公式计算:
正确字节 = 4 * 0A + 8
即正确字节 = 28 + 8 = 30,即’0’的ASCII码。
你也可以在命令栏窗口中验证一下:
image140.jpg
因此第二个字节等于30,即字符’0’的ASCII码。
下一个字节依然是08,所以结果依然是30,即字符’0’的ASCII码。
然后是03。
正确字节 = 5 * 0A + 3
即正确字节 = 32 + 3 = 35(注意是十六进制),即字符’5’的ASCII码。
然后是05。
正确字节 = 5 * 0A + 5
即正确字节 = 32 +5 = 37,即字符’7’的ASCII码。
接着还是05,正确字节 = 32 +5= 37,即字符’7’的ASCII码。
最后是03,前面计算过了字符’5’的ASCII码。
因此,名称”narvaja”对应的正确序列号是4005775。删除之前设置的所有断点运行起来。
image142.jpg
单击Name/Serial Check按钮。
image144.jpg
嘿嘿,这个CrackMe就完成了。
留个练习的CrackMe,名字叫mexcrk1。

本系列文章汉化版转载看雪论坛

感谢原作者:RicardoNarvaja(西班牙人)
原作者个人主页:http://www.ricardonarvaja.info/

感谢热心翻译的朋友:
1~3章译者:BGCoder
4~58章译者:安于此生

全集配套程序下载地址:
链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv



评分

参与人数 12HB +13 THX +3 收起 理由
Jawon + 2
一路走来不容易 + 1
Soul1999 + 1
yexing + 2
行行行行行行 + 1
消逝的过去 + 2
冷亦飞 + 1
凌夏随缘 + 1
成丰羽 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
hackysh + 1
jaunic + 2
hnymsh + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
hackysh 发表于 2022-2-8 15:56 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-3-1 03:33 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
weiran324 发表于 2022-4-1 23:19 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
凌夏随缘 发表于 2022-6-2 23:36 | 显示全部楼层

谢谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
yexing 发表于 2022-11-10 13:47 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-11-17 22:19 | 显示全部楼层

牛啊!爱了爱了!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2023-4-3 09:55 | 显示全部楼层

看了楼主的帖子。打算去自己练一下。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2023-4-20 10:19 | 显示全部楼层

嗯 谢谢大佬指点
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表