适合新手的160个creakme(一)

先跑一下

适合新手的160个creakme(一)

适合新手的160个creakme(一)

适合新手的160个creakme(一)

直接使用这个字符串去check,发现提示信息有关键字符串

CODE:0042FB80 00000021 C Sorry , The serial is incorect !

适合新手的160个creakme(一)

找到这个字符串的引用,有两个

适合新手的160个creakme(一)

跟下去发现这两个字符串都在一个函数中,最下面的3个框中左右都是错误,中间是对的,所以核心就在最上层和中间的这段代码

适合新手的160个creakme(一)

下面看看这段代码,直接在ollydbg中暂停,查看参数和返回值等信息

CODE:0042F998                 push    ebp
CODE:0042F999                 mov     ebp, esp
CODE:0042F99B                 xor     ecx, ecx
CODE:0042F99D                 push    ecx
CODE:0042F99E                 push    ecx
CODE:0042F99F                 push    ecx
CODE:0042F9A0                 push    ecx
CODE:0042F9A1                 push    ecx
CODE:0042F9A2                 push    ecx
CODE:0042F9A3                 push    ebx
CODE:0042F9A4                 push    esi
CODE:0042F9A5                 mov     ebx, eax
CODE:0042F9A7                 xor     eax, eax
CODE:0042F9A9                 push    ebp
CODE:0042F9AA                 push    offset loc_42FB67  
CODE:0042F9AF                 push    dword ptr fs:[eax]
CODE:0042F9B2                 mov     fs:[eax], esp
CODE:0042F9B5                 mov     ds:dword_431750, 29h
CODE:0042F9BF                 lea     edx, [ebp+var_10]
CODE:0042F9C2                 mov     eax, [ebx+1DCh]
CODE:0042F9C8                 call    sub_41AA58        ;这个函数返回18
CODE:0042F9CD                 mov     eax, [ebp+var_10]    ;这里取得了用户名字符串
CODE:0042F9D0                 call    sub_403AB0        ;以用户名作为参数,调用sub_403AB0,这是一个判断用户名是不是空的函数
CODE:0042F9D5                 mov     ds:dword_43176C, eax  ;将结果存放在固定位置,后面的第一个关键判断使用这个字符串
CODE:0042F9DA                 lea     edx, [ebp+var_10]
CODE:0042F9DD                 mov     eax, [ebx+1DCh]
CODE:0042F9E3                 call    sub_41AA58
CODE:0042F9E8                 mov     eax, [ebp+var_10]
CODE:0042F9EB                 movzx   eax, byte ptr [eax]
CODE:0042F9EE                 mov     esi, eax
CODE:0042F9F0                 shl     esi, 3
CODE:0042F9F3                 sub     esi, eax
CODE:0042F9F5                 lea     edx, [ebp+var_14]
CODE:0042F9F8                 mov     eax, [ebx+1DCh]
CODE:0042F9FE                 call    sub_41AA58
CODE:0042FA03                 mov     eax, [ebp+var_14]
CODE:0042FA06                 movzx   eax, byte ptr [eax+1]
CODE:0042FA0A                 shl     eax, 4
CODE:0042FA0D                 add     esi, eax
CODE:0042FA0F                 mov     ds:dword_431754, esi
CODE:0042FA15                 lea     edx, [ebp+var_10]
CODE:0042FA18                 mov     eax, [ebx+1DCh]
CODE:0042FA1E                 call    sub_41AA58
CODE:0042FA23                 mov     eax, [ebp+var_10]
CODE:0042FA26                 movzx   eax, byte ptr [eax+3]
CODE:0042FA2A                 imul    esi, eax, 0Bh
CODE:0042FA2D                 lea     edx, [ebp+var_14]
CODE:0042FA30                 mov     eax, [ebx+1DCh]
CODE:0042FA36                 call    sub_41AA58
CODE:0042FA3B                 mov     eax, [ebp+var_14]
CODE:0042FA3E                 movzx   eax, byte ptr [eax+2]
CODE:0042FA42                 imul    eax, 0Eh
CODE:0042FA45                 add     esi, eax
CODE:0042FA47                 mov     ds:dword_431758, esi
CODE:0042FA4D                 mov     eax, ds:dword_43176C
CODE:0042FA52                 call    sub_406930        ;以用户名作为参数调用
CODE:0042FA57                 cmp     eax, 4
CODE:0042FA5A                 jge     short loc_42FA79    ;第一个关键判断
CODE:0042FA5C                 push    0               ; uType
CODE:0042FA5E                 mov     ecx, offset aTryAgain_0 ; "Try Again!"
CODE:0042FA63                 mov     edx, offset aSorryTheSerial ; "Sorry , The serial is incorect !"
CODE:0042FA68                 mov     eax, ds:off_430A48
CODE:0042FA6D                 mov     eax, [eax]      ; int
CODE:0042FA6F                 call    sub_42A170
CODE:0042FA74                 jmp     loc_42FB37
CODE:0042FA79 ; ---------------------------------------------------------------------------
CODE:0042FA79
CODE:0042FA79 loc_42FA79:                             ; CODE XREF: _TNS_BitBtn1Click+C2↑j
CODE:0042FA79                 lea     edx, [ebp+var_10]
CODE:0042FA7C                 mov     eax, [ebx+1DCh]
CODE:0042FA82                 call    sub_41AA58
CODE:0042FA87                 mov     eax, [ebp+var_10]    ;取字符串
CODE:0042FA8A                 movzx   eax, byte ptr [eax]   ;取出字符串的第一个地址
CODE:0042FA8D                 imul    ds:dword_431750      ;前面将这个位置赋值成了0x29
CODE:0042FA93                 mov     ds:dword_431750, eax   ;将第一个字符乘以0x29
CODE:0042FA98                 mov     eax, ds:dword_431750
CODE:0042FA9D                 add     ds:dword_431750, eax    ;这里应该相当于乘以2了
CODE:0042FAA3                 lea     eax, [ebp+var_4]      ;将这个字符串的地址放到局部变量中
CODE:0042FAA6                 mov     edx, offset _str_CW.Text
CODE:0042FAAB                 call    sub_403708          ;以字符串CW作为第二参数
CODE:0042FAB0                 lea     eax, [ebp+var_8]        ;同上,将字符串地址放入局部变量
CODE:0042FAB3                 mov     edx, offset _str_CRACKED.Text
CODE:0042FAB8                 call    sub_403708          ;以字符串CRACKED作为第二参数
CODE:0042FABD                 push    [ebp+var_4]          ;push了CW
CODE:0042FAC0                 push    offset _str___5.Text    ;push了又一个字符串
CODE:0042FAC5                 lea     edx, [ebp+var_18]      ;这里是局部变量
CODE:0042FAC8                 mov     eax, ds:dword_431750    ;这里是用户名第一个字符串经过运算之后的结果
CODE:0042FACD                 call    sub_406718          ;这里又对第一个字符串的运行结果再次进行一个运算
CODE:0042FAD2                 push    [ebp+var_18]         ;将第二次运算结果放入var_18中,这里入栈了
CODE:0042FAD5                 push    offset _str___5.Text    ;应该也是参数
CODE:0042FADA                 push    [ebp+var_8]
CODE:0042FADD                 lea     eax, [ebp+var_C]
CODE:0042FAE0                 mov     edx, 5
CODE:0042FAE5                 call    sub_4039AC          ;关键函数了,第一个参数是var_C,第二个是5,后面3个参数依次是前面push的内容
CODE:0042FAEA                 lea     edx, [ebp+var_10]
CODE:0042FAED                 mov     eax, [ebx+1E0h]
CODE:0042FAF3                 call    sub_41AA58        ;这个函数读取了序列码的地址,然后返给var_10中作为下一个函数的参数
CODE:0042FAF8                 mov     edx, [ebp+var_10]    ;第二个参数是序列码字符串
CODE:0042FAFB                 mov     eax, [ebp+var_C]    ;第一个参数是var_C,也是字符串
CODE:0042FAFE                 call    sub_4039FC        ;要求这个函数返回0
CODE:0042FB03                 jnz     short loc_42FB1F
CODE:0042FB05                 push    0               ; uType
CODE:0042FB07                 mov     ecx, offset aCongratz_0 ; "Congratz !!"
CODE:0042FB0C                 mov     edx, offset aGoodJobDude ; "Good job dude =)"
CODE:0042FB11                 mov     eax, ds:off_430A48
CODE:0042FB16                 mov     eax, [eax]      ; int
CODE:0042FB18                 call    sub_42A170
CODE:0042FB1D                 jmp     short loc_42FB37
CODE:0042FB1F ; ---------------------------------------------------------------------------
CODE:0042FB1F
CODE:0042FB1F loc_42FB1F:                             ; CODE XREF: _TNS_BitBtn1Click+16B↑j
CODE:0042FB1F                 push    0               ; uType
CODE:0042FB21                 mov     ecx, offset aTryAgain_0 ; "Try Again!"
CODE:0042FB26                 mov     edx, offset aSorryTheSerial ; "Sorry , The serial is incorect !"
CODE:0042FB2B                 mov     eax, ds:off_430A48
CODE:0042FB30                 mov     eax, [eax]      ; int
CODE:0042FB32                 call    sub_42A170

直接以默认的方式去运行,在ollydbg中看各个函数调用的参数和返回情况

在sub_406930处,传入用户名字符串,然后返回-2-(-1-length),也就是length-1,这里的length包括了'\0'字符,也就是说,最后这个函数的返回位用户名的字符串长度,最后结果为0x19,所以第一个条件判断为字符串长度大于4。这里已经符合了

然后是loc_42FA79处的函数,这个函数最后的跳转步骤在sub_4039FC处,要求这个函数返回0,而这个函数参数有两个,第一个参数是CW-6560-CRACKED,第二参数为序列码。所以这里猜测应该是根据用户名生成了6560这个字符串,和CW和CRACKED进行拼接,然后在这里进行最后一步的判断

从0042FA79开始,对汇编码进行了简要分析,这段可以直接在ollydbg中看各个函数的参数,结果以及栈的变化,可以大致猜出sub_4039AC应该是字符串拼接函数,而关键点的函数应该是一个字符串相对的判断函数。然后直接在序列码中输入CW-6560-CRACKED,发现果然正确,而6560这个值就是根据用户名字符串第一个字符乘以0x29再成2得到的,上文中没有分析的函数就是用来做字符串拼接(6560这个值在跟踪函数的过程中也会被放入到栈上,所以只需要用ollydbg跟踪调试每一步的变化就很容易得出结果了)

最后就OK了

适合新手的160个creakme(一)

 

上一篇:LeetCodeWeeklyContest-160


下一篇:逆向破解之160个CrackMe —— 021