逆向crackme之ESp定律脱壳

2023-10-31

1 前言

此题来自攻防世界高手进阶区的一道逆向题目 crackme,通过对可执行程序进行脱壳,该壳为北斗的壳,涉及到ESP定律,大体流程是找到call处的ESp,在数据窗口中跟随,下个硬件访问断点,就到了OEP处,用ODdump脱壳就行了。脱壳完成之后使用IDA打开查看main函数里面的伪代码写脚本,最后得到flag,这里面涉及到三个常用逆向工具的使用,exeinfope,onllydbg ida;

2 工具介绍

OllyDug

OLLYDBG是一个新的动态追踪工具,将IDA与SoftICE结合起来的思想,Ring 3级调试器,非常容易上手,己代替SoftICE成为当今最为流行的调试解密工具了。同时还支持插件扩展功能,是目前最强大的调试工具。

Ollydbg基本功能快捷键:

F2:设置断点 说明:在一条指令上设置断点,再按一次就取消断点。

F4:执行到当前光标所在的指令 说明:在遇到循环时可以使用F4执行到循环结束后的指令。

F7:单步步入 说明:遇到函数调用就跟入。

F8:单步步过 说明:遇到函数调用不跟入。

F9:继续执行 说明:运行程序直到下一个断点处。

IDA

交互式反汇编器专业版(Interactive Disassembler Professional),人们常称其为IDA Pro,或简称为IDA,是总部位于比利时列日市(Liège)的Hex-Rayd公司的一款产品。

IDA基本功能快捷键:

Enter 跟进函数实现,查看标号对应的地址

Esc 返回跟进处

A 解释光标处的地址为一个字符串的首地址

B 十六进制数与二进制数转换

C 解释光标处的地址为一条指令

D 解释光标处的地址为数据

G 快速查找到对应地址

H 十六进制数与十进制数转换

PEID

PEID是一款著名的查壳工具,其功能强大,几乎可以侦测出所有的壳,其数量已超过470 种PE 文档的加壳类型和签名。

3 实验过程

3.1 实验分析

从网站下载出可执行程序之后,首先先按照流程用PEID打开观察程序是否加壳,如下图所示:

从图中显示的结果我们可以看到,该程序存在nsPack壳,程序是32位的,这个壳的名字叫做北斗压缩壳(nsPack),下面还提示用Quick unpack工具去壳,但是这道题使用的是ESP定律手工去壳,当然,直接使用万能的脱壳工具也可以实现,但这并不是目的;

3.2 实验原理

ESP定律的原理就是“堆栈平衡”原理。

对于RETN我们可以这样来理解:

1.将当前的ESP中指向的地址出栈;

2.JMP到这个地址。

这个就完成了一次调用子程序的过程。在这里关键的地方是:如果我们要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RETN这条指令之前,ESP指向的是我们压入栈中的地址。这也就是著名的“堆栈平衡”原理!

所以我们可以把壳假设为一个子程序,当壳把代码解压前和解压后,他必须要做的是遵循堆栈平衡的原理。ESP定律一般理解可以为:

1、在命令行下断hr esp-4(此时的ESP就是OD载入后当前显示的值)

2、hr ESP(关键标志下一行代码所指示的ESP值(单步通过))

ESP定律的适用范围:几乎全部的压缩壳,部分加密壳。只要是在JMP到OEP后,ESP=0012FFC4的壳,理论上我们都可以使用。但是在何时下断点避开校验,何时下断OD才能断下来,这还需要多多总结和多多积累。

内存断点寻找OEP的原理:首先,在OD中内存断点和普通断点(F2下断)是有本质区别的。内存断点等效于命令bpm,他的中断要用到DR0-DR7的调试寄存器,也就是说OD通过这些DR0-DR7的调试寄存器来判断是否断下普通断点(F2下 断)等效于bpx,他是在所执行的代码的当前地址的一个字节修改为CC(int3)。当程序运行到int3的时候就会产生一个异常,而这个异常将交给OD 处理,把这个异常给EIP-1以后,就正好停在了需要的中断的地方(这个根据系统不同会不一样),同时OD在把上面的int3修改回原来的代码。内存断点分为:内存访问断点,内存写入断点。

