一、实验目的
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段
二、实验内容与实验要求
三个实践内容如下:
1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
3.注入一个自己制作的shellcode并运行这段shellcode。
要求:
1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
2.掌握反汇编与十六进制编程器
3.能正确修改机器指令改变程序执行流程
4.能正确构造payload进行bof攻击
三、实验环境
我使用的是kali官网提供的直接使用的虚拟机,方便快捷
四、实验过程与分析
1.基础知识理解
NOP:不执行任何有效操作,仅消耗一个指令周期,常用于指令对齐或延迟。
CMP:比较两个操作数,仅修改标志寄存器,不保存结果。
JE:相等则跳转。
JNE:不相等跳转。
JMP:无条件跳转。
反汇编:反汇编是将机器码(二进制指令)转换为人类可理解的汇编语言的过程,其核心目的是分析已编译程序的执行逻辑。
十六进制编程器:直接以十六进制(或二进制)形式查看、编辑文件字节的工具,允许用户修改文件的原始二进制数据。
2.直接修改程序机器指令,改变程序执行流程
2.1下载目标文件pwn1,反汇编
2.2找到调用foo函数的目标指令
这里的 call 8048491 指令,作用是调用位于 8048491 地址处的 foo 函数。它对应的机器指令是 e8 d7 ff ff ff,其中 e8 代表跳转操作,d7 ff ff ff 则指向 foo 函数的地址。基于此,我们要把 d7 ff ff ff 修改为 getShell 函数的地址,让指令直接调用 getShell 函数。
2.3修改返回地址
将其中的call指令的目标地址由d7ffffff变为c3ffffff,如图
2.4检验,反汇编观察是否正确调用getshell
2.5结果
3.通过构造输入参数,造成BOF攻击,改变程序执行流
如果输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。
getShell的内存地址,通过反汇编时可以看到,即0804847d。
因为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。
可以使用16进制查看指令xxd查看input文件的内容是否如预期。
然后将input的输入,通过管道符“|”,作为pwn20232410a的输入。得出结果
4.注入Shellcode并执行
4.1 通过对函数foo进行反汇编,可以发现可以发现foo的结束地址是0x080484ae,在此处设置一个断点。
4.2 当程序运行到断点时,我们发现可以发现esp寄存器的内容为0xffc61ec
4.3shellcode的地址为0xffc61ec+4=0xffc6d1f0,进行更改
4.4得到结果
五、实验结果总结
1.问题及解决
实验中,我遇到了执行文件权限不够的问题,在ai的帮助下,我使用了如下命令解决
2.实验体会
本次逆向及 Bof 基础实践围绕修改 pwn1 文件、触发 getShell 函数展开,让我对程序底层逻辑与漏洞利用有了深刻理解。
手工修改可执行文件时,通过 objdump 反汇编定位关键指令,计算地址偏移补码,再用工具修改十六进制代码,成功让程序跳转至 getShell。这一过程让我真切掌握了 call 指令与 EIP 寄存器的作用。
利用 Bof 漏洞时,借助 gdb 调试观察到输入字符串如何覆盖缓冲区、篡改返回地址,用 perl 生成攻击字符串并通过管道传入,成功触发 shell,让我体会到精准控制内存数据是漏洞利用的核心。
注入 shellcode 的实践充满挑战,从设置环境到调整 payload 结构,反复调试后才解决段错误问题。这让我明白漏洞利用不仅需技术,更需耐心。总而言之,本次实验让我受益匪浅,提升了我的网络安全素养。