VMP加壳(三):VMP壳爆破实战-破解某编辑类软件

摘要:
同时,记住在内存视图中向VMP0段提供断点后继续单击确认按钮,以查看调用方法的位置(此处的返回地址为0x5E01E9),但此处返回push(或vm条目)。这个地方会是验证码检测的入口吗!通过字符串查找各种键提示(sn、不正确注册等)的内存:通过访问断点查找键代码,然后找出调用该函数的函数,这与JCC指令的距离更远。

  这次爆破的是某编辑类软件,版本是32位绿色版本:V4.3.1

  VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第1张

  1、OD打开后发现了VMP0段,这里下个内存访问断点:

  VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第2张

  又来到这里了,非常明显的VMP入口特征:

  VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第3张

  一大堆push指令又开始保存物理寄存器;同时让esi指向虚拟指令集;和上面一篇文章分析的混淆手法一模一样,个人猜测用的VMP也是3.5.0版本的;

 VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第4张

 分配虚拟栈空间:

 VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第5张、 

  这里就不再重复分析整个VMP过程了,感兴趣的小伙伴建议看看之前的VMP系列介绍;为了快速定位关键位置,来到注册地方,随便输入一个辨识度较高的注册码:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第6张

   同时记得继续在内存视图给VMP0段下断点后点击确认按钮,断到这里了,继续F7:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第7张

   单步F7走着,同时在栈中回溯,找到了自己输入的sn,这个地址就很重要了,果断取消VMP0段的断点,对这个地址下读的断点:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第8张

   这里也下访问断点;继续回溯栈,在栈下方凡是这个exe本身的调用都下断点:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第9张

   这里有messageBox,栈里面也有sn和“该注册码不正确!”的关键提示,说明这里已经走到了注册错误的分支,需要回溯栈,看看在哪调用了这个方法(这里的返回地址是0x5E01E9)

   这里的地址是0x3E6000,text段的基址是0x381000,偏移=0x3E6000-0x381000=0x65000,记住这个偏移,后续可能有用;

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第10张

    继续F7,执行完messbaox弹窗后,居然回到了某个VM的入口:正常情况下,ret会回到call的下一行,但这里回到了push(或则说vm的入口),说明ret的的地址因该是人为故意加上的,也说明这段代码是关键代码,作者故意不想让逆向人员破解,真是此地无银三百两啊

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第11张

   上面这个地方会不会是验证码检测的入口了?我没仔细分析,不过既然断到这里了,就有可能是,不管那么多了,先NOP这些代码试试,结果直接崩掉,说明不能这么粗暴,重新来!

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第12张

     上面是爆破软件的传统思路:通过字符串找到各种关键提示(sn、注册不正确之类的)的内存,通过访问断点定位到关键代码,然后逐步往上回溯找到关键的JCC指令,改变JCC指令的跳转方向达到爆破的目的;由于被VMP加了很多混淆指令,直接这样简单粗暴找JCC难度不小,这条路暂时放弃,得换个思路和打法!

      2、既然3E6000是弹窗的,那么只要找出是哪个函数调用了这个函数距离JCC指令就更进一步了,上面就是这种思路。但ret后发现是VM的入口,并不是我们传统意义上的函数调用。既然动态分析行不通,那就静态查找试试;打开IDA,默认的base是401000,函数偏移是0x65000,绝对地址是466000,正好是目标函数:

  VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第13张

    为了方便,可以把base改成exe运行的base,也就是0x380000,能在3E6000这里直接看到函数了:

  VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第14张

     通过function calls能找到所有调用这个函数的函数:注意,这里的call用的是相对地址,不是绝对地址,所以直接用硬编码找是不行的

      VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第15张

     一共有24个,如果挨个看代码难度非常大,只能继续接着动态调试:每个地方都下断点,然后继续操作注册的流程,满以为能找到调用点,结果一个都没断下来,说明注册失败弹窗的函数不是这么调用了,要么是jmp到这里,要么是call 寄存器这种间接调用

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第16张

    3、静态分析也没找到关键的调用点,继续动态分析;VMP最大的特点就是混淆:明明一个简单的指令,非要用复杂的多行指令替代,那么这次就trace一下,看看从VM入口一直到弹窗,这中间究竟执行了哪些代码!

     (1)既然5E01E9是关键代码,那么先trace一下,看看都有哪些代码执行过!先在0x5E01E9下个断点,然后开启trace功能,接着上面输入sn验证的操作重新做一遍,run trace界面就能看到指令执行的记录了,如下(这里顺便吐槽一下log to file的功能,只能看到地址和寄存器的值,看不到执行的指令,WTF.......):

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第17张

    接下来就是个体力活了:挨个找寄存器里面的值等于00000040的行(后续会解释原因),挨个下断点,比如下面这样:

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第18张

    这里不得不吐槽一下OD的trace功能不好用:OD内部没法搜索关键词,保存到文件后又看不到执行的指令,很不方便,果断弃坑,换成x32dbg;trace的步骤:       

  •     在内存布局那找到VMP0段下个一次性的访问断点,然后操作注册的流程,正常情况下会断到VM入口。这时单步步进,进入VM
  •     在“跟踪”页面右键选择“启动追踪”,最后再在菜单栏选择“追踪->自动步进”,或则直接CTRL+F7

     此时x32dbg会自动开始单步步进,直到注册界面弹框;整个过程我花了一上午+中午,超过5小时,终于看到弹框;在跟踪界面查到一共执行了0x3F617=259607行代码;

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第19张

     (2)这么多行代码,该怎么分析才能找到关键的JCC指令?在“跟踪”界面,右键选择搜索->常数,表达式这里输入00000040(后面会详细解释为啥是这个数),点击确定; 

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第20张

    和0x40相关的指令有近100条,逐条筛选and指令(后续会详细解释为什么要重点查找and指令)

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第21张

    可以看到除最后一条,所有的指令都是and eax,ecx; 第1、2条分别执行一次,第3条执行了30次;

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第22张

    接下来就是纯体力活了:

  •     选中某条,右键 复制->索引;(虚拟机不好截图,用手机拍的,读者请多担待)
  • VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第23张
  •     回到跟踪窗口,ctrl+g后粘贴刚才复制的索引,定位到那行and代码;然后 右键->信息 查看寄存器的值

        VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第24张

       对于eax=0x40、eflags=0x246或0xFFFFxxxxx开始的值,都下个断点(其实一共只有3个,也不用挨个检查,直接下断点也行);

      VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第25张

       VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第26张

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第27张

     这三个and eax,ecx都有个共同点:之前都执行了not eax和not ecx,原理后续再介绍!3个断点下来后,继续操作注册的流程,3个断点都成功断下,然后挨个过滤,把执行完and eax,ecx后eax=0x0的选出来,人为把eax改成0x40或0x246;

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第28张

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第29张

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第30张

   除此以外,由于影响eax的是ecx,所以把ecx=FFFFFDB9(或者是~276,因为刚好让ZF位=0,和eax与后也会让ZF=0)找出来,挨个下断点查看:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第31张

    关键的两个and指令夹杂在jmp中间,如果不是trace,根本找不到这些关键点:

   VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第32张

   凡是eax不等于0x40的全都改成0x40

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第33张

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第34张

   终于,在改了好多次eax=0x40后,成功爆破!

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第35张

    输入注册码购买之类的也没了!

     VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第36张

      4、(1)VMP的万用门

      学过逻辑电路的朋友们都知道有一种门电路,叫与非门(俗称万用门),表示为: Nand(a,b) = ~a & ~b,就是两个数取反后再与;这是一个很普通的表达式,为啥要专门拿出来介绍?用名字就能看出来:万用门!汇编里面最基本的4种逻辑运算,都能用万用门表示,推导过程如下:

  • Not(a) = ~a = ~a & ~a = Nand(a,a)
  • Or(a,b) = a | b = ~(~a & ~b) = Nand(Nand(a,b),Nand(a,b))
  • And(a,b) = a & b = ~~a & ~~b = Nand(Nand(a,a),Nand(b,b))
  • Xor(a,b) = (~a & b) | (a & ~b) = (0 | (a & ~b)) | (0 | (b & ~a)) = (a & (~a | ~b)) | (b & (~a | ~b)) = (~a | ~b) & (a | b) = ~(a & b) | ~(~a & ~b) = Nand(And(a,b),Nand(a,b)) =Nand(Nand(Nand(a,a),Nand(b,b)),Nand(a,b))

      这里感觉就有点饶了: ~a表示a取反,用Nand(a,a)表示时是~a&~a,表达式里面又嵌套了取反,感觉有点像盗梦空间............

      再VMP 3.5.0版本中,大量使用了Nand运算来表示其他的各种逻辑,真实地隐藏了原本的各种逻辑运算,有效地加大了逆向分析的难度!所以上面

     (2)指令模拟     

     JCC跳转要依赖efalgs的标志位,而标志位又收到sub/cmp等指令的影响,如果逆向人员顺着sub/cmp等指令找JCC,会很容易暴露关键的JCC指令(我第一次就是用这种思路分析的),但找了很久都没找到关键的JCC指令,原因就是sub、cmp这种指令被混淆和模拟,请看下面的推导过程:

      cmp指令本质上是减法,只不过结果不会写回操作数,所以模拟减法就很重要了!下面是减法的模拟过程:
  •       -a = ~a+1  => ~a = -a -1
  •       ~(~a+b) = ~(-a-1+b) = -(-a-1+b)-1 = a-b  => a-b = Not(NotT(a)+b)
        a-b最终可以由Not(NotT(a)+b)来表示,而Not(a)又可以用Nand(a,a)来表示,这就导致了VMP中not eax; not ecx; and eax,ecx代码大量出现,在trace的时候某些代码甚至执行了上千次
 
     (3)eflags位模拟

       前面做的CMP、sub等指令,结果都会反馈到eflags的ZF位,不考虑其他位,当eflags=0x40时,ZF=1,JCC指令才会根据实际情况跳转, 所以要想办法改变eflags的ZF位。很不幸的是:x86汇编指并未提供可以直接修改ZF位的指令(只有STC、CTC、CMC、bt等少数指令可以修改CF位),这个该怎么修改ZF位了?

       VM的一大特点:寄存器都是虚拟的,存放在栈中,所以VM的eflags是可以随便改的!那么vm的eflags值是怎么计算得到的了? 计算方式如下:

  •  eflags = and( eflags1, 0x815) + and( eflags2, not(0x815)) ,其中eflag1和eflags2都是Nand(sn,sn)+随机数得到的,不过这两个数不重要,只要eflags的ZF=0就行;下面标红的这段就是前半段and(eflags1,0x815),eflags1原值0x286,保存在ecx;0x815在eax,and eax,ecx后把结果保存在eax=0x4,然后写入epb+4的位置(也即是虚拟eflags的位置)

         VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第37张

  • zf   = and(0x40, eflags)    ZF取决于原eflags的值。具体到汇编代码层面,用的还是and eax, ecx;,所以上面要重点对这行代码下断点调试;eflags保存在ecx(应该是0x246或0xFFFFxxxx形式),0x40保存在eax,所以断点可以根据这两个条件筛选;执行完后的结果保存在eax,然后写回栈上面的VM_CONTEXT中的eflags位置,这样代码执行完后如果eax=0,要手动改成0x40

    VMP加壳(三):VMP壳爆破实战-破解某编辑类软件第38张

    参考:  1、https://www.52pojie.cn/thread-1304279-1-2.html  爆破vm代码关键点之某文本编辑辑xxxxEdit4.3.1(4480)的分析与爆破

                 2、https://bbs.pediy.com/thread-224732.htm 谈谈vmp的爆破

                 3、https://www.52pojie.cn/thread-1036956-1-1.html  VMP学习笔记之万用门

