https://www.exploit-db.com/exploits/46907
我的理解是,由于 x64 呼叫約定,第三個引數 execve,即 envp,應該存盤在 rdx 中。但是這個shellcode并沒有將這個暫存器清零,它只是將rsi暫存器(存盤arv)清零。因此,如果 rdx 的當前值未指向有效位置,則會導致段錯誤,不是嗎?
我錯過了什么嗎?
uj5u.com熱心網友回復:
ASM的確實寫RDX(0):注意cdq權利之前syscall。的符號位EAX=59為 0,所以 EDX = 0,并且將 EDX 零擴展到 RDX。
給定已知的非負 EAX ,這是使用 1 位元組指令而不是 將 EDX/RDX 歸零的標準代碼高爾夫技巧xor edx,edx。
Linux 特殊情況 NULLargv或envp指標像空串列一樣作業(指向記憶體中的 NULL 的指標)。請參閱手冊頁:https : //man7.org/linux/man-pages/man2/execve.2.html#NOTES
手冊頁不鼓勵C 程式的實踐,因為它不能移植到其他 unix,但 shellcode 已經不是,并且它節省了機器代碼大小的位元組。
在_startLinux 下的靜態可執行檔案中,除 RSP 之外的所有 regs 都將是0. (x86-64 SysV ABI 不保證這一點,這只是內核在進入用戶空間之前選擇避免資訊泄漏的方便值。)因此,即使它確實存在您認為的錯誤,它也會以這種方式作業。
但他們也通過將機器碼位元組放入.dataC 程式中的陣列中并從main(). 這也適用于使 RDX 保持不變的有缺陷的 shellcode:編譯器生成的用于通過函式指標呼叫的代碼可能會使 RDX保持不變。
在進入 main 時,EDI=argc,RSI=argv,RDX=envp。所以這個機器代碼塊將從 RDX 開始,它已經是一個有效的指標char **envp!也許比他們預期的要少一些測驗。:P
第三對Arg的main存在envp不是由POSIX指定,但廣泛的支持:是char * envp []作為第三個引數main()的便攜式
的x86-64 linux的系統呼叫約定頗為相似,其函式呼叫約定,故意使該系統呼叫包裝功能只需要mov r10, rcx/ mov eax, __NR_.../ syscall。
順便說一句,系統呼叫的錯誤引數永遠不會導致分段錯誤(SIGSEGV 信號被傳遞到您的行程)。相反,-EFAULT當您傳遞指向未映射記憶體的指標時,Linux 系統呼叫會回傳錯誤代碼,以防萬一。
(有趣的事實:write(1, buf, way_past_end)將成功寫入從buf地址開始實際映射的頁面的末尾,并回傳該長度。只有-EFAULT在遇到不可讀的頁面之前將 0 個位元組寫入 fd才會得到。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/367452.html
