博客
关于我
逆向工程初步160个crackme-------3
阅读量:661 次
发布时间:2019-03-16

本文共 8651 字,大约阅读时间需要 28 分钟。

这个Crackme3 涉及到浮点指令以及浮点数的存储与运算,我没学习过浮点指令,不得不从网上恶补了1个小时,一边看汇编指令一边百度其指令含义。 回头得好好补补这方面的知识了,太菜了!

我大致了解了一下浮点数运算的一些知识:

计算机中浮点数运算是由FPU进行处理的,现在FPU都集成在CPU中。FPU和CPU一样有自己独立的寄存器。FUP有8个80位的通用寄存器(这8个通用寄存器组成一个首尾相连的栈),1个状态寄存器,1个标志寄存器和1个控制寄存器
8个通用的寄存器为 st(0) - st(7),他们用来参与浮点数的相关运算。运算完所产生的的结果反映在状态和标志寄存器中(其每个位都有每个位独立的含义)。

下面我们就开始分析这个程序!

运行一下这个程序,程序首先会弹出一个小窗口

显示几秒后又弹出一个对话框,让输入用户名和序列号。(其还有个要求是把一开始弹出的窗口去除,这个我还没有实现,哈哈我还太菜!)

我们输入错误后其会弹出一个消息框,提示:输入错误让再次尝试!
我们熟悉完程序后开始正式分析程序

  1. 我们先用PEID打开程序查看其基本信息。
    发现是用VB写的32位程序,而且无壳!
  2. 然后我们打开程序并运行此程序,随便输入用户名和序列号后先不要点击确定。因为我们输入的是错误的序列号,所以我们点击确定后其会弹出消息框提示失败!此程序使用VB写的,VB一般使用弹出消息框的API函数为rtcMsgBox(),我们在此函数处下断点后点击确定按钮程序会停在此函数处。
    然后我们在取消此处断点后,在栈窗口中栈顶位置右击鼠标,点击反汇编窗口跟随,反汇编窗口就会显示其调用处的代码。然后我们在此函数调用处下断点运行程序让程序停在其调用处。
    我们发现在其调用处上面有序列号错误的提示信息,我们继续往上看又发现的成功的提示信息,这应该就是序列号是否正确的判断处!
    往上寻找我们发现关键判断处!
