[轉]N種核心注入DLL的思路及實現

來源:互聯網
上載者:User

標籤:

核心注入,技術古老但很實用。現在部分RK趨向無進程,玩的是SYS+DLL,有的無檔案,全部存在於記憶體中。可能有部分人會說:“都進核心了.什麼不能幹?”。是啊,要是核心中可以做包括R3上所有能做的事,軟體開發商們也沒必要做應用程式了。有時,我們確實需要R3程式去幹驅動做起來很困難或者沒必要驅動中去做的事,進程 /  DLL是不錯的選擇,但進程目標太大,所以更多的同學趨向於注DLL。 
    若要開發安全軟體、小型工具,可借鑒其思路,Anti Rootkits時,在某些極端情況下,可使用同樣的技術發現、清除RK,保證使用者電腦的正常使用。在此,我將探討幾種核心注入DLL的思路及實現原理。 
(1) APC技術 
    給一個Alertbale的使用者態線程插APC,讓其執行其中的ShellCode,來執行我們的代碼。這個方法簡單易行,但是不夠穩定,相容性不好。測試中發現經常出現Explorer.exe等插崩潰的情況,而且有殺軟在的情況下,插入有時會被攔截,起不到應有的效果。(可參考我以前逆過的一個驅動:逆向fuck.sys--編譯通過--源碼) 
(2) 核心Patch  [url=file://KnownDLLs/Kernel32.dll]//KnownDLLs//Kernel32.dll[/url] CreateThread 
    [url=file://KnownDLLs/]//KnownDLLs[/url]是系統載入時對象管理器載入最新磁碟DLL到記憶體的,當其他進程想調用某個DLL時,就不用重複從磁碟載入了,而會從這裡映射一份到自己的進程空間中去。這樣給我們做全域Patch提供了一個很好的機會: 
        ZwOpenSection開啟 [url=file://KnownDlls/kernel32.dll]//KnownDlls//kernel32.dll[/url],調用ZwMapViewOfSection映射一份到自己進程空間,然後尋找kernel32.dll在記憶體中代碼節的空隙,選擇這裡作為我們fake函數的儲存Buffer。修改CreateThread函數的開頭5位元組跳轉到這個間隙,當系統任何一個線程建立時,會走到CreateThread函數,然後執行空隙中的ShellCode,其負責調用LoadLibrary載入我們的DLL。DLL一經載入,會發IOCTL通知本驅動,讓驅動卸載HOOK。這樣就完成了核心注DLL的過程。測試時發現Svchost.exe進程調用CreateThread函數很頻繁,所以觸發也會很快,基本1秒不到就能將DLL載入進去,而我們的HOOK也卸掉了。所以穩定性提高不少。如下: 
 
(3) 核心 HOOK ZwMapViewOfSection 
    有部分模組載入時會調用ZwMapViewOfSection,比如進程建立時映射N份DLL到自己的虛擬空間中去.我們替換SSDT中的這個函數,過濾出是載入Kernel32.dll的情況,從參數中取得其基址,Inline Hook其EAT中的CreateThread函數,跳轉到在這個進程虛擬位址空間中申請的Buffer,在其中完成DLL的載入過程. 
關鍵API: 
ZwAllocateVirtualMemory ---- 在此進程空間中分配記憶體,存放Shellcode 
ZwProtectVirtualMemory ---- 使當前記憶體塊具有可讀可寫屬性 
IoAllocateMdl ---- 建立MDL 
關鍵Code如下: 
 
 
    同方法2相比,原理類似。但修改時機不同,效果差不多,只是注入DLL的時間會慢一些。至於Shellcode的編寫,就大同小異了.蘿蔔白菜各有所愛,主要看個人發揮。要是閑寫shellcode麻煩,請到看雪學院去查資料,模板很多,在這裡就不YY了。 
【看雪讀書月】學習ShellCode編寫 
[note]一個簡單的Shellcode 
shellcode之小小琢磨 
Add_Section 
(4) 核心 HOOK 
NtCreateThread 
    跟蹤進程建立的流程,會很明晰的發現有多點可以patch來實現DLL的注入。 
    進程建立完時是一個空水壺,裡面沒有沸騰的熱水(threads),於是系統調用NtCreateThread建立其主線程(給空水壺注水 – 涼水),在這個暫停線程裡面折騰了一陣後完事了也厭倦了,於是系統跳了出來,回到進程空間中,調用Kernel32.dll去通知CSRSS.EXE,對它說:“這裡有一個新進程出生了,你在你的表裡標記一下”。然後就開始載入DLL啦,把系統KnownDLLs中的自己需要的DLL都Map一份到這個大水壺中。接著KiThreadStartup加熱水壺中的涼水,於是水就開始沸騰了,此時主線程開始工作。。。 
    攔截NtCreateThread,取得當前線程上下文,儲存它要返回的地址(會回到空水壺中去),劫持為我們自己分配的地址,在其中填充ShellCode來載入目的DLL。至於選擇Buffer,思路很多。這裡可簡單的Attach到當前進程,在充足的虛擬2GB進程地址空間中分配屬於你自己的一塊小記憶體,夠放ShellCode足矣。如下: 
 
(5) 核心感染常用模組,讓感染模組幫我們Load DLL 
    這個方法就有點繞遠了,開始了最本質最原始的感染,可增加新節,可插空隙,總之,讓別人的模組Load進記憶體時順路的幫我們載入下DLL,DLL一旦載入就可以恢複感染,清除痕迹。至於感染代碼,網上一堆。只要不是驅動感染驅動(多了個校正和),其他性質都一樣,看自己發揮啦。 
(6) 攔截NtCreateUserProcessNtCreateSymbolicLinkObject 
    前者在Vista下才有. 攔截後通過PsLookupProcessThreadByCid得到ETHREAD / EPROCESS,判斷是否是CSRSS.EXE引起的,若是則在此進程空間內分配一塊記憶體,調用NtGetContextThread得到當前的線程上下文,調用ZwWriteVirtualMemory填充Shellcode地區,取得LdrUnloadDllLdrGetDllHandle等函數地址,通過他們載入DLL。然後調用NtSetContextThread恢複原始的Context。關於這種方法,可參考DriverDevelop上某人發的BIN。 
[”核心實現DLL注入.可以完美繞過KAV瑞星等殺毒軟體”] 
(7) 核心攔截NtResumeThread 
(8)NtUserSetWindowsHookEx 注入 
順便提下R3上DLL的注入: 
1.CreateRemoteThread (or NtCreateThreadEx (Used in Vista)) 
  2.SetThreadContext (change the EIP) 
  3.NtQueueAPCThread 
  4.RtlCreateUserThread 
  5. SetWindowHookEx 
小結: 
    縱觀進程啟動的全過程,可patch的地方很多,只要保證進程、線程上下文不被破壞,注入的手法可多種多樣。只要保證我們的DLL注入時間足夠短,穩定性足夠高即可。當我們迫不得已要從核心注入DLL到使用者進程去時,系統已經中毒很深,此時運用類似上面提到的技術來載入DLL,讓DLL做我們驅動無法完成的任務,是可以接受的。 
    上面提到的思路是我暫時想到並且已經實現了的,詳細過程可參見代碼。歡迎積極探討更好更穩定而且不邪惡的方法。

[轉]N種核心注入DLL的思路及實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.