[逆向工程] Linux 二进制分析(3):ELF 代码注入技术

Linux 二进制分析(3):ELF 代码注入技术

Task 1:使用十六进制编辑器修改 Bare-Metal 二进制文件

修复off-by-one漏洞

  • 按照提示将大于判断改为大于等于,意为能够遍历到组后一个字节

image-20230425234028087

image-20230425234103243

  • 这里改为了自减一后与n比较,大于等于1后跳转

image-20230425235648274

最后一字节已加密

image-20230425235140709

Task 2:使用 LD_PRELOAD 修改共享库行为

堆溢出漏洞

  • 主要原理使对标准库函数进行重写,比如对一些关键的函数,只要重写这个函数,他在执行的时候就会按照我们重写的代码取执行,以达到修改二进制行为的目的

image-20230426002424683

这里存在输入字符串的长度大于第一个参数长度,有可能将多余的字符串复制到了堆的外面,导致了堆溢出

测试:

  • 良性输入

    image-20230426004954309

  • 字符串超长

    image-20230426005019300

Q :根据执行结果,程序出现崩溃的具体原因是什么?

A :实际为缓冲区只分配了13 字节的长度,此处输入100 字节的A 导致了堆的缓冲区溢出,将字节写到了一些存有其他数据的内存区域。可能导致程序无法正常执行。如图,出现了崩溃。

检测堆溢出漏洞

image-20230426005751893

使用heapcheck.so 库来防止堆溢出

image-20230426005856926

Task 3:注入代码节(Code Section)

****elfinject 的原理:

  • 将新的节附加到二进制文件的末尾。

  • 为注入的节创建程序头和节头。(此处是覆盖现有的程序头而不是添加一个新的程序头)

分析:

  • 覆盖 PT_NOTE 段

考虑覆盖的是PT_NOTE 的程序头信息。

该头部信息只是包括了一些辅助信息,没有这部分,加载器会默认其为本机文件。因此可以安全地覆盖该头部。

  • 重定向ELF 入口点.

将ELF 头部中的e_entry 字段修改为指向新的.injected 节的地址,而不是原始入口点。

使用elfinject 注入ELF 节

将/bin/ls程序复制到当前文件夹中

image-20230426021521730

使用readelf查看该文件,在节头中有.note.ABI.tag,也就是需要覆盖的头部

image-20230426021700882

程序头部看到NOTE段,也是需要覆盖的地方

image-20230426021749428

接着,使用elfinject 工具,为ls 程序中注入hello.bin 程序。其中,设置注入的节名为.injected 。使用0x800000 作为加载地址,0 表示程序的入口点,即hello.bin 的入口点。

image-20230426021902252

之前的NOTE和tag两个已经消失,并且能看到注入的节

image-20230426022027779

image-20230426022048331

(NOTE变LOAD)

image-20230426022126711

结果

image-20230426022157004

打印出了信息

Task 4:调用注入的代码

入口点修改

使用elfinject 命令将hello.bin 文件注入到ls.entry 文件中,注入后的节名是.injected ,地址是0x8000000 。

需要注意的是这里的注入代码入口点的偏移设置为-1 ,表示没有入口点。使得elfinject 不修改入口点。

如下图,可以看到二进制文件的原始入口地址是0x4049a0 。该地址也就是执行完注入的代码之后,需要跳转去的地址。也就是打印完hello,world !之后需要去执行ls 的代码。

image-20230426041130640

image-20230426041154086

  • 使用readelf 命令查看修改之后注入代码的地址,是0x800e78 开始的实际地址。

image-20230426041048850

  • 正常执行

image-20230426041249502

  • 用hexedit修改程序入口,程序运行时也会先跳转到该执行位置执行代码

image-20230426043532680

image-20230426043518105

  • 再次执行发现成功执行

image-20230426043713704

劫持构造函数和析构函数

  • 通过readelf 可以查看到存在的.init_array 节,这也就是我们要劫持的构造函数,需要找到这个构造函数保存的指针,把这个指针改为注入代码的地址即可。

也可看到我们注入的代码在.injected 节。

image-20230426044313906

  • 使用objdump 查看.init_array 节的构造函数指针,可以看到是小端形式保存的704a40 ,也就是0x404a70

image-20230426044533264

  • 接着使用HexEdit 工 具搜索这个小端地址704a40 ,并将其改为780e80 ,就完成了对于构造函数的劫持过程。构造函数的指针已经被替换为了目标代码的地址。

image-20230426044711362

  • 此时表示,先执行注入的代码,接着注入的代码会将控制权转移回原始的构造函数。

image-20230426044741728

  • 先执行了注入的代码,后执行了ls 的命令

image-20230426044836924

篇外

  • 22
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值