solly 发表于 2019-7-19 00:37

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”,验证成功:



分析完毕!!!


alexskyboy 发表于 2019-7-19 11:05

感谢,非常详细

Joduska 发表于 2019-7-19 19:58

{:1_919:} 下次能不能把分析的文件也带上.

solly 发表于 2019-7-19 20:41

Joduska 发表于 2019-7-19 19:58
下次能不能把分析的文件也带上.

文件在这一个贴子内:

https://www.52pojie.cn/thread-709699-1-1.html
页: [1]
查看完整版本: 160 个 CrackMe 之 009 Andrénalin.2 (VB5 Native)的算法代码详解和注册机实现