文章

目前顯示的是 2020的文章

[Windows] 逆向工程 C++ 中入口函數參數 main(argc, argv) 與如何正確的進行參數劫持

圖片
前言 我在 Github 上三年前開源了精簡的以 C/C++ 撰寫的 Windows 執行程式裝載器: aaaddress1/RunPE-In-Memory  用以從記憶體執行以 C/C++ 開發的 *.exe 程式不必以 CreateProcess() 來叫起,算是一種概念性 PoC 啦畢竟這種手段在惡意程式和殼上經常使用,所以寫一寫就丟出來給大家玩 XD 不過有人在我的專案發起了 Issue:既然能從記憶體中執行 *.exe 那能否偽造 *.exe 取得的參數呢?嗯好問題XD 正逢去年蠻忙的所以一直懶得弄,這個月比較閒於是就決定在專案中新增 參數偽造 的功能,這邊簡單提一下 C++ 中 main() 入口所收的 argc 與 argv 來的。 [附註] 以下逆向工程內容以 MinGW 生產的程式為例, 系統逆向工程為 Win10 企業版 1809版  CRTStartup 在 Windows 下通常取得參數通常分為兩種狀況:  WINAPI GetCommandLineW() 系統函數返回字串指針指向當前完整應用程式參數 從 main(argc, argv) 拿回來的參數,那麼第二種狀況在編譯器是怎麼吐參數給開發者 main 入口的呢? 在編譯器吐出執行程式後,連結器會生產一段 CRTStartup 的函數用於做一些基礎的例如像是 Security Cookies、Control Flow Guard 保護的初始化,在一系列初始化之後 .data 段的全域變數 _argv、argc 紀錄著要傳入給開發者入口函數的 參數陣列 與 數量,就以參數形式呼叫 main() 函數 好問題,那這兩個全域變數是在哪裡被初始化的? 你會發現以 MinGW 為例的話,會去呼叫 msvcrt!__getmainargs() 來取得參數資訊保存到 .data 全域變數上,後續再傳遞給 main() 函數;如果是 VC++ 吐出來的則是直接呼叫 GetCommandLineW() 在做文字切割取出參數 MSVCRT MSVCRT.dll 有導出一系列 C 函數是引用 #include <stdio.h> 時會用到的,例如 printf, sprintf, gets 等等。我們剛剛提到了其導出函數 _