最新消息:想得多,做的少。一天到晚瞎鸡巴搞。

160个CrackMe – 002

套路与反套路 阿虚 782浏览 0评论

文章内容包含:一、爆破程序,二、找出算法

一:爆破程序

.     这个程序是一个VB的程序,以前并没有摸过除C++之外的程序。程序载入时,下BP MessageBoxA和MessageBoxW都无法断下弹窗。

.     临时看下《加密解密三》VB程序得知VB的显示对话框函数为:rtcMsgBox。吾爱的OD插件中有VB函数断点,点击下即可下rtcMsgBox断点。然后输入账户tqdn密码1234点击控件OK让程序跑起来。

.     程序跑起来后断在了MSVBVM50的动态链接库中。这里应该就是rtcMsgBox函数范围内。直接F8走出这个函数。F8往下的过程中会弹出消息框显示“You Get Wrong   Try Again”估摸着就是错误的消息吧。

.     走出函数后就返回到下面

004025E1   .  51            push ecx
004025E2   .  52            push edx
004025E3   .  EB 56         jmp XAfkayas_.0040263B                             ;  跳过了错误的显示
004025E5   >  68 C81B4000   push Afkayas_.00401BC8                             ;  UNICODE "You Get Wrong"
004025EA   .  68 9C1B4000   push Afkayas_.00401B9C                             ;  ASCII "\r"
004025EF   .  FFD7          call edi
004025F1   .  8BD0          mov edx,eax
004025F3   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]
004025F6   .  FFD3          call ebx
004025F8   .  50            push eax
004025F9   .  68 E81B4000   push Afkayas_.00401BE8                             ;  UNICODE "Try Again"
004025FE   .  FFD7          call edi
00402600   .  8945 CC       mov dword ptr ss:[ebp-0x34],eax
00402603   .  8D45 94       lea eax,dword ptr ss:[ebp-0x6C]
00402606   .  8D4D A4       lea ecx,dword ptr ss:[ebp-0x5C]
00402609   .  50            push eax
0040260A   .  8D55 B4       lea edx,dword ptr ss:[ebp-0x4C]
0040260D   .  51            push ecx
0040260E   .  52            push edx
0040260F   .  8D45 C4       lea eax,dword ptr ss:[ebp-0x3C]
00402612   .  6A 00         push 0x0
00402614   .  50            push eax
00402615   .  C745 C4 08000>mov dword ptr ss:[ebp-0x3C],0x8
0040261C   .  FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>]               ;  显示错误信息弹框的函数
00402622   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]                    ;  当前EIP的位置

.     在当前EIP处网上看,离最近的是一个JMP指令,这条指令在OD上点上去是直接跳过了这个显示错误信息的函数。那么在往上面找找。有没有什么跳转指令。

00402569   .  83C4 0C       add esp,0xC
0040256C   .  B9 04000280   mov ecx,0x80020004
00402571   .  B8 0A000000   mov eax,0xA
00402576   .  894D 9C       mov dword ptr ss:[ebp-0x64],ecx
00402579   .  66:85F6       test si,si                          ;  比较SI是否为0
0040257C   .  8945 94       mov dword ptr ss:[ebp-0x6C],eax
0040257F   .  894D AC       mov dword ptr ss:[ebp-0x54],ecx
00402582   .  8945 A4       mov dword ptr ss:[ebp-0x5C],eax
00402585   .  894D BC       mov dword ptr ss:[ebp-0x44],ecx
00402588   .  8945 B4       mov dword ptr ss:[ebp-0x4C],eax
0040258B   .  74 58         je XAfkayas_.004025E5               ;  如果SI等于0那么跳转到错误的显示
0040258D   .  68 801B4000   push Afkayas_.00401B80              ;  UNICODE "You Get It"
00402592   .  68 9C1B4000   push Afkayas_.00401B9C              ;  ASCII "\r"
00402597   .  FFD7          call edi
00402599   .  8BD0          mov edx,eax
0040259B   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]
0040259E   .  FFD3          call ebx
004025A0   .  50            push eax
004025A1   .  68 A81B4000   push Afkayas_.00401BA8              ;  UNICODE "KeyGen It Now"
004025A6   .  FFD7          call edi
004025A8   .  8D4D 94       lea ecx,dword ptr ss:[ebp-0x6C]
004025AB   .  8945 CC       mov dword ptr ss:[ebp-0x34],eax
004025AE   .  8D55 A4       lea edx,dword ptr ss:[ebp-0x5C]
004025B1   .  51            push ecx
004025B2   .  8D45 B4       lea eax,dword ptr ss:[ebp-0x4C]
004025B5   .  52            push edx
004025B6   .  50            push eax
004025B7   .  8D4D C4       lea ecx,dword ptr ss:[ebp-0x3C]
004025BA   .  6A 00         push 0x0
004025BC   .  51            push ecx
004025BD   .  C745 C4 08000>mov dword ptr ss:[ebp-0x3C],0x8
004025C4   .  FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>>;  msvbvm50.rtcMsgBox
004025CA   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]
004025CD   .  FF15 80414000 call dword ptr ds:[<&MSVBVM50.__vba>;  msvbvm50.__vbaFreeStr
004025D3   .  8D55 94       lea edx,dword ptr ss:[ebp-0x6C]
004025D6   .  8D45 A4       lea eax,dword ptr ss:[ebp-0x5C]
004025D9   .  52            push edx
004025DA   .  8D4D B4       lea ecx,dword ptr ss:[ebp-0x4C]
004025DD   .  50            push eax
004025DE   .  8D55 C4       lea edx,dword ptr ss:[ebp-0x3C]
004025E1   .  51            push ecx
004025E2   .  52            push edx
004025E3   .  EB 56         jmp XAfkayas_.0040263B              ;  跳过了错误的显示
004025E5   >  68 C81B4000   push Afkayas_.00401BC8              ;  UNICODE "You Get Wrong"
004025EA   .  68 9C1B4000   push Afkayas_.00401B9C              ;  ASCII "\r"
004025EF   .  FFD7          call edi
004025F1   .  8BD0          mov edx,eax
004025F3   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]