00408662   .  894D 9C       mov dword ptr ss:[ebp-0x64],ecx00408665   .  66:85F6       test si,si                               ;  关键判断处00408668   .  8945 94       mov dword ptr ss:[ebp-0x6C],eax0040866B   .  894D AC       mov dword ptr ss:[ebp-0x54],ecx0040866E   .  8945 A4       mov dword ptr ss:[ebp-0x5C],eax00408671   .  894D BC       mov dword ptr ss:[ebp-0x44],ecx00408674   .  8945 B4       mov dword ptr ss:[ebp-0x4C],eax00408677   .  74 62         je XAfKayAs_.004086DB                    ;  爆破只需把此处用nop填充即可00408679   .  8B35 14B14000 mov esi,dword ptr ds:[<&MSVBVM50.__vbaSt>;  MSVBVM50.__vbaStrCat0040867F   .  68 C06F4000   push AfKayAs_.00406FC0                   ;  UNICODE "You Get It"00408684   .  68 DC6F4000   push AfKayAs_.00406FDC                   ; /String = ""00408689   .  FFD6          call esi                                 ; \__vbaStrCat0040868B   .  8BD0          mov edx,eax0040868D   .  8D4D E8       lea ecx,dword ptr ss:[ebp-0x18]00408690   .  FF15 94B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrMo>;  MSVBVM50.__vbaStrMove00408696   .  50            push eax00408697   .  68 E86F4000   push AfKayAs_.00406FE8                   ;  UNICODE "KeyGen It Now"0040869C   .  FFD6          call esi0040869E   .  8945 CC       mov dword ptr ss:[ebp-0x34],eax

接着我们需要往上追码:分析其判断处理算法。

004085D8   .  8B4D E4       mov ecx,dword ptr ss:[ebp-0x1C]004085DB   .  DD9D 1CFFFFFF fstp qword ptr ss:[ebp-0xE4]004085E1   .  51            push ecx004085E2   .  FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>004085E8   .  833D 00904000>cmp dword ptr ds:[0x409000],0x0004085EF   .  75 08         jnz XAfKayAs_.004085F9004085F1   .  DCBD 1CFFFFFF fdivr qword ptr ss:[ebp-0xE4]            ;  让我们输入的序列号与真正的序列号相除,结果为1则相等004085F7   .  EB 11         jmp XAfKayAs_.0040860A004085F9   >  FFB5 20FFFFFF push dword ptr ss:[ebp-0xE0]004085FF   .  FFB5 1CFFFFFF push dword ptr ss:[ebp-0xE4]00408605   .  E8 888AFFFF   call 
0040860A > DFE0 fstsw ax0040860C . A8 0D test al,0xD0040860E . 0F85 AB010000 jnz AfKayAs_.004087BF00408614 . FF15 34B14000 call dword ptr ds:[<&MSVBVM50.__vbaFpR8>>0040861A . DC1D 28104000 fcomp qword ptr ds:[0x401028] ; if( st(0) == [0x401028]) CR3状态位才为100408620 . DFE0 fstsw ax ; 将状态字保存到ax中00408622 . F6C4 40 test ah,0x40 ; ah的第6位必须为1才能使esi不为0,其第6位刚好是CR3状态位00408625 . 74 07 je XAfKayAs_.0040862E00408627 . BE 01000000 mov esi,0x10040862C . EB 02 jmp XAfKayAs_.004086300040862E > 33F6 xor esi,esi00408630 > 8D55 E4 lea edx,dword ptr ss:[ebp-0x1C]00408633 . 8D45 E8 lea eax,dword ptr ss:[ebp-0x18]00408636 . 52 push edx00408637 . 50 push eax00408638 . 6A 02 push 0x20040863A . FF15 80B14000 call dword ptr ds:[<&MSVBVM50.__vbaFreeS>00408640 . 83C4 0C add esp,0xC00408643 . 8D4D D8 lea ecx,dword ptr ss:[ebp-0x28]00408646 . 8D55 DC lea edx,dword ptr ss:[ebp-0x24]00408649 . 51 push ecx0040864A . 52 push edx0040864B . 6A 02 push 0x20040864D . FF15 08B14000 call dword ptr ds:[<&MSVBVM50.__vbaFreeO>00408653 . F7DE neg esi ; esi不能为000408655 . 83C4 0C add esp,0xC00408658 . B9 04000280 mov ecx,0x800200040040865D . B8 0A000000 mov eax,0xA00408662 . 894D 9C mov dword ptr ss:[ebp-0x64],ecx00408665 . 66:85F6 test si,si ; 关键判断处,要想成功就得esi为000408668 . 8945 94 mov dword ptr ss:[ebp-0x6C],eax0040866B . 894D AC mov dword ptr ss:[ebp-0x54],ecx0040866E . 8945 A4 mov dword ptr ss:[ebp-0x5C],eax00408671 . 894D BC mov dword ptr ss:[ebp-0x44],ecx00408674 . 8945 B4 mov dword ptr ss:[ebp-0x4C],eax00408677 . 74 62 je XAfKayAs_.004086DB ; 爆破只需把此处用nop填充即可00408679 . 8B35 14B14000 mov esi,dword ptr ds:[<&MSVBVM50.__vbaSt>0040867F . 68 C06F4000 push AfKayAs_.00406FC0 ; UNICODE "You Get It"00408684 . 68 DC6F4000 push AfKayAs_.00406FDC ; /String = ""00408689 . FFD6 call esi ; \__vbaStrCat

只有当我们输入的序列号的值等于 st(0)时才能成功,而st(0)中存储的是正确的序列号的浮点数形式。 我们接下来需要分析此序列号是如何产生的。

我们继续往上分析发现从函数头部到判断转移处共有四处代码块参与序列号的生成。
第一处代码块:

004081E9   > \8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0]004081EF   .  8B45 E4       mov eax,dword ptr ss:[ebp-0x1C]004081F2   .  50            push eax                                         ; /004081F3   .  8B1A          mov ebx,dword ptr ds:[edx]                       ; |004081F5   .  FF15 F8B04000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>]     ; \004081FB   .  8BF8          mov edi,eax                                      ;  edi =  用户名的长度004081FD   .  8B4D E8       mov ecx,dword ptr ss:[ebp-0x18]00408200   .  69FF 385B0100 imul edi,edi,0x15B38                             ;  edi * 0x15B3800408206   .  51            push ecx                                         ; /00408207   .  0F80 B7050000 jo AfKayAs_.004087C4                             ; |0040820D   .  FF15 0CB14000 call dword ptr ds:[<&MSVBVM50.#516>]             ; \00408213   .  0FBFD0        movsx edx,ax                                     ;  edx = 用户名的第一个字符00408216   .  03FA          add edi,edx                                      ;  edi = edi + edx00408218   .  0F80 A6050000 jo AfKayAs_.004087C40040821E   .  57            push edi                                         ;  把edx转化为字符串0040821F   .  FF15 F4B04000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>]

第二处代码块:

004082E6   .  52            push edx004082E7   .  8B19          mov ebx,dword ptr ds:[ecx]004082E9   .  FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>]       ;  st(0)  = 刚才计算产生的字符串的浮点形式004082EF   .  D905 08104000 fld dword ptr ds:[0x401008]                      ;  st(0)  =  10.0   栈中各个数据都往下压一层([0x401008] 的值为10.0)004082F5   .  833D 00904000>cmp dword ptr ds:[0x409000],0x0004082FC   .  75 08         jnz XAfKayAs_.00408306004082FE   .  D835 0C104000 fdiv dword ptr ds:[0x40100C]                     ;  st(0) = st(0) / 5.0    ([0x40100c] 的值为5.0)00408304   .  EB 0B         jmp XAfKayAs_.0040831100408306   >  FF35 0C104000 push dword ptr ds:[0x40100C]0040830C   .  E8 578DFFFF   call 
00408311 > 83EC 08 sub esp,0x800408314 . DFE0 fstsw ax00408316 . A8 0D test al,0xD00408318 . 0F85 A1040000 jnz AfKayAs_.004087BF0040831E . DEC1 faddp st(1),st ; st(0) = st(1) + s(0) 同时 st(0)出栈00408320 . DFE0 fstsw ax00408322 . A8 0D test al,0xD00408324 . 0F85 95040000 jnz AfKayAs_.004087BF0040832A . DD1C24 fstp qword ptr ss:[esp] ; 把st(0)的数据保存到[esp],在把浮点栈出栈0040832D . FF15 48B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrR8>]00408333 . 8BD0 mov edx,eax

第三处代码块:

004083F3   .  8B19          mov ebx,dword ptr ds:[ecx]004083F5   .  FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>]004083FB   .  DC0D 10104000 fmul qword ptr ds:[0x401010]                     ;  st(0) = st(0) * 3.0      ([0x401010]处值为3.0)00408401   .  83EC 08       sub esp,0x800408404   .  DC25 18104000 fsub qword ptr ds:[0x401018]0040840A   .  DFE0          fstsw ax                                         ;  st(0) = st(0) - 2.0      ([0x401018]处的值为2.0)

第四处代码块:

004084DD   .  8B19          mov ebx,dword ptr ds:[ecx]004084DF   .  FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>]004084E5   .  DC25 20104000 fsub qword ptr ds:[0x401020]                     ;  st(0) = st(0) + 15.0

