• 20145229吴姗珊逆向BOF实践


    20145229吴姗珊逆向BOF实践

    实践

    实践目标

    • 本次实践的对象是一个名为pwn1的linux可执行文件
    • 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
    • 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。
    • 我们将学习两种方法:
      1. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
      2. 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。

    实践步骤

    • 安装虚拟机、靶机及Kali,安装成功如下图

    • 建立姓名学号文件夹,放入pwn1

    • 直接运行pwn1,知道其作用为回显刚刚输入的字符

    • 当输入的字符过长会导致缓冲区溢出

    • 指令objdump反汇编pwn1,more管道按页显示,命令 objdump -d pwn1 | more

    • 分析代码并修改指令改变其功能
      main函数反汇编的第4行,"call 8048491 "是汇编指令,是说这条指令将调用位于地址8048491处的foo函数;其对应机器指令为"e8 d7ffffff",e8即跳转之意。本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但一解释e8这条指令呢,CPU就会转而执行 "EIP + d7ffffff"这个位置的指令。"d7ffffff"是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值(foo函数调用入口),main函数调用foo,对应机器指令为" e8 d7ffffff",那我们想让它调用getShell,只要修改"d7ffffff"为,"getShell-80484ba"对应的补码就行。用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。

    之后汇编码将由e8d7ffffff变为e8c3ffffff

    • 下载图形化的16进制编辑器
      指令:apt-get install wxhexeditor
      wxHexEditor

    • 通过构造输入参数,造成BOF攻击,分析各函数功能

    main:函数的第四行call 8048491意思为跳转到foo函数

    getshell:我们的目标是触发函数getShell,这个恶意代码可以实现shell
    foo:可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞

    • 缓冲区溢出跳转getshell
      1.首先尝试用gdb调试

    2.输入1111111122222222333333334444444455555555,观察寄存器数值

    3.发现eip为0x35353535,查ASCLL表发现是5555。eip寄存器的功能就是保存程序下一步要执行指令的地址,可以看出本来应返回到foo函数的返回地址已被"5555"覆盖

    4.通过将55555555换成12345678,再观察eip值找出谁被覆盖,通过查表可知为1234

    5.确认getshell地址的字节序列0804847d如何组合

    • 通过设置断点查看0804847d的顺序,在0804049d处设置断点,通过查看之后的eip值,eip值不变,对比之前 eip 0x34333231 0x34333231 ,通过查表查出为4321,可以确定getshell字符序列应该是11111111222222223333333344444444x7dx84x04x08

    码表如下

    • 生成字符串
      我们没法通过键盘输入x7dx84x04x08这样的16进制值,所以先生成包括这样字符串的一个文件。x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
      Perl是一门解释型语言,不需要预编译,可以在命令行上直接使用。
      使用输出重定向“>”将perl生成的字符串存储到文件input中。可以使用16进制查看指令xxd查看input文件的内容是否如预期。

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

    • 注入shellcode
      shellcode:
      Shellcode是一组可注入的指令,可在被攻击的程序内运行。由于shellcode要直接操作寄存器,通常用汇编语言编写并翻译成十六进制操作码。我们想让目标程序以不同与设计折预期的方式运行,操纵程序的方法之一是强制它产生系统调用。ShellCode就是一段程序的机器码形式,而ShellCode的编写过程,就是得到我们想要程序的机器码的过程。
      在Linux里有两种方法来执行系统调用。间接的方法是libc,直接的方法是用汇编指令调用软中断执行系统调用。在Linux里,程序通过int 0x80软中断来执行系统调用,调用过程如下:
      1、把系统调用编号载入EAX;
      2、把系统调用的参数压入其他寄存器;最多支持6个参数,分别保存在EBX、ECX、EDX、ESI、EDI和EBP里;
      3、执行int 0x80指令;
      4、CPU切换到内核模式;
      5、执行系统函数。

    • 需要一个shellcode代码,在网上找了一个,命名为helloshellcode,直接对这个程序进行编译,编译时注意需要首先转换为32位

    • 想提取其中的shellcode就需要通过反汇编来获取相应的汇编代码或是二进制代码。如果要提取该程序中的获取shell的shellcode,就是要获取函数execve调用时参数及相应的系统调用。接下来进行反汇编

    • 使用gdb查看反汇编

    从上图中可以看出execve函数是先赋值寄存器后进行调用*0x80e8a90,可以看出就是上面所说的第一种放大—调用软中断执行系统调用。一旦加载寄存器之后,就会调用int 0x80 汇编指令来发出软中断,强迫内核暂停手头上的工作并处理该中断。

    • 提取shellcode
      在上面放的用gdb查看的反汇编的图里的部分指令进行组合就可以了,不过老师在上课的时候说过里面不能包含0字符,需要把0字符全部去掉,否则无法执行

    • 汇编写helloshellcode及编译

    • 本次的shellcode参考了网上大神的分享,自己对这汇编方面理解太少,能理解整个过程的原理,在实践代码方面举步维艰,不过熟能生巧,自己会多加强这方面的学习

    实践感想

    本次的实践是本次课的第一次实验,根据老师给出的教程一步步往下做没有遇到太大的问题,只是在确定大端小端的时候遇到了一些疑难,缓冲区溢出最重要的就是找出覆盖的部分,然后进行一个计算即可进行跳转,其实原理很简单,只是对汇编方面的知识太过生疏导致理解汇编时非常吃力,但是在做注入shellcode的时候,根据网上的教程做下来,大体的概念清楚,做下来花了不少时间,还需要花一定的时间理解消化,希望自己以后也可以加强对汇编的学习,将所有知识融会贯通进行学习。

  • 相关阅读:
    VMware虚拟机中调整Linux分区大小手记(转发)
    Linux下查看文件和文件夹大小的df和du命令
    Hadoop 安装 (4) SSH无密码验证配置
    Hadoop 安装(3) JDK 的安装
    Hadoop安装(2)安装hadoop 前的centos 设置
    Hadoop 安装大纲
    Hadoop 安装(1) CENTOS 安装与配置
    WLW 截屏插件
    查看Myeclipse中集成的Eclipse的版本号
    Quartz关闭Tomcat时异常:The web application [/****] appears to have started a thread named [startQuertz_Worker-1] buthas
  • 原文地址:https://www.cnblogs.com/20145229ss/p/6464079.html
Copyright © 2020-2023  润新知