环境:
window xp sp3
工具:
ollydbg ,exeinfo pe
拿到程序后,查壳。显示是无壳的VB程序
用之前用的VB decompiler载入,没找到有用的东西,还是用回了OD。
OD载入,运行起来。输入“GNUBD”然后点击“”check it",弹出错误消息框,回到OD,F12暂停,Alt+F9回到用户领空,然后把错误消息框的“确定”点掉,然后就可以看到在OD中程序在哪里调用了MessageBox。
00403A4E . C785 58FFFFFF>mov dword ptr ss:[ebp-0xA8],bjanes_1.004>; UNICODE "Wrong serial!"
00403A58 . 89BD 50FFFFFF mov dword ptr ss:[ebp-0xB0],edi
00403A5E . FFD6 call esi ; <&MSVBVM60.__vbaVarDup>
00403A60 . 8D95 60FFFFFF lea edx,dword ptr ss:[ebp-0xA0]
00403A66 . 8D4D C0 lea ecx,dword ptr ss:[ebp-0x40]
00403A69 . C785 68FFFFFF>mov dword ptr ss:[ebp-0x98],bjanes_1.004>; UNICODE "Sorry, try again!"
00403A73 . 89BD 60FFFFFF mov dword ptr ss:[ebp-0xA0],edi
00403A79 . FFD6 call esi
00403A7B . 8D45 90 lea eax,dword ptr ss:[ebp-0x70]
00403A7E . 8D4D A0 lea ecx,dword ptr ss:[ebp-0x60]
00403A81 . 50 push eax
00403A82 . 8D55 B0 lea edx,dword ptr ss:[ebp-0x50]
00403A85 . 51 push ecx
00403A86 . 52 push edx
00403A87 . 8D45 C0 lea eax,dword ptr ss:[ebp-0x40]
00403A8A . 53 push ebx
00403A8B . 50 push eax
00403A8C . FF15 30104000 call dword ptr ds:[<&MSVBVM60.#595>] ; MSVBVM60.rtcMsgBox
00403A92 . 8D4D 90 lea ecx,dword ptr ss:[ebp-0x70] ; 停在这里
往上可以看到是错误的信息,往下翻一翻可以看到:
00403A8C . FF15 30104000 call dword ptr ds:[<&MSVBVM60.#595>] ; MSVBVM60.rtcMsgBox
00403A92 . 8D4D 90 lea ecx,dword ptr ss:[ebp-0x70] ; 停在这里
00403A95 . 8D55 A0 lea edx,dword ptr ss:[ebp-0x60]
00403A98 . 51 push ecx
00403A99 . 8D45 B0 lea eax,dword ptr ss:[ebp-0x50]
00403A9C . 52 push edx
00403A9D . 8D4D C0 lea ecx,dword ptr ss:[ebp-0x40]
00403AA0 . 50 push eax
00403AA1 . 51 push ecx
00403AA2 . EB 7E jmp Xbjanes_1.00403B22
00403AA4 > 8B35 A4104000 mov esi,dword ptr ds:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarDup 有东西跳到这里来,往上翻看看是哪里跳转过来这里的
00403AAA . B9 04000280 mov ecx,0x80020004
00403AAF . 894D 98 mov dword ptr ss:[ebp-0x68],ecx
00403AB2 . B8 0A000000 mov eax,0xA
00403AB7 . 894D A8 mov dword ptr ss:[ebp-0x58],ecx
00403ABA . BF 08000000 mov edi,0x8
00403ABF . 8D95 50FFFFFF lea edx,dword ptr ss:[ebp-0xB0]
00403AC5 . 8D4D B0 lea ecx,dword ptr ss:[ebp-0x50]
00403AC8 . 8945 90 mov dword ptr ss:[ebp-0x70],eax
00403ACB . 8945 A0 mov dword ptr ss:[ebp-0x60],eax
00403ACE . C785 58FFFFFF>mov dword ptr ss:[ebp-0xA8],bjanes_1.004>; UNICODE "Correct serial!"
00403AD8 . 89BD 50FFFFFF mov dword ptr ss:[ebp-0xB0],edi
00403ADE . FFD6 call esi ; <&MSVBVM60.__vbaVarDup>
00403AE0 . 8D95 60FFFFFF lea edx,dword ptr ss:[ebp-0xA0]
00403AE6 . 8D4D C0 lea ecx,dword ptr ss:[ebp-0x40]
00403AE9 . C785 68FFFFFF>mov dword ptr ss:[ebp-0x98],bjanes_1.004>; UNICODE "Good job, tell me how you do that!"
00403AF3 . 89BD 60FFFFFF mov dword ptr ss:[ebp-0xA0],edi
00403AF9 . FFD6 call esi
00403AFB . 8D55 90 lea edx,dword ptr ss:[ebp-0x70]
00403AFE . 8D45 A0 lea eax,dword ptr ss:[ebp-0x60]
00403B01 . 52 push edx
00403B02 . 8D4D B0 lea ecx,dword ptr ss:[ebp-0x50]
00403B05 . 50 push eax
00403B06 . 51 push ecx
00403B07 . 8D55 C0 lea edx,dword ptr ss:[ebp-0x40]
00403B0A . 53 push ebx
00403B0B . 52 push edx
00403B0C . FF15 30104000 call dword ptr ds:[<&MSVBVM60.#595>] ; MSVBVM60.rtcMsgBox
00403B12 . 8D45 90 lea eax,dword ptr ss:[ebp-0x70]
下面就是显示正确的消息框。
0040375A . 8985 14FFFFFF mov dword ptr ss:[ebp-0xEC],eax
00403760 . C745 E8 01000>mov dword ptr ss:[ebp-0x18],0x1 ; serial与这个有关
00403767 . FF15 C0104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
0040376D . 8D4D D4 lea ecx,dword ptr ss:[ebp-0x2C]
00403770 . FF15 C4104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObj
00403776 . 8B35 AC104000 mov esi,dword ptr ds:[<&MSVBVM60.__vbaSt>; MSVBVM60.__vbaStrMove
0040377C > 66:8B8D 14FFF>mov cx,word ptr ss:[ebp-0xEC] ; 这里是下面一个JMP回来的地方
00403783 . 66:394D E8 cmp word ptr ss:[ebp-0x18],cx ; 这里是比较次数,大于9次了就跳往成功
00403787 . 0F8F 17030000 jg bjanes_1.00403AA4 ; 这里是跳到正确的消息框的窗口
0040378D . 8B17 mov edx,dword ptr ds:[edi]
0040378F . 57 push edi
在00403787 跳转 这个位置下一个断点,再来一次“check it”,发现没有OD停下来。往上找一找看看是什么情况:
004036DC . 50 push eax ; /String
004036DD . FF15 08104000 call dword ptr ds:[<&MSVBVM60.__vbaLenBs>; \__vbaLenBstr
004036E3 . 33C9 xor ecx,ecx
004036E5 . 83F8 09 cmp eax,0x9 ; 输入的serial长度与0x9比较
004036E8 . 0F95C1 setne cl ; 如果eax 不等于 0x9,cl就等于赋值为1
004036EB . F7D9 neg ecx ; ecx取反,如果ecx为0则不变,如果为1则变成0xFFFFFFFF
004036ED . 8BF1 mov esi,ecx ; 赋值给esi到下面比较
004036EF . 8D4D E4 lea ecx,dword ptr ss:[ebp-0x1C]
004036F2 . FF15 C0104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStr
004036F8 . 8D4D D4 lea ecx,dword ptr ss:[ebp-0x2C]
004036FB . FF15 C4104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObj
00403701 . 66:3BF3 cmp si,bx ; ebx的值一直为0,所有要si的值也为0
00403704 . 0F85 1A030000 jnz bjanes_1.00403A24 ; 这里跳到显示错误消息的地方
0040370A . 8B17 mov edx,dword ptr ds:[edi]
输入的长度要9位
然后将“GNUBD”改为“GNUBD1234”,然后“check it”
这次可以看到断点断下来了。然后单步走,发现有几个比较,但是后面都没有跟跳转。
00403985 . A8 0D test al,0xD
00403987 . 0F85 1A020000 jnz bjanes_1.00403BA7
0040398D . 8B45 D8 mov eax,dword ptr ss:[ebp-0x28]
00403990 . C745 D8 00000>mov dword ptr ss:[ebp-0x28],0x0
00403997 . 8945 98 mov dword ptr ss:[ebp-0x68],eax
0040399A . 8D45 80 lea eax,dword ptr ss:[ebp-0x80]
0040399D . 50 push eax ; 字符串位置
0040399E . C745 90 08000>mov dword ptr ss:[ebp-0x70],0x8
004039A5 . FF15 B0104000 call dword ptr ds:[<&MSVBVM60.#619>] ; MSVBVM60.rtcRightCharVar
004039AB . 8D8D 30FFFFFF lea ecx,dword ptr ss:[ebp-0xD0] ; 0x8005
004039B1 . 8D55 80 lea edx,dword ptr ss:[ebp-0x80] ; 0x8
004039B4 . 51 push ecx ; /var18
004039B5 . 52 push edx ; |var28
004039B6 . FF15 A0104000 call dword ptr ds:[<&MSVBVM60.__vbaVarTs>; \__vbaVarTstNe
004039BC . 8BF8 mov edi,eax ; 这里是上面两个位置比较
004039BE . 8D45 D8 lea eax,dword ptr ss:[ebp-0x28] ; 这里是有点疑问的,两个位置的值是显然不一样的,为什么返回值eax为0xFFFFFFFF
004039C1 . 8D4D DC lea ecx,dword ptr ss:[ebp-0x24] ; 下面这些不用看
004039C4 . 50 push eax
004039C5 . 8D55 E0 lea edx,dword ptr ss:[ebp-0x20]
004039C8 . 51 push ecx
004039C9 . 8D45 E4 lea eax,dword ptr ss:[ebp-0x1C]
004039CC . 52 push edx
004039CD . 50 push eax
004039CE . 6A 04 push 0x4
004039D0 . FF15 90104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeS>; MSVBVM60.__vbaFreeStrList
004039D6 . 83C4 14 add esp,0x14
004039D9 . 8D4D D4 lea ecx,dword ptr ss:[ebp-0x2C]
004039DC . FF15 C4104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeO>; MSVBVM60.__vbaFreeObj
004039E2 . 8D4D 80 lea ecx,dword ptr ss:[ebp-0x80]
004039E5 . 8D55 90 lea edx,dword ptr ss:[ebp-0x70]
004039E8 . 51 push ecx
004039E9 . 8D45 A0 lea eax,dword ptr ss:[ebp-0x60]
004039EC . 52 push edx
004039ED . 8D4D B0 lea ecx,dword ptr ss:[ebp-0x50]
004039F0 . 50 push eax
004039F1 . 8D55 C0 lea edx,dword ptr ss:[ebp-0x40]
004039F4 . 51 push ecx
004039F5 . 52 push edx
004039F6 . 6A 05 push 0x5
004039F8 . FF15 0C104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeV>; MSVBVM60.__vbaFreeVarList
004039FE . 83C4 18 add esp,0x18 ;
00403A01 . 66:85FF test di,di ;来到这里,测试di是否为0,不为0则跳
00403A04 . 75 1C jnz Xbjanes_1.00403A22 ; 这跳了就wrong serial
00403A06 . 8B7D 08 mov edi,dword ptr ss:[ebp+0x8]
00403A09 . B8 01000000 mov eax,0x1 ; eax赋值为1
00403A0E . 66:0345 E8 add ax,word ptr ss:[ebp-0x18] ; 将[ebp-0x18]的值加上去
00403A12 . 0F80 94010000 jo bjanes_1.00403BAC ;
00403A18 . 8945 E8 mov dword ptr ss:[ebp-0x18],eax
00403A1B . 33DB xor ebx,ebx
00403A1D .^ E9 5AFDFFFF jmp bjanes_1.0040377C ; 这里是跳回去的,回到0040377C
于是就有个猜想,每次比较一个字符,比较9次,那么与serial比较的字符在哪里呢?
004038F1 > \66:8B45 E8 mov ax,word ptr ss:[ebp-0x18] ; 这里就是刚刚在403760位置赋值的地方,也可以在434A0E找到它
004038F5 . 8B1D 74104000 mov ebx,dword ptr ds:[<&MSVBVM60.#536>] ; MSVBVM60.rtcStrFromVar
004038FB . 66:35 0200 xor ax,0x2 ; 将取出来的值异或0x2,异或后的值就是serial
004038FF . 8D4D A0 lea ecx,dword ptr ss:[ebp-0x60]
00403902 . 0F80 A4020000 jo bjanes_1.00403BAC
00403908 . 51 push ecx
00403909 . 66:8945 A8 mov word ptr ss:[ebp-0x58],ax
0040390D . C745 A0 02000>mov dword ptr ss:[ebp-0x60],0x2
00403914 . FFD3 call ebx ; <&MSVBVM60.#536>
00403916 . 8BD0 mov edx,eax ; 值转为字符
00403918 . 8D4D D8 lea ecx,dword ptr ss:[ebp-0x28]
0040391B . FFD6 call esi ; 将字符串移动到ecx的地址中
0040391D . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C]
00403920 . 8D55 C0 lea edx,dword ptr ss:[ebp-0x40]
00403923 . 52 push edx
00403924 . 57 push edi
00403925 . 50 push eax
00403926 . C745 C8 01000>mov dword ptr ss:[ebp-0x38],0x1
0040392D . C745 C0 02000>mov dword ptr ss:[ebp-0x40],0x2
00403934 . FF15 44104000 call dword ptr ds:[<&MSVBVM60.#631>] ; MSVBVM60.rtcMidCharBstr
0040393A . 8BD0 mov edx,eax ; 读取字符串eax第edi位的值
0040393C . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20]
0040393F . FFD6 call esi
00403941 . 50 push eax ; /String
00403942 . FF15 1C104000 call dword ptr ds:[<&MSVBVM60.#516>] ; \rtcAnsiValueBstr
00403948 . 8D4D B0 lea ecx,dword ptr ss:[ebp-0x50]
0040394B . 66:8945 B8 mov word ptr ss:[ebp-0x48],ax
0040394F . 51 push ecx
00403950 . C745 B0 02000>mov dword ptr ss:[ebp-0x50],0x2 ; 这里将字符转为了数值,但是仍然用字符格式保存
00403957 . FFD3 call ebx
00403959 . 8BD0 mov edx,eax ; 转成了十进制的数
0040395B . 8D4D DC lea ecx,dword ptr ss:[ebp-0x24]
0040395E . FFD6 call esi
00403960 . 50 push eax
00403961 . FF15 84104000 call dword ptr ds:[<&MSVBVM60.__vbaR8Str>; MSVBVM60.__vbaR8Str
00403967 . DC25 D8104000 fsub qword ptr ds:[0x4010D8] ; 转成double再减去48,'0'的字符编码为48
0040396D . 8D55 90 lea edx,dword ptr ss:[ebp-0x70] ;
00403970 . 6A 01 push 0x1
00403972 . 52 push edx ;
显然可以看出[ebp-0x18]的值取出来eax,然后将异或0x2后的结果与输入的serial比较,相同就继续往下,又因为每次jmp之前[ebp-0x18]的值都会加1且[ebp-0x18]一开始就是1,所以结果就是:
for(int i = 1;i<=9;i++){printf("%d ",i^2);
}
会发现最后面的结果是10和11,又因为serial的长度为9位,所以不可能将10和11输入进去,再次载入的时候把前面7位输入正确“3016745”,后面两位随便来。在跟随一次。
还是没找到程序在哪里将输入的serial后面两位与10和11进行了比较,但是仍然可以从10和11的结果中猜出搭配来的。
最后的正确的serial是“301674501”
总结:
1.多留意一下那些运算的指令,可能运算结果就是serial
2.对应对在对serial进行判断前有一个跳转回来的,可以猜测是对serial的循环判断。在跳回来之前会改变比较的对象,可以从中看出每一次是用谁来进行比较、