[网安实践III] 实验5.补丁

[网安实践III] 实验5.补丁

冷补丁

该作业主要考察同学们对二进制文件补丁修补方法及栈溢出漏洞的理解与掌握. 所用的实验环境和工具为: 
ubuntu 18.04 LTS
gcc 7.5.0
IDA Pro 7.0
Keypatch v2.2
程序的功能是实现一个非常简单的用户交互: 要求同学们输入自己的学号, 若输入的学号为10个字符, 则在屏幕上打印一段感谢和表扬的话. 源代码中共设计了一个逻辑缺陷和一个栈溢出漏洞, 要求同学们在没有程序源代码的情况下对二进制文件进行修补. 
程序的逻辑缺陷是当输入的学号为10个字符时, 重复打印了对男孩和女孩进行感谢和表扬的话, 正常情况下只需打印其中一句即可. 修补的方法比较简单, 直接用IDA中的Keypatch插件将其中一条打印语句改为空指令即可. 

1 修改逻辑缺陷

程序的功能是实现一个非常简单的用户交互: 要求同学们输入自己的学号, 若输入的学号为 10 个字符, 则在屏幕上打印一段感谢和表扬的话. 源代码中共设计了一个逻辑缺陷和一个栈溢出漏洞, 要求同学们在没有程序源代码的情况下对二进制文件进行修补.
程序的逻辑缺陷是当输入的学号为10个字符时, 重复打印了对男孩和女孩进行感谢和表扬的话, 正常情况下只需打印其中一句即可. 修补的方法比较简单, 直接用 IDA 中的 Keypatch 插件将其中一条打印语句改为空指令即可.

  1. 修改前运行截图, 可以看到会同时输出两句话
    在这里插入图片描述
  2. 修改过程截图
    修改前程序汇编代码:
    在这里插入图片描述
  3. 将其中一个 call _puts 指令替换为空指令. 修改后程序汇编代码:
    在这里插入图片描述
  4. 最后使用 Edit->Patch program->Apply patches to input file… 将修改保存到原二进制文件中. 运行结果如图, 仅显示其中一条语句:
    在这里插入图片描述

2 修改栈溢出函数

gets() 函数是一个非常典型的栈溢出函数, 常用的修补方法是改用 read() 函数来实现 gets() 函数的功能. 由于原始的程序中没有调用 read() 函数, 因此只能利用 .eh_frame 段, 通过 3 号 syscall 调用 read() 函数来实现补丁修补.
注: .eh_frame 段是 gcc 生成的用于异常处理的代码, 它生成一个用于描述如何展开函数调用栈的表. (Ref: .eh_frame的一些资料 - CSDN)

  1. 修改前运行截图, 可以看到当输入字符超过 10 个时会使程序崩溃
    在这里插入图片描述
  2. 修改前程序汇编代码:
    在这里插入图片描述
  3. .eh_frame 段添加调用 read() 的代码. 使用 IDA Pro 通过 Edit->Patch Program->Change byte… 修改 .eh_frame 中的机器码, 机器码如下:
BA 0A 00 00 00 48 8D 75 F5 48 C7 C7 00 00 00 00 0F 05 E9 6A FE FF FF

修改后汇编代码如图:
在这里插入图片描述
注: 按 C 键可以进行数据段到代码段的表示形式的切换.
4. 在 main() 函数中将 gets() 函数替换为调用 read() 函数的代码. 方法与上述相同, 修改 main 中的 call _gets 指令为 jmp loc_880, 机器码如下:

E9 7F 01 00 00

修改后汇编代码如图:
在这里插入图片描述
5. 最后使用 Edit->Patch program->Apply patches to input file… 将修改保存到原二进制文件中. 最后运行程序, 如图, 同样输入超过 10 个字符, 但程序并不会崩溃, 不会引发栈溢出漏洞.
在这里插入图片描述

热补丁

  1. 原始程序的功能包括一个简单的用户交互: 要求同学们输入自己的学号用于进行一些运算, 运算完成之后, 程序sleep若干秒, 之后退出. 原始程序的执行效果如下图所示:
    在这里插入图片描述
  2. 查看程序的源代码, 如图. 由于使用了不安全的 gets() 函数处理输入数据, 且缓冲区大小仅 11 个字节, 因此存在栈溢出可能性. 需要进行修补.
  3. 为修补 gets() 函数栈溢出漏洞, 可以使用安全的 fgets() 函数替换 gets() 函数, 编写的补丁代码如下(假设学号为 10 位, 另含一个结束符 \0)
    在这里插入图片描述
  4. 为了修改程序的功能, 定义了新的 sleep() 函数, 代码如下:
    在这里插入图片描述
  5. 对修改后的代码进行编译, 生成 .so 链接库文件. 代码如下:
$ gcc -fPIC --shared patch.c -o patch.so
  1. 利用 PRELOAD HOOK 进行补丁修补, 使用命令:
$ LD_PRELOAD=./patch.so ./original

新的程序执行效果如图:
在这里插入图片描述

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值