.     往上找找到了一个靠谱的跳转点:

.     0040258B  je XAfkayas_.004025E5  ;  如果SI等于0那么跳转到错误的显示

.     尝试把此处的JE修改成nop。然后跑程序试试~~ 爆破成功!

二:找出算法

.     首先想找算法那么先应该在爆破点下断点,并且跑到这里来。

00402561   .  6A 02         push 0x2
00402563   .  FF15 F4404000 call dword ptr ds:[<&MSVBVM50.__vba>;  msvbvm50.__vbaFreeObjList
00402569   .  83C4 0C       add esp,0xC
0040256C   .  B9 04000280   mov ecx,0x80020004
00402571   .  B8 0A000000   mov eax,0xA
00402576   .  894D 9C       mov dword ptr ss:[ebp-0x64],ecx
00402579   .  66:85F6       test si,si                          ;  比较SI是否为0
0040257C   .  8945 94       mov dword ptr ss:[ebp-0x6C],eax
0040257F   .  894D AC       mov dword ptr ss:[ebp-0x54],ecx
00402582   .  8945 A4       mov dword ptr ss:[ebp-0x5C],eax
00402585   .  894D BC       mov dword ptr ss:[ebp-0x44],ecx
00402588   .  8945 B4       mov dword ptr ss:[ebp-0x4C],eax
0040258B   .  74 58         je XAfkayas_.004025E5               ;  如果SI等于0那么跳转到错误的显示
0040258D   .  68 801B4000   push Afkayas_.00401B80              ;  UNICODE "You Get It"
00402592   .  68 9C1B4000   push Afkayas_.00401B9C              ;  ASCII "\r"
00402597   .  FFD7          call edi

.     JE的跳转是由TEST SI, SI来控制,所以我们应当找到那里给SI赋值的指令。

0040252D   .  8D4D E0       lea ecx,dword ptr ss:[ebp-0x20]
00402530   .  FFD3          call ebx                            ;  <&MSVBVM50.__vbaStrMove>
00402532   .  50            push eax
00402533   .  FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vba>;  msvbvm50.__vbaStrCmp
00402539   .  8BF0          mov esi,eax                         ;  vbaStrCmp 字符串比较函数的返回值给了ESI
0040253B   .  8D55 E0       lea edx,dword ptr ss:[ebp-0x20]
0040253E   .  F7DE          neg esi
00402540   .  8D45 E8       lea eax,dword ptr ss:[ebp-0x18]
00402543   .  52            push edx
00402544   .  1BF6          sbb esi,esi
00402546   .  8D4D E4       lea ecx,dword ptr ss:[ebp-0x1C]
00402549   .  50            push eax
0040254A   .  46            inc esi
0040254B   .  51            push ecx
0040254C   .  6A 03         push 0x3
0040254E   .  F7DE          neg esi
00402550   .  FF15 5C414000 call dword ptr ds:[<&MSVBVM50.__vba>;  msvbvm50.__vbaFreeStrList
00402556   .  83C4 10       add esp,0x10
00402559   .  8D55 D8       lea edx,dword ptr ss:[ebp-0x28]
0040255C   .  8D45 DC       lea eax,dword ptr ss:[ebp-0x24]
0040255F   .  52            push edx
00402560   .  50            push eax
00402561   .  6A 02         push 0x2
00402563   .  FF15 F4404000 call dword ptr ds:[<&MSVBVM50.__vba>;  msvbvm50.__vbaFreeObjList
00402569   .  83C4 0C       add esp,0xC
0040256C   .  B9 04000280   mov ecx,0x80020004
00402571   .  B8 0A000000   mov eax,0xA
00402576   .  894D 9C       mov dword ptr ss:[ebp-0x64],ecx
00402579   .  66:85F6       test si,si                          ;  比较SI是否为0
0040257C   .  8945 94       mov dword ptr ss:[ebp-0x6C],eax
0040257F   .  894D AC       mov dword ptr ss:[ebp-0x54],ecx

.     从 TEST SI, SI 处往上找,在很近的地方vbaStrCmp 字符串比较函数的返回值给了ESI。我们在vbaStrCmp 处下断点,OD跑过来看看比较的是什么内容。观察栈中可以看到函数直接是以明文方式作比较,我输入的密码1234和程序计算出来的KEY值。

.     我们往上看看反汇编代码

004024E5   .  8D45 D8       lea eax,dword ptr ss:[ebp-0x28]
004024E8   .  50            push eax
004024E9   .  FFD3          call ebx
004024EB   .  8BF0          mov esi,eax
004024ED   .  8D55 E4       lea edx,dword ptr ss:[ebp-0x1C]
004024F0   .  52            push edx
004024F1   .  56            push esi
004024F2   .  8B0E          mov ecx,dword ptr ds:[esi]
004024F4   .  FF91 A0000000 call dword ptr ds:[ecx+0xA0]
004024FA   .  85C0          test eax,eax
004024FC   .  7D 12         jge XAfkayas_.00402510
004024FE   .  68 A0000000   push 0xA0
00402503   .  68 5C1B4000   push Afkayas_.00401B5C
00402508   .  56            push esi
00402509   .  50            push eax
0040250A   .  FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresu>;  msvbvm50.__vbaHresultCheckObj
00402510   >  8B45 E8       mov eax,dword ptr ss:[ebp-0x18]
00402513   .  8B4D E4       mov ecx,dword ptr ss:[ebp-0x1C]
00402516   .  8B3D 00414000 mov edi,dword ptr ds:[<&MSVBVM50.__vbaSt>;  msvbvm50.__vbaStrCat
0040251C   .  50            push eax
0040251D   .  68 701B4000   push Afkayas_.00401B70                   ;  UNICODE "AKA-"
00402522   .  51            push ecx                                 ; /String
00402523   .  FFD7          call edi                                 ; \__vbaStrCat
00402525   .  8B1D 70414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaSt>;  msvbvm50.__vbaStrMove
0040252B   .  8BD0          mov edx,eax
0040252D   .  8D4D E0       lea ecx,dword ptr ss:[ebp-0x20]
00402530   .  FFD3          call ebx                                 ;  <&MSVBVM50.__vbaStrMove>
00402532   .  50            push eax
00402533   .  FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vbaStrCm>;  msvbvm50.__vbaStrCmp
00402539   .  8BF0          mov esi,eax                              ;  vbaStrCmp 字符串比较函数的返回值给了ESI

.     vbaStrCmp的第一个参数是由vbaStrMove的返回值给的。观察反汇编

00402525   .  8B1D 70414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaSt>;  msvbvm50.__vbaStrMove
0040252B   .  8BD0          mov edx,eax
0040252D   .  8D4D E0       lea ecx,dword ptr ss:[ebp-0x20]
00402530   .  FFD3          call ebx                                 ;  <&MSVBVM50.__vbaStrMove>
00402532   .  50            push eax
00402533   .  FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vbaStrCm>;  msvbvm50.__vbaStrCmp
00402539   .  8BF0          mov esi,eax                              ;  vbaStrCmp 字符串比较函数的返回值给了ESI

. 并没有看到vbaStrMove存在PUSH参数的指令。我们在这里下断点进去看看vbaStrMove的实现是什么样子的。

vbaStrMove的实现
7403F8DA >  56              push esi
7403F8DB    57              push edi
7403F8DC    8B01            mov eax,dword ptr ds:[ecx]               ; ECX去一个DWORD给EAX
7403F8DE    8BFA            mov edi,edx                              ; EDX的内容给EDI
7403F8E0    8BF1            mov esi,ecx                              ; ECX的内容给ESI
7403F8E2    85C0            test eax,eax                             ; 判断ECX 去内容是否为NULL
7403F8E4    75 07           jnz Xmsvbvm50.7403F8ED
7403F8E6    8BC7            mov eax,edi
7403F8E8    893E            mov dword ptr ds:[esi],edi               ; ECX取内容不等于NULL就将EDI存放至ECX中
7403F8EA    5F              pop edi
7403F8EB    5E              pop esi
7403F8EC    C3              retn
7403F8ED    50              push eax
7403F8EE    FF15 88190274   call dword ptr ds:[<&OLEAUT32.#6>]       ; oleaut32.SysFreeString
7403F8F4  ^ EB F0           jmp Xmsvbvm50.7403F8E6                   ; 否则就直接返回了

.     通过解释反汇编,可以知道vbaStrMove不是使用栈来传参数而是使用了两个寄存器EDX和ECX。结合反汇编,EDX是由vbaStrCat的返回值给与的。ECX由ebp-0x20来的。

.     vbaStrCat的两个参数是直接push一个字符串”AKA-”和push了一个ECX,ECX指向了一个字符串“390240”。最开始在爆破点下断点得出来的KEY位“AKA-390240”理算法很近了。我们接下来需要就是找到ECX是从哪来的。但是失败了。我对VB不熟悉,函数这里给出的结果让我很莫名其妙。

.     所以我决定在用最挫的方式重新在爆破点的函数头下断点,然后单步跟一次流程。并且关注函数的返回值和传出参数(lea EXX, ebp-XX,遇见这种考虑是传出参数,直接在十六进制窗口查看当前地址是什么内容,函数走完后修改成了什么数据!)

004023ED   .  FF90 A0000000 call dword ptr ds:[eax+0xA0]                   ;  这里获得了账户
004023F3   .  3BC7          cmp eax,edi
004023F5   .  7D 12         jge XAfkayas_.00402409
004023F7   .  68 A0000000   push 0xA0                                      ;  如果返回值小于0就走这里
004023FC   .  68 5C1B4000   push Afkayas_.00401B5C
00402401   .  53            push ebx
00402402   .  50            push eax
00402403   .  FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>;  msvbvm50.__vbaHresultCheckObj
00402409   >  8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0]
0040240F   .  8B45 E4       mov eax,dword ptr ss:[ebp-0x1C]                ;  vbaLenBstr 获取 账户的长度,eax返回长度
00402412   .  50            push eax                                       ; /String
00402413   .  8B1A          mov ebx,dword ptr ds:[edx]                     ; |
00402415   .  FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>]   ; \__vbaLenBstr
0040241B   .  8BF8          mov edi,eax                                    ;  账户长度存储在EDI中
0040241D   .  8B4D E8       mov ecx,dword ptr ss:[ebp-0x18]
00402420   .  69FF FB7C0100 imul edi,edi,0x17CFB                           ;  将账户长度 * 0x17CFB
00402426   .  51            push ecx                                       ; /String
00402427   .  0F80 91020000 jo Afkayas_.004026BE                           ; |计算出来的结果>=0x80000000 就异常
0040242D   .  FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>]           ; \rtcAnsiValueBstr
00402433   .  0FBFD0        movsx edx,ax                                   ;  返回账户的第一个字符代码
00402436   .  03FA          add edi,edx                                    ;  返回的字符代码与账户长度 * 0x17CFB相加
00402438   .  0F80 80020000 jo Afkayas_.004026BE                           ;  结果大于0x80000000就异常
0040243E   .  57            push edi                                       ;  这个函数是将I4转换成STR
0040243F   .  FF15 E0404000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>]     ;  msvbvm50.__vbaStrI4
00402445   .  8BD0          mov edx,eax                                    ;  返回值为390240字符串

.    这里得到了字符串为390240,通过第一次失败的跟踪。那么可以知道这个地方是算出后面整数字符串的地方,对于KEY只需要在字符串前拼接一个”AKA-”就好了

.    这个算法很简单,也是和001一样只取了账户的第一个字节。不过这个账户有取账户长度做计算得出的结果。所以一个账户算出来的KEY只能在首字母和账户长度都相等的情况才能正常得出正确的结果!

void Fun(char *ZhangHu)
{
    char szBuff[256];
    unsigned long data = strlen(ZhangHu) * 0x17CFB + (unsigned long)ZhangHu[0];
    sprintf(szBuff, "AKA-%d", data);
    printf("%s \r\n", szBuff);
}

转载请注明:虚无 » 160个CrackMe – 002

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址