总结st(0)的值产生的算法:

(用户名的长度 * 0x15B38 + 用户名的第一个字符)* 3 + 13

算法并不复杂,主要是这些算法都是依靠浮点指令和浮点数的运算以及浮点寄存器完成的,所以 没接触过浮点数指令的不容易分析此程序。(有时间要去补点浮点运算的知识,还有那个窗口还没有去除。害!菜的不行看来汇编知识还是不扎实,还得多扣扣汇编。)

转载地址:http://dscqz.baihongyu.com/

你可能感兴趣的文章
wxwidgets事件处理
查看>>
用OpenCv转换原始图像数据到wximage
查看>>
codeblocks下wxWidgets编译与配置
查看>>
OpenCv+wxwidgets尝试
查看>>
wxwidgets自定义事件+调试
查看>>
wxwidgets编写多线程程序--wxThread
查看>>
BUUCTF:[湖南省赛2019]Findme
查看>>
ciscn2021西北部分pwn
查看>>
p144循环网络
查看>>
Finger.01 - ESP8266模块STA模式调试
查看>>
三维点云处理
查看>>
springboot security 基于redis的session共享(7)
查看>>
vue 权限管理 菜单按钮权限控制(7)
查看>>
vue 权限管理 主题切换(8)
查看>>
Qt 在Excel文件中Chart绘图
查看>>
U3D资源加载
查看>>
01-webpack5理解及配置
查看>>
JavaScript作用域和作用域链
查看>>
webpack的安装和使用
查看>>
Unable to run Intel® HAXM installer: 无法启动过程,工作目录
查看>>