3.3 操作流程

将程序拖到ollydbg中打开,如下图所示:

可以看到pushfd 和 pushad 是北斗壳的特征,前两个pushfd和pushad压入所有EFlags寄存器和通用寄存器。call执行后压入下一指令地址并跳转。

这三个指令执行后的ESP值分别0019FF74,0019FF70、0019FF50,0019FF4C,call指令是壳内代码,解压缩用的,短跳转到下一条的004061B2

两次F8执行到call语句后,然后就是在ESP处数据窗口跟踪,再在数据窗口中右键设置word级或Dword级的硬件访问断点,如图所示:

然后再点击AB所在位置设置硬件访问断点:

为什么设置断点是word级别:

除了为硬件断点指定一种模式外,还必须指定一个大小。执行类断点的大小必须为1字节,写入类或读取/写入类断点的大小可以设置为1、2或4字节。如果将大小设置为2字节,则断点的地址必须为字对齐(2字节的整数倍)。同样,4字节断点的地址必须为双字对齐(4字节的整数倍)。硬件断点的大小和它的地址共同构成了触发这类断点的地址范围。下面举例说明。以在地址0804C834h处设置的一个4字节写入式断点为例,这个断点将由1字节写入0804C837h、2字节写入0804C836h、4字节写入0804C832h等操作触发。

断点设置好之后,shift+F9运行程序,

图中我们可以看到,程序暂停在了popfd处,框中的代码就是顶替了retn语句,这里标识壳函数调用完毕,要返回了,程序为什么会停止在popfd呢;因为我们硬件访问断点断的是0019ff50,而壳内解压缩代码最多涉及call压入的0019ff4c的栈所以能访问0019ff50的只有popad,当他执行后就访问截断,所以停在popfd这里

Popfd下面的jmp就是解压缩后跳出壳外代码的OEP处;

继续F8运行

jmp跳出壳后就是解压缩的代码了,右键分析当前代码把.text.段中数据重新反汇编成汇编代码

分析之后结果如下:

然后就是在这个位置处脱壳,用OD插件OllyDump来脱壳,生成新的可执行程序:

保存之后,至此手工脱壳完成

再将脱壳之后的程序拖到IDA中;F5查看main主函数里面的伪代码可以发现:

int __cdecl main(int argc, const char **argv, const char **envp)

{

  int v3; // ebp@0

  char *v4; // ecx@1

  char v5; // al@2

  int result; // eax@4

  signed int v7; // eax@5

  int v8; // ecx@10

  *(_BYTE *)(v3 - 56) = 0;

  memset((void *)(v3 - 55), 0, 0x31u);

  printf("Please Input Flag:");

  gets_s((char *)(v3 - 56), 0x2Cu);

  v4 = (char *)(v3 - 56);

  do

    v5 = *v4++;

  while ( v5 );

  if ( &v4[-v3 + 55] == (char *)42 )

  {

    v7 = 0;

    while ( (*(_BYTE *)(v3 + v7 - 56) ^ byte_402130[v7 % 16]) == dword_402150[v7] )

    {

      if ( ++v7 >= 42 )

      {

        printf("right!\n");

        goto LABEL_10;

      }

    }

    printf("error!\n");

LABEL_10:

    v8 = v3 ^ *(_DWORD *)(v3 - 4);

    result = 0;

  }

  else

  {

    printf("error!\n");

    result = -1;

  }

  return result;

}

通过第15行代码,我们知道输入的正确flag与byte_402130[v4 % 16]进行异或等于dword_402150[v4],这个v4就是一个数组下标,最大为41

实际上就是"this_is_not_flag"

这个数字取42个就行,然后写代码:

byte_402130 = "this_is_not_flag"

dword_402150 = [ 0x12, 4, 8, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A, 0x10, 0x67,

0, 0x41, 0, 1, 0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D,

0x40, 0x3E, 0x4B, 0x5F, 2, 1, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,

0x5B, 0x12, 0, 0, 0x48 ]

x = ''

for i in range(0,42):

    x += chr(dword_402150[i]^ord(byte_402130[i%16]))

print(x)

运行代码之后得到flag:

3 结论

