本文最后更新于:2021-08-09 晚上
初探
打开程序看到需要输入用户名和序列号尝试输入后提示错误
分析
使用工具查看,发现未加壳,语言是VB。
用OD打开程序,直接搜素错误字符串即可定位。首先还是和002一样,先是获取长度然后进行一些操作再加上NAME[0]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 004081E3 . FF15 18B14000 call dword ptr ds:[<&MSVBVM50.__vbaHresu>; Msvbvm50.__vbaHresultCheckObj 004081E9 > 8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0] 004081EF . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C] ; 获取输入的name 004081F2 . 50 push eax ; /String = 00004000 ??? 004081F3 . 8B1A mov ebx,dword ptr ds:[edx] ; | 004081F5 . FF15 F8B04000 call dword ptr ds:[<&MSVBVM50.__vbaLenBs>; \获取name长度 004081FB . 8BF8 mov edi,eax 004081FD . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18] 00408200 . 69FF 385B0100 imul edi,edi,0x15B38 ; 长度乘以0x15B38 00408206 . 51 push ecx ; /String = 091C840A ??? 00408207 . 0F80 B7050000 jo AfKayAs_.004087C4 ; | 0040820D . FF15 0CB14000 call dword ptr ds:[<&MSVBVM50.#516>] ; \获取输入name的第一次ascii码 00408213 . 0FBFD0 movsx edx,ax 00408216 . 03FA add edi,edx ; 长度计算后加上name[0] 00408218 . 0F80 A6050000 jo AfKayAs_.004087C4 0040821E . 57 push edi ; Msvbvm50.__vbaObjSet 0040821F . FF15 F4B04000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>; 转字符串(十进制)
|
然后将结果转为浮点数执行了几次操作。
第一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 004082E9 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>; 转为浮点数 004082EF . D905 08104000 fld dword ptr ds:[0x401008] ; 10 004082F5 . 833D 00904000>cmp dword ptr ds:[0x409000],0x0 004082FC . 75 08 jnz short AfKayAs_.00408306 004082FE . D835 0C104000 fdiv dword ptr ds:[0x40100C] ; 10/5 00408304 . EB 0B jmp short AfKayAs_.00408311 00408306 > FF35 0C104000 push dword ptr ds:[0x40100C] 0040830C . E8 578DFFFF call <jmp.&MSVBVM50._adj_fdiv_m32> 00408311 > 83EC 08 sub esp,0x8 00408314 . DFE0 fstsw ax 00408316 . A8 0D test al,0xD 00408318 . 0F85 A1040000 jnz AfKayAs_.004087BF 0040831E . DEC1 faddp st(1),st ; +2 00408320 . DFE0 fstsw ax 00408322 . A8 0D test al,0xD 00408324 . 0F85 95040000 jnz AfKayAs_.004087BF 0040832A . DD1C24 fstp qword ptr ss:[esp] 0040832D . FF15 48B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrR8>; 转回去
|
第二次
| 004083F5 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>; Msvbvm50.__vbaR8Str 004083FB . DC0D 10104000 fmul qword ptr ds:[0x401010] ; *3 00408401 . 83EC 08 sub esp,0x8 00408404 . DC25 18104000 fsub qword ptr ds:[0x401018] ; -2 0040840A . DFE0 fstsw ax 0040840C . A8 0D test al,0xD 0040840E . 0F85 AB030000 jnz AfKayAs_.004087BF 00408414 . DD1C24 fstp qword ptr ss:[esp] 00408417 . FF15 48B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrR8>; Msvbvm50.__vbaStrR8
|
第三次
| 004084DF . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>; Msvbvm50.__vbaR8Str 004084E5 . DC25 20104000 fsub qword ptr ds:[0x401020] ; +15 004084EB . 83EC 08 sub esp,0x8 004084EE . DFE0 fstsw ax 004084F0 . A8 0D test al,0xD 004084F2 . 0F85 C7020000 jnz AfKayAs_.004087BF 004084F8 . DD1C24 fstp qword ptr ss:[esp] 004084FB . FF15 48B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrR8>; Msvbvm50.__vbaStrR8
|
最后的比较也是使用浮点数进行比较,用计算出结果除以我们输入,再与1进行比较。
| 004085F1 . DCBD 1CFFFFFF fdivr qword ptr ss:[ebp-0xE4] ; 计算的serial/输入 004085F7 . EB 11 jmp short AfKayAs_.0040860A 004085F9 > FFB5 20FFFFFF push dword ptr ss:[ebp-0xE0] 004085FF . FFB5 1CFFFFFF push dword ptr ss:[ebp-0xE4] 00408605 . E8 888AFFFF call <jmp.&MSVBVM50._adj_fdivr_m64> 0040860A > DFE0 fstsw ax 0040860C . A8 0D test al,0xD 0040860E . 0F85 AB010000 jnz AfKayAs_.004087BF 00408614 . FF15 34B14000 call dword ptr ds:[<&MSVBVM50.__vbaFpR8>>; Msvbvm50.__vbaFpR8 0040861A . DC1D 28104000 fcomp qword ptr ds:[0x401028] ; 结果与1进行比较 00408620 . DFE0 fstsw ax ; 将寄存器的值传给AX 00408622 . F6C4 40 test ah,0x40 ; 比较ah值与0x40 00408625 . 74 07 je short AfKayAs_.0040862E ; 若不相等就会跳到清空esi处 00408627 . BE 01000000 mov esi,0x1 ; 相等esi赋值1 0040862C . EB 02 jmp short AfKayAs_.00408630 0040862E > 33F6 xor esi,esi ; 清空寄存器
|
这里 fcomp是比较后改变寄存器状态,然后再由fstsw指令将寄存器值传给ax
比较结果 |
C3 |
C0 |
ST(0)>源操作数 |
0 |
0 |
ST(0)<源操作数 |
0 |
1 |
ST(0)=源操作数 |
1 |
0 |
ST(0)不可比较 |
1 |
1 |
看一下FST寄存器,看到寄存器中的值,此时是输入等于计算的时候,看到FST是4000,C3是1
计算器转换一下看的仔细
注册机
| #include "pch.h" #include <iostream> #include <Windows.h> int main() { printf("输入name\n"); char name[20]; gets_s(name, 20); int len = strlen(name); int serial; serial = len * 0x15B38; serial += name[0]; serial = (serial + 2) * 3 - 2 + 15; printf("serial:%d\n", serial); return 0; }
|
输入正确的serial