逆向工程初步160个crackme-------3
这个Crackme3 涉及到浮点指令以及浮点数的存储与运算,我没学习过浮点指令,不得不从网上恶补了1个小时,一边看汇编指令一边百度其指令含义。 回头得好好补补这方面的知识了,太菜了!
我大致了解了一下浮点数运算的一些知识:
计算机中浮点数运算是由FPU进行处理的,现在FPU都集成在CPU中。FPU和CPU一样有自己独立的寄存器。FUP有8个80位的通用寄存器(这8个通用寄存器组成一个首尾相连的栈),1个状态寄存器,1个标志寄存器和1个控制寄存器。
8个通用的寄存器为 st(0) - st(7),他们用来参与浮点数的相关运算。运算完所产生的的结果反映在状态和标志寄存器中(其每个位都有每个位独立的含义)。
下面我们就开始分析这个程序!
运行一下这个程序,程序首先会弹出一个小窗口
显示几秒后又弹出一个对话框,让输入用户名和序列号。(其还有个要求是把一开始弹出的窗口去除,这个我还没有实现,哈哈我还太菜!)
我们输入错误后其会弹出一个消息框,提示:输入错误让再次尝试!
我们熟悉完程序后开始正式分析程序
- 我们先用PEID打开程序查看其基本信息。
发现是用VB写的32位程序,而且无壳!
- 然后我们打开程序并运行此程序,随便输入用户名和序列号后先不要点击确定。因为我们输入的是错误的序列号,所以我们点击确定后其会弹出消息框提示失败!此程序使用VB写的,VB一般使用弹出消息框的API函数为rtcMsgBox(),我们在此函数处下断点后点击确定按钮程序会停在此函数处。
然后我们在取消此处断点后,在栈窗口中栈顶位置右击鼠标,点击反汇编窗口跟随,反汇编窗口就会显示其调用处的代码。然后我们在此函数调用处下断点运行程序让程序停在其调用处。
我们发现在其调用处上面有序列号错误的提示信息,我们继续往上看又发现的成功的提示信息,这应该就是序列号是否正确的判断处!
往上寻找我们发现关键判断处!
00408662 . 894D 9C mov dword ptr ss:[ebp-0x64],ecx
00408665 . 66:85F6 test si,si ; 关键判断处
00408668 . 8945 94 mov dword ptr ss:[ebp-0x6C],eax
0040866B . 894D AC mov dword ptr ss:[ebp-0x54],ecx
0040866E . 8945 A4 mov dword ptr ss:[ebp-0x5C],eax
00408671 . 894D BC mov dword ptr ss:[ebp-0x44],ecx
00408674 . 8945 B4 mov dword ptr ss:[ebp-0x4C],eax
00408677 . 74 62 je XAfKayAs_.004086DB ; 爆破只需把此处用nop填充即可
00408679 . 8B35 14B14000 mov esi,dword ptr ds:[<&MSVBVM50.__vbaSt>; MSVBVM50.__vbaStrCat
0040867F . 68 C06F4000 push AfKayAs_.00406FC0 ; UNICODE "You Get It"
00408684 . 68 DC6F4000 push AfKayAs_.00406FDC ; /String = "
"
00408689 . FFD6 call esi ; \__vbaStrCat
0040868B . 8BD0 mov edx,eax
0040868D . 8D4D E8 lea ecx,dword ptr ss:[ebp-0x18]
00408690 . FF15 94B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrMo>; MSVBVM50.__vbaStrMove
00408696 . 50 push eax
00408697 . 68 E86F4000 push AfKayAs_.00406FE8 ; UNICODE "KeyGen It Now"
0040869C . FFD6 call esi
0040869E . 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 ecx
004085E2 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>
004085E8 . 833D 00904000>cmp dword ptr ds:[0x409000],0x0
004085EF . 75 08 jnz XAfKayAs_.004085F9
004085F1 . DCBD 1CFFFFFF fdivr qword ptr ss:[ebp-0xE4] ; 让我们输入的序列号与真正的序列号相除,结果为1则相等
004085F7 . EB 11 jmp XAfKayAs_.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>>
0040861A . DC1D 28104000 fcomp qword ptr ds:[0x401028] ; if( st(0) == [0x401028]) CR3状态位才为1
00408620 . DFE0 fstsw ax ; 将状态字保存到ax中
00408622 . F6C4 40 test ah,0x40 ; ah的第6位必须为1才能使esi不为0,其第6位刚好是CR3状态位
00408625 . 74 07 je XAfKayAs_.0040862E
00408627 . BE 01000000 mov esi,0x1
0040862C . EB 02 jmp XAfKayAs_.00408630
0040862E > 33F6 xor esi,esi
00408630 > 8D55 E4 lea edx,dword ptr ss:[ebp-0x1C]
00408633 . 8D45 E8 lea eax,dword ptr ss:[ebp-0x18]
00408636 . 52 push edx
00408637 . 50 push eax
00408638 . 6A 02 push 0x2
0040863A . FF15 80B14000 call dword ptr ds:[<&MSVBVM50.__vbaFreeS>
00408640 . 83C4 0C add esp,0xC
00408643 . 8D4D D8 lea ecx,dword ptr ss:[ebp-0x28]
00408646 . 8D55 DC lea edx,dword ptr ss:[ebp-0x24]
00408649 . 51 push ecx
0040864A . 52 push edx
0040864B . 6A 02 push 0x2
0040864D . FF15 08B14000 call dword ptr ds:[<&MSVBVM50.__vbaFreeO>
00408653 . F7DE neg esi ; esi不能为0
00408655 . 83C4 0C add esp,0xC
00408658 . B9 04000280 mov ecx,0x80020004
0040865D . B8 0A000000 mov eax,0xA
00408662 . 894D 9C mov dword ptr ss:[ebp-0x64],ecx
00408665 . 66:85F6 test si,si ; 关键判断处,要想成功就得esi为0
00408668 . 8945 94 mov dword ptr ss:[ebp-0x6C],eax
0040866B . 894D AC mov dword ptr ss:[ebp-0x54],ecx
0040866E . 8945 A4 mov dword ptr ss:[ebp-0x5C],eax
00408671 . 894D BC mov dword ptr ss:[ebp-0x44],ecx
00408674 . 8945 B4 mov dword ptr ss:[ebp-0x4C],eax
00408677 . 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 * 0x15B38
00408206 . 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 + edx
00408218 . 0F80 A6050000 jo AfKayAs_.004087C4
0040821E . 57 push edi ; 把edx转化为字符串
0040821F . FF15 F4B04000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>]
第二处代码块:
004082E6 . 52 push edx
004082E7 . 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],0x0
004082FC . 75 08 jnz XAfKayAs_.00408306
004082FE . D835 0C104000 fdiv dword ptr ds:[0x40100C] ; st(0) = st(0) / 5.0 ([0x40100c] 的值为5.0)
00408304 . EB 0B jmp XAfKayAs_.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 ; st(0) = st(1) + s(0) 同时 st(0)出栈
00408320 . DFE0 fstsw ax
00408322 . A8 0D test al,0xD
00408324 . 0F85 95040000 jnz AfKayAs_.004087BF
0040832A . 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,0x8
00408404 . 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
算法并不复杂,主要是这些算法都是依靠浮点指令和浮点数的运算以及浮点寄存器完成的,所以 没接触过浮点数指令的不容易分析此程序。(有时间要去补点浮点运算的知识,还有那个窗口还没有去除。害!菜的不行看来汇编知识还是不扎实,还得多扣扣汇编。)
逆向工程初步160个crackme-------3的更多相关文章
- 逆向工程初步160个crackme-------2
有了第一个crackme的经验后,这个crackme用了半个小时就验证成功了.(思路和第一个crackme相似) 动态调试工具:ollydbg (2.10) 文件分析工具:PEID (0.95) 同样 ...
- 逆向工程初步160个crackme-------7
这两天有点发烧,被这个疫情搞得人心惶惶的.我们这里是小镇平常过年的时候人来人往的,今年就显得格外的冷清.这是老天帮让在家学习啊,破解完这个crackme明天就去接着看我的加密解密,算了算没几天就开学了 ...
- 逆向工程初步160个crackme-------4
crackme–3因为涉及到浮点数操作以及一些指令和寄存器(由于本人对浮点指令不了解),所以先隔过去分析后面的程序. 工具:1. 按钮事件地址转换工具E2A 2. PEID 3. Ollydbg 首先 ...
- 逆向工程初步160个crackme-------1
放假在家学习的效率真的很低,看完看雪加密解密的前两章就迫不及待的找了几个crackme练习一下,顺便熟悉ollydbg的使用. 工具:exeinfope(查壳工具),ollydbg(2.10版) 1. ...
- 逆向工程初步160个crackme-------6
工具:1. 按钮事件地址转换器E2A 2. PEID 3. Ollydbg 同样我们先来运行一下这个程序, ok按钮是被禁用的,有一个help按钮点击后弹出一个消息框:消息框显示提示信息为.本程序需要 ...
- [反汇编练习]160个CrackMe之001
[反汇编练习] 160个CrackMe之001. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之027
[反汇编练习] 160个CrackMe之027. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之026
[反汇编练习] 160个CrackMe之026. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- [反汇编练习] 160个CrackMe之025
[反汇编练习] 160个CrackMe之025. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
随机推荐
- 2018ICPC南京I. Magic Potion
题目: 题意:n个士兵打m个怪兽,每个士兵只能打一个,但是如果有魔法药水就可多打一个问最多能打几个. 题解:如果没有魔法药就是一道裸二分图,因为现在有魔法要我们可以这样建图: 多建一个i+n的节点存放 ...
- .net core 和 WPF 开发升讯威在线客服系统【私有化部署免费版】发布
希望 .net 和 WPF 技术时至今日,还能有一些存在感. 这个项目源于2015年前后,当时开发的初版,我使用了 ASP.NET MVC 做为后端,数据库使用原生 ADO.NET 进行操作.WPF ...
- node_exporter自定义监控
背景 我们在使用Zabbix的时候,可以自己写自定义脚本.在使用Promethues的时候,有很多的exporter,但是有一些特殊的情况没有,比如,我需要监控进程一启动就告警,但是进程没启动,是使用 ...
- .Net Core3.1中SameSite的使用方法、遇到的问题以及解决办法
一.关于SameSite的介绍 1. 什么是SameSite? SameSite是浏览器请求中Set-Cookie响应头新增的一种属性,它用来标明这个 cookie 是否是"同站 cook ...
- 【JVM进阶之路】七:垃圾收集器盘点
在前面,我们已经了解了JVM的分代收集,知道JVM垃圾收集在新生代主要采用标记-复制算法,在老年代主要采用标记-清除和标记-整理算法.接下来,我们看一看JDK默认虚拟机HotSpot的一些垃圾收集器的 ...
- kubernetes dashboard 2.0 部署
dashboard 可以从微软中国提供的 gcr.io :http://mirror.azure.cn/help/gcr-proxy-cache.html免费代理下载被墙的镜像 docker pull ...
- CSS @property,让不可能变可能
本文主要讲讲 CSS 非常新的一个特性,CSS @property,它的出现,极大的增强的 CSS 的能力! 根据 MDN -- CSS Property,@property CSS at-rule ...
- OO 第一单元
OO第一单元总结 前言 第一单元 OO 作业的主题是求导,从最简单的幂函数求导,到添加三角函数求导,再到最后添加嵌套规则.(对熬夜有了新体验,OO 作业比较适合晚上写,OO 博客也是一样 doge) ...
- Java后端部署以及与Android通信注意事项
1 概述 本文列举了一些Android+后端Java通信/部署时的问题以及注意事项,覆盖的问题包括但不限于安全组.数据库.路径等,如果各位读者的Android端不能正常访问Java后端,希望这里的解决 ...
- 网络编程NIO之Reactor线程模型
目录 单Reactor线程模型 基于工作线程的Reactor线程模型 多Reactor线程模型 多Reactor线程模型示例 结束语 上篇文章中写了一些NIO相关的知识以及简单的NIO实现示例,但是示 ...