160 个 CrackMe 之 009 Andrénalin.2 (VB5 Native)的算法代码详解和注册机实现
本帖最后由 solly 于 2019-7-19 11:13 编辑160 个 CrackMe 之 009 Andrénalin.2 (VB5 Native)的注册算法很简单,但是 VB5 编译出来的原生汇编代码非常难看,差不多就对 p-code 代码的翻译,任何变量都要复制一下才可使用,相当于原有p-code模式中在msvbvm50.dll 与应用之间的变量复制一样,看起来一大堆的代码,却完成不了多少功能。
这个 CrackMe 在本论坛也有多个分析了,我这里分析主要不是算法,而是针对VB Native 代码和变量存贮进行详细説明。
首先,我们要确定注册验证的代码位置。
OD 载入 CrackMe 后,如下图,一看就是 VB5 程序:
直接 F9 运行,输入相关信息,点击"OK" 进行验证,如下所示,会报验证失败的提示:
是通过 MsgBox 调用来显示提示的。我们先查一下字符串资源,VB5 及以后版本的字符串,都是 Unicode 格式,所以需要查找 Unicode 字符串:
果然,最后一条就是要找的字符串。双击这一条字符串,跳转到引用该字符串的代码位置,如下图所示:
可以看到最上面有一个 JMP 00402446,就是跳过这段代码的,如下图所示:
我们选中紧接 JMP 00402446 的下一行指令,就看到有一个“红色”箭头指向这一行指令,表示有跳转指令会跳转到这里,所以,我们转到这条指令,如下图所示,回溯到该跳转:
可见是从0x004022CB 过来的,选择上面的菜单,就可转到这一条指令的位置:
可以看出,是针对函数 __vbaVarTstEq() 的返回结果进行检查,这里就是字符串变量比较的地方了,如下图所示:
我们一直往上回溯,找到代码所在函数的起点,如下所示,就是这段代码起点:
这就是注册码验证的函数了。因此,我们找到验证注册码的地方了。
我们在 0x00402009 这一行下断点,如上图所示。然后回到 CrackMe 界面,再次按“OK”,进行算法代码跟踪,分析其算法,下面是对这一段代码的详细分析,并有内存存贮格式説明。
VB 中,如果变量没有定义具体类型,则都是 variable 变量。这种变量占用 16 字节内存空间。前2字节是类型,指明变量当前存贮的值的类型,从第9字节开始的字节是存贮的数据。主要是这两个位置是有效的。我在代码注释中用括号进行定位,如下所示:
0x0019F18C(08 00) 00 00 00 00 00 00 (E4 64 78 00) 0E 00 00 00),0x007864E4 ===> 用户名字符串
最前面的(08 00),即 0x0008,表示存贮是字符串,实际是存贮的字符串地址 (E4 64 78 00),即 0x007864E4,表示在 0x007864E4 保存的才是实际字符串的内容。
还有如下格式的:
0x0019F164(03 00) 00 00 00 00 00 00 (05 00 00 00) 0E 00 00 00
最前的(03 00),即 0x0003,表示存贮的是 32 位整数(Long),这时候存贮的是实际的值,不是地址了,如上,存贮内容为(05 00 00 00),代表32位整数 0x00000005。
如果类型是 0x0002,表示存贮的是 16 位整(Integer),如下,存贮的是 0x0073。
0x0019F144(02 00) 00 00 A6 EE D9 00 (73 00) 00 00 00 00 00 00
如果类型是 0x0005,表示存贮的是 64 浮点数(Double),格式如下:
0x0019F19C(05 00) 00 00 00 00 00 00 (00 C0 7A 06 9D 3A 64 42)
最后面8个字节都是存贮的数据了。
上面对内存数据格式説明了,下面是具体代码的分析:
00401FF0 55 push ebp
00401FF1 8BEC mov ebp, esp
00401FF3 83EC 0C sub esp, 0C
00401FF6 68 26104000 push <jmp.&MSVBVM50.__vbaExceptHandler>
00401FFB 64:A1 00000000 mov eax, dword ptr fs:
00402001 50 push eax
00402002 64:8925 00000000 mov dword ptr fs:, esp ; SEH
00402009 81EC 18010000 sub esp, 118
0040200F 53 push ebx
00402010 8B5D 08 mov ebx, dword ptr ; 函数参数,FORM 对象
00402013 8BC3 mov eax, ebx
00402015 56 push esi
00402016 83E3 FE and ebx, FFFFFFFE
00402019 57 push edi
0040201A 8965 F4 mov dword ptr , esp
0040201D 83E0 01 and eax, 1
00402020 8B3B mov edi, dword ptr
00402022 C745 F8 00104000 mov dword ptr , 00401000 ; hInstance
00402029 53 push ebx
0040202A 8945 FC mov dword ptr , eax ; 返回值
0040202D 895D 08 mov dword ptr , ebx
00402030 FF57 04 call dword ptr ; call (MSVBVM50.BASIC_CLASS_AddRef), 引用控件
;
; 变量初始化
;
00402033 33F6 xor esi, esi ; 0
00402035 53 push ebx ; 下面的call参数
00402036 8975 DC mov dword ptr , esi ; 初始化局部变量为空变量(循环变量),即 Variable 变量的类型为0,变量的长度为 0x10 字节
00402039 8975 CC mov dword ptr , esi ; 初始化 variable 变量,应该保存用户名字符的累加值的变量
0040203C 8975 BC mov dword ptr , esi ; 初始化 variable 变量,保存用户名
0040203F 8975 AC mov dword ptr , esi ; 初始化 variable 变量,rtcMsgBox 的返回值
00402042 8975 A8 mov dword ptr , esi ; 初始化 Long 类型变量,首先保存地址,在循环中保存用户名字符的 ASCII 值
00402045 8975 A4 mov dword ptr , esi ; 初始化 Long 类型变量,保存Form或控件对象
00402048 8975 94 mov dword ptr , esi ; 初始化 variable 变量,多用途,中间保存过用户名的长度
0040204B 8975 84 mov dword ptr , esi ; 初始化 variable 变量,Mid() 调用返回结果字符
0040204E 89B5 74FFFFFF mov dword ptr , esi ; 初始化 variable 变量,保存 用户名 中所有字符的 ASCII 值加法时的临时值
00402054 89B5 64FFFFFF mov dword ptr , esi ; 初始化 variable 变量,保存 VT_ERROR
0040205A 89B5 54FFFFFF mov dword ptr , esi ; 初始化 variable 变量,循环 step
00402060 89B5 44FFFFFF mov dword ptr , esi ; 初始化 variable 变量,循环开始值,MsgBox 标题字符串
00402066 89B5 14FFFFFF mov dword ptr , esi ; 初始化 variable 变量,保存 rtcMsgBox 的返回值(临时)
0040206C 89B5 F8FEFFFF mov dword ptr , esi ; 初始化 variable 变量,临时变量
00402072 89B5 E8FEFFFF mov dword ptr , esi ; 初始化 variable 变量,临时变量
;
; 取用户名数据
;
00402078 FF97 FC020000 call dword ptr ; 取得输入用户名的控件信息
0040207E 8D4D A4 lea ecx, dword ptr
00402081 50 push eax ; 控件对象
00402082 51 push ecx
00402083 FF15 24414000 call dword ptr [<&MSVBVM50.__vbaObjSet>] ; MSVBVM50.__vbaObjSet
00402089 8BD8 mov ebx, eax ; eax ==>控件对象, == eax,保存控件对象
0040208B 8D45 A8 lea eax, dword ptr ; 缓冲区,用来保存字符串的地址
0040208E 50 push eax
0040208F 53 push ebx
00402090 8B13 mov edx, dword ptr ; 控件对象
00402092 FF92 A0000000 call dword ptr ; call EditBox.GetText()
00402098 3BC6 cmp eax, esi ; == 0x007864E4 ===> "solly",取得用户名
0040209A 7D 12 jge short 004020AE ; 成功则跳转,eax == 0 表示成功
0040209C 68 A0000000 push 0A0
004020A1 68 201C4000 push 00401C20 ; 资源地址
004020A6 53 push ebx
004020A7 50 push eax
004020A8 FF15 14414000 call dword ptr [<&MSVBVM50.__vbaHresultCheckObj>] ; 对上面的调用结果(eax的值)进行检查,eax != 0 时才检查,就是调用失败才检查
;
; username = TextBox.Text
;
; 保存用户名
;
004020AE 8B45 A8 mov eax, dword ptr ; 取得字符串的地址,eax==> "solly", eax == 0x007864E4
004020B1 8975 A8 mov dword ptr , esi ; 将地址保存回去,这个编译器编译没有优化好的原因
004020B4 8B35 FC404000 mov esi, dword ptr [<&MSVBVM50.__vbaVarMove>] ; esi 设为函数(MSVBVM50.__vbaVarMove)的入口,VB字符串复制函数
004020BA 8D55 94 lea edx, dword ptr ; edx ===> 指向 variable 变量(0x0019F164),用来保存用户名的来源变量
004020BD 8D4D BC lea ecx, dword ptr ; edx ===> 指向 variable 变量,保存用户名的目标变量
004020C0 8945 9C mov dword ptr , eax ; 将用户名地址存入 variable 变量 , 即 0x0019F164 处
004020C3 C745 94 08000000 mov dword ptr , 8 ; 将 variable 变量的类型设为 8, 表示保存的是字符串: 0x0019F164(08 00) 00 00 00 00 00 00 (E4 64 78 00) 0E 00 00 00
004020CA FFD6 call esi ; call (MSVBVM50.__vbaVarMove) 复制用户名字符串至,复制后:0x0019F18C(08 00) 00 00 00 00 00 00 (E4 64 78 00) 0E 00 00 00
004020CC 8D4D A4 lea ecx, dword ptr ; ecx ===> 控件对象
004020CF FF15 B4414000 call dword ptr [<&MSVBVM50.__vbaFreeObj>] ; call (MSVBVM50.__vbaFreeObj),释放对象的引用
;
; 取用户名长度,并初始化循环操作的各个变量
;
004020D5 B8 01000000 mov eax, 1
004020DA 8D8D 54FFFFFF lea ecx, dword ptr ; ecx ===> variable 变量
004020E0 8985 5CFFFFFF mov dword ptr , eax ; 变量值 == 1
004020E6 8985 4CFFFFFF mov dword ptr , eax ; 变量值 == 1
004020EC 8D55 BC lea edx, dword ptr ; edx ===> 局部 variable 变量,现在保存的用户名
004020EF 51 push ecx ; ecx(0x0019F124)入栈,值为1,下面的循环的 step 参数
004020F0 8D45 94 lea eax, dword ptr ; eax ===> 空的 variable 变量:(前面call varMove()后就释放了)
004020F3 BB 02000000 mov ebx, 2 ; 变量类型2,VT_INT,16位整数,给后面初始化 variable 变量用的
004020F8 52 push edx ; edx ====> 用户名,参数
004020F9 50 push eax ; eax ===> 空变量,用来保存用户名长度,参数
004020FA 899D 54FFFFFF mov dword ptr , ebx ; 变量值类型 == 2,16位整数,值为1,保存在 0x0019F124(02 00) 00 00 01 00 00 00 (01 00) 00 00 A6 EE D9 00
00402100 899D 44FFFFFF mov dword ptr , ebx ; 变量值类型 == 2,16位整数,值为1,保存在 0x0019F114(02 00) 00 00 A6 EE D9 00 (01 00) 00 00 00 00 00 00
00402106 FF15 18414000 call dword ptr [<&MSVBVM50.__vbaLenVar>] ; call (MSVBVM50.__vbaLenVar),取用户名的长度, 结果 eax===> 0x0019F164(03 00) 00 00 00 00 00 00 (05 00 00 00) 0E 00 00 00,类型为 3,表示32位整数值:0x00000005,用户名的长度
;
; n = len(username)
; 取得用户名长度
;
; 下面继续初始化循环变量,准备循环计算用户名字符累加和
;
0040210C 8D8D 44FFFFFF lea ecx, dword ptr ; ecx ===> 前面初始化的 variable,值为 1
00402112 50 push eax ; eax === 保存用户名长度的 variable 变量,作为循环变量的结束值入栈:0x0019F164(03 00) 00 00 00 00 00 00 (05 00 00 00) 0E 00 00 00
00402113 8D95 E8FEFFFF lea edx, dword ptr ; edx ===> 空 variable 变量
00402119 51 push ecx ; ecx (0x0019F114) 入栈,循环开始值入栈
0040211A 8D85 F8FEFFFF lea eax, dword ptr ; eax ===> 空 variable 变量
00402120 52 push edx ; edx (0x0019F0B8) 入栈,作为循环函数临时变量
00402121 8D4D DC lea ecx, dword ptr ; ecx (0x0019F1AC) 指向另一个空的 variable 变量,循环计数变量
00402124 50 push eax ; eax (0x0019F0C8) 入栈,循环函数临时变量
00402125 51 push ecx ; ecx (0x0019F1AC) 入栈,这个是循环变量
00402126 FF15 20414000 call dword ptr [<&MSVBVM50.__vbaVarForInit>] ; call (MSVBVM50.__vbaVarForInit),开始循环, For i=1 to 5 step 1'读取用户名的每个字符
0040212C 8B3D 04414000 mov edi, dword ptr [<&MSVBVM50.__vbaFreeVarList>] ; edi == ds:=0F10182B (MSVBVM50.__vbaFreeVarList),函数指针
00402132 85C0 test eax, eax ; eax == 1,调用成功,开始循环
00402134 0F84 9C000000 je 004021D6 ; 如果 eax == 0,则生成循环失败,直接跳过此循环
;
; for i=1 to n step 1
;
; 循环体开始,开始计算用户名字符的累加和
;
0040213A 8D55 94 lea edx, dword ptr ; edx ===> 目前为户名长度 variable 变量:0x0019F164(03 00) 00 00 00 00 00 00 (05 00 00 00) 0E 00 00 00
0040213D 8D45 DC lea eax, dword ptr ; eax == 循环变量i=1, 指向 variable 变量:0x0019F1AC(03 00) 79 E3 38 AA 6C 02 (01 00 00 00) 00 00 00 00
00402140 52 push edx ; Mid()函数参数,length参数,后面会改成 1
00402141 50 push eax ; 下面转换函数(__vbaI4Var)的参数
00402142 C745 9C 01000000 mov dword ptr , 1 ; 重新设置 variable 变量的数值为 0x00000001,即mid()的length参数为1
00402149 895D 94 mov dword ptr , ebx ; 重新设置 variable 变量的类型为 2, 16 位整数:0x0019F164(02 00) 00 00 00 00 00 00 (01 00) 00 00 0E 00 00 00
0040214C FF15 90414000 call dword ptr [<&MSVBVM50.__vbaI4Var>] ; call (MSVBVM50.__vbaI4Var) 类型转换,Variable to Long,返回值 eax == 1,(0x0019F1AC的值)
00402152 8D4D BC lea ecx, dword ptr ; ecx ==> 保存用户名的 variable 变量 (0x0019F18C(08 00) 00 00 00 00 00 00 (E4 64 78 00) 0E 00 00 00),0x007864E4 ===> 用户名字符串
00402155 50 push eax ; 循环变量i的值,Mid()函数start参数,根据循环变量的值 变化
00402156 8D55 84 lea edx, dword ptr ; 保存结果的缓冲区
00402159 51 push ecx ; ecx(0x0019F18C) ===> 用户名,mid()函数的 string 参数
0040215A 52 push edx ; edx(0x0019F154)用于 Mid() 函数返回结果字符的缓冲区
0040215B FF15 38414000 call dword ptr [<&MSVBVM50.#632>] ; MSVBVM50.rtcMidCharVar
;
;ch = Mid(username, i, 1)'从用户名中依次取字符
;
00402161 8D45 84 lea eax, dword ptr ; eax ===> Mid()函数返回结果字符串:0x0019F154(08 00) 19 00 11 00 00 00 (44 3F 7C 00) 2C 21 40 00,字符地址为:0x007C3F44: "s",即用户名中的字符
00402164 8D4D A8 lea ecx, dword ptr ; ecx == 0x0019F178,用于保存 Val() 函数的结果
00402167 50 push eax ; 转换函数__vbaStringVarVal()参数
00402168 51 push ecx ; 转换函数__vbaStringVarVal()参数
00402169 FF15 70414000 call dword ptr [<&MSVBVM50.__vbaStrVarVal>] ; call (MSVBVM50.__vbaStrVarVal), 将 variable 变量转换成 String 变量eax(0x007C3F44), eax ===>"s"
0040216F 50 push eax ; 下面 asc() 函数的 string 参数,入栈
00402170 FF15 0C414000 call dword ptr [<&MSVBVM50.#516>] ; call (MSVBVM50.rtcAnsiValueBstr),将字符转换成 ASCII 码值,eax == asc("s")
;
;ch_val = Asc(ch) '取ASCII码值
;
00402176 66:8985 4CFFFFFF mov word ptr , ax ; 保存 ASCII 值到 variable 变量 中 (0x0019F114)
0040217D 8D55 CC lea edx, dword ptr ; 参数2,edx ==> 空的 variable 变量,相当于0
00402180 8D85 44FFFFFF lea eax, dword ptr ; 参数1, 保存前面取得 ASCII 值:0x0019F114(02 00) 00 00 A6 EE D9 00 (73 00) 00 00 00 00 00 00, 就是 0x73
00402186 52 push edx ; edx == 0x0019F19C
00402187 8D8D 74FFFFFF lea ecx, dword ptr ; ecx ==> 空的 variable 变量
0040218D 50 push eax ; 参数1
0040218E 51 push ecx ; 结果
0040218F 899D 44FFFFFF mov dword ptr , ebx ; 将variable 变量的类型设置为2, 16位integer
00402195 FF15 94414000 call dword ptr [<&MSVBVM50.__vbaVarAdd>] ; call (MSVBVM50.__vbaVarAdd),加法
;
; sum = sum + ch_val '累加
;
0040219B 8BD0 mov edx, eax ; eax == 0x0019F144 ==> 结果 0x0019F144(02 00) 00 00 A6 EE D9 00 (73 00) 00 00 00 00 00 00
0040219D 8D4D CC lea ecx, dword ptr ; ecx ===> 空的 variable 变量,前面加法用过,应该保存累加值的变量
004021A0 FFD6 call esi ; call (MSVBVM50.__vbaVarMove), ==> 0019F19C(02 00) 00 00 A6 EE D9 00 (73 00) 00 00 00 00 00 00,累加和
004021A2 8D4D A8 lea ecx, dword ptr ; ecx ===> String 变量(0019F178),前面的转换结果字符串
004021A5 FF15 B8414000 call dword ptr [<&MSVBVM50.__vbaFreeStr>] ; call (MSVBVM50.__vbaFreeStr),释放一个字符串变量(edx)
004021AB 8D55 84 lea edx, dword ptr
004021AE 8D45 94 lea eax, dword ptr
004021B1 52 push edx ; edx ===> 需要释放的变量,variable 字符串"s"
004021B2 50 push eax ; eax ===> 需要释放的变量, variable 整数1
004021B3 53 push ebx ; ebx == 2,表示释放2个变量
004021B4 FFD7 call edi ; call (MSVBVM50.__vbaFreeVarList) 释放多个变量, push ebx 表示释放2个变量,eax, edx 为 variable 变量地址
004021B6 83C4 0C add esp, 0C ; 平衡 esp
;
; 循环体结束
;
004021B9 8D8D E8FEFFFF lea ecx, dword ptr ; tmp_end,循环结束值: 0x0019F0B8(03 00) 79 E3 38 AA 6C 02 (05 00 00 00) 00 00 00 00),值为 5
004021BF 8D95 F8FEFFFF lea edx, dword ptr ; tmp_step,循环步进值:0x0019F0C8(03 00) 79 E3 38 AA 6C 02 (01 00 00 00) 00 00 00 00,step == 1
004021C5 8D45 DC lea eax, dword ptr ; 循环变量 i
004021C8 51 push ecx
004021C9 52 push edx
004021CA 50 push eax
004021CB FF15 AC414000 call dword ptr [<&MSVBVM50.__vbaVarForNext>] ; call (MSVBVM50.__vbaVarForNext),循环结束, Next i
004021D1^ E9 5CFFFFFF jmp 00402132 ; Next i
;
; Next i
;
004021D6 8D4D CC lea ecx, dword ptr ; ecx == 0019F19C 累加和:0x0019F19C(02 00) 00 00 A6 EE D9 00 (33 02) 00 00 00 00 00 00,累加和为 0x0233, 即 563
004021D9 8D95 54FFFFFF lea edx, dword ptr ; edx ===> variable 变量(0x0019F124),用于保存常量,后面赋值
004021DF 51 push ecx ; Mul() 参数2,累加和入栈
004021E0 8D45 94 lea eax, dword ptr ; 结果缓冲区
004021E3 52 push edx ; Mul() 参数1
004021E4 50 push eax ; 结果
004021E5 C785 5CFFFFFF D20296>mov dword ptr , 499602D2 ; 初始化的数据,常量 0x499602D2,即 1234567890
004021EF C785 54FFFFFF 030000>mov dword ptr , 3 ; 初始化 variable 变量的类型为3,Long类型
004021F9 FF15 5C414000 call dword ptr [<&MSVBVM50.__vbaVarMul>] ; call (MSVBVM50.__vbaVarMul),乘法函数,累加和*1234567890
;
; s = sum * 1234567890 ' 这里s还是类型为5的浮点数,保存的是64位(8字节)的浮点数值
;
004021FF 8BD0 mov edx, eax ; edx == 0x0019F164 ===> variable 变量,保存乘法结果:0x0019F164(05 00) 00 00 00 00 00 00 (00 C0 7A 06 9D 3A 64 42),类型5,VT_R8,为64位浮点数
00402201 8D4D CC lea ecx, dword ptr ; ecx == 0x0019F19C ===> 目标缓冲区
00402204 FFD6 call esi ; call (MSVBVM50.__vbaVarMove),复制计算结果, eax == 0x0019F19C ==> 0x0019F19C(05 00) 00 00 00 00 00 (00 00 C0 7A 06 9D 3A 64 42)
00402206 8B1D A0414000 mov ebx, dword ptr [<&MSVBVM50.__vbaMidStmtVar>] ; ebx == (MSVBVM50.__vbaMidStmtVar),函数入口
0040220C 8D4D CC lea ecx, dword ptr ; variable 数据,参数
0040220F 51 push ecx ; 操作数
00402210 6A 04 push 4 ; 位置参数,第4个位置
00402212 8D95 54FFFFFF lea edx, dword ptr ; 用于替换的字符
00402218 6A 01 push 1 ; 长度
0040221A 52 push edx
0040221B C785 5CFFFFFF 341C40>mov dword ptr , 00401C34 ; 常量字符,减号 “-”
00402225 C785 54FFFFFF 080000>mov dword ptr , 8 ; 设置 variable 变量类型为8,字符串,保存的是“-”,0019F124(08 00) 00 00 01 00 00 00 (34 1C 40 00) A6 EE D9 00,00401C34 ===> "-"
0040222F FFD3 call ebx ; call (MSVBVM50.__vbaMidStmtVar)
;
; Mid(s, 4, 1) = "-"'替换字符,这个函数调用将s的类型改成了8,变量了字符串了,保存的字符串地址。
;
00402231 8D45 CC lea eax, dword ptr ; eax == 0x0019F19C 返回结果为字符串:0x0019F19C(08 00) 00 00 A0 EE D9 00 (44 3F 7C 00) 02 00 00 00,0x007C3F44 ===> "6.9.5.-.6.1.7.2.2.0.7.0.",点号是表unicode字符串,需要去掉的
00402234 8D8D 54FFFFFF lea ecx, dword ptr ; 用于替换的字符
0040223A 50 push eax ; 前面的返回结果再次当作参数
0040223B 6A 09 push 9 ; 位置参数,第9个位置
0040223D 6A 01 push 1 ; 长度
0040223F 51 push ecx ; 用于替换的字符
00402240 C785 5CFFFFFF 341C40>mov dword ptr , 00401C34 ; 常量字符,减号 “-”
0040224A C785 54FFFFFF 080000>mov dword ptr , 8 ; 设置类型为8,作用同前一次__vbaMidStmtVar调用
00402254 FFD3 call ebx ; call (MSVBVM50.__vbaMidStmtVar),返回结果为字符串:0x0019F19C(08 00) 00 00 A0 EE D9 00 (44 3F 7C 00) 02 00 00 00,0x007C3F44 ===> "6.9.5.-.6.1.7.2.-.0.7.0.",点号是表unicode字符串,需要去掉的
;
; Mid(s, 9, 1) = "-"'替换字符
;
00402256 8B45 08 mov eax, dword ptr ; 传入的参数,表单或控件对象
00402259 50 push eax
0040225A 8B10 mov edx, dword ptr ;
0040225C FF92 04030000 call dword ptr ; 取输入序列号的TextBox控件
00402262 50 push eax ; 控件对象
00402263 8D45 A4 lea eax, dword ptr ; 保存对象地址
00402266 50 push eax
00402267 FF15 24414000 call dword ptr [<&MSVBVM50.__vbaObjSet>] ; MSVBVM50.__vbaObjSet
0040226D 8BD8 mov ebx, eax ; eax ===> 对象地址
0040226F 8D55 A8 lea edx, dword ptr ; 用于保存输入的序列号的地址, [] ===> 输入的序列号
00402272 52 push edx
00402273 53 push ebx
00402274 8B0B mov ecx, dword ptr
00402276 FF91 A0000000 call dword ptr ; 取得界面输入的序列号
0040227C 85C0 test eax, eax ; eax == 0,操作成功
0040227E 7D 12 jge short 00402292
00402280 68 A0000000 push 0A0
00402285 68 201C4000 push 00401C20
0040228A 53 push ebx
0040228B 50 push eax
0040228C FF15 14414000 call dword ptr [<&MSVBVM50.__vbaHresultCheckObj>] ; MSVBVM50.__vbaHresultCheckObj
;
; 取输入的序列号
; sn = TextBox.Text
;
00402292 8B45 A8 mov eax, dword ptr ; 取得输入的序列号成功来到这里,eax ===> "78787878",输入的假码
00402295 8D4D CC lea ecx, dword ptr ; ecx == 0x0019F19C(08 00) 00 00 A0 EE D9 00 (44 3F 7C 00) 02 00 00 00), 0x007C3F44 ===>"695-6172-070",真正的序列号
00402298 8945 9C mov dword ptr , eax ; 地址存入 variable 变量中。
0040229B 8D45 94 lea eax, dword ptr ; eax == 0x0019F164 ===> 保存输入的序列号的 variable 变量
0040229E 50 push eax
0040229F 51 push ecx
004022A0 C745 A8 00000000 mov dword ptr , 0 ; 原 string 变量清0
004022A7 C745 94 08800000 mov dword ptr , 8008 ; 修改 variable 变量的类型为保留的字符串,0x0019F164(08 80) 00 00 00 00 00 00 (2C 51 71 00) 9D 3A 64 42,0x0071512C ===> ""78787878""
004022AE FF15 48414000 call dword ptr [<&MSVBVM50.__vbaVarTstEq>] ; call (MSVBVM50.__vbaVarTstEq),测试两个字符串是否相等,eax==0 表示不相等,为false
004022B4 8D4D A4 lea ecx, dword ptr ; ecx ===> 控件对象
004022B7 8BD8 mov ebx, eax ; 保存字符串比对结果到 ebx
004022B9 FF15 B4414000 call dword ptr [<&MSVBVM50.__vbaFreeObj>] ; call (MSVBVM50.__vbaFreeObj),释放对象()
004022BF 8D4D 94 lea ecx, dword ptr
004022C2 FF15 00414000 call dword ptr [<&MSVBVM50.__vbaFreeVar>] ; call (MSVBVM50.__vbaFreeVar),释放变量ecx
004022C8 66:85DB test bx, bx ; 检查字符串检查结果
004022CB 0F84 C0000000 je 00402391 ; 不相等则跳转
;
; 比较
; if (s = sn) then
;
; 相等执行以下代码
004022D1 FF15 74414000 call dword ptr [<&MSVBVM50.#534>] ; call (MSVBVM50.rtcBeep),发出beep声
004022D7 8B1D 98414000 mov ebx, dword ptr [<&MSVBVM50.__vbaVarDup>] ; MSVBVM50.__vbaVarDup
004022DD B9 04000280 mov ecx, 80020004 ; 错误码: 0x80020004
004022E2 898D 6CFFFFFF mov dword ptr , ecx
004022E8 B8 0A000000 mov eax, 0A ; 变量类型0x0A,VT_ERROR
004022ED 898D 7CFFFFFF mov dword ptr , ecx
004022F3 8D95 44FFFFFF lea edx, dword ptr ; vbaVarDup参数,源串(临时,常量)
004022F9 8D4D 84 lea ecx, dword ptr ; vbaVarDup参数,目的串
004022FC 8985 64FFFFFF mov dword ptr , eax ; 变量类型0x0A,VT_ERROR, 错误码: 0x80020004(ecx)
00402302 8985 74FFFFFF mov dword ptr , eax ; 变量类型0x0A,VT_ERROR, 错误码: 0x80020004(ecx)
00402308 C785 4CFFFFFF A81C40>mov dword ptr , 00401CA8 ; richtig !
00402312 C785 44FFFFFF 080000>mov dword ptr , 8 ; 类型为8,字符串,指向上面的字符串“richtig !”
0040231C FFD3 call ebx ; MSVBVM50.__vbaVarDup
0040231E 8D95 54FFFFFF lea edx, dword ptr ; vbaVarDup参数,源串(临时,常量)
00402324 8D4D 94 lea ecx, dword ptr ; vbaVarDup参数,目的串
00402327 C785 5CFFFFFF 3C1C40>mov dword ptr , 00401C3C ; UNICODE "RiCHTiG !!!! ....weiter mit dem N"
00402331 C785 54FFFFFF 080000>mov dword ptr , 8 ; 类型为8,字符串,指向上面的字符串
0040233B FFD3 call ebx ; MSVBVM50.__vbaVarDup
0040233D 8D95 64FFFFFF lea edx, dword ptr ; 变量类型0x0A,VT_ERROR, 错误码: 0x80020004(ecx)
00402343 8D85 74FFFFFF lea eax, dword ptr ; 变量类型0x0A,VT_ERROR, 错误码: 0x80020004(ecx)
00402349 52 push edx ; Context
0040234A 8D4D 84 lea ecx, dword ptr
0040234D 50 push eax ; Helpfile
0040234E 51 push ecx ; MsgBox 窗口标题
0040234F 8D55 94 lea edx, dword ptr ;
00402352 6A 30 push 30 ; vbOKOnly + vbExclamation
00402354 52 push edx ;msgbox 内容提示字符串
00402355 FF15 28414000 call dword ptr [<&MSVBVM50.#595>] ; call (MSVBVM50.rtcMsgBox),显示成功的信息
0040235B 8D95 14FFFFFF lea edx, dword ptr ; edx ===> variable 变量
00402361 8D4D AC lea ecx, dword ptr ; 用来保存 rtcMsgBox 的返回值的 variable 变量
00402364 8985 1CFFFFFF mov dword ptr , eax ; rtcMsgBox 的返回值
0040236A C785 14FFFFFF 030000>mov dword ptr , 3 ; 变量类型为3,32位整数 Long
00402374 FFD6 call esi ; call (MSVBVM50.__vbaVarMove)
00402376 8D85 64FFFFFF lea eax, dword ptr
0040237C 8D8D 74FFFFFF lea ecx, dword ptr
00402382 50 push eax
00402383 8D55 84 lea edx, dword ptr
00402386 51 push ecx
00402387 8D45 94 lea eax, dword ptr
0040238A 52 push edx
0040238B 50 push eax
0040238C E9 B5000000 jmp 00402446
;
; MsgBox "RiCHTiG !!!! ....weiter mit dem N", vbOKOnly + vbExclamation, "richtig !"
;
; else
;
; 不相等执行以下代码
;
00402391 8B1D 98414000 mov ebx, dword ptr [<&MSVBVM50.__vbaVarDup>] ; 序列号比对不相等来到这里(下面指令的注释与前面类似,不提供了)
00402397 B9 04000280 mov ecx, 80020004
0040239C 898D 6CFFFFFF mov dword ptr , ecx
004023A2 B8 0A000000 mov eax, 0A
004023A7 898D 7CFFFFFF mov dword ptr , ecx
004023AD 8D95 44FFFFFF lea edx, dword ptr
004023B3 8D4D 84 lea ecx, dword ptr
004023B6 8985 64FFFFFF mov dword ptr , eax
004023BC 8985 74FFFFFF mov dword ptr , eax
004023C2 C785 4CFFFFFF 9C1D40>mov dword ptr , 00401D9C ; leider falsch !
004023CC C785 44FFFFFF 080000>mov dword ptr , 8
004023D6 FFD3 call ebx
004023D8 8D95 54FFFFFF lea edx, dword ptr
004023DE 8D4D 94 lea ecx, dword ptr
004023E1 C785 5CFFFFFF C01C40>mov dword ptr , 00401CC0 ; leider falsch! nochmal veruschen ! wenn du es nicht schaffen solltest, schreib mir !andrenalin@gmx.net
004023EB C785 54FFFFFF 080000>mov dword ptr , 8
004023F5 FFD3 call ebx
004023F7 8D8D 64FFFFFF lea ecx, dword ptr
004023FD 8D95 74FFFFFF lea edx, dword ptr
00402403 51 push ecx
00402404 8D45 84 lea eax, dword ptr
00402407 52 push edx
00402408 50 push eax
00402409 8D4D 94 lea ecx, dword ptr
0040240C 6A 10 push 10 ; vbOKOnly + vbCritical
0040240E 51 push ecx
0040240F FF15 28414000 call dword ptr [<&MSVBVM50.#595>] ; call (MSVBVM50.rtcMsgBox),显示失败的信息
00402415 8D95 14FFFFFF lea edx, dword ptr ; edx ===> variable 变量
0040241B 8D4D AC lea ecx, dword ptr
0040241E 8985 1CFFFFFF mov dword ptr , eax ; rtcMsgBox 的返回值
00402424 C785 14FFFFFF 030000>mov dword ptr , 3 ; 变量类型为3,32位整数 Long
0040242E FFD6 call esi ; call (MSVBVM50.__vbaVarMove)
00402430 8D95 64FFFFFF lea edx, dword ptr
00402436 8D85 74FFFFFF lea eax, dword ptr
0040243C 52 push edx
0040243D 8D4D 84 lea ecx, dword ptr
00402440 50 push eax
00402441 8D55 94 lea edx, dword ptr
00402444 51 push ecx
00402445 52 push edx
;
; MsgBox "leider falsch! nochmal veruschen ! wenn du es nicht schaffen solltest, schreib mir !andrenalin@gmx.net", vbOKOnly + vbCritical, "leider falsch !"
;
; end if
;
; 下面是函数结束释放资源的代码
;
00402446 6A 04 push 4
00402448 FFD7 call edi
0040244A 83C4 14 add esp, 14
0040244D C745 FC 00000000 mov dword ptr , 0
00402454 68 C3244000 push 004024C3
00402459 EB 34 jmp short 0040248F
0040245B 8D4D A8 lea ecx, dword ptr ; 释放 1 个字符串变量
0040245E FF15 B8414000 call dword ptr [<&MSVBVM50.__vbaFreeStr>] ; MSVBVM50.__vbaFreeStr
00402464 8D4D A4 lea ecx, dword ptr ; 释放 1 个对象变量
00402467 FF15 B4414000 call dword ptr [<&MSVBVM50.__vbaFreeObj>] ; MSVBVM50.__vbaFreeObj
0040246D 8D85 64FFFFFF lea eax, dword ptr
00402473 8D8D 74FFFFFF lea ecx, dword ptr
00402479 50 push eax
0040247A 8D55 84 lea edx, dword ptr
0040247D 51 push ecx
0040247E 8D45 94 lea eax, dword ptr
00402481 52 push edx
00402482 50 push eax
00402483 6A 04 push 4 ; 释放 4 个 Variable 变量
00402485 FF15 04414000 call dword ptr [<&MSVBVM50.__vbaFreeVarList>] ; MSVBVM50.__vbaFreeVarList
0040248B 83C4 14 add esp, 14
0040248E C3 retn
0040248F 8D8D E8FEFFFF lea ecx, dword ptr
00402495 8D95 F8FEFFFF lea edx, dword ptr
0040249B 51 push ecx
0040249C 52 push edx
0040249D 6A 02 push 2 ; 释放 2 个 Variable 变量
0040249F FF15 04414000 call dword ptr [<&MSVBVM50.__vbaFreeVarList>] ; MSVBVM50.__vbaFreeVarList
004024A5 8B35 00414000 mov esi, dword ptr [<&MSVBVM50.__vbaFreeVar>] ; MSVBVM50.__vbaFreeVar
004024AB 83C4 0C add esp, 0C
004024AE 8D4D DC lea ecx, dword ptr
004024B1 FFD6 call esi ; 释放 1 个 Variable 变量
004024B3 8D4D CC lea ecx, dword ptr
004024B6 FFD6 call esi ; 释放 1 个 Variable 变量
004024B8 8D4D BC lea ecx, dword ptr
004024BB FFD6 call esi ; 释放 1 个 Variable 变量
004024BD 8D4D AC lea ecx, dword ptr
004024C0 FFE6 jmp esi ; 释放 1 个 Variable 变量
004024C2 C3 retn
004024C3 8B45 08 mov eax, dword ptr
004024C6 50 push eax
004024C7 8B08 mov ecx, dword ptr
004024C9 FF51 08 call dword ptr
004024CC 8B4D EC mov ecx, dword ptr ; 原有 SEH
004024CF 8B45 FC mov eax, dword ptr ; 返回值
004024D2 5F pop edi
004024D3 5E pop esi
004024D4 64:890D 00000000 mov dword ptr fs:, ecx ; 恢复 SEH
004024DB 5B pop ebx
004024DC 8BE5 mov esp, ebp
004024DE 5D pop ebp
004024DF C2 0400 retn 4
根据算法分析,注册机代码如下,使用 Dev-C++ 调试通过:
#include <iostream>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char name[] = "solly"; /// 名字自己改
char regcode;
intn = strlen(name);
unsigned long long sum = 0;
for(int i=0; i<n; i++) {
sum += (unsigned)name;
}
sprintf(regcode, "%llu", sum * 1234567890ULL);
regcode = '-';
regcode = '-';
printf(" name: %s\n regcode: %s\n", name, regcode);
return 0;
}
运行结果,如下:
name: solly
regcode: 695-6172-070
--------------------------------
Process exited after 0.03192 seconds with return value 0
请按任意键继续. . .
重新回到 CrackMe,输入正确的注册码:695-6172-070,点“OK”,验证成功:
分析完毕!!!
感谢,非常详细 {:1_919:} 下次能不能把分析的文件也带上. Joduska 发表于 2019-7-19 19:58
下次能不能把分析的文件也带上.
文件在这一个贴子内:
https://www.52pojie.cn/thread-709699-1-1.html
页:
[1]