崙?zhàn):用 pattern 命令基于 De Bruijn 序列定位溢出偏移量)
網(wǎng)絡(luò)安全開(kāi)發(fā)工具【免費(fèi)下載鏈接】gefGEF (GDB Enhanced Features) - a modern experience for GDB with advanced debugging capabilities for exploit devs reverse engineers on Linux項(xiàng)目地址https://gitcode.com/gh_mirrors/gef/gef點(diǎn)擊查看免費(fèi)下載在緩沖區(qū)溢出分析中被覆蓋的寄存器里殘留著哪段數(shù)據(jù)、溢出發(fā)生在第幾個(gè)字節(jié)是必須回答的問(wèn)題。GEF 的pattern命令通過(guò)生成與搜索 De Bruijn德布魯恩循環(huán)序列把猜偏移量變成一次可復(fù)制的查表操作先向目標(biāo)程序灌入一段每個(gè)子串都唯一的填充串崩潰后讀取被破壞的寄存器值再用搜索子命令反查出精確的字節(jié)偏移。本文以 pattern 命令文檔 為核心結(jié)合 gef.py 中的實(shí)現(xiàn)源碼與 tests/commands/pattern.py 測(cè)試用例完整講解pattern create/pattern search的參數(shù)、底層算法與端到端使用流程。讀完本文你將能夠獨(dú)立生成與 pwntools 完全兼容的 De Bruijn 序列理解 GEF 如何根據(jù)架構(gòu)字長(zhǎng)與字節(jié)序自動(dòng)選擇搜索方向掌握從崩潰寄存器值反推返回地址、棧指針偏移的完整工作流。1. De Bruijn 循環(huán)序列為什么它能唯一定位偏移pattern命令生成的字符串由大量互不重復(fù)的定長(zhǎng)子串組成。以n4為例aaaabaaacaaadaaae...中任意連續(xù) 4 個(gè)字符都是唯一的——因此當(dāng)這段字符串覆蓋了某個(gè)緩沖區(qū)并在溢出后殘留在寄存器中時(shí)只要讀出寄存器里的 4 個(gè)字符就能在序列中反查出這 4 個(gè)字符起始位置的字節(jié)偏移即溢出點(diǎn)距離緩沖區(qū)首地址的距離。官方文檔指出一個(gè)關(guān)鍵設(shè)計(jì)決策GEF 實(shí)現(xiàn)的算法與 pwntools 完全一致因此兩側(cè)工具生成的序列互為兼容崩潰后即使脫離 GDB 也可以把泄漏值貼進(jìn) pwntools 腳本求偏移from pwn import * p cyclic(128, n8)1.1 源碼實(shí)現(xiàn)與 pwnlib 兼容的遞歸生成器生成邏輯位于 gef.pydef de_bruijn(alphabet: bytes, n: int) - Generator[int, None, None]: De Bruijn sequence for alphabet and subsequences of length n (for compat. w/ pwnlib). k len(alphabet) a [0] * k * n def db(t: int, p: int) - Generator[int, None, None]: if t n: if n % p 0: for j in range(1, p 1): yield alphabet[a[j]] else: a[t] a[t - p] yield from db(t 1, p) for j in range(a[t - p] 1, k): a[t] j yield from db(t 1, t) return db(1, 1) def generate_cyclic_pattern(length: int, cycle: int 4) - bytearray: Create a length byte bytearray of a de Bruijn cyclic pattern. charset bytearray(babcdefghijklmnopqrstuvwxyz) return bytearray(itertools.islice(de_bruijn(charset, cycle), length))從源碼可以看出幾個(gè)實(shí)現(xiàn)細(xì)節(jié)字母表固定為 26 個(gè)小寫(xiě)字母a-z即charset babcdefghijklmnopqrstuvwxyz這也是為什么泄漏值通常是aaaab...這類純字母序列de_bruijn是一個(gè)惰性生成器按 DAWGDe Bruijn 序列標(biāo)準(zhǔn)構(gòu)造法遞歸產(chǎn)出字符generate_cyclic_pattern再用itertools.islice截取所需的length字節(jié)因此生成任意長(zhǎng)度的序列都不會(huì)一次性構(gòu)造完整超串docstring 中明確標(biāo)注 for compat. w/ pwnlib印證了與 pwntoolscyclic()的算法級(jí)兼容。2.pattern create生成并暫存序列2.1 語(yǔ)法與參數(shù)pattern create [-h] [-n N] [length]參數(shù)含義默認(rèn)值length生成的序列總字節(jié)數(shù)配置項(xiàng)pattern.length默認(rèn)1024-n N唯一子串的定長(zhǎng)周期當(dāng)前架構(gòu)指針寬度gef.arch.ptrsizex86_64 為 832 位為 4默認(rèn)長(zhǎng)度來(lái)自命令自身注冊(cè)的配置項(xiàng)——PatternCommand.__init__中self[length] (1024, Default length of a cyclic buffer to generate)見(jiàn) gef.py可通過(guò) GEF 的config機(jī)制持久化修改對(duì)應(yīng)文檔見(jiàn) config 命令。2.2 運(yùn)行示例gef? pattern create -n 4 128 [] Generating a pattern of 128 bytes (n4) aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab [] Saved as $_gef0執(zhí)行流程對(duì)應(yīng) PatternCreateCommand.do_invoke解析length缺省讀gef.config[pattern.length]與n缺省讀gef.arch.ptrsize→ 調(diào)用generate_cyclic_pattern(length, n)生成字節(jié)串 → 打印明文 → 通過(guò)gef_convenience(pattern_str)存入一個(gè)GDB 便捷變量。2.3 便捷變量$_gef0溢出 payload 的搬運(yùn)工gef_conveniencegef.py按$_gef0、$_gef1…… 的遞增序號(hào)命名字符串值會(huì)被定義為形如$_gef0 aaaabaaac...的便捷變量。這個(gè)設(shè)計(jì)讓 payload 的傳遞非常自然gef? pattern create 256 [] Generating a pattern of 256 bytes (n8) ... [] Saved as $_gef0 gef? set args $_gef0 gef? run在命令行直接引用$_gef0即可把整段循環(huán)序列作為目標(biāo)程序的輸入?yún)?shù)無(wú)需手動(dòng)拷貝長(zhǎng)字符串。3.pattern search從泄漏值反查偏移量3.1 語(yǔ)法與參數(shù)pattern search [-h] [-n N] [--max-length MAX_LENGTH] [pattern]search子命令在 De Bruijn 序列中查找給定pattern返回其偏移。參數(shù)說(shuō)明參數(shù)含義默認(rèn)值pattern待搜索的值GDB 符號(hào)如寄存器名、字符串或十六進(jìn)制數(shù)無(wú)必填-n N子串定長(zhǎng)應(yīng)與pattern長(zhǎng)度一致gef.arch.ptrsize--max-length搜索所覆蓋的序列最大長(zhǎng)度即假設(shè)溢出最多發(fā)生在前 N 字節(jié)內(nèi)pattern.length默認(rèn) 1024pattern search還有一個(gè)別名pattern offset源碼中_aliases_ [pattern offset]見(jiàn) gef.py語(yǔ)義上更直白地表達(dá)求偏移。源碼中的參數(shù)校驗(yàn)值得注意PatternSearchCommand.do_invokemax_length args.max_length or gef.config[pattern.length] n args.period or gef.arch.ptrsize if n not in (2, 4, 8) or n gef.arch.ptrsize: err(Incorrect value for period)即-n只接受 2/4/8且不能超過(guò)當(dāng)前架構(gòu)指針寬度——這是為了保證子串長(zhǎng)度 ≥ 泄漏值寬度時(shí)查表結(jié)果不產(chǎn)生歧義。3.2 三種輸入形式與官方示例文檔給出的三組示例覆蓋了全部輸入形式gef? pattern search 0x6161616161616167 [] Searching 0x6161616161616167 [] Found at offset 48 (little-endian search) likely [] Found at offset 41 (big-endian search) gef? pattern search $rbp [] Searching $rbp [] Found at offset 32 (little-endian search) likely [] Found at offset 25 (big-endian search) gef? pattern search aaaaaaac [] Searching for aaaaaaac [] Found at offset 16 (little-endian search) likely [] Found at offset 9 (big-endian search)三種形式分別對(duì)應(yīng)十六進(jìn)制值寄存器里讀出的原始機(jī)器碼GDB 符號(hào)直接傳$rbp這類寄存器名GEF 會(huì)先gdb.parse_and_eval取值明文字符串直接粘貼泄漏的字符。4. 搜索原理小端/大端雙向查找與 likely 標(biāo)記PatternSearchCommand.search 的實(shí)現(xiàn)揭示了輸出中l(wèi)ittle-endian / big-endian / likely三個(gè)詞的由來(lái)def search(self, pattern: str, size: int, period: int) - None: # 1. check if its a symbol (like $sp or 0x1337) symbol safe_parse_and_eval(pattern) if symbol: addr int(abs(to_unsigned_long(symbol))) ... mask (1 (8 * period)) - 1 addr mask pattern_le addr.to_bytes(period, little) pattern_be addr.to_bytes(period, big) else: # 2. assume its a plain string pattern_be gef_pybytes(pattern) pattern_le gef_pybytes(pattern[::-1]) cyclic_pattern generate_cyclic_pattern(size, period) off cyclic_pattern.find(pattern_le) if off 0: ok(fFound at offset {off:d} (little-endian search) f{Color.colorify(likely, bold red) if gef.arch.endianness Endianness.LITTLE_ENDIAN else }) return off cyclic_pattern.find(pattern_be) ...可以歸納出四條機(jī)制符號(hào)優(yōu)先解析先用safe_parse_and_eval嘗試按 GDB 表達(dá)式求值。成功則按數(shù)值處理并用(1 8*period) - 1掩碼只保留低n字節(jié)——因?yàn)?8 字節(jié)的$rbp值里可能混入非 pattern 的高位如 0x7ffd... 的棧地址只有低n字節(jié)落在循環(huán)序列上明文字符串則構(gòu)造雙字節(jié)序把字符串本身當(dāng)大端字節(jié)串、反轉(zhuǎn)后當(dāng)小端字節(jié)串各自在序列中find先小端、后大端命中哪一端就報(bào)告哪一端并只報(bào)告第一個(gè)命中的方向所以輸出里同時(shí)出現(xiàn)兩行如 48 與 41是文檔示例在不同場(chǎng)景下的組合展示實(shí)際單次運(yùn)行按小端優(yōu)先短路返回likely 由架構(gòu)字節(jié)序決定當(dāng)前架構(gòu)是小端時(shí)小端命中行加粗紅色標(biāo)注likely大端架構(gòu)則反之gef.py。這個(gè)提示告訴用戶該結(jié)果與目標(biāo)機(jī)器字節(jié)序一致可信度更高在跨字節(jié)序分析如遠(yuǎn)程調(diào)試時(shí)另一端的偏移同樣有用。搜索所用的序列是按--max-length默認(rèn) 1024與-n現(xiàn)場(chǎng)重新生成的——由于生成器確定性與 pwntools 兼容無(wú)需與pattern create時(shí)保存的$_gefN嚴(yán)格一致但兩者參數(shù)保持一致才能覆蓋真實(shí) payload 長(zhǎng)度如果實(shí)際 payload 有 2048 字節(jié)而搜索時(shí)max_length仍是默認(rèn) 1024超過(guò) 1024 的偏移將顯示 not found。5. 端到端工作流以 strcpy 溢出為例倉(cāng)庫(kù)自帶的測(cè)試二進(jìn)制 tests/binaries/pattern.c 就是一個(gè)標(biāo)準(zhǔn)的棧溢出靶場(chǎng)void greetz(char* buf) { char name[8] {0,}; strcpy(name, buf); // 8 字節(jié)緩沖無(wú)邊界檢查 printf(Hello %s\n, name); }tests/commands/pattern.py 中的自動(dòng)化用例完整演示了標(biāo)準(zhǔn)工作流可直接照搬為手動(dòng)調(diào)試步驟gef? file tests/binaries/pattern gef? pattern create 64 -n 4 [] Generating a pattern of 64 bytes (n4) aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaab [] Saved as $_gef0 gef? set args aaaabaaacaaadaaaeaaafaaagaaahaaa gef? run # 在 strcpy 崩潰點(diǎn)斷住后查看 $rbp gef? pattern search -n 4 $rbp [] Found at offset 8 (little-endian search) likely測(cè)試用例 test_cmd_pattern_search 在不同架構(gòu)下驗(yàn)證了相同偏移結(jié)論x86_64 上-n 4搜索$rbp期望得到 offset 8即 8 字節(jié)緩沖name之后恰好是保存的幀指針-n 8搜索同樣期望 832 位 i686 因棧布局不同期望 16。用例最后還斷言了搜索不存在模式JUNK時(shí)輸出 not found 的分支tests/commands/pattern.py。得到 offset 后的典型利用動(dòng)作是偏移 4/8 覆蓋saved rbp后ret地址的起始位置從而精確控制返回地址。5.1 與 pwntools 聯(lián)合使用的注意事項(xiàng)由于算法兼容同一泄漏值可以離線復(fù)算from pwn import * offset cyclic_find(baaaag\x00\x00\x00, n4) # 注意字節(jié)序與 n 必須與 GEF 端一致需要保持兩側(cè)n周期一致GEF 端-n 4對(duì)應(yīng) pwntools 端n4若一側(cè)用 8 另一側(cè)用 4偏移結(jié)果會(huì)完全不同。文檔示例p cyclic(128, n8)即與pattern create -n 8 128一一對(duì)應(yīng)。6. 小結(jié)命令作用關(guān)鍵默認(rèn)值pattern create [-n N] [length]生成 De Bruijn 序列并存入$_gefNlength1024pattern.lengthn架構(gòu)指針寬度pattern search [-n N] [--max-length L] [pattern]在序列中反查偏移別名pattern offsetn架構(gòu)指針寬度max-length1024GEF 的pattern命令把緩沖區(qū)溢出分析中偏移計(jì)算這一環(huán)節(jié)封裝成了兩步操作且其 De Bruijn 生成器與 pwntools 保持算法級(jí)兼容見(jiàn) gef.py 的de_bruijn與generate_cyclic_pattern。配合$_gefN便捷變量傳參、寄存器直接作為搜索參數(shù)、小/大端雙向查找與字節(jié)序 likely 提示它構(gòu)成了從 payload 注入到偏移反查的閉環(huán)。理解-n與max-length兩個(gè)參數(shù)如何共同決定搜索空間是避免 not found 假陰性的關(guān)鍵。贊分享網(wǎng)絡(luò)安全開(kāi)發(fā)工具【免費(fèi)下載鏈接】gefGEF (GDB Enhanced Features) - a modern experience for GDB with advanced debugging capabilities for exploit devs reverse engineers on Linux項(xiàng)目地址https://gitcode.com/gh_mirrors/gef/gef點(diǎn)擊查看免費(fèi)下載相關(guān)推薦pwntools cyclic 模塊詳解De Bruijn 序列生成、偏移定位與 Metasploit 模式pwntools cyclic 模塊詳解De Bruijn 序列生成、偏移定位與 Metasploit 模式 pwnlib.util.cyclic 是 pwn網(wǎng)絡(luò)安全滲透測(cè)試逆向工程ESP-DL實(shí)戰(zhàn)教程在ESP32上部署YOLO11n目標(biāo)檢測(cè)模型ESP DL實(shí)戰(zhàn)教程在ESP32上部署YOLO11n目標(biāo)檢測(cè)模型 ESP DLEspressif deep learning library是樂(lè)鑫科技推出人工智能推理引擎嵌入式pwndbg 的 hi 命令堆地址歸屬快速定位與 malloc_chunk 逆向解析實(shí)戰(zhàn)pwndbg 的 hi 命令堆地址歸屬快速定位與 malloc_chunk 逆向解析實(shí)戰(zhàn) 導(dǎo)讀 hi 是 pwndbg 面向 glibc ptmalloc2逆向工程調(diào)試器應(yīng)用安全開(kāi)發(fā)工具上一篇【免費(fèi)下載】 探索Tikhonov正則化與L曲線MATLAB代碼資源推薦【matlab下載】下一篇Matrix-Game-3.0開(kāi)發(fā)者指南自定義動(dòng)作控制與模型微調(diào)教程創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考