APC注入的原理是利用當線程被喚醒時APC中的註冊函數會被執行的機制,並以此去執行我們的DLL加載代碼,進而完成DLL注入的目的,其具體流程如下:
1)當EXE裏某個線程執行到SleepEx()或者WaitForSingleObjectEx()時,系統就會產生一個軟中斷。
2)當線程再次被喚醒時,此線程會首先執行APC隊列中的被註冊的函數。
3)利用QueueUserAPC()這個API可以在軟中斷時向線程的APC隊列插入一個函數指針,如果我們插入的是Loadlibrary()執行函數的話,就能達到注入DLL的目的。
1.編寫測試文件
新建MFC工程,添加按鈕控件,雙擊寫代碼如下所示: 這裏我們需要注意一下SleepEx中第二個參數爲TRUE,查下msdn,上面寫到: 大概意思是說當第二個參數爲FALSE,APC是不被執行的,從此可以認爲APC注入的使用條件還是有很大約束的。
2.編寫APC注入程序
由於我們需要時使用LoadLibrary()函數完成注入,因此需要爲其先準備好必要的參數,需要我們可以通過在遠程進程中申請空間的方式寫入LoadLibrary()函數所需要的參數(也就是DLL的路徑)。關鍵代碼如下所示: 當我們準備好用於注入DLL的LoadLibrary()函數後,接下來需要使用QueueUserAPC()函數將此函數插入到軟中斷線程的APC隊列中。但是由於QueueUserAPC()函數的第三個參數是線程ID,因此我們需要根據現有進程ID,並通過遍歷對比得到線程ID,具體API如下表所示:
關鍵代碼如下所示: 3.MFC工程設置和提升權限
經過以上兩步的操作,我們已經準備好APC注入的關鍵代碼,現在我們需要將自己的程序提升權限以方便注入操作(另,動態MFC庫編譯有可能造成注入失敗)。主要代碼如下: 4.測試注入效果
點擊待注入的EXE進行SleepEx,這時EXE的窗口是不可以移動的,因爲只有一個線程,處於SleepEx的掛起狀態,然後進行注入,我們此時會發現處於掛起狀態的進程窗口突然可以移動了,這是因爲進程在掛起狀態等待時,如果有APC隊列就會退出等待並執行APC隊列中的函數,然後程序繼續運行。執行效果如下圖所示