zoukankan      html  css  js  c++  java
  • X86逆向10:学会使用硬件断点

    本节课我们将学习硬件断点的使用技巧,硬件断点是由硬件提供给我们的一组寄存器,我们可以对这些硬件寄存器设置相应的值,然后让硬件帮我们断在需要下断点的地址上面,这就是硬件断点,硬件断点依赖于寄存器,这些寄存器有个通用的名称,即调试寄存器,调试寄存器一共有8个分别从Dr0-Dr7。在软件破解中硬件断点常用来寻找赋值或读取的原始位置。

    硬件断点并不是OD等调试器的特有功能,调试器只是把用户的需求转换成特定的格式,并写入DRX寄存器组中,等待硬件返回执行结果,由于硬件断点是由CPU直接提供硬件级别的支持,所以硬件断点的效率是所有断点中最高的。

    在OD等调试器中,除了硬件断点之外,还有个内存断点,内存断点通过修改内存页的属性并捕获异常来间接暂停被调试的程序运行,内存断点的效率大大低于硬件断点,但内存断点的自由性大于硬件断点,通常情况下能用硬件断点则不要使用内存断点,有时候容易卡成狗。

    ------------------------------------------------------------
    本章难度:★★★★☆☆☆☆☆☆
    课程课件:CM_10.zip
    ------------------------------------------------------------

    1.老样子在进行破解实战之前,我们先来看一个CM小程序,先了解一下硬件断点的使用技巧,如下OD直接载入这个CM程序然后运行。

    2.我们直接按下【Ctrl + B】,输入按钮事件特征码【FF 55 FC 5F 5E】,然后在CALL的位置下断点。

    3.回到CM程序,点击【测试硬件写入断点】,OD断下后按下【F7】进入到CALL的内部,也就是按钮的按钮事件。

    上图有CMP指令,该指令取出【4A25F0】中的数值,和0做了一次比较,从而影响了JNZ跳转,我们接下来就是找到是谁向这个内存地址写入的数据。

    4.直接在数据窗口,按下【Ctrl +G】,输入内存地址【4A25F0】,会发现其中的数值是0。

    5.选择数据窗口中的第一个DWORD数据,然后选择【断点】,【硬件写入】,【DWORD】,这里的DWORD是由CMP指令决定的,此处【CMP DWORD PTR】所以我们需要下一个DWORD断点。

    6.下完断点后重新载入程序,然后运行程序会直接断下,你会发现一条【MOV DWORD 】这样的赋值语句,没错这就是源头。

    实战:破解 HofoSetup 2019

    免责声明:该教程仅用于技术交流,并无任何商业目的,您不得将下述内容用于商业或者非法用途,否则后果自负,如果您喜欢该程序,请支持正版软件,购买注册 ,得到更好的正版服务,如有侵权请邮件联系作者!

    1.首先OD载入然后直接,【F9】运行程序,并记下关键字符串,这里我们记下【vip】这段。

    2.直接在反汇编窗口,右键选择中文搜索,智能搜索字符串,并查找带有vip的字符串,这里我找到了如下字符串。

    3.这里我们看到了关键的比较和关键的跳转,但并没有发现关键CALL,这里的CMP指令的意思是,取出[eax]寄存器地址里面的一个字节和0进行比较并影响关键的跳转,接下来我们将查找是谁向这个内存地址中写入了数据,也就是说我们要找到谁给[eax]寄存器赋值找它的源头。

    4.直接在反汇编窗口中选择,数据窗口中跟随,选择内存地址,会发现数据窗口地址变了。

    5.直接在数据窗口中右键选择,断点,硬件写入断点,字节型。

    6.此时,取消其他的所有内存断点,只保留一个硬件写入断点,然后我们重新载入程序并运行起来。

    7.运行后会断下多次,我们不用管直接再次运行,然后回到程序中,点击【添加自定义快捷方式】,此时OD会直接断下。

    8.下方会发现OD自动断在了【0042128A】的位置上,也就是说是上一条命令写入的,我们从下向上分析一下代码。

    【mov byte ptr [ebx+4D8],al  】将al中的数写入到,[ebx+4D8]的地址中去,0011F700+4D8=0011FBD8刚好是我们下硬件断点的地址处。

    【setne al】 这条指令很有意思,经过我的测试,当al中的数值不为0时直接返回al=1,如果为零则al就等于0,此处al只会从【1,0】中取值。

    【CALL CNsCode::CheckCode】 这一段应该就是验证我们是否为合法用户的关键CALL了,内部是计算的核心代码。

    9.我们就直接跟在CALL的位置下一个断点,并删除硬件断点吧,找到了更近的我们就删除远的,然后点击运行,让程序运行起来。

    10.回到程序,再次点击【添加自定义快捷方式】按钮,程序会断在刚才的CALL处,我们直接【F7】跟进去看看,嗯!果然是核心CALL,看下方这么多处调用了这个CALL来完成用户身份的验证。

    11.此时我们直接到CALL的断尾,看返回值返回了多少,直接单步【F8】,或者按下【Ctrl + F9】执行到返回,这里我们暂时不分析注册算法。

    12.好了,回到CALL的断首,然后写入以下汇编代码,直接让其返回1。

    13.直接点击OD的运行按钮,让程序跑起来,然后点击箭头指向的图标,选择【注册VIP用户按钮】,程序提示完成了注册。

    写教程不容易,转载请加出处,您添加出处,是我创作的动力!


    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
  • 相关阅读:
    JavaScript cookie详解
    Javascript数组的排序:sort()方法和reverse()方法
    javascript中write( ) 和 writeln( )的区别
    div做表格
    JS 盒模型 scrollLeft, scrollWidth, clientWidth, offsetWidth 详解
    Job for phpfpm.service failed because the control process exited with error code. See "systemctl status phpfpm.service" and "journalctl xe" for details.
    orm查询存在价格为空问题
    利用救援模式破解系统密码
    SSH服务拒绝了密码
    C# 调用 C++ DLL 中的委托,引发“对XXX::Invoke类型的已垃圾回收委托进行了回调”错误的解决办法
  • 原文地址:https://www.cnblogs.com/LyShark/p/11181812.html
Copyright © 2011-2022 走看看