先跑一下,这个程序应该是有定时器,多久之后自动开启,测试一下输入,序列号以字母方式输入会出现类型不匹配,之后程序自动退出
但是如果以数字方式输入序列号,则会出现,Try Again,所以这里序列号应该是一个数字
直接找Try Again这个字符串的位置,同上一题,在IDA中还是找不到,所以看Ollydbg,在地址4086f9处,这里是前一部分的标号为
004086DB loc_4086DB
应该是从下面这句跳转过来的
.text:00408677 jz short loc_4086DB
验证一下,将00408677处的jz改成jnz,74改75,然后输入序列号111,则可以发现成功了
剩下的就是算法了。
从这个位置往前找,标志位应该是下面这句设置的
.text:00408665 test si, si
再往前找,有下面两句影响了si的值
.text:0040862E xor esi, esi
.text:00408653 neg esi
xor的操作由下面这段代码决定
.text:0040860A fnstsw ax .text:0040860C test al, 0Dh ;低位为0Dh .text:0040860E jnz loc_4087BF .text:00408614 call ds:__vbaFpR8 .text:0040861A fcomp ds:dbl_401028 .text:00408620 fnstsw ax .text:00408622 test ah, 40h ;也就是说ah不能为40h .text:00408625 jz short loc_40862E .text:00408627 mov esi, 1 .text:0040862C jmp short loc_408630 .text:0040862E ; --------------------------------------------------------------------------- .text:0040862E .text:0040862E loc_40862E: ; CODE XREF: .text:00408625↑j .text:0040862E xor esi, esi ;不能走到这里,esi被清零后就会跳到错误路径 .text:00408630 .text:00408630 loc_408630: ; CODE XREF: .text:0040862C↑j
往前找到判断函数为__vbaFpR8的返回值,它的高16位不能为40h,这个是浮点寄存器的值
__vbar8Str 将一个字符串转为双精度单精度浮点型(8个字节)的数值形式
.text:004085CE mov eax, [ebp-18h] ;可以看出函数局部变量值ebp-18h表示的是序列号字符串 .text:004085D1 push eax .text:004085D2 call ds:__vbaR8Str ;此时参数为unicode编码字符串"111",也就是输入的序列号字符串 .text:004085D8 mov ecx, [ebp-1Ch] ;根据下面这个值又可以推测出这个地方局部变量的值 .text:004085DB fstp qword ptr [ebp-0E4h] .text:004085E1 push ecx .text:004085E2 call ds:__vbaR8Str ;此时参数为unicode编码字符串"4533559" .text:004085E8 cmp dword_409000, 0 .text:004085EF jnz short loc_4085F9 .text:004085F1 fdivr qword ptr [ebp-0E4h] .text:004085F7 jmp short loc_40860A
向上追到这里就可以分析出ebp-18h和ebp-1ch这两个局部变量的值,后面的浮点运算就是比较这两个值,只不过换了形式而已。直接将4533559作为序列号输入,发现直接就可以输出正确结果了。
关于字符串"4533559"的来源就是计算序列号的算法的结果。
过一下整个这段函数,其实只需要关注vbaR8Str、__vbaStrMove、__vbaStrR8这几个函数,其他函数可以直接过掉,整个流程就是不断的将字符串转成浮点数,进行操作之后又转回字符串。
整个算法流程如下: