Exp1 PC平台逆向破解 实验报告—20201229赵斌

1 逆向及Bof基础实践说明

1.1 实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

  • 三个实践内容如下:

    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode。
  • 这几种思路,基本代表现实情况中的攻击目标:

    • 运行原本不可访问的代码片段
    • 强行修改程序执行流
    • 以及注入运行任意代码。

1.2 基础知识

基础指令

  1. NOP:CPU空转(机器码:0x90)

  2. JNE:Jump if Not Equal(机器码:0x75)

  3. JE: Jump if Equal(机器码:0x74)

  4. JMP:无条件转移指令。
    JMP 类型      释义                     机器码                                    
    段内短直接    JMP SHORT mylabel         0xEB [signed byte]                 short 8bits ±126字节的地址范围
    段内近直接    JMP NEAR PTR mylabel      0xE9 [low byte][high byte]         word 16bits ±32768字节的地址范围
    段间远直接    JMP DS:[mylabel]          0xEA [IP low][IP high][CS low][CS high]     double word 32bits 全局
    段内近间接    JMP BX                    0xFF (0xFF25 0xFF15...)                                                                               
  
  5. CMP:比较指令(机器码:0x39 0x3C 0x83......)

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

下载pwn1改名为pwn1229,然后objdump -d pwn1229 | more进行反汇编

长按回车键直到找到main函数

主函数会通过call调用foo函数,该指令对应的机器指令为“e8 d7ffffff”,e8即跳转之意
正常流程下,eip中原本存储的是下一条指令的地址,即80484ba,但一解释e8这条指令,CPU就会转而执行 ”eip + e8后面的四字节地址“ 这个位置的指令
因此,eip = 80484ba+fffffd7=8048491(注意d7ffffff是补码,小段优先,计算时应写为ffffffd7),也就是foo函数的地址
我们想让它调用getShell,只要修改“d7ffffff”为 "getShell-80484ba"对应的补码即可

修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff:

1.vi进入pwn201229,在乱码界面按Esc键,然后输入:%!xxd
2.找到e8d7,修改d7为c3(先按i进入编辑模式再改,改完按Esc键退出)
3.输入:%!xxd -r
4.输入:wq退出

对pwn201229反汇编,检验修改是否正确


运行pwn201229,会得到shell提示符。执行ls命令后,成功打印出当前目录下的所有文件。

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

3.1 反汇编了解程序基本功能

可执行文件pwn1229正常运行是调用函数foo。foo函数有Buffer overflow漏洞:foo读入字符串,但系统只预留了(28)字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址

3.2 确认输入的字符串哪几个会覆盖到返回地址

3.2.1 安装gdb

sudo chmod a+w /etc/apt/sources.list
sudo chmod a-w /etc/apt/sources.list
sudo su
apt-get update
apt-get install gdb

输入gdb -v,检查是否安装成功

3.2.2 分析覆盖返回地址的字符

输入为1111111122222222333333334444444455555555时可以看到eip的值0x35353535,也就是5555的ASCII码;输入字符串1111111122222222333333334444444412345678,发现eip的值为0x34333231,即1234(小端)的ASCII码。

3.3 确认覆盖返回地址的值

反汇编时我们已知getShell的内存地址0x0804847d,由1234对应0x34333231分析出是小端写法,所以我们应当输入11111111222222223333333344444444\x7d\x84\x04\x08

3.4 构造输入字符串

我们无法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。\x0a表示回车。使用输出重定向“>”将perl生成的字符串存储到文件input中。
使用16进制查看指令xxd查看input文件的内容是否如预期,然后将input的输入,通过管道符“|”,作为pwn1229的输入


攻击成功,获得了一个交互式shell

4 注入shellcode并执行

4.1 准备一段shellcode

shellcode就是一段机器指令(code)

  • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
  • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

4.2 准备工作

输入sudo apt-get install execstack ,安装execstack命令。
进行如下操作:
1.先通过execstack - s指令来设置堆栈可执行
2.再用 execstack -q 指令查询文件的堆栈是否可执行
3.检查地址随机化保护是否关闭(因为我之前做了好几次,所以这里直接是关闭的)

4.3 构造要注入的payload

  • Linux下有两种基本构造攻击buf的方法:

    • retaddr+nop+shellcode
    • nop+shellcode+retaddr。
  • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。

  • 简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

  • 我们这个buf够放这个shellcode了,所以shellcode放后边

  • 结构为:retaddr+nop+shellcode(指导书里此处是坑)

    • nop一为是了填充,二是作为“着陆区/滑行区”。
    • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

开启两个新终端,都进入root模式
终端1注入攻击buf,回车一次即可

终端2执行到下图位置时,在终端1中按下回车

终端2继续执行,看到 0x01020304了,就是返回地址的位置。shellcode就在后面,所以地址是 0xffffd500.
将 0xffffd500放进shellcode,运行后发现成功获取shell,攻击成功

4.4 结合nc模拟远程攻击

靶机为kali,攻击机为ubuntu。二者互ping可通。
靶机IP:192.168.247.134
攻击机IP:192.168.247.132
靶机输入以下命令:

nc -lvnp 1324 -e ./pwn201229


然后就能在攻击机上获取靶机的shell

5 bof攻击防御技术

5.1 从防止注入的角度

在编译时,编译器在每次函数调用前后都加入一定的代码,用来设置和检测堆栈上设置的特定数字,以确认是否有bof攻击发生。

5.2 注入也不让运行

结合CPU的页面管理机制,通过DEP/NX用来将堆栈内存区设置为不可执行。这样即使是注入的shellcode到堆栈上,也执行不了。

5.3 增加shellcode构造难度

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

/proc/sys/kernel/randomize_va_space用于控制Linux下 内存地址随机化机制,其取值有以下三种情况
0 - 表示关闭进程地址空间随机化。
1 - 表示将mmap的基址,stack和vdso页面随机化。
2 - 表示在1的基础上增加栈(heap)的随机化。

6 实验总结

6.1 问题与解决

缓冲区溢出的实验之前在别的课程里也有过涉及,可以说称得上是经典的安全攻击实验。这次实验总体来说难度不大,在指导书和课题负责人的帮助下,我总共用时四个小时完成了本次实验。期间也遇到一些问题,比如忘记大端小端写法,这让我又找到之前的教材学了一番。另外就是使用apt-get下载安装包时出现了一些问题,不过这个一谷歌就很快解决了。我前前后后总共做了三次,第一次是被指导书里的坑堵了好久,刚开始那个地方一直没想明白,觉得是自己之前操作有问题,于是又重新来了一遍。第二次顺利做完后,一看报告要求,发现主机名没改又白做一次。虽然可能浪费的时间比较多,但我觉得一次比一次做得快,一次比一次思路更清晰,也就值得了。

6.2实验体会

这次试验让我接触到了Kali虚拟机,一开始我觉得它和Ubuntu没啥区别,后来一查才发现它自带很多比较厉害的功能。因为之前学过的Linux命令好久没用过了,在实验过程中,也加深了我对这些指令的记忆。此外,我对缓冲区溢出攻击的原理有了更进一步的理解,对它的各种实现方式产生了浓厚的兴趣,希望能在以后有更多地深入了解。

posted @ 2023-03-16 22:46  20201229赵斌  阅读(23)  评论(0编辑  收藏  举报