Atlantis Word Processor V1.6.5算法分析
【文章标题】: Atlantis Word Processor V1.6.5算法分析及注册机的实现【文章作者】: playboysen
【作者邮箱】: playboysen&126.com
【软件大小】: 3.65Mb
【下载地址】: http://www.atlantiswordprocessor.com/
【保护方式】: 注册码
【使用工具】: OD、Atlantis Word Processor
【版权声明】: 版权所有,转载注明!新手参考,老鸟飞过~
【作者声明】: 本文仅作个人学习研究之用,以探讨程序逆向方法为目的。如对软件本身有兴趣,请支持正版!
-----------------------------------------------------------------------------------------------------------
Atlantis Word Processor 一个独立的word处理器,支持读取并编辑*.rtf *.doc *.docx *.cod *.txt等数种格式的文档,支持命令行,软件小巧界面清爽,占用内存小,处理速度快,打开保存文件时支持全word格式的预览。(两个小小遗憾--word文档中的中文引号会显示乱码;竟不支持中文txt文件,汗。期待更新)
试运行得知软件以用户名、注册码方式保护(其实用户名不参与运算),有出错提示,UPX弱壳。
脱壳OD加载后,查找字符串“invalid”找到以下关键部位,以用户名playboysen,注册码HelloHenu试炼(算法分析一般都是随便输入假码后粗略跟踪几次注册码的验证流程,根据验证流程一次次地修正假码,最终得出一组可用注册码,弄清算法)
00495FC7 E8 9CC31600 call Atlantis.00602368
00495FCC 837D FC 00 cmp dword ptr ss:,0
00495FD0 75 17 jnz short Atlantis.00495FE9
00495FD2 B8 88604900 mov eax,Atlantis.00496088 ; ASCII "Please enter your registration code."
00495FD7 E8 28E31400 call Atlantis.005E4304
00495FDC 8B86 9C010000 mov eax,dword ptr ds:
00495FE2 8B10 mov edx,dword ptr ds:
00495FE4 FF52 68 call dword ptr ds:
00495FE7 EB 45 jmp short Atlantis.0049602E
00495FE9 8D55 FC lea edx,dword ptr ss:
00495FEC 8B86 9C010000 mov eax,dword ptr ds:
00495FF2 E8 71C31600 call Atlantis.00602368 ; 算出注册码长度
00495FF7 8B45 FC mov eax,dword ptr ss: ; 假码放入eax
00495FFA E8 0D060000 call Atlantis.0049660C ; 关键处,跟进
00495FFF 84C0 test al,al
00496001 75 17 jnz short Atlantis.0049601A
00496003 B8 B8604900 mov eax,Atlantis.004960B8 ; ASCII "The registration code you have specified is invalid..."
跟进00495FFA关键call
......
00496640 8B45 FC mov eax,dword ptr ss:
00496643 E8 4C5AF7FF call Atlantis.0040C094 ; 注册码第一次变形,把假码中的小写字母转换成大写
00496648 8B45 F0 mov eax,dword ptr ss: ; 转换后的假码放入
0049664B B1 30 mov cl,30 ; 数字“0”
0049664D B2 4F mov dl,4F ; 大写字母“O”
0049664F E8 CC711400 call Atlantis.005DD820 ; 看上面入栈的参数,猜测这个函数里面有猫腻儿
00496654 8B55 F4 mov edx,dword ptr ss: ; 上面的函数就是注册码的第二次变形了
数字“0”、大写字符“O”和假码同时入栈,葫芦里卖的什么药?进去遛遛
......
005DD83C E8 4B5DE2FF call Atlantis.0040358C ; 算出注册码长度
005DD841 83F8 01 cmp eax,1
005DD844 7C 1D jl short Atlantis.005DD863
005DD846 89C7 mov edi,eax ; 注册码长度放入
005DD848 8B06 mov eax,dword ptr ds: ; 注册码放入
005DD84A 3A5C38 FF cmp bl,byte ptr ds: ; 假码从后往前逐位与大写字母“O”比较
005DD84E 75 0E jnz short Atlantis.005DD85E ; 一路小跑过去,发现这里是把注册码中出现的字母“O”替换成数字“0”
005DD850 8BC6 mov eax,esi ; 企图混淆视听啊
005DD852 E8 055FE2FF call Atlantis.0040375C
汗,这都行?至此,我们的假码经过了两次加工,记住
......
0049665F 8B45 FC mov eax,dword ptr ss:
00496662 E8 25CFF6FF call Atlantis.0040358C ; 算出注册码长度
00496667 8BF0 mov esi,eax
00496669 83FE 01 cmp esi,1
0049666C 7C 3D jl short Atlantis.004966AB
0049666E 8B45 FC mov eax,dword ptr ss: ; 经过以上两次加工后的变形假码放入EAX
00496671 8A4430 FF mov al,byte ptr ds: ; 注册码从后往前依次参与运算
00496675 8BD0 mov edx,eax
00496677 80EA 20 sub dl,20 ; 逐位比较是不是空格
0049667A 74 05 je short Atlantis.00496681
0049667C 80EA 0D sub dl,0D ; 逐位比较是不是连字符“-”
0049667F 75 11 jnz short Atlantis.00496692
00496681 8D45 FC lea eax,dword ptr ss:
00496684 B9 01000000 mov ecx,1
00496689 8BD6 mov edx,esi
0049668B E8 40D1F6FF call Atlantis.004037D0 ; 去除注册码中的“-”
00496690 EB 14 jmp short Atlantis.004966A6
00496692 8B55 FC mov edx,dword ptr ss: ; 假码放入edx
00496695 25 FF000000 and eax,0FF
0049669A 8B15 4C7E6100 mov edx,dword ptr ds: ; Atlantis.0061CC30
004966A0 803C02 FF cmp byte ptr ds:,0FF ; 此时eax的值就是假码中每一位字母或数字的十六进制值
004966A4 74 77 je short Atlantis.0049671D ; 注册码中的每一位只能是 数字或a~f或A~F或字母o/O(不明白看下面的分析)
004966A6 4E dec esi
004966A7 85F6 test esi,esi
004966A9^ 75 C3 jnz short Atlantis.0049666E
004966AB 8B45 FC mov eax,dword ptr ss: ; 无连字符“-”的大写注册码放入
004966AE E8 D9CEF6FF call Atlantis.0040358C ; 求经过三次变形后的假码长度
004966B3 83F8 10 cmp eax,10 ; 注册码16位啊
004966B6 75 65 jnz short Atlantis.0049671D
上述代码的后半部分理解有些费力
0049669A 8B15 4C7E6100 mov edx,dword ptr ds: ; Atlantis.0061CC30
指向的地址是0061CC30,我们看一下数据窗口对应位置的数值
醒目一点的估计看出来了,截图上的地址是从0061CC60开始的,为什么呢?
0049669A 8B15 4C7E6100 mov edx,dword ptr ds: ; Atlantis.0061CC30
004966A0 803C02 FF cmp byte ptr ds:,0FF ; 此时eax的值就是假码中每一位字母或数字对应的十六进制值
问题就出在第二句的处,静态解释不易理解,动态跟踪一下就明白了
假设假码中其中一位字符是“8” 对应十六进制是 0x38
而edx == 0061CC30,所以 == 0061CC68 这个地址对应上图可知值为0x08,并不等于0xFF,证明假码中的这一位合格
好,跟踪至此,我们的假码可以进行修正了
HelloHenu --> Babe-5214-0987-acef
以上都是一些准备工作,下面就真的进入了算法核心了
……
004966B8 BE 01000000 mov esi,1 ; 核心算法开始了esi初始值为1
004966BD 8BC6 mov eax,esi ; 一个大的算法循环 开始处
004966BF 48 dec eax
004966C0 03C0 add eax,eax
004966C2 40 inc eax
004966C3 8B55 FC mov edx,dword ptr ss: ; 几次变形后的注册码放入
004966C6 0FB65402 FF movzx edx,byte ptr ds:; 注册码从前往后依次运算
004966CB 8B0D 4C7E6100 mov ecx,dword ptr ds: ; Atlantis.0061CC30
004966D1 8A1411 mov dl,byte ptr ds:
004966D4 C1E2 04 shl edx,4
004966D7 8B4D FC mov ecx,dword ptr ss:
004966DA 0FB60401 movzx eax,byte ptr ds:
004966DE 8B0D 4C7E6100 mov ecx,dword ptr ds: ; Atlantis.0061CC30
004966E4 021401 add dl,byte ptr ds:
004966E7 8855 FA mov byte ptr ss:,dl ; 可以看出,从前往后依次取出注册码的每两位进行下面的运算
004966EA B8 58674900 mov eax,Atlantis.00496758 ; 00496758地址处有段8位的密钥参与运算
004966EF 8A4430 FF mov al,byte ptr ds:
004966F3 C645 F9 01 mov byte ptr ss:,1 ; (这里 标志位哦)
004966F7 B3 08 mov bl,8
004966F9 E8 0AFFFFFF call Atlantis.00496608 ; 把密钥的对应位数值做一次ror(循环右移)运算
004966FE 3A45 FA cmp al,byte ptr ss: ; 比较置换后的对应位注册码值是否等于ror后的密钥值
00496701 75 06 jnz short Atlantis.00496709 ; 事实证明,如果不等于,最终就提示注册码错误
00496703 C645 F9 00 mov byte ptr ss:,0
00496707 EB 04 jmp short Atlantis.0049670D
00496709 FECB dec bl ; 对应密钥可以循环8次ror运算,共产生8个值
0049670B^ 75 EC jnz short Atlantis.004966F9 ; 每次对应取出的两位注册码值必须等于上述8个结果的其中一个
其实,软件核心的算法就是:
1、注册码应为16位,有没有“-”连接都可以
2、注册码中的每一位只能是 0~9或a~f或A~F或字母o/O
3、从前往后每次取出2位注册码值,转换成一个字节的十六进制值
如字符“a5c3” 就转换成 0xA5 0xC3
这样十六位的注册码,就变成了占8字节的一串十六进制值
4、程序预置8位密钥,如下
5、每位密钥都进行 至少一次的ror运算,把第一次ror后得出的值与相应位置的注册码值比较,如果不相等则在第一次算出值的基础上进行第二次的ror运算,依次循环,共可循环8次--如果还不相等,就说明是错误注册码了,不再继续运算
可以004966FE处为切入点,其中al的值就是密钥ror运算出的值--可用的注册码的其中两个值。在004966FE处下断,修改00496701处的jnz跳转为NOP,F9继续运算可以很轻易地跟出可用注册码
004966FE 3A45 FA cmp al,byte ptr ss: ; 比较置换后的对应位注册码值是否等于ror后的密钥值
随便F9了几下
总结了几个类似A7B1-A6B4-2732-E1F27A1B6A4B72231E2F这样的值,不知道有什么用o_0
软件注册后,相关信息保存于注册表以下位置(软件没有对关键信息加密,也是一个败笔):
Windows Registry Editor Version 5.00
"RegCode"="XXXXXXXXXXXXXXXX"
"RegTo"="playboysen"
总结:
看算法的分析有很多,但最主要的验证算法只有以下几行
Mov esi,1
mov eax,00496758 //这里是预置的一个8位数组,具体参考上图
mov al,byte ptr ds:
mov bl,8
004966F9:
Ror al,1
cmp al,byte ptr ss: //在这里添加相应代码取出al中的值转换后连接成16位的字符串即为一组注册码
dec bl
jnz004966F9
inc esi
cmp esi,9
jz XXXXX
预祝大家新的一年虎虎生威~ 精品文章 沙发学习
:handshake 2010年2月4日发布V1.6.5.1
增加文件拖放处理支持 等……
算法未变 好文章,学习了 很难懂
页:
[1]