好友
阅读权限10
听众
最后登录1970-1-1
|
1. 爆破
2. 找算法
一:爆破程序
这个程序是一个VB的程序,以前并没有摸过除C++之外的程序。程序载入时,下BP MessageBoxA和MessageBoxW都无法断下弹窗。
临时看下《加密解密三》VB程序得知VB的显示对话框函数为:rtcMsgBox。吾爱的OD插件中有VB函数断点,点击下即可下rtcMsgBox断点。然后输入账户tqdn密码1234点击控件OK让程序跑起来。
. 程序跑起来后断在了MSVBVM50的动态链接库中。这里应该就是rtcMsgBox函数范围内。直接F8走出这个函数。F8往下的过程中会弹出消息框显示“You Get Wrong Try Again”估摸着就是错误的消息吧。
. 走出函数后就返回到下面
[Asm] 纯文本查看 复制代码
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上点上去是直接跳过了这个显示错误信息的函数。那么在往上面找找。有没有什么跳转指令。
[Asm] 纯文本查看 复制代码 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。然后跑程序试试~~ 爆破成功!
二:找出算法
. 首先想找算法那么先应该在爆破点下断点,并且跑到这里来。
[Asm] 纯文本查看 复制代码 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赋值的指令。
[Asm] 纯文本查看 复制代码 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值。
. 我们往上看看反汇编代码. 我们往上看看反汇编代码
[Asm] 纯文本查看 复制代码 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的返回值给的。观察反汇编
[Asm] 纯文本查看 复制代码 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的实现是什么样子的。
[Asm] 纯文本查看 复制代码 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,遇见这种考虑是传出参数,直接在十六进制窗口查看当前地址是什么内容,函数走完后修改成了什么数据!)
[Asm] 纯文本查看 复制代码 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只能在首字母和账户长度都相等的情况才能正常得出正确的结果!
[C] 纯文本查看 复制代码
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);
}
|
免费评分
-
查看全部评分
|