20211917 2021-2022-2 《网络攻防实践》第九周作业
1.实践内容
1.1 实践目标
-
这一实践的目标是 linux可执行程序pwn1。这个程序的正常运行过程如下: main调用 foo函数, foo函数将只显示出用户所输入的字符串。这个程式包含了另外一段程式码,即 getShell,它会传回一个有效的 Shell。通常不会执行该代码。我们的目的是找到一种方法来执行这些代码。我们将学到两种运行此代码的方式,并了解怎样将 Shellcode注入其中。
-
三个实践内容如下:
(1)手动地对可执行文件进行修改,更改程序的运行过程,并直接跳到 getShell功能。
(2)使用 foo函数 Bof的缺陷,构建一个覆盖返回地址并触发 getShell功能的攻击输入字串。
(3)输入你自己创建的 shellcode,然后运行这个 shellcode。
1.2 实验要求
- 熟练使用非、 JNE、 JE、 JMP、 CMP汇编指令
- 精通十六进制解集程序
- 能够正确地更改机械指示,更改程序的运行过程
- 能够为 bof攻击构建合适的 payload
2.实践过程
2.1 手动地修改可执行文件、更改程序的运行过程、直接跳到 getShell功能
-
将 Kali虚拟机用作该实践的主机。
-
试图通过 objdump解压缩指令来检查pwn1程序的代码和逻辑。
-
命令: objdump- d./pwn1| more.

-
在代码节中发现 getshell。

-
检查主函数的程式码,会发现在80484b5上,e8d7 ff ff fff fF ff,从这里可以看出,e8是 call,d7 fff是 foo函数的移位,在这个时候, EIP的地址是80484ba, foo函数是这样的。因此,如果改变相对位移量,使得主函数调用 getshell,则可以得到修正的位移量:(0x0804847d-0x080484ba)%0x100000000=0x8048491。
-
因此,我们需要先找出d7,然后将d7改为c3。
-
如果你用 vim来打开pwn1,就会发现所有的代码都是乱七八糟的,所以就把pwn1拷贝一份(cp./pwn1pwn2),并把pwn2作为对照。

- pwn2中的 vim打开:%!xxd是否可以通过 vim的查询功能转化为16进制?d7找到d7,并进行修正。

-
完成修改后,输入%!xxd- r恢复, wq保存。
-
如果你同时运行pwn1和pwn2,就会发现你已经完成了修改,并且已经获得了 shell。

2.2 使用 foo功能的 Bof缺陷,构建一个覆盖返回地址并触发 getShell功能的攻击输入字符串
-
先检查pwn1文件中的 foo功能的汇编代码,然后再进行拆装指令。

-
因为没有限定输入长度, foo函数有 BOF漏洞,保留了0x38的本地变量, gets函数将读入的字符串存储到0x1c,即28个字节。当一个字串的长度大于28个字节时,会有一个缓冲溢出。
-
pwn1是用 gdb来调试的。
-
输入一个“aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee”的字符串,该字符串具有40个长度。

-
输入 info r来检查目前的注册值, ebp注册的值是0x6464646464, d是 ASCLL代码的64位数,而 eip寄存器中的数据是0x65656565, e是 ASCLL代码的十六进位是65。溢出到电子注册中的空格。
-
然后我们就可以在这个溢出中执行 getShell功能,只需要把它的输入字串的位置正确地设定为一个 getShell函数的一个条目。由于 ebp和 eip的单元长度都是4个字节,因此,我们只需要在33到36个字节中,将 getShell函数的条目地址填满。
-
通过命令 perl- e" print"190419041904\x7d\x84\x04\x08\x0a"'》 input生成十六进制字符串“input”
-
通过(输入;pwn1命令把 input作为pwn1的输入,这样就可以得到 shell

2.3 输入您自己创建的 shellcode,然后执行这个 shellcode
- 利用 execstack等指令来设定可运行的堆叠和停用地址的随机性

-
使用 retaddr+ nop+ shellcode的方式来构建 shellcode,将 shellcode放在缓冲后面。
-
通过命令来构建一个输入的字串perl\x68\x68\x2f\x62\x69\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
-
由(输入编码;pwn1指令在pwn1中输入input_shellcode。

-
打开其他终端来检查pwn1的处理 id,然后用 gdb对pwn1进行调试,然后在 foo功能完成前设置断点,然后继续运行,这时您需要回到pwn1中输入特定的字符串,当断点被切断后,再检查当前的 esp寄存器,从前面的输入可以看出,如果栈顶指针是\X4\X3\X2\X1,那么 retaddr的值就能计算出来。

- 得到 retaddr的值,就可以构建32个 A+ retaddr+ nop+ shellcode: perl- e' print" A"x32;\x90\x90\x31\xc0\x50\x68\x2f\x62\x69\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"'》input_shellcode1
- 把它作为pwn1的输入,可以获得 shell

3.学习中遇到的问题及解决
-
问题1:execstack无法安装
-
问题1解决方式:更换kali源并apt update
4.实践总结
- 在这个试验中,我了解了怎样改变可执行程序的顺序,来调用特定的功能。还有一种方法,就是使用 BoF漏洞,它会让缓存溢出比缓存大得多的字符串,导致程序的执行次序发生变化。字符串包含了一些函数在程序中的相对偏移,使得溢出的部分恰好是偏移;虽然实验很顺利,但也证明了程序的安全性问题,这一次的操作,让我对程序的安全性有了更深的认识。
浙公网安备 33010602011771号