能力值:
( LV2,RANK:10 )
27 楼
1、crackme_7.exe无法上传,在论坛上有(我已经忘记原来的链接了)!
2、Serial部分我不懂的该如何下断才好,我是在参考文本中看到提示:
You have found the correct Serial 进入代码分析后再跟踪下断的了。
3、相关图
0044C648 /. 55 push ebp
0044C649 |. 8BEC mov ebp, esp
0044C64B |. 83C4 F8 add esp, -8
0044C64E |. 53 push ebx
0044C64F |. 56 push esi
0044C650 |. 33C9 xor ecx, ecx
0044C652 |. 894D F8 mov [ebp-8], ecx
0044C655 |. 8BF0 mov esi, eax
0044C657 |. 33C0 xor eax, eax
0044C659 |. 55 push ebp
0044C65A |. 68 83C74400 push 0044C783
0044C65F |. 64:FF30 push dword ptr fs:[eax]
0044C662 |. 64:8920 mov fs:[eax], esp
0044C665 |. 33C0 xor eax, eax
0044C667 |. 8945 FC mov [ebp-4], eax
0044C66A |. A1 80F84400 mov eax, [44F880] ; 用户名应大于6位
0044C66F |. E8 0074FBFF call 00403A74 ; 取位数mov eax, [eax-4]
0044C674 |. 83F8 06 cmp eax, 6
0044C677 |. 0F8E F0000000 jle 0044C76D ; 位数限制
0044C67D |. A1 80F84400 mov eax, [44F880]
0044C682 |. E8 ED73FBFF call 00403A74
0044C687 |. 83F8 14 cmp eax, 14 ; 用户名小于14位
0044C68A |. 0F8D DD000000 jge 0044C76D
0044C690 |. A1 80F84400 mov eax, [44F880]
0044C695 |. E8 DA73FBFF call 00403A74
0044C69A |. 85C0 test eax, eax
0044C69C |. 7E 17 jle short 0044C6B5
0044C69E |. BA 01000000 mov edx, 1
0044C6A3 |> 8B0D 80F84400 /mov ecx, [44F880] ; 用户名算法
0044C6A9 |. 0FB64C11 FF |movzx ecx, byte ptr [ecx+edx-1]
0044C6AE |. 014D FC |add [ebp-4], ecx ; 把用户名的各字符值相加
0044C6B1 |. 42 |inc edx ; edx为用户名字符指针
0044C6B2 |. 48 |dec eax ; 把值2FE保存到堆栈BF8参数
0044C6B3 |.^ 75 EE \jnz short 0044C6A3
0044C6B5 |> A1 84F84400 mov eax, [44F884] ; 取公司名称
0044C6BA |. E8 B573FBFF call 00403A74
0044C6BF |. 83F8 02 cmp eax, 2 ; 不小于2位,不大于8位
0044C6C2 |. 7E 18 jle short 0044C6DC
0044C6C4 |. A1 84F84400 mov eax, [44F884]
0044C6C9 |. E8 A673FBFF call 00403A74
0044C6CE |. 83F8 08 cmp eax, 8
0044C6D1 |. 7D 09 jge short 0044C6DC
0044C6D3 |. 8B45 FC mov eax, [ebp-4] ; 用户名值
0044C6D6 |. 6BC0 02 imul eax, eax, 2 ; 乘2后的值为5FC
0044C6D9 |. 8945 FC mov [ebp-4], eax
0044C6DC |> 68 98C74400 push 0044C798 ; ASCII "I Love Cracking and "
0044C6E1 |. 8D55 F8 lea edx, [ebp-8] ; 原值为0
0044C6E4 |. 8B45 FC mov eax, [ebp-4] ; 堆栈基址,用户名5FCH
0044C6E7 |. E8 68B0FBFF call 00407754
0044C6EC |. FF75 F8 push dword ptr [ebp-8] ; 字符串为1532=5FCH
0044C6EF |. 68 B8C74400 push 0044C7B8 ; ASCII " Girls ;)"
0044C6F4 |. B8 8CF84400 mov eax, 0044F88C
0044C6F9 |. BA 03000000 mov edx, 3
0044C6FE |. E8 3174FBFF call 00403B34
0044C703 |. 33C0 xor eax, eax
0044C705 |. 8945 FC mov [ebp-4], eax ; 密值被改0
0044C708 |. A1 88F84400 mov eax, [44F888] ; 假序列号
0044C70D |. E8 6273FBFF call 00403A74 ; 取位数mov eax, [eax-4]
0044C712 |. 8BD8 mov ebx, eax ; 假号长度
0044C714 |. A1 8CF84400 mov eax, [44F88C] ; 上述字符串
0044C719 |. E8 5673FBFF call 00403A74 ; 取位数mov eax, [eax-4]
0044C71E |. 3BD8 cmp ebx, eax ; 值为21H
0044C720 |. 75 4B jnz short 0044C76D ; 算出的值跟序列号值相等
0044C722 |. A1 88F84400 mov eax, [44F888]
0044C727 |. E8 4873FBFF call 00403A74 ; 假序列号
0044C72C |. 85C0 test eax, eax
0044C72E |. 7E 27 jle short 0044C757
0044C730 |. BA 01000000 mov edx, 1
0044C735 |> 8B0D 88F84400 /mov ecx, [44F888] ; 假序列号
0044C73B |. 0FB64C11 FF |movzx ecx, byte ptr [ecx+edx-1]
0044C740 |. 034D FC |add ecx, [ebp-4] ; 字符值加上差值
0044C743 |. 8B1D 8CF84400 |mov ebx, [44F88C] ; 原算出的字符串
0044C749 |. 0FB65C13 FF |movzx ebx, byte ptr [ebx+edx-1]
0044C74E |. 2BCB |sub ecx, ebx ; 两值相减
0044C750 |. 894D FC |mov [ebp-4], ecx
0044C753 |. 42 |inc edx
0044C754 |. 48 |dec eax
0044C755 |.^ 75 DE \jnz short 0044C735
0044C757 |> 837D FC 00 cmp dword ptr [ebp-4], 0 ; 检查两串是否一样
0044C75B |. 75 10 jnz short 0044C76D
0044C75D |. 8B86 14030000 mov eax, [esi+314] ; 序列号成功提示
0044C763 |. BA CCC74400 mov edx, 0044C7CC ; ASCII "You have found the correct Serial "
0044C768 |. E8 E790FDFF call 00425854
0044C76D |> 33C0 xor eax, eax
0044C76F |. 5A pop edx
0044C770 |. 59 pop ecx
0044C771 |. 59 pop ecx
0044C772 |. 64:8910 mov fs:[eax], edx
0044C775 |. 68 8AC74400 push 0044C78A
0044C77A |> 8D45 F8 lea eax, [ebp-8]
0044C77D |. E8 7670FBFF call 004037F8
0044C782 \. C3 retn
0044C783 .^ E9 306BFBFF jmp 004032B8
0044C788 .^ EB F0 jmp short 0044C77A
0044C78A . 5E pop esi
0044C78B . 5B pop ebx
0044C78C . 59 pop ecx
0044C78D . 59 pop ecx
0044C78E . 5D pop ebp
0044C78F . C3 retn
能力值:
( LV2,RANK:10 )
28 楼
一,常见判断有壳方法知识总结
1.PEID查壳
2.载入OD是否有提示代码被压缩
3.根据程序入口代码
4.看是否可以查得到明码字符串
5.资源编辑工具看是否可以改资源
二,常见判断与解决附加数据知识总结
1.PEID查壳时显示[overlay],95%的情况下是有附加数据,但是有个别程序没有附加数据,PEID可能误报,此时你可以在脱壳后先试运行程序,如果能运行说明就没有附加数据;
2.脱壳后的文件明显比脱壳前的文件小,且经修复无法运行——>十之八九是附加数据在搞鬼!
3.脱壳后运行提示“Invalid
data in the file.”说明有附加数据。
修复方法
1.工具overlay修复
2.进制工具打开复制数据修复
三,常见自校检解决办法知识总结
1.双开OD法(如果软件有防多开窗口的限制,需要先解决这个问题。(不推荐
因为这样学不到东西)
2.跟踪退出函数。一般都是调用ExitProcess、PostQuitMessage
3.利用PEID的插件KANAL
V2.90 。找到密码学算法和核心 CRC或者MD5实现磁盘文件校验或者内存映像校验关键的地方
四,常见自校检解决办法知识总结
1.校检日期
2.校检大小
3.校检旁文件
校检自身大小的软件一般方法
我们看一下未脱壳文件的大小为:10752字节转16进制为2A00,再看看脱壳后的文件大小30208字节,即7600,关键是如何找到对自身大小进行对比的语句,
1.W32Dasm上场。用W32Dasm载入脱壳文件,我们只要搜索00002A00即可。更改代码002A00为脱壳后的大小007600即可。(太多局限)
2.对于VB检测自身大小的软件我们还可以跟踪FileLen函数,因为VB一般都用FileLen检测自身的大小,用OD载入脱壳文件下断BP
rtcFileLen,F9后断下,ALT+F9返回。
五,常见工具暴破方法知识总结找不到跳转,狂返回到主程序代码段内 在判关键跳转
1.跳过错误
相反与JMP。
2.不跳成功 相反与NOP。
3.改比较。
4.改比较中其中一个返回直.
六,常见去NAG窗方法知识总结
1.下调用窗口函数法
2.堆栈F12调用法
3.改跳转法(如果是注册才取消的NAG窗)
思路:不让NAG窗口运行就行```
七,常见工具追明码方法知识总结
1.OD追码法
找到关键CALL 直接下INT段点 然后运行到这
直接看堆栈上下或寄存器的直
关键CALL上面的PUSH POP LEA等传输数据等````
2.WinHex追码法
步骤:
1.启动需要破解软件
2.输入用户名和注册码,然后按确定
3.弹出一个对话框(切记,不要按确定!!!!!!!!)
4.启动WinHex
5.选择Ram编辑器
6.打开你所要破的软件的Ram的主要内存(基本上是最下面那个+)
7.搜索注册码
8.如果第一次没搜到按F3搜索下一个
9.然后就可以发现注册码
3.TRW2000追注册码的通法
1.将程式的注册对话框打开,输入你的姓名和任意的注册码(推荐用987654321)
2.按Ctrl+N呼叫出TRW2000,然后下中断(一般用bpx hmemcpy),回车,键入g,回车
3.返回注册界面,按下注册窗中的"确定"按钮.
4.如果被TRW拦到,说明刚才打的中断发挥作用了,可以继续工作.如果出现的是"注册失败"的对话框,说明TRW的中断没有作用,只有重复第二步,换个中断试试.(中断设置,看雪教程很详细,不重复)
5.键入bc*,回车,键入pmodule,回车,猛按F12键,等到出现"注册失败"的画面时,记下刚才按F12键的按数
6.第二次重复第一步至第四步,这次按(第五步记下的按数减去1)下的按数,停下来.
7.开始按F10键单独追寻,找到关键Call和关键跳转,在这个关键Call处d eax d edx,,多看看,有时就会看到注册码,出现在TRW的右上方
8.如果没找到,当然要按F8键进去关键Call观察了,继续追踪可疑Call和可疑跳转
注意:如果搜到最后还是没搜到,可以采取以下的方法,再试.(如果真找不到,就只能用其它软件了)
对于没有弹出对话框的软件似乎这方法没用!!!!
1.如果用注册码没搜到,就用搜用户名
2.有些软件对于中文用户名不支持,因此就使用英文用户名
3.有些软件对于注册码又长度要求,因此就使用比原先的注册码较长或较短的注册码
4.建议输入的注册码为987654321,因为如果是123456789会与机器中的一些数字重复
八,常见跳出与填加的网页解决知识总结
现在我们同时再找那个跳出的网页.
我们在堆线出现的真码处右键
-- 按在数据窗口中跟随
看到啦数据窗口出现很多你要改的字串了
除便改吧, 不用客气
先向上找 看到004F5040的网页地址吗..就是要找它
我们先不要急..再向上找004F4418 这个地址才是我们要找的真正修改地址
怎样改啦 :
先再打开多一个OD 在命令栏里打上 dd 004F4418 > ENTER >
再指着地址改为
HEX HEX/ASCLL(8位)
在004F4418 > 1A 处改为 00 就成功了
添加弹网页
006CE000 > 6A 01 push
1
006CE002 6A 00 push
0
006CE004 6A 00 push
0
006CE006 68 00E16C00 push
dumped_.006CE100
; ASCII "http://Blog.ShowHmily.Cn"
006CE00B
68 19E16C00 push dumped_.006CE119
; ASCII "open"
006CE010
6A 00 push 0
006CE012
E8 C92EF47C call
ShellExecuteA
具体怎么用,你只要让这段代码运行就可以了,可以让这段代码运行完再跳转到OEP也可以~
能力值:
( LV2,RANK:10 )
39 楼
原创]浅谈NT下Ring3无驱进入Ring0的方法
关键字:NT,Ring0,无驱
(测试环境:Windows 2000 SP4,Windows XP SP2.
Windows 2003 未测试)
在NT下无驱进入Ring0是一个老生常谈的方法了,网上也有一些C代码的例
子,我之所以用汇编重写是因为上次在
[原创/探讨]Windows 核心编程研究系列之一(改变进程 PTE)
的帖子中自己没有实验成功(其实已经成功了,只是自己太马虎,竟然还不
知道 -_-b),顺面聊聊PM(保护模式)中的调用门的使用情况。鉴于这些都是
可以作为基本功来了解的知识点,所以对此已经熟悉的朋友就可以略过不看
了,当然由于本人水平有限,各位前来“挑挑刺”也是非常欢迎的,呵呵。
下面言归正传,我们知道在NT中进入Ring0的一般方法是通过
驱动,我的Windows 核心编程研究系列 文章前两篇都使用了
这个方法进入Ring0 完成特定功能。现在我们还可以通过在Ring3下直接写
物理内存的方法来进入Ring0,其主要步骤是:
0 以写权限打开物理内存对象;
1 取得 系统 GDT 地址,并转换成物理地址;
2 构造一个调用门;
3 寻找 GDT 中空闲的位置,将 CallGate 植入;
4 Call植入的调用门。
前面已打通主要关节,现在进一步看看细节问题:
[零] 默认只有 System 用户有写物理内存的权限
administrators 组的用户只有读的权限,但是通过修改用户
安全对象中的DACL 可以增加写的权限:
_SetPhyMemDACLs proc uses ebx edi esi \
_hPhymem:HANDLE,\
_ptusrname:dword
local @dwret:dword
local @htoken:HANDLE
local @hprocess:HANDLE
local @个
local @OldDACLsACL
local @SecurityDescriptorSECURITY_DESCRIPTOR
local @Access:EXPLICIT_ACCESS
mov @dwret,FALSE
invoke RtlZeroMemory,addr @NewDACLs,sizeof @NewDACLs
invoke RtlZeroMemory,addr @SecurityDescriptor,\
sizeof @SecurityDescriptor
invoke GetSecurityInfo,_hPhymem,SE_KERNEL_OBJECT,\
DACL_SECURITY_INFORMATION,NULL,NULL,\
addr @OldDACLs,NULL,\
addr @SecurityDescriptor
.if eax != ERROR_SUCCESS
jmp SAFE_RET
.endif
invoke RtlZeroMemory,addr @Access,sizeof @Access
mov @Access.grfAccessPermissions,SECTION_ALL_ACCESS
mov @Access.grfAccessMode,GRANT_ACCESS
mov @Access.grfInheritance,NO_INHERITANCE
mov @Access.stTRUSTEE.MultipleTrusteeOperation,\
NO_MULTIPLE_TRUSTEE
mov @Access.stTRUSTEE.TrusteeForm,TRUSTEE_IS_NAME
mov @Access.stTRUSTEE.TrusteeType,TRUSTEE_IS_USER
push _ptusrname
pop @Access.stTRUSTEE.ptstrName
invoke GetCurrentProcess
mov @hprocess,eax
invoke OpenProcessToken,@hprocess,TOKEN_ALL_ACCESS,\
addr @htoken
invoke SetEntriesInAcl,1,addr @Access,\
@OldDACLs,addr @NewDACLs
.if eax != ERROR_SUCCESS
jmp SAFE_RET
.endif
invoke SetSecurityInfo,_hPhymem,SE_KERNEL_OBJECT,\
DACL_SECURITY_INFORMATION,NULL,NULL,\
@NewDACLs,NULL
.if eax != ERROR_SUCCESS
jmp SAFE_RET
.endif
mov @dwret,TRUE
SAFE_RET:
.if @NewDACLs != NULL
invoke LocalFree,@NewDACLs
mov @NewDACLs,NULL
.endif
.if @SecurityDescriptor != NULL
invoke LocalFree,@SecurityDescriptor
mov @SecurityDescriptor,NULL
.endif
mov eax,@dwret
ret
_SetPhyMemDACLs endp
[一] 可以在Ring3下使用SGDT指令取得系统GDT表的虚拟地址,
这条指令没有被Intel设计成特权0级的指令。据我的
观察,在 Windows 2000 SP4 中 GDT 表的基址都是相同的,
而且在 虚拟机VMware 5.5 虚拟的 Windows 2000 SP4中
执行 SGDT 指令后返回的是错误的结果,在虚拟的 Windows XP
中也有同样情况,可能是虚拟机的问题,大家如果有条件可以试一下:
local @stGE:GDT_ENTRY
mov @dwret,FALSE
lea esi,@stGE
sgdt fword ptr [esi]
assume esi:ptr GDT_ENTRY
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;在 VMware 虚拟环境下用以下两条指令替代
;只用于 Windows 2000 SP4
;mov [esi].Base,80036000h
;mov [esi].Limit,03ffh
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
mov eax,[esi].Base
invoke @GetPhymemLite,eax
.if eax == FALSE
jmp quit
.endif
下面就是虚拟地址转换物理地址了,这在Ring0中很简单,
直接调用MmGetPhysicalAddress 即可,但在Ring3中要
另想办法,还好系统直接将 0x80000000 ? 0xa0000000 影射到物
理0地址开始的位置,所以可以写一个轻量级的GetPhysicalAddress
来替代
@GetPhymemLite proc uses esi edi ebx _vaddr
local @dwret:dword
mov @dwret,FALSE
.if _vaddr = 0a0000000h
jmp quit
.endif
mov eax,_vaddr
and eax,01ffff000h ;or sub eax,80000000h
mov @dwret,eax
quit:
mov eax,@dwret
ret
@GetPhymemLite endp
[二]调用门在保护模式中可以看成是低特权级代码向高特权级代
码转换的一种实现机制,如图1所示(由于本人较懒,所以借用李
彦昌先生所著的80x86保护模式系列教程 中的部分截图,希望李先
生看到后不要见怪 ^-^):
能力值:
( LV2,RANK:10 )
40 楼
作者:鹭影依凌
转贴自:一蓑烟雨
前言:论坛上有关算法分析的文章不少,也不少精品
但对于刚学CARACK来说,只是叹为观止
原因如下:
1.论坛高手如云,菜鸟也不占少数,有些甚至对汇编指令还不是很熟悉
2.不少算法分析文章分析的是相当完美了,但是作者仅仅展示给的是最终的成果,而没有把分析的思路,分析的过程展示给我们
相信更多的兄弟需要的是一种分析思想,分析理念!
本文(本系列)将对这些问题展开逐一讨论
第一篇:必要基础知识
第二篇:软件注册流程
第三篇:算法分析实例 声明:
1.以下内容都是个人在学习中的一些心得体会,写给新手的,高手飘过
2.文章难免有疏漏之处,欢迎各位兄弟批评指正
3.本文原创于UnPaKcN,如转载,请保持文章完整性 ==文章结构==
1.ASCii表(基础)
2.对特殊汇编指令讲解(推荐)
3.定位程序注册代码段 一、ASCII表
◇数 字类:
数 字 0 1 2 3 4 5 6 7 8 9
十六进制 30 31 32 33 34 35 36 37 38 39
十 进制 48 49 50 51 52 53 54 55 56 57
◇大写字母:
字 母 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
十六进制 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A
十 进制 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
◇小写字母:
小写字母 a b c d e f g h i j k l m n o p q r s t u v w x y z
十六进制 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A
十 进制 97 98 99 100101102103104105106107108109110111112113114115116117118119120121122
◇特殊字符:
字 符 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
十六进制 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 3A 3B 3C 3D 3E 3F 40 5B 5C 5D 5E 5F 60 7B 7C 7D 7E
十 进制 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 59 60 61 62 63 64 91 92 93 94 95 96123124125126 =>记忆技巧<=
数 字:'0'~'9' -> 31~39
大写字母:'A'~'Z' -> 41~5A
小写字母:'a'~'z' -> 61~7A
特别字符:空 格' ' -> 20
连字符'-' -> 2D
备注:连字符在序列号中经常用到,应熟记 ■对字符的ASCII值一定要熟悉,深入分析非密码学算法的关键
很多算法是在字符的ASCII值上"做文章"的
#举个典型的例子
算法描述如下:
->取用户名每个字符的ASCII值,累加以后做为序列号
示例代码
004B32BB |> 8B4D F0 /mov ecx, dword ptr [ebp-10] ; ASCII "prc2.0ultrain@163.com"
004B32BE |. 8A0C01 |mov cl, byte ptr [ecx+eax] ; 字符串的第i个字符
004B32C1 |. 81E1 FF000000 |and ecx, 0FF ; 取cl
004B32C7 |. 0FAFC8 |imul ecx, eax ; ECX = ECX * EAX
004B32CA |. 03F9 |add edi, ecx ; EDI = EDI + ECX
004B32CC |. 40 |inc eax ; EAX++
004B32CD |. 4A |dec edx ; EDX--
004B32CE |.^ 75 EB \jnz short 004B32BB ; 循环length(string)次 ■大写小写转化
大写 -> 小写: 加30H
小写 -> 大写: 减30H ■另外,还要对一下知识有一定了解
1.数值的十进制和16进制转化
2.字符直接变数字
3.数字直接变字符
4.... 二、汇编指令
1.数据传送(Data transfer)
2.算术运算(Arithmetic)
3.逻辑运算和移位指令(Logic& Shift)
4.串操作(String manipulation)
5.控制转移(Control Transfer)
6.处理器控制(Processor Control)
具体查阅8086系统指令手册 常用指令特别讲解
●指令MOV作用:
1.完成寄存器与寄存器、寄存器与内存之间数据传递
2.完成标志位、密码表等的初始化
其中密码表一般为内存地址
标志位一般为寄存器,少量是内存地址
●关于堆栈的指令
1.压栈
ESP的值要减少
2.出栈
ESP的值要增加
跟踪堆栈的时候,不同的ESP格式的内存地址指向同一内存地址
建议尽量不要在内存地址是ESP格式的情况下锁定跟踪 ●目的地址传送指令LEA
作用主要有两个
1.装载有效地址
指令示例:
mov eax, dword ptr [esi+XX] ;
lea ebx, dword ptr [esi+XX] ;
经过跟踪发现[esi+XX]存放的是某字符串
那么EBX保存的是该字符串的地址
2.完成算术运算
lea eax, dword ptr [edi+XX] ;
等价于:EAX = EDI + XX;
●算术运算指令
求反:NEC
主要理解其用法:以 0 减之
往往和OR一起结合,完成对字符串长度的取值
乘法MUL
MUL ECX
运算:EAX = EAX * ECX
除法DIV
DIV ECX
运算:EAX = EAX / ECX
EDX = EAX % ECX
●逻辑运算指令
"与"运算&
"或"运算^
"异或"运算|
以上三条指令常用作算法运算
做注册机时候分析起来比较头痛
"测试"test
操作,进行异或运算
特点:
(1).不保存异或结果
(2).常和条件跳转指令结合在一起
测试一般有三个方向
1.对标志位值进行测试
格式如下
test EAX,EAX
je/jne xxxxxxxx
2.对某位进行测试
test EAX,4
je/jne xxxxxxxx
对倒数第三位进行测试
3.进行奇偶测试
test EAX,80000001
je/jne xxxxxxxx ●移位指令
左移->乘
SHL EAX,2
等价于EAX = EAX * (2^2)
右移->除
SHR EAX,3
等价于EAX = EAX / (2^3) 三、定位程序注册代码段
1.试注册,判断保护方式
序列号(变相的序列号)
所谓变相的序列号就是程序没有输入注册码的地方,但会以文本文件方式通过读取特定的文件
如keyfile等
这类仍可以归类为序列号保护方式 2.查壳/脱壳
有壳脱之
无壳进行下一步 3.定位程序注册代码段
(1)超级字符串定位
A.有错误提示"invalid regcode!"
B.没有错误提示,但有正确提示"Thank you,..."
C.[unregistered] (2)通过API断点
A.有对话框
bp MessageBoxA(W)
B.没有对话框
bp GetWindowTextA(W)
bp GetDlgItemTextA(W)
C.重启验证
bp RegCreateKeyA(W)
bp RegDeleteKeyA(W)
bp RegQueryValueA(W)
bp RegCloseKey
bp RegOpenKeyA(W)
(3)其它
对付不同语言的工具选择
DEDE:确定delphi的按钮动作对应的代码
VB:SmartCheck
注意:必须是明码比较的VB程序
4.方法的选择
选择流程如下
字符串->对话框->文本->其它
调试还很依赖经验和运气,暂时无思路的程序可以先放放
有时候可以根据软件注册对话框样式猜出大致用什么思路定位,甚至可以猜到它的加密算法 5.AntiDbg
"高级话题",暂时回避{偶暂时对这方面涉猎太少}o(n_n)o 暂时先告一段落,希望能对论坛的兄弟们有所帮助~~ 鹭影依凌[2007.12.14]
能力值:
( LV2,RANK:10 )
41 楼
作者:鹭影依凌
转贴自:一蓑烟雨
声明:
1.以下内容都是个人在学习中的一些心得体会,写给新手的,高手飘过
2.文章难免有疏漏之处,欢迎各位兄弟批评指正
3.本文原创于UnPaKcN,如转载,请保持文章完整性 有了第一篇的基础知识学习
下面我们以AuRRa公司的龙头产品Media-WorkShop为实例来进行第二篇 学习目标
1.培养良好的"破解书写习惯"
2.学会判断程序段代码的功能
3.学会逆向分析和爆破 一、培养良好的破解习惯
1.在指令右侧注释栏填写必要的跟踪注释
应该着重注释的内容
(1).寄存器的值(数值/字符串)
(2).运算表达式
便于完成将来对算法的总结
(3).CALL功能
确定哪些CALL是关键CALL,哪些是无大意义的CALL
比如:
A.经过一个CALL后,字符串中的小写字母全部变为大写字母
这样的CALL,显然没有必要跟进去
B.又如
CALL XXXXXXXX
TEST EAX,EAX
JE xxxxxxxx //跳向注册成功
这样的CALL一般来说是关键CALL(算法CALL)
很有必要跟进去探个究竟
(4).代码段的功能
确定代码段的功能,以便从全局的角度对整个注册流程进行分析 2.调试过程中,不同阶段,观察侧重点不同
A.首次调试
通常需要着重观察反汇编窗口和信息提示窗口
B.区段集中调试时期
应多注意寄存器和堆栈窗口
C.某条特殊指令
集中跟随数据窗口 3.一气呵成,又不拘泥
所谓一气呵成,就是指已经有了思路,那么就要一鼓作气,将其进行到底
不然,开工一半,中途搁置
过几天再拿起来...晕,又得从头分析
不拘泥
不是每个软件都是软柿子,不是每个软件设计者都不懂得ANTI-DBG
要知道,现在的程序员的软件保护意识越来越强的!!
暂时没有思路就先放一放,说生活中的某个细节会突然触发你的灵感
如果只是为了破解而破解,那么建议你放弃CRACKER这条路
学习破解只是一种很好的学习别人程序设计思路的方式
并在学习过程中体会到自身提高的乐趣 二、过程分析笔记
!!!阅读建议:
由于本篇是完全面向新手的文章,读者可以先下载注释笔记,然后浏览下
然后边调试边看以下分析内容,效果会更好
切记:一定要自己亲手调试
在本例中
我们用提示字符串进行注册代码段的定位
提示信息:"invalid username or registration code"
向上看代码,一般是在程序段的段首下断点
关于"段首"的概念
可以这样理解:在向上代码段中出现第一个retn的下方
一般是push esp,push -1,push A,B格式的 本例中,我们在地址0045BDB0处F2下断
流程大致应该是这样的:
1.运行程序,输入试练码,程序被断下
2.进行首次跟踪
主要完成些重要数据的记录(旁白注释)
3.将程序细分段,确定各个分段的作用
4.进行细跟踪
搞定算法 实例讲解:
输入试练码:
ID:luying10
SN:9876543210abcdef
点击确定,程序被OD断下
注意观察代码窗口、信息提示窗口、(寄存器窗口只要注意字符串类型数据就好)
并随时记录有用信息
;====================================================================|
0045BDB0 . 6A FF push -1 ; //断在这
0045BDB2 . 68 983A4700 push 00473A98 ;
0045BDB7 . 64:A1 0000000>mov eax, dword ptr fs:[0]
0045BDBD . 50 push eax
0045BDBE . 64:8925 00000>mov dword ptr fs:[0], esp
0045BDC5 . 51 push ecx
0045BDC6 . 53 push ebx
0045BDC7 . 56 push esi
0045BDC8 . 8BF1 mov esi, ecx
0045BDCA . 57 push edi
0045BDCB . 8D4C24 0C lea ecx, dword ptr [esp+C]
0045BDCF . E8 D4BE0000 call <jmp.&MFC42.#540>
0045BDD4 . 6A 01 push 1
0045BDD6 . 8BCE mov ecx, esi
0045BDD8 . C74424 1C 000>mov dword ptr [esp+1C], 0
0045BDE0 . E8 43C30000 call <jmp.&MFC42.#6334>
0045BDE5 . E8 6CC20000 call <jmp.&MFC42.#1168>
0045BDEA . 8B48 04 mov ecx, dword ptr [eax+4]
0045BDED . E8 78C30000 call <jmp.&MFC42.#1669>
;
0045BDF2 . 68 E8030000 push 3E8 ; /Timeout = 1000. ms
0045BDF7 . FF15 3C524700 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
0045BDFD . E8 54C20000 call <jmp.&MFC42.#1168>
0045BE02 . 8B48 04 mov ecx, dword ptr [eax+4]
在经过地址0045BDF7的CALL时候,程序停顿了一小会儿
我们看英文注释也大概猜到这段代码的作用了----加入延时验证,防止暴力攻击
;--------------------------------------------------------------------|
0045BE05 . E8 5AC30000 call <jmp.&MFC42.#2652> ;
0045BE0A . 8B46 64 mov eax, dword ptr [esi+64] ;
0045BE0D . 8B4E 60 mov ecx, dword ptr [esi+60] ;
程序运行到0045BE0A这行时候
信息提示窗口提示dword ptr [esi+64] = "9876543210abcdef"
[esi+64]中保存的是序列号
这不正是我们最开始天的序列号嘛
运行本行代码后,发现EAX变成了序列号
同样,运行0045BE0D这行,ECX被赋予了用户名
;--------------------------------------------------------------------|
0045BE10 . 8D5E 64 lea ebx, dword ptr [esi+64] ;
0045BE13 . 8D7E 60 lea edi, dword ptr [esi+60] ;
这两行只有值,没有所谓的字符串的东东
我们学过LEA是装载有效地址的指令
[esi+64]中保存的是序列号
那么,执行完lea ebx, dword ptr [esi+64]后,EBX中保存的就应该是序列号的地址
同样,EDI中保存用户名的地址
;--------------------------------------------------------------------|
0045BE16 . 50 push eax ; 序列号压栈
0045BE17 . 51 push ecx ; 用户名压栈
压栈操作,不用多解释,下面是一个CALL,我们首次跟踪,先F8过
;---------------------------------------------------------------------
0045BE18 . E8 83430000 call 004601A0 ;
0045BE1D . 83C4 08 add esp, 8
0045BE20 . 85C0 test eax, eax
0045BE22 . 75 1F jnz short 0045BE43 ;
运行了0045BE18这行的CALL后,EAX变为0
继续F8,来到跳转,跳转指向是绿色,跳转未实现
下面英文提示invalid username or registration code
显然再继续下去是提示注册失败咯
;--------------------------------------------------------------------|
0045BE24 . 6A 40 push 40
0045BE26 . 68 9C7C4900 push 00497C9C ; sorry
0045BE2B . 68 707C4900 push 00497C70 ; invalid username or registration code sorry
0045BE30 . 8BCE mov ecx, esi
0045BE32 . E8 EDC30000 call <jmp.&MFC42.#4224> ;
提示注册失败,点击确定按钮,继续F8
;--------------------------------------------------------------------|
0045BE37 . C705 082C4E00>mov dword ptr [4E2C08], 0 ;
0045BE41 . EB 76 jmp short 0045BEB9 ; //跳走
程序跳走
;跳到这里来
0045BEB9 > 8BCE mov ecx, esi ; ->来到这
0045BEBB . E8 74C20000 call <jmp.&MFC42.#4853>
0045BEC0 . 8D4C24 0C lea ecx, dword ptr [esp+C]
0045BEC4 . C74424 18 FFF>mov dword ptr [esp+18], -1
0045BECC . E8 8FBD0000 call <jmp.&MFC42.#800>
0045BED1 . 8B4C24 10 mov ecx, dword ptr [esp+10]
0045BED5 . 5F pop edi
0045BED6 . 5E pop esi
0045BED7 . 5B pop ebx
0045BED8 . 64:890D 00000>mov dword ptr fs:[0], ecx
0045BEDF . 83C4 10 add esp, 10
0045BEE2 . C3 retn ; //结束
;====================================================================|
首轮跟踪结束,总结下:
1.关键跳转0045BE22
2.关键CALL->004601A0
3.标志位EAX
EAX = 0 注册失败
EAX = 1 注册成功
4.可疑处,地址:0045BE7 mov dword ptr [4E2C08], 0 两个研究方向
1.关键CALL->004601A0
2.可疑的赋值 首先研究关键CALL
;====================================================================|
;在地址0045BE18处跟进关键CALL->004601A0
;--------------------------------------------------------------------|
004601A0 /$ 53 push ebx ;
OD下方显示:本地调用来自 00428B46, 00429225, 0044BB64, 0045120C, 00455368, 0045BE18, 0045E824
004601A1 |. 55 push ebp
注意:从这里我们可疑看到,程序有多处代码调用了CALL=>004601A0
这也验证了为了程序只修改0014BE22处的关键跳转不能达到完全爆破的目的
;--------------------------------------------------------------------|
004601A2 |. 8B6C24 0C mov ebp, dword ptr [esp+C] ;
EBP = [esp+C] = 用户名
004601A6 |. 56 push esi
004601A7 |. 57 push edi
004601A8 |. BE 84014A00 mov esi, 004A0184 ; ESI = 4A0184
004601AD |. 8BC5 mov eax, ebp ; EAX = 用户名
004601AF |> 8A10 /mov dl, byte ptr [eax] ; 用户名的第1个字符
004601B1 |. 8A1E |mov bl, byte ptr [esi]
004601B3 |. 8ACA |mov cl, dl
004601B5 |. 3AD3 |cmp dl, bl
004601B7 |. 75 1E |jnz short 004601D7 ;
跳转实现//跳出循环体(跳至EAX置零)
;----------------------------
004601B9 |. 84C9 |test cl, cl
004601BB |. 74 16 |je short 004601D3 ;
004601BD |. 8A50 01 |mov dl, byte ptr [eax+1]
004601C0 |. 8A5E 01 |mov bl, byte ptr [esi+1]
004601C3 |. 8ACA |mov cl, dl
004601C5 |. 3AD3 |cmp dl, bl
004601C7 |. 75 0E |jnz short 004601D7
004601C9 |. 83C0 02 |add eax, 2
004601CC |. 83C6 02 |add esi, 2
004601CF |. 84C9 |test cl, cl
004601D1 |.^ 75 DC \jnz short 004601AF ; //循环
004601D3 |> 33C0 xor eax, eax ;
004601D5 |. EB 05 jmp short 004601DC ;
程序跳出了循环体,条件是用户名不为空
我们可以看看如果程序从004601D5这跳会怎样
首先跳至004601DC
因为EAX = 0,所以又跳至00460242
接着EAX置零后返回
而我们的主程序在EAX=0的时候是注册失败的
;----------------------------
004601D7 |> 1BC0 sbb eax, eax ;
004601D9 |. 83D8 FF sbb eax, -1 ;
004601DC |> 85C0 test eax, eax
004601DE |. 74 62 je short 00460242 ;
EAX=1,跳转未实现
综上,我们可疑得出,上段代码是检查用户名是否为空
;--------------------------------------------------------------------|
004601E0 |. 8B7C24 18 mov edi, dword ptr [esp+18] ;
EDI = [esp+18] = 序列号
004601E4 |. BE 84014A00 mov esi, 004A0184 ; ESI = 4A0184
004601E9 |. 8BC7 mov eax, edi ;
004601EB |> 8A10 /mov dl, byte ptr [eax] ; 序列号的第i个字符
004601ED |. 8A1E |mov bl, byte ptr [esi]
004601EF |. 8ACA |mov cl, dl
004601F1 |. 3AD3 |cmp dl, bl
004601F3 |. 75 1E |jnz short 00460213 ;
跳转实现//跳出循环体(跳至EAX置零)
004601F5 |. 84C9 |test cl, cl
004601F7 |. 74 16 |je short 0046020F ;
004601F9 |. 8A50 01 |mov dl, byte ptr [eax+1]
004601FC |. 8A5E 01 |mov bl, byte ptr [esi+1]
004601FF |. 8ACA |mov cl, dl
00460201 |. 3AD3 |cmp dl, bl
00460203 |. 75 0E |jnz short 00460213
00460205 |. 83C0 02 |add eax, 2
00460208 |. 83C6 02 |add esi, 2
0046020B |. 84C9 |test cl, cl
0046020D |.^ 75 DC \jnz short 004601EB ; //循环
0046020F |> 33C0 xor eax, eax ;
00460211 |. EB 05 jmp short 00460218 ;
程序跳出了循环体,条件是序列号不为空
我们可以看看如果程序从00460211这跳会怎样
首先跳至00460218
因为EAX = 0,所以又跳至00460242
接着EAX置零后返回
而我们的主程序在EAX=0的时候是注册失败的
00460213 |> 1BC0 sbb eax, eax ;
00460215 |. 83D8 FF sbb eax, -1 ;
00460218 |> 85C0 test eax, eax ;
0046021A |. 74 26 je short 00460242 ;
EAX=1,跳转未实现
综上,我们可疑得出,上段代码是检查序列号是否为空
;--------------------------------------------------------------------|
0046021C |. 57 push edi ;
0046021D |. 55 push ebp ;
0046021E |. E8 6DF9FFFF call 0045FB90 ;
00460223 |. 83C4 08 add esp, 8
00460226 |. 85C0 test eax, eax ;
00460228 |. 75 0E jnz short 00460238 ;
EDI保存序列号
EBP保存用户名
EAX = 0
跳转未实现,继续
有一个CALL->0045FB90 ,下次跟入 假设跳转实现,程序跳至00460238
EAX = 1,返回-》注册成功
;--------------------------------------------------------------------|
0046022A |. 57 push edi ;
0046022B |. 55 push ebp ;
0046022C |. E8 8FFBFFFF call 0045FDC0 ;
00460231 |. 83C4 08 add esp, 8
00460234 |. 85C0 test eax, eax ;
00460236 |. 74 0A je short 00460242 ;
EDI保存序列号
EBP保存用户名
EAX = 0
跳转实现
EAX = 0,返回,注册失败 假设跳转未实现
EAX = 1,返回,注册成功
;--------------------------------------------------------------------|
00460238 |> 5F pop edi
00460239 |. 5E pop esi
0046023A |. 5D pop ebp
0046023B |. B8 01000000 mov eax, 1 ;
00460240 |. 5B pop ebx
00460241 |. C3 retn ;
标志位赋值:EAX = 1 //返回
;--------------------------------------------------------------------|
00460242 |> 5F pop edi ;
跳转来自 004601DE, 0046021A, 00460236
00460243 |. 5E pop esi
00460244 |. 5D pop ebp
00460245 |. 33C0 xor eax, eax ;
00460247 |. 5B pop ebx
00460248 \. C3 retn ;
EAX置零//返回
;====================================================================| 跟进call 0045FB90 ,只有一处调用
跟进call 0045FDC0 ,只有一处调用 我们可以爆破了
在第二层中想办法让EAX的返回值为1
思路.
1.修改关键跳转
地址00460236处jnz改为jmp
2.修改赋值语句
地址00460245处xor eax,eax修改为inc eax(nop填充) 哈哈,这么简单就搞定``````
还有个可疑点呢,别忘了噢~~~
我们在运行到0045BE20 . 85C0 test eax, eax
这行时候,修改下EAX的值,将其由0置为1
使下面的跳转实现
;--------------------------------------------------------------------|
0045BE43 > 8B07 mov eax, dword ptr [edi] ;
0045BE45 . 8D4C24 0C lea ecx, dword ptr [esp+C]
0045BE49 . 50 push eax ;
0045BE4A . 68 547C4900 push 00497C54 ; license to:%s
0045BE4F . 51 push ecx
0045BE50 . E8 07C20000 call <jmp.&MFC42.#2818>
0045BE55 . 8B5424 18 mov edx, dword ptr [esp+18] ;
提示窗口信息(ASCII "License To:luying10 ")
;---------------------------
0045BE59 . 83C4 0C add esp, 0C
0045BE5C . 8BCE mov ecx, esi
0045BE5E . 6A 40 push 40
0045BE60 . 68 487C4900 push 00497C48 ; thank you
0045BE65 . 52 push edx ;
提示窗口信息(ASCII "License To:luying10 ")
0045BE66 . E8 B9C30000 call <jmp.&MFC42.#4224> ;
提示注册成功
;---------------------------
0045BE6B . 57 push edi
0045BE6C . B9 04034A00 mov ecx, 004A0304 ; ASCII "萷?"
0045BE71 . E8 3EBE0000 call <jmp.&MFC42.#858>
0045BE76 . 53 push ebx
0045BE77 . B9 08034A00 mov ecx, 004A0308 ; ASCII "乇?"
0045BE7C . E8 33BE0000 call <jmp.&MFC42.#858>
0045BE81 . C705 082C4E00>mov dword ptr [4E2C08], 1 ;
这块很可疑噢~
mov dword ptr [4E2C08], 1
;---------------------------
0045BE8B . 8B3F mov edi, dword ptr [edi] ;
0045BE8D . 57 push edi ;
0045BE8E . 68 A0F24800 push 0048F2A0 ; username
0045BE93 . 68 94F24800 push 0048F294 ; register
0045BE98 . B9 F4014A00 mov ecx, 004A01F4
0045BE9D . E8 5EC7FEFF call 00448600 ;
EDI为用户名
0045BEA2 . 8B1B mov ebx, dword ptr [ebx] ;
0045BEA4 . B9 F4014A00 mov ecx, 004A01F4
0045BEA9 . 53 push ebx ;
0045BEAA . 68 84F24800 push 0048F284 ; registercode
0045BEAF . 68 94F24800 push 0048F294 ; register
0045BEB4 . E8 47C7FEFF call 00448600 ;
EBX为序列号
;---------------------------
0045BEB9 > 8BCE mov ecx, esi ;
0045BEBB . E8 74C20000 call <jmp.&MFC42.#4853>
0045BEC0 . 8D4C24 0C lea ecx, dword ptr [esp+C]
0045BEC4 . C74424 18 FFF>mov dword ptr [esp+18], -1
0045BECC . E8 8FBD0000 call <jmp.&MFC42.#800>
0045BED1 . 8B4C24 10 mov ecx, dword ptr [esp+10]
0045BED5 . 5F pop edi
0045BED6 . 5E pop esi
0045BED7 . 5B pop ebx
0045BED8 . 64:890D 00000>mov dword ptr fs:[0], ecx
0045BEDF . 83C4 10 add esp, 10
0045BEE2 . C3 retn ; //结束
;====================================================================| 注册失败mov dword ptr [4E2C08], 0
注册成功mov dword ptr [4E2C08], 1
分析,将注册失败后[4E2C08]也赋值为1
但在整个程序中,有很多地方调用关键CALL
并且两段是不相干的代码
修改地址赋值不能改变关键CALL
修改关键CALL后该地址赋值就相应随之发生变化
结论:修改此处,不能达到完美爆破的目的
只修改关键CALL就可以达到完美爆破的目的 通过本文,主要是让兄弟们学会如何给程序加注释,和确定程序代码段的功能
两点说明:
1.恰当的书写注释
注释不是越多越好,太多的注释反而影响程序的阅读
用最少的文字表达概括语句含义
2.注册流程分析的意义
明确区段代码的作用,为以后定位注册关键代码段做铺垫,减少不必要的代码分析
Now,check it yourself```Come On,U'll be the best!!
鹭影依凌[2007.12.15]
能力值:
( LV2,RANK:10 )
42 楼
作者:鹭影依凌
转贴自:一蓑烟雨
声明:
1.以下内容都是个人在学习中的一些心得体会,写给新手的,高手飘过
2.文章难免有疏漏之处,欢迎各位兄弟批评指正
3.本文原创于UnPaKcN,如转载,请保持文章完整性 经过的前面两篇知识积累和过程分析,下面我们开始进行第三篇---算法分析
程序实例仍旧是Media-WorkShop
前文回顾
先来看看我们在第二篇的部分代码分析
;---------------------------<载入注册计算方案(一)>-------------------|
0046021C |. 57 push edi ; 压栈(序列号)
0046021D |. 55 push ebp ; 压栈(用户名)
0046021E |. E8 6DF9FFFF call 0045FB90 ; |*|注册算法<一>
00460223 |. 83C4 08 add esp, 8
00460226 |. 85C0 test eax, eax ; 标志位测试
00460228 |. 75 0E jnz short 00460238 ; //不跳则进入算法二
;---------------------------<载入注册计算方案(二)>-------------------|
0046022A |. 57 push edi ; 压栈(序列号)
0046022B |. 55 push ebp ; 压栈(用户名)
0046022C |. E8 8FFBFFFF call 0045FDC0 ; |*|注册算法<二>
00460231 |. 83C4 08 add esp, 8
00460234 |. 85C0 test eax, eax ; 标志位测试
00460236 |. 74 0A je short 00460242 ; //跳则挂
;---------------------------<标志位赋值(注册成功EAX=1)>--------------|
00460238 |> 5F pop edi
00460239 |. 5E pop esi
0046023A |. 5D pop ebp
0046023B |. B8 01000000 mov eax, 1 ; 标志位赋值:EAX = 1
00460240 |. 5B pop ebx
00460241 |. C3 retn ; //返回
;---------------------------<标志位赋值(注册失败EAX=0)>--------------|
00460242 |> 5F pop edi ; 跳转来自 004601DE, 0046021A, 00460236
00460243 |. 5E pop esi
00460244 |. 5D pop ebp
00460245 |. 33C0 xor eax, eax ; EAX置零
00460247 |. 5B pop ebx
00460248 \. C3 retn ; //返回
;--------------------------------------------------------------------| 下面开始进行注册算法一的分析
;====================================================================|
;在地址0046021E处F7跟进注册算法CALL->0045FB90
;--------------------------------------------------------------------|
0045FB90 /$ 6A FF push -1 ; //本地调用来自 0046021E
0045FB92 |. 68 70414700 push 00474170 ; SE 处理程序安装
0045FB97 |. 64:A1 0000000>mov eax, dword ptr fs:[0]
0045FB9D |. 50 push eax
0045FB9E |. 64:8925 00000>mov dword ptr fs:[0], esp
0045FBA5 |. 83EC 14 sub esp, 14
0045FBA8 |. 8B4424 24 mov eax, dword ptr [esp+24] ; EAX = 用户名
0045FBAC |. 53 push ebx
0045FBAD |. 55 push ebp ; 用户名压栈
0045FBAE |. 56 push esi
0045FBAF |. 57 push edi ; 序列号压栈
0045FBB0 |. 50 push eax ; 用户名压栈
0045FBB1 |. 8D4C24 18 lea ecx, dword ptr [esp+18]
0045FBB5 |. E8 B8800000 call <jmp.&MFC42.#537>
0045FBBA |. 8D4C24 14 lea ecx, dword ptr [esp+14] ; ECX = 用户名的地址
0045FBBE |. C74424 2C 000>mov dword ptr [esp+2C], 0
0045FBC6 |. E8 E5840000 call <jmp.&MFC42.#6282>
0045FBCB |. 8D4C24 14 lea ecx, dword ptr [esp+14]
0045FBCF |. E8 D6840000 call <jmp.&MFC42.#6283>
0045FBD4 |. 6A 20 push 20
0045FBD6 |. 8D4C24 18 lea ecx, dword ptr [esp+18]
0045FBDA |. E8 71870000 call <jmp.&MFC42.#2915>
0045FBDF |. 8B4C24 38 mov ecx, dword ptr [esp+38] ; ECX = 序列号
0045FBE3 |. 8BD8 mov ebx, eax ; EBX = 用户名
0045FBE5 |. 51 push ecx ; 序列号压栈
0045FBE6 |. 8D4C24 14 lea ecx, dword ptr [esp+14]
0045FBEA |. E8 83800000 call <jmp.&MFC42.#537>
0045FBEF |. 8D4C24 10 lea ecx, dword ptr [esp+10]
0045FBF3 |. C64424 2C 01 mov byte ptr [esp+2C], 1
0045FBF8 |. E8 B3840000 call <jmp.&MFC42.#6282>
0045FBFD |. 8D4C24 10 lea ecx, dword ptr [esp+10]
0045FC01 |. E8 A4840000 call <jmp.&MFC42.#6283>
0045FC06 |. 6A 20 push 20
0045FC08 |. 8D4C24 14 lea ecx, dword ptr [esp+14]
0045FC0C |. E8 3F870000 call <jmp.&MFC42.#2915>
0045FC11 |. 8BD0 mov edx, eax ; EDX = 序列号
0045FC13 |. 83CE FF or esi, FFFFFFFF
0045FC16 |. 8BFA mov edi, edx ; EDI = 序列号
0045FC18 |. 8BCE mov ecx, esi
0045FC1A |. 33C0 xor eax, eax ; EAX置零
;---------------------------<用户名长度不能大于序列号长度>---------------|
0045FC1C |. 895424 20 mov dword ptr [esp+20], edx ; [esp+20] = 序列号
0045FC20 |. F2:AE repne scas byte ptr es:[edi]
0045FC22 |. F7D1 not ecx
0045FC24 |. 49 dec ecx ; ECX = 序列号长度
0045FC25 |. 8BFB mov edi, ebx ; EDI = 用户名
0045FC27 |. 8BE9 mov ebp, ecx ; EBP = 用户名长度
0045FC29 |. 8BCE mov ecx, esi
0045FC2B |. F2:AE repne scas byte ptr es:[edi]
0045FC2D |. F7D1 not ecx
0045FC2F |. 49 dec ecx ; ECX = 用户名长度
0045FC30 |. 3BCD cmp ecx, ebp
0045FC32 |. 0F87 54010000 ja 0045FD8C ; //跳则挂(未实现)
;---------------------------<用户名不能为空>---------------------------|
0045FC38 |. 8BFB mov edi, ebx ; EDI = 用户名
0045FC3A |. 8BCE mov ecx, esi
0045FC3C |. F2:AE repne scas byte ptr es:[edi]
0045FC3E |. F7D1 not ecx
0045FC40 |. 49 dec ecx ; ECX = 用户名长度
0045FC41 |. 0F84 45010000 je 0045FD8C ; //跳则挂(未实现)
;---------------------------<序列号不能为空>---------------------------|
0045FC47 |. 8BFA mov edi, edx ; EDI = 序列号
0045FC49 |. 8BCE mov ecx, esi
0045FC4B |. F2:AE repne scas byte ptr es:[edi]
0045FC4D |. F7D1 not ecx
0045FC4F |. 49 dec ecx ; ECX = 序列号长度
0045FC50 |. 0F84 36010000 je 0045FD8C ; //跳则挂(未实现)
;---------------------------<注册运算验证>-----------------------------|
0045FC56 |. 894424 38 mov dword ptr [esp+38], eax ; [esp+38]初始化为0
;------------------------------------[第一层开始]
0045FC5A |> 8B5424 38 /mov edx, dword ptr [esp+38] ; EDX = [esp+38]
0045FC5E |. 8D4C24 34 |lea ecx, dword ptr [esp+34] ; 加载序列号地址
0045FC62 |. 8A82 887E4900 |mov al, byte ptr [edx+497E88] ; 三次依次出现'P'/'W'/'M'
0045FC68 |. 884424 18 |mov byte ptr [esp+18], al ; [esp+18] = al
0045FC6C |. E8 37800000 |call <jmp.&MFC42.#540>
0045FC71 |. 8BFB |mov edi, ebx ; EDI = 用户名
0045FC73 |. 83C9 FF |or ecx, FFFFFFFF
0045FC76 |. 33C0 |xor eax, eax ; EAX置零
0045FC78 |. 33ED |xor ebp, ebp ; EBP置零
0045FC7A |. F2:AE |repne scas byte ptr es:[edi]
0045FC7C |. F7D1 |not ecx
0045FC7E |. 49 |dec ecx ; ECX = 用户名长度
0045FC7F |. C64424 2C 02 |mov byte ptr [esp+2C], 2 ; [esp+2C] = 2
0045FC84 |. 74 4B |je short 0045FCD1 ; //作用:跳过下面循环体
;---------------------------[第二层开始] [对用户名字符进行查表替换]
0045FC86 |> 8A042B |/mov al, byte ptr [ebx+ebp] ; 用户名的第i个字符
0045FC89 |. 33F6 ||xor esi, esi ; ESI置零
;---------[第三层开始] [对第i个字符进行查表替换]
0045FC8B |> 3A0475 207E49>||/cmp al, byte ptr [esi*2+497E20] ; 查表比较
0045FC92 |. 74 08 |||je short 0045FC9C ; //找到后,跳出本循环体
0045FC94 |. 46 |||inc esi ; ESI++
0045FC95 |. 83FE 34 |||cmp esi, 34
0045FC98 |.^ 7C F1 ||\jl short 0045FC8B ; //继续查找密码表中下一个字符
;---------[第三层结束]
0045FC9A |. EB 11 ||jmp short 0045FCAD ; //没找到,跳走
;---------<(I)找到了则跳到这>
0045FC9C |> 8A0C75 217E49>||mov cl, byte ptr [esi*2+497E21] ; 找到密码表中对应的字母
0045FCA3 |. 51 ||push ecx
0045FCA4 |. 8D4C24 38 ||lea ecx, dword ptr [esp+38]
0045FCA8 |. E8 83820000 ||call <jmp.&MFC42.#940>
;---------<(II)没找到则跳到这>
0045FCAD |> 83FE 34 ||cmp esi, 34 ; 和34比较
0045FCB0 |. 75 0E ||jnz short 0045FCC0 ; 若上面没找到,则在此处不跳
;---------<没有找到时进行的操作>
0045FCB2 |. 8B5424 18 ||mov edx, dword ptr [esp+18] ;
0045FCB6 |. 8D4C24 34 ||lea ecx, dword ptr [esp+34] ; 加载序列号地址
0045FCBA |. 52 ||push edx
0045FCBB |. E8 70820000 ||call <jmp.&MFC42.#940> ; 将替换字符和前面所得字符串链接
;---------|
0045FCC0 |> 8BFB ||mov edi, ebx ; EDI = 用户名
0045FCC2 |. 83C9 FF ||or ecx, FFFFFFFF
0045FCC5 |. 33C0 ||xor eax, eax ; EAX置零
0045FCC7 |. 45 ||inc ebp
0045FCC8 |. F2:AE ||repne scas byte ptr es:[edi]
0045FCCA |. F7D1 ||not ecx
0045FCCC |. 49 ||dec ecx ; 用户名长度
0045FCCD |. 3BE9 ||cmp ebp, ecx
0045FCCF |.^ 72 B5 |\jb short 0045FC86 ; //循环length(name)次
;---------------------------[第二层]
;---------<当运算所得字符串长度>=10H时,直接作为序列号>
0045FCD1 |> 8B4424 34 |mov eax, dword ptr [esp+34] ; (ASCII "eWHEyMPP")
0045FCD5 |. 8B48 F8 |mov ecx, dword ptr [eax-8] ; 字符串的长度
0045FCD8 |. 83F9 10 |cmp ecx, 10
0045FCDB |. 7D 3A |jge short 0045FD17 ; //大于等于10跳走
;---------<当运算所得字符串长度<10H时,进行尾部补充>
0045FCDD |. 8BC1 |mov eax, ecx ; EAX = 长度
0045FCDF |. B9 10000000 |mov ecx, 10 ; ECX = 10H
0045FCE4 |. 2BC8 |sub ecx, eax ; ECX = ECX - EAX
0045FCE6 |. 8D5424 1C |lea edx, dword ptr [esp+1C] ; 加载补充字符串地址
0045FCEA |. 51 |push ecx ; 补充字符串长度压栈
0045FCEB |. 52 |push edx
0045FCEC |. B9 C02B4E00 |mov ecx, 004E2BC0
0045FCF1 |. E8 42800000 |call <jmp.&MFC42.#4129> ; 确定补充字符串
0045FCF6 |. 50 |push eax
0045FCF7 |. 8D4C24 38 |lea ecx, dword ptr [esp+38] ; 加载上面运算所得字符串地址
0045FCFB |. C64424 30 03 |mov byte ptr [esp+30], 3
0045FD00 |. E8 25820000 |call <jmp.&MFC42.#939> ; 将两字符川进行链接
0045FD05 |. 8D4C24 1C |lea ecx, dword ptr [esp+1C]
0045FD09 |. C64424 2C 02 |mov byte ptr [esp+2C], 2
0045FD0E |. E8 4D7F0000 |call <jmp.&MFC42.#800>
0045FD13 |. 8B4424 34 |mov eax, dword ptr [esp+34] ; (ASCII "eWHEyMPPLdQsBcmp")
0045FD17 |> 8B4C24 20 |mov ecx, dword ptr [esp+20] ; 假码
0045FD1B |. 51 |push ecx ; /s2 = 真码
0045FD1C |. 50 |push eax ; |s1 = 假码
0045FD1D |. FF15 A45A4700 |call dword ptr [<&MSVCRT._mbscmp>] ; \(msvcrt._mbscmp)字符串比较
0045FD23 |. 83C4 08 |add esp, 8
0045FD26 |. 8D4C24 34 |lea ecx, dword ptr [esp+34]
0045FD2A |. 85C0 |test eax, eax ; 测试标志位
0045FD2C |. C64424 2C 01 |mov byte ptr [esp+2C], 1 ; [esp+2C] = 1
0045FD31 |. 74 1B |je short 0045FD4E ; //跳出循环体
0045FD33 |. 33F6 |xor esi, esi ; ESI置零
0045FD35 |. E8 267F0000 |call <jmp.&MFC42.#800>
0045FD3A |. 8B4424 38 |mov eax, dword ptr [esp+38]
0045FD3E |. 40 |inc eax ; EAX++
0045FD3F |. 83F8 03 |cmp eax, 3
0045FD42 |. 894424 38 |mov dword ptr [esp+38], eax ; [esp+38] = eax
0045FD46 |.^ 0F8C 0EFFFFFF \jl 0045FC5A ; //循环(三次)
;------------------------------------[第一层结束]
;---------<若从这跳则越过ESI=1,进而EAX=ESI=0,注册失败>
0045FD4C |. EB 0A jmp short 0045FD58
0045FD4E |> BE 01000000 mov esi, 1 ; ESI = 1
0045FD53 |. E8 087F0000 call <jmp.&MFC42.#800>
0045FD58 |> 8D4C24 10 lea ecx, dword ptr [esp+10] ; 加载假码地址
0045FD5C |. C64424 2C 00 mov byte ptr [esp+2C], 0
0045FD61 |. E8 FA7E0000 call <jmp.&MFC42.#800>
0045FD66 |. 8D4C24 14 lea ecx, dword ptr [esp+14] ; 加载用户名地址
0045FD6A |. C74424 2C FFF>mov dword ptr [esp+2C], -1
0045FD72 |. E8 E97E0000 call <jmp.&MFC42.#800>
0045FD77 |. 8BC6 mov eax, esi ; EAX = ESI
0045FD79 |. 5F pop edi
0045FD7A |. 5E pop esi
0045FD7B |. 5D pop ebp
0045FD7C |. 5B pop ebx
0045FD7D |. 8B4C24 14 mov ecx, dword ptr [esp+14]
0045FD81 |. 64:890D 00000>mov dword ptr fs:[0], ecx
0045FD88 |. 83C4 20 add esp, 20
0045FD8B |. C3 retn ; //返回(EAX=ESI)
;-------------<跳到下面就算玩完~~~>
0045FD8C |> 8D4C24 10 lea ecx, dword ptr [esp+10] ; 跳转来自 0045FC32, 0045FC41, 0045FC50
0045FD90 |. C64424 2C 00 mov byte ptr [esp+2C], 0
0045FD95 |. E8 C67E0000 call <jmp.&MFC42.#800>
0045FD9A |. 8D4C24 14 lea ecx, dword ptr [esp+14]
0045FD9E |. 897424 2C mov dword ptr [esp+2C], esi
0045FDA2 |. E8 B97E0000 call <jmp.&MFC42.#800>
0045FDA7 |. 8B4C24 24 mov ecx, dword ptr [esp+24]
0045FDAB |. 5F pop edi
0045FDAC |. 5E pop esi
0045FDAD |. 5D pop ebp
0045FDAE |. 33C0 xor eax, eax ; EAX置零
0045FDB0 |. 5B pop ebx
0045FDB1 |. 64:890D 00000>mov dword ptr fs:[0], ecx
0045FDB8 |. 83C4 20 add esp, 20
0045FDBB \. C3 retn ; //返回(EAX=0)
;====================================================================|
在运行到0045FC8B时候,
0045FC62 |. 8A82 887E4900 |mov al, byte ptr [edx+497E88]
0045FC8B |> 3A0475 207E49>||/cmp al, byte ptr [esi*2+497E20]
跟随数据窗口,可以得到一张密码表换算表:
00497E20 61 43 62 78 63 69 64 49 65 41 66 58 67 4D 68 6B aCbxcidIeAfXgMhk
00497E30 69 45 6A 56 6B 5A 6C 65 6D 52 6E 79 6F 42 70 4B iEjVkZlemRnyoBpK
00497E40 71 64 72 54 73 53 74 50 75 57 76 6C 77 6A 78 44 qdrTsStPuWvlwjxD
00497E50 79 48 7A 46 41 7A 42 71 43 70 44 4F 45 6B 46 67 yHzFAzBqCpDOEkFg
00497E60 47 59 48 6D 49 74 4A 61 4B 72 4C 51 4D 6E 4E 73 GYHmItJaKrLQMnNs
00497E70 4F 75 50 55 51 47 52 4A 53 4C 54 4E 55 62 56 63 OuPUQGRJSLTNUbVc
00497E80 57 66 58 68 59 6F 5A 77 50 57 4D 00 25 30 32 64 WfXhYoZwPWM.%02d
00497E90 3A 25 30 32 64 3A 25 30 32 64 00 00 25 73 25 73 :%02d:%02d..%s%s
00497EA0 00 00 00 00 4C 64 51 73 42 63 6D 70 4A 70 61 45 ....LdQsBcmpJpaE
00497EB0 73 58 74 6F 00 00 00 00 25 30 38 6C 58 2D 25 30 sXto....%08lX-%0
换算关系如下:
a -> C b -> q c -> i d -> H e -> S f -> X g -> M
h -> k i -> E j -> V k -> Z l -> e m -> R n -> y
o -> B p -> K q -> d r -> T s -> A t -> F
u -> W v -> l w -> j x -> D y -> I z -> P
A -> z B -> x C -> p D -> O E -> k F -> g G -> Y
H -> m I -> t J -> a K -> r L -> Q M -> n N -> s
O -> u P -> U Q -> G R -> J S -> L T -> N
U -> b V -> c W -> f X -> h Y -> o Z -> w
非大小写类字母统一替换成P或W或M
注意,只能替换成同一个字母,不允许P、W、M交杂
用于补充作用的链接字符串为dQsBcmpJpaEsXto
算法总结:
1.先将用户名的各个字符进行替换
替换规则如下
(1).大小写字母进行查表
(2).非字母则统一替换为P或W或M
2.进行序列号长度校验
若长度小于10H,则用LdQsBcmpJpaEsXto进行补充,直至长度等于10H
若长度>=10H,则直接作为序列号 运算示例:
ID:luying10
SN:eWHEyMPPLdQsBcmp eWHEyMWWLdQsBcmp eWHEyMMMLdQsBcmp
一个有趣的小问题
如果ID是中文的,因为不是英文字符,所以只能用P或W或M统一替换
所以,所有中文用户名对应的序列号只有三个
PPPPPPPPLdQsBcmp WWWWWWWWLdQsBcmp MMMMMMMMLdQsBcmp 好了,分析完注册算法一,借着兴致,一举拿下注册算法二
试练码:
ID:luying10
SN:10000000-02000000-00300000-00040000-00005000-00000600-00000070-00000008
BTW:在地址0045FF2B 处%08lx...提示了我们序列号的格式
sn = s1-s2-s3-s4-s5-s6-s7-s8
;====================================================================|
;在地址0046022C处跟进注册算法(二)CALL->0045FDC0
;====================================================================|
0045FDC0 /$ 6A FF push -1 ; //本地调用来自 0046022C
0045FDC2 |. 68 D9414700 push 004741D9 ; SE 处理程序安装
0045FDC7 |. 64:A1 0000000>mov eax, dword ptr fs:[0]
0045FDCD |. 50 push eax
0045FDCE |. 64:8925 00000>mov dword ptr fs:[0], esp
0045FDD5 |. 81EC 94000000 sub esp, 94
0045FDDB |. 8B8424 A40000>mov eax, dword ptr [esp+A4] ; EAX = [esp+A4] = 用户名
0045FDE2 |. 53 push ebx
0045FDE3 |. 56 push esi
0045FDE4 |. 50 push eax ; 用户名压栈
0045FDE5 |. 8D4C24 10 lea ecx, dword ptr [esp+10]
0045FDE9 |. C74424 60 DF4>mov dword ptr [esp+60], C95841DF
0045FDF1 |. C74424 64 12E>mov dword ptr [esp+64], 717AE412
0045FDF9 |. C74424 68 ACE>mov dword ptr [esp+68], F015E3AC
0045FE01 |. C74424 6C B17>mov dword ptr [esp+6C], 1127EB1
0045FE09 |. C74424 70 895>mov dword ptr [esp+70], 1D455E89
0045FE11 |. C74424 74 51F>mov dword ptr [esp+74], 5375F151
0045FE19 |. C74424 78 6E4>mov dword ptr [esp+78], D34D4B6E
0045FE21 |. C74424 7C 81F>mov dword ptr [esp+7C], 88C5F181
n = 0x88C5F181D34D4B6E5375F1511D455E8901127EB1F015E3AC717AE412C95841DF
0045FE29 |. E8 447E0000 call <jmp.&MFC42.#537>
0045FE2E |. 8B8C24 B00000>mov ecx, dword ptr [esp+B0] ; ECX = [esp+B0] = 序列号
0045FE35 |. C78424 A40000>mov dword ptr [esp+A4], 0
0045FE40 |. 51 push ecx ; 序列号压栈
0045FE41 |. 8D4C24 0C lea ecx, dword ptr [esp+C]
0045FE45 |. E8 287E0000 call <jmp.&MFC42.#537>
0045FE4A |. 8B5424 0C mov edx, dword ptr [esp+C] ; EDX = [esp+0C] = 用户名
0045FE4E |. 8B35 A45A4700 mov esi, dword ptr [<&MSVCRT._mbscmp>; msvcrt._mbscmp
;---------------------------<检测用户名是否为空>---------------------|
0045FE54 |. 68 84014A00 push 004A0184 ; /s2 = ""
0045FE59 |. 52 push edx ; |s1 = "用户名"
0045FE5A |. C68424 AC0000>mov byte ptr [esp+AC], 1 ; |[esp+AC] = 1
0045FE62 |. FFD6 call esi ; \_mbscmp
0045FE64 |. 83C4 08 add esp, 8
0045FE67 |. 85C0 test eax, eax
0045FE69 |. 0F84 0F020000 je 0046007E ; //跳则挂(未实现)
;---------------------------<检测序列号是否为空>---------------------|
0045FE6F |. 8B4424 08 mov eax, dword ptr [esp+8] ; EAX = [esp+8] = 序列号
0045FE73 |. 68 84014A00 push 004A0184
0045FE78 |. 50 push eax ; 序列号压栈
0045FE79 |. FFD6 call esi
0045FE7B |. 83C4 08 add esp, 8
0045FE7E |. 85C0 test eax, eax
0045FE80 |. 0F84 F8010000 je 0046007E ; //跳则挂(未实现)
;--------------------------------------------------------------------|
0045FE86 |. 57 push edi ; 序列号压栈
0045FE87 |. 6A 00 push 0 ;
0045FE89 |. 8D4C24 44 lea ecx, dword ptr [esp+44]
0045FE8D |. E8 EE3D0000 call 00463C80 ;
0045FE92 |. 6A 00 push 0
0045FE94 |. 8D4C24 4C lea ecx, dword ptr [esp+4C]
0045FE98 |. C68424 AC0000>mov byte ptr [esp+AC], 2
0045FEA0 |. E8 DB3D0000 call 00463C80 ;
0045FEA5 |. B3 03 mov bl, 3
0045FEA7 |. 68 01000100 push 10001 ; e = 10001H = 65537D
0045FEAC |. 8D4C24 5C lea ecx, dword ptr [esp+5C]
0045FEB0 |. 889C24 AC0000>mov byte ptr [esp+AC], bl
0045FEB7 |. E8 C43D0000 call 00463C80 ;
0045FEBC |. 8D4C24 58 lea ecx, dword ptr [esp+58]
0045FEC0 |. C68424 A80000>mov byte ptr [esp+A8], 4
0045FEC8 |. 51 push ecx
0045FEC9 |. 8D4C24 4C lea ecx, dword ptr [esp+4C]
0045FECD |. E8 0E3E0000 call 00463CE0
0045FED2 |. 8D4C24 58 lea ecx, dword ptr [esp+58]
0045FED6 |. 889C24 A80000>mov byte ptr [esp+A8], bl
0045FEDD |. E8 4E3E0000 call 00463D30
0045FEE2 |. 8D5424 60 lea edx, dword ptr [esp+60]
0045FEE6 |. 6A 08 push 8
0045FEE8 |. 52 push edx
0045FEE9 |. 8D4C24 48 lea ecx, dword ptr [esp+48]
0045FEED |. E8 5E3C0000 call 00463B50
0045FEF2 |. B9 08000000 mov ecx, 8
0045FEF7 |. 33C0 xor eax, eax ; EAX置零
0045FEF9 |. 8D7C24 18 lea edi, dword ptr [esp+18]
0045FEFD |. 8D5424 2C lea edx, dword ptr [esp+2C]
0045FF01 |. F3:AB rep stos dword ptr es:[edi]
0045FF03 |. 8D4424 34 lea eax, dword ptr [esp+34]
0045FF07 |. 8D4C24 30 lea ecx, dword ptr [esp+30]
0045FF0B |. 50 push eax
0045FF0C |. 51 push ecx
0045FF0D |. 8D4424 30 lea eax, dword ptr [esp+30]
0045FF11 |. 52 push edx
0045FF12 |. 8D4C24 30 lea ecx, dword ptr [esp+30]
0045FF16 |. 50 push eax
0045FF17 |. 8D5424 30 lea edx, dword ptr [esp+30]
0045FF1B |. 51 push ecx
0045FF1C |. 8D4424 30 lea eax, dword ptr [esp+30]
0045FF20 |. 52 push edx
0045FF21 |. 8B5424 24 mov edx, dword ptr [esp+24] ; EDX = [esp+24] = 序列号
0045FF25 |. 8D4C24 30 lea ecx, dword ptr [esp+30]
;---------------------------<对假序列号进行变形运算>-----------------|
0045FF29 |. 50 push eax
0045FF2A |. 51 push ecx
0045FF2B |. 68 B87E4900 push 00497EB8 ; |%08lx-%08lx-%08lx-%08lx-%08lx-%08lx-%08lx-%08lx\n
0045FF30 |. 52 push edx ; |s
0045FF31 |. FF15 405A4700 call dword ptr [<&MSVCRT.sscanf>] ; \sscanf
0045FF37 |. 8B4424 50 mov eax, dword ptr [esp+50] ; s5 = 00005000
0045FF3B |. 8B4C24 4C mov ecx, dword ptr [esp+4C] ; s4 = 00040000
0045FF3F |. 8B7C24 48 mov edi, dword ptr [esp+48] ; s3 = 00300000
0045FF43 |. 8B5424 44 mov edx, dword ptr [esp+44] ; s2 = 02000000
0045FF47 |. 03C1 add eax, ecx ; s5 = s5 + s4 = 00045000
0045FF49 |. 8B4C24 5C mov ecx, dword ptr [esp+5C] ; s8 = 00000008
0045FF4D |. 03C7 add eax, edi ; s5 = s5 + s3 = 00345000
0045FF4F |. 8B7C24 58 mov edi, dword ptr [esp+58] ; s7 = 00000070
0045FF53 |. 03C2 add eax, edx ; s5 = s5 + s2 = 02345000
0045FF55 |. 8B5424 40 mov edx, dword ptr [esp+40] ; s1 = 10000000 (CDRIP.#299)
0045FF59 |. 33C8 xor ecx, eax ; s8 = s8 | s5 = 02345008
0045FF5B |. 8B4424 54 mov eax, dword ptr [esp+54] ; s6 = 00000600
0045FF5F |. 83C4 28 add esp, 28
0045FF62 |. 03C2 add eax, edx ; s6 = s6 + s1 = 10000600
0045FF64 |. 894C24 34 mov dword ptr [esp+34], ecx ; ecx=02345008
0045FF68 |. 33F8 xor edi, eax ; s7 = s7 | s6 = 10000670
;--------------------------------------------------------------------|
0045FF6A |. 6A 00 push 0
0045FF6C |. 8D4C24 3C lea ecx, dword ptr [esp+3C]
0045FF70 |. 897C24 34 mov dword ptr [esp+34], edi ; [esp+34] = edi = 10000670 (CDRIP.10000670)
0045FF74 |. E8 073D0000 call 00463C80
0045FF79 |. 8D4C24 18 lea ecx, dword ptr [esp+18]
0045FF7D |. 6A 08 push 8
0045FF7F |. 51 push ecx ; sn变形后的SerNum
0045FF80 |. 8D4C24 40 lea ecx, dword ptr [esp+40]
0045FF84 |. C68424 B00000>mov byte ptr [esp+B0], 5
0045FF8C |. E8 BF3B0000 call 00463B50 ; rsa_de(),计算 c = SerNum^e mod n
0045FF91 |. 8D5424 38 lea edx, dword ptr [esp+38]
0045FF95 |. 8D4424 50 lea eax, dword ptr [esp+50]
0045FF99 |. 52 push edx
0045FF9A |. 50 push eax
0045FF9B |. 8D4C24 48 lea ecx, dword ptr [esp+48]
0045FF9F |. E8 0CC5FFFF call 0045C4B0 ; 结果以大数输出 c
0045FFA4 |. B9 08000000 mov ecx, 8
0045FFA9 |. 33C0 xor eax, eax
0045FFAB |. 8D7C24 18 lea edi, dword ptr [esp+18]
0045FFAF |. 6A 08 push 8
0045FFB1 |. F3:AB rep stos dword ptr es:[edi]
0045FFB3 |. 8D4C24 1C lea ecx, dword ptr [esp+1C]
0045FFB7 |. C68424 AC0000>mov byte ptr [esp+AC], 6
0045FFBF |. 51 push ecx
0045FFC0 |. 8D4C24 58 lea ecx, dword ptr [esp+58]
0045FFC4 |. E8 C73B0000 call 00463B90 ; 大数结果转为十六进制字节串
0045FFC9 |. B9 08000000 mov ecx, 8
0045FFCE |. 33C0 xor eax, eax ; EAX置零
0045FFD0 |. 8DBC24 800000>lea edi, dword ptr [esp+80]
0045FFD7 |. F3:AB rep stos dword ptr es:[edi] ;
0045FFD9 |. 5F pop edi ; 序列号
;-------------<交换每一个dword的高位,低位>
0045FFDA |> 8A5404 17 /mov dl, byte ptr [esp+eax+17]
0045FFDE |. 8A4C04 16 |mov cl, byte ptr [esp+eax+16]
0045FFE2 |. 885404 7C |mov byte ptr [esp+eax+7C], dl
0045FFE6 |. 8B5404 14 |mov edx, dword ptr [esp+eax+14]
0045FFEA |. 884C04 7D |mov byte ptr [esp+eax+7D], cl
0045FFEE |. 8A4C04 14 |mov cl, byte ptr [esp+eax+14]
0045FFF2 |. C1EA 08 |shr edx, 8
0045FFF5 |. 885404 7E |mov byte ptr [esp+eax+7E], dl
0045FFF9 |. 884C04 7F |mov byte ptr [esp+eax+7F], cl
0045FFFD |. 83C0 04 |add eax, 4 ; EAX = EAX + 4
00460000 |. 83F8 20 |cmp eax, 20
00460003 |.^ 7C D5 \jl short 0045FFDA ; //循环(8次)
循环前:
0012EEF4 C4 3A 70 C1 5B DE 26 77 90 A1 42 3B E5 D8 0E 8A ?p羀?w悺B;遑
0012EF04 40 B3 B2 FE 55 96 4A 1B EC B3 E0 78 D2 AE 42 6A @巢