软件逆向是一个熟能生巧的过程,除了学习别人的经验技巧之外,更多的是需要不断的练习。软件逆向过程是比较枯燥的,必须要有足够的耐心和细心。对于我的理解:破解软件最基本的工具就是别人写好的专门用于破解分析的软件,这样的软件很多,最基本的是三个。老大叫PEID,老二叫DIE64,老三叫OD。遇到要破解的软件,兄弟依次上阵。老大先上,作用是查一下这个软件有没有加壳,是什么壳?壳就是软件的防弹衣,这个防弹衣是用专门的程序编写的,这个防弹衣是在软件有了使用验证以后又增加的一层保护。其目的就是对付我们使用的破解工具,让我们不好下手。我们的老大查了以后,知道这个防弹衣的型号就可以用对应的脱防弹衣的工具来对付它了。接着,老二再上,作用是识别这个软件是什么语言编写的,通常来说有C、VC、VB、DELPHI、易语言等,因为不同的语言有特殊的破解方法。知道有没有壳?是什么语言编写的?然后老三就闪亮登场了。OD的作用就是分析软件。分析什么?就是要找出验证的关键位置,分析验证机制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

逆向crackme之ESp定律脱壳 的相关文章

  • 【C语言刷题】将一个十进制数字转化为二进制数字

    题目描述 将一个十进制的数字转化为二进制的数字 测试用例 输入 10 输出 1010 输入 9 输出 1001 思路 可以发现二进制位是满2进1 则可以通过 2来判断是否需要进位 依次作为循环终止条件 通过 2可以判断二进制的每一位对应的数