免责声明:文章转载自《VMP加壳(三):VMP壳爆破实战-破解某编辑类软件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇RedisTemplatec++ 发送消息,模拟拖拽文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VxWorks固件分析方法总结

VxWorks固件分析方法总结 最近研究基于VxWorks系统的iot设备的固件分析方法,将学习心得记录于此,以备将来的查询需要。 1.VxWorks是什么? VxWorks是美国WindRiverSystem公司(风河公司)推出的一个RTOS(实时操作系统),凭借良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地...

[Swift]字符串大小写转换,同时实现本地化或设置语言环境

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)➤GitHub地址:https://github.com/strengthen/LeetCode➤原文地址:https://w...

用Delphi进行word开发

使用以CreateOleObjects方式调用Word 实际上还是Ole,但是这种方式能够真正做到完全控制Word文件,能够使用Word的所有属性,包括自己编写的VBA宏代码。----------------------------------------- Word宏编辑器Word能够真正地进行VBA代码的编辑,可以编写窗体、函数。进入Word宏编辑器的...

centos7配置国内yum源

文章目录 1、什么是yum仓库? 2、yum仓库配置 2.1、阿里镜像仓库配置 2.1.1、配置步骤 2.1.2、epel源 安装和配置 2.1.3、查看yum源 2.2、配置 清华大学镜像仓库 1、什么是yum仓库? yum仓库就是使用yum命令下载软件的镜像地址。 我们通常使用 yum install 命令来在线安装 linu...

如何高效判断java数组是否包含某个值

在java中,我们如何判断一个未排序数组中是否包含一个特定的值?这在java中是一个频繁非常实用的操作。那么什么样的方法才是最高效的方式?当然 ,这个问题在Stack Overflow也是得票率非常高的一个问答。得票率排在最前的几个答案给出集中不同的方法,但是他们的时间复杂度却相差甚远。本文将详细的探讨主流的方法,并给出他们各自的时间损耗。四种方法List...

《网络攻防》实验九:web安全基础实践

本次实验在XX同学的指导下完成 1.实验后回答问题 (1)SQL注入攻击原理,如何防御 SQL注入攻击的基本原理,是从客户端合法接口提交特殊的非法代码,让其注入到服务器端执行业务的SQL中去,进而改变SQL语句的原有逻辑和影响服务器端正常业务的处理。 SQL注入攻击是Web应用中一个重要的安全问题,虽然Java具备较高的安全性,但如果开发人员不注意,也有可...