网络安全综合实践-补丁技术-韩兰胜老师
实验环境
- IDA Pro 7.5
- WSL Ubuntu 20.04
keypatch插件
从网上下载的IDA Pro 7.5里是已经装了keypatch插件的,但是在安装之后,我手贱点了idapyswitch.exe,然后把整个IDA Pro的Python环境设置成了自己电脑上装的Anaconda,于是keypatch插件不仅消失了,还完全没法正常运行。需要通过以下命令将python环境设置为IDA Pro安装目录下的python.exe
.\idapyswitch.exe --force-path "{IDA_ROOT}\IDA_Pro_v7.5_Portable\python38\python3.dll"
之后再打开IDA Pro就可以找到keypatch插件并可以正常使用了
作业1
行为分析
按照老师给的实验手册,测试验证确实有两个需要打补丁的点
- 输入10位字符串后,同时输出对boy和对girl的欢迎语
- 输入少于10位字符时,程序直接结束
- 输入超出长度后,程序出现段错误
逆向分析
反汇编到C可以看到问题主要出在gets函数上
补丁修改
修补逻辑漏洞
ctrl+alt+k将girl相关内容的语句设置为nop,效果如下
修改后将内容同步到原文件
在WSL里运行一下发现只输出一种
修补栈溢出漏洞
按照指导书第三节、第四节内容,将gets函数修改为跳转到eh_frame段,在eh_frame段里将gets函数修改为只读10个字符的read系统调用,该操作对应汇编代码
mov edx, 0Ah
lea rsi, [rbp+s]
mov rdi, 0
syscall
jmp {原位置的下一条语句}
选定0x0875开始向后的一段位置填充代码,将call _gets修改为jmp 0x0875
由于keypatch识别符号有点麻烦,所以这里将lea rsi, [rbp+s]
指令留到main函数中修改,其他内容写入到eh_frame段
在main中,将这里修改
修改后执行,结果符合预期
作业2
行为分析
直接运行getshell程序,结果如下
逆向分析
反汇编看到想要利用的语句printf,需要将这里的"/bin/sh"执行
补丁修改
仿照指导书第五节内容,选择将补丁写入到目标程序的eh_frame段的方式
C代码
由于需要将汇编插入eh_frame段,直接写汇编的话就和作业1一样一样了,所以这里选择在C里写汇编的方法
int qsyPrintf(char *a, int b) {
asm("mov $0x3b, %rax\n"
"syscall\n");
}
将其生成为机器指令
gcc qsyPrintf.c -o qsyPrintf.o
Python代码
修改python代码如下(原Python代码是Python2的,但是lief早在2020年停止了对Python2的支持)
(另外由于Python2与Python3对bytes和str的区别,中间做了一些小改动)
import lief
from pwn import *
def patch_call(file, srcaddr, dstaddr, arch="amd64"):
print(hex(dstaddr))
length = p32((dstaddr - (srcaddr + 5)) & 0xffffffff)
order = b'\xe8' + length
print((disasm(order, arch=arch)))
file.patch_address(srcaddr, list(order))
binary = lief.parse("./getshell")
hook = lief.parse("./qsyPrintf.o")
sec_ehframe = binary.get_section('.eh_frame')
print(sec_ehframe.content)
sec_text = hook.get_section('.text')
print(sec_text.content)
sec_ehframe.content = sec_text.content
print(binary.get_section('.eh_frame').content)
dstaddr = sec_ehframe.virtual_address
srcaddr = 0x401149
patch_call(binary, srcaddr, dstaddr)
binary.write('getshell.patched')
执行结果
修改段属性
但是这样操作后,执行生成的getshell.patched就会报错
需要用010Editor修改段属性,需要使用010Editor的ELF模板
至于要修改哪儿呢,还得回到linux用readelf查看一下
可以看到.eh_frame段是保存在了04节,对应虚拟地址起始地址0x402000
于是修改这部分的p_flags为可执行
修改后就可以执行了