随机推荐

  • python 实现微秒级等待(windows)

    windows限制 python 的 time sleep 方法 在windows操作系统下 最低只能实现到0 001秒 即最少等待1毫秒 时间单位 秒 second 时间单位 s 毫秒 millisecond 时间单位 ms 微秒 mic
  • Python趣味代码整合之提升学生编程兴趣

    这篇文章主要是整合一些趣味代码 一方面自己对这些内容比较感兴趣 另一方面希望这些代码能提升学生的编程兴趣 其主旨是代码能在我的电脑上运行并有些趣味 参考资料 知乎 可以用 Python 编程语言做哪些神奇好玩的事情 知乎 学习Python的
  • Windows Server 2012 R2超级详细安装教程(附下载链接)

    一 百度网盘 链接 点我下载 注意 包内有安装教程和镜像 以下是主要步骤 1 打开安装好的虚拟机 2 两种类型随意选择 第一种 典型 比较简单 快速建立虚拟机 安装比自定义的步骤较少 3 选择虚拟机硬件兼容性 我们选择当前硬件兼容性 Wor
  • 服务器连接异常系统无法登录,win10系统无法登录LOL提示“服务器连接异常”的解决方法...

    很多小伙伴都遇到过win10系统无法登录LOL提示 服务器连接异常 的困惑吧 一些朋友看过网上零散的win10系统无法登录LOL提示 服务器连接异常 的处理方法 并没有完完全全明白win10系统无法登录LOL提示 服务器连接异常 是如何解决
  • 【C++11智能指针】unique_ptr概述、初始化、常用操作、返回unique_ptr、指定删除器、尺寸

    文章目录 1 unique ptr概述 2 unique ptr的初始化 2 1 直接初始化 2 2 make unique函数 3 unique ptr不支持拷贝构造和拷贝赋值 4 unique ptr支持移动构造和移动赋值 5 uniq
  • thanos配置promethes高可用

    参考文档 https www kubernetes org cn 7217 html prometheus高可用方案 prometheus官方的高可用有几种方案 HA 即两套 prometheus 采集完全一样的数据 外边挂负载均衡 HA
  • 从技术布局看,苹果离元宇宙还有多远?

    扎克伯格的Meta元宇宙令人津津乐道 从2021年10月28日更名之始 元宇宙 Metaverse 便开始在各大媒体及圈内人士间被不断谈论 但在此之外 元宇宙的另一个 实力选手 依旧赫然在列 扎克伯格一直把它看作是竞争对手 在一次内部的谈话
  • HarmonyOS开发:解决DevEco Studio低版本导入高版本项目运行失败问题

    前言 基于DevEco Studio 4 0 Beta2 hvigorVersion为3 0 2 开发了一个项目 上传到了远程仓库 当同事下载后 却始终无法运行 频繁报错 由于API都是使用的9 第一感觉就是开发环境不同 于是 让其发来了他
  • go 进阶 gin底层原理相关: 四. gin中间件底层原理

    目录 一 gin 中间件基础 二 中间件初始化流程 1 初始化中间件保存到RouterGroup的HandlersChain数组中 HandlersChain是什么 2 整合中间件函数与业务相关的mainHandler构建前缀树 三 中间件
  • Matlab:自定义绘图颜色

    Matlab 自定义绘图颜色 在 Matlab 中绘制图形时 我们可能需要使用自己指定的颜色来填充线条 散点或者其他图案 这可以让我们的图像更加美观和易读 下面介绍两种常见的设置自定义颜色的方法 使用 RGB 颜色值 RGB 颜色值是一种由
  • idea如何导入一个spring boot 项目

    1 菜单 gt File gt New gt Project From Existing Sources 2 选中项目中的pom xml 3 点击OK 然后后面就一路 Next 直到 finish就行了 需注意你的idea工具中项目jdk和
  • 面试必问 - AES 加密 和 RSA 加密是什么?它们有什么区别

    1 什么是 AES 加密 和 RSA 加密 AES Advanced Encryption Standard 高级加密标准 AES 是一种对称加密算法 即加密和解密使用相同的密钥 AES 的密钥长度可以选择 128 位 192 位或 256
  • Vue中通过localStorage存储信息并获取显示到页面中

    这两天写了一个日程表功能 包括日程表内容的增加 删除功能 解决办法一 可以在后端写接口 把日程表的内容写到数据库中 再通过接口从数据库中获取 通过后端的接口来对数据进行增删改查 解决办法二 这次我没想着做后端接口 因为是写在浏览器首页面中
  • 怎样优化Pentium系列处理器的代码 From:http://www.codingnow.com/2000/download/pentopt.htm#26_14

    How to optimize for the Pentium family of microprocessors Copyright 1996 2000 by Agner Fog Last modified 2000 07 03 Cont
  • Redis集群实现分布式Session共享

    Cookie 保存在客户端浏览器中 而 Session 保存在服务器上 客户端浏览器访问服务器的时候 服务器把客户端信息以某种形式记录在服务器上 这就是 Session 客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就
  • Redis分布式锁的使用和实现原理详解

    这篇文章主要给大家介绍了关于Redis分布式锁的使用和实现原理的相关资料 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友们下面随着小编来一起学习学习吧 模拟一个电商里面下单减库存的场景 第一版代码 存
  • nn.LayerNorm的实现及原理

    LayerNorm 在transformer中一般采用LayerNorm LayerNorm也是归一化的一种方法 与BatchNorm不同的是它是对每单个batch进行的归一化 而batchnorm是对所有batch一起进行归一化的 y x
  • 是面试官放水,还是公司实在是太缺人?这都没挂,腾讯原来这么容易进···

    本人211非科班 之前在字节和腾讯实习过 这次其实没抱着什么特别大的希望投递 没想到腾讯可以再给我一次机会 还是挺开心的 本来以为有个机会就不错啦 没想到能成功上岸 在这里要特别感谢帮我内推的同学 中间投递比较曲折 是他帮了我很多 非常负责
  • ARM64架构-Ubuntu20更换国内镜像源

    前言 在嵌入式开发中 常用到ARM64的开发平台 进行下载东西时想换国内源 下面以中科大源为参考 一 什么是源 其实吧它就像苹果和案桌的软件应用商店一样 为Linux用户提供软件下载及更新服务的 Linux家族有三个软件源系统 yum源 使
  • 逆向crackme之ESp定律脱壳

    1 前言 此题来自攻防世界高手进阶区的一道逆向题目 crackme 通过对可执行程序进行脱壳 该壳为北斗的壳 涉及到ESP定律 大体流程是找到call处的ESp 在数据窗口中跟随 下个硬件访问断点 就到了OEP处 用ODdump脱壳就行了