使用 Windwos 鉤子獲取丟失的密碼
關(guān)鍵字:鉤子 進(jìn)程間通訊 單實(shí)例 操作系統(tǒng)版本 簡(jiǎn)介 幾年前我在CodeGuru 上下載了一個(gè)叫 Eureka的程序,如果你忘記了密碼,你可以用程序把密碼“取”回來(lái)。它不是密碼破解程序,相反,它利用了一個(gè)Windows的安全漏洞來(lái)拷貝另外一個(gè)運(yùn)行中的程序的密碼。我對(duì)這個(gè)程序很感興趣,決定寫(xiě)一個(gè)自己的版本。后來(lái),Windows 2000 發(fā)布,我失望地發(fā)現(xiàn),微軟修補(bǔ)了那個(gè)漏洞,這樣一來(lái)那個(gè)程序在Windows 2000上也就不靈了。經(jīng)過(guò)一番嘗試,我終于找到一個(gè)方法拷貝任何在32-位Windows 系統(tǒng)上運(yùn)行程序的密碼。 本文例子程序: ![]() 使用方法: PasswordSpy程序的使用非常簡(jiǎn)單。你只要運(yùn)行包含忘記了密碼的程序,再運(yùn)行PasswordSpy。然后將放大鏡拖動(dòng)到密碼輸入域上,PasswordSpy則會(huì)將密碼顯示出來(lái)。PasswordSpy程序并沒(méi)有惡意,開(kāi)發(fā)它的目的只是想把密碼找回來(lái),該程序在Win95/98/ME and WinNT/2K/XP/Windows 2003 上測(cè)試通過(guò)。 功能說(shuō)明: 除了PasswordSpy本身的用途之外,它還示范了一些有用和有趣的代碼:
代碼實(shí)現(xiàn)細(xì)節(jié): 到目前為止,PasswordSpy 程序最有趣的部分其實(shí)是使用 SetWindowsHookEx API.函數(shù)設(shè)置Windows 鉤子。利用該函數(shù)你可以將鉤子安裝到操作系統(tǒng)中或者某個(gè)特定的進(jìn)程中。鉤子的種類有很多種,每種鉤子作用也不盡相同,用來(lái)監(jiān)視特定的一組事件。當(dāng)某一類事件發(fā)生時(shí),鉤子代碼被調(diào)用。PasswordSpy使用WH_GETMESSAGE鉤子,它監(jiān)視對(duì)GetMessage 和PeekMessage 的調(diào)用。關(guān)于鉤子更詳細(xì)的信息請(qǐng)參考MSDN庫(kù)的SetWindowsHookEx。
現(xiàn)在假設(shè)進(jìn)程A要在進(jìn)程B中設(shè)置鉤子。鉤子注入進(jìn)程B以后,該鉤子句柄被返回到進(jìn)程A,同時(shí)DLL被映射到進(jìn)程B的地址空間。當(dāng)進(jìn)程B中某個(gè)鉤子事件發(fā)生時(shí),你的鉤子代碼便在進(jìn)程B中被調(diào)用。(應(yīng)該注意的一點(diǎn)是你的鉤子代碼是從遠(yuǎn)程進(jìn)程空被調(diào)用的!鉤子代碼里,如果調(diào)用GetCurrentProcessId 函數(shù),那么獲得的是鉤子進(jìn)程的ID,而不是設(shè)置鉤子的進(jìn)程ID)。你可以在鉤子代碼中做任何想做的事情,但是在鉤子代碼退出之前,你應(yīng)該調(diào)用CallNextHookEx。如果這個(gè)函數(shù)調(diào)用失敗,其它任何已經(jīng)安裝的鉤子無(wú)法獲得消息。因?yàn)镃allNextHookEx需要該鉤子句柄,但我們當(dāng)前是在進(jìn)程B中,而句柄被返回到進(jìn)程A,因此,此時(shí)需要進(jìn)程間通訊來(lái)傳輸鉤子句柄。 #pragma data_seg("Shared") HHOOK g_hHook = NULL; #pragma data_seg() #pragma comment(linker, "/section:Shared,rws")其實(shí),此處創(chuàng)建了一個(gè)變量,所有已經(jīng)被加載的DLL實(shí)例共享這個(gè)變量。但這個(gè)方法有幾個(gè)問(wèn)題,第一,有些編譯器不支持這個(gè)選項(xiàng),第二,如果微軟要是在未來(lái)的Windows中改變“共享”內(nèi)存區(qū)的工作模式該怎么辦?這意味著這個(gè)技術(shù)不再適用。此外,這個(gè)方法不是線程同步的,由于有多個(gè)線程要訪問(wèn)這個(gè)變量,線程同步就變得很重要。為了解決這些問(wèn)題,我在進(jìn)程間通訊(IPC)過(guò)程中使用了內(nèi)存映射文件,并利用互斥機(jī)制進(jìn)程線程同步。我將這方面的代碼全部封裝在一個(gè)類中,這個(gè)類就是 CIPC。通過(guò)使用內(nèi)存映射文件,我解決了特定編譯器選項(xiàng)問(wèn)題,不用再考慮編譯器是否支持共享內(nèi)存區(qū);僅僅借助Win32 API調(diào)用以及用MMFs來(lái)提供多進(jìn)程間共享數(shù)據(jù)的機(jī)制就可以解決問(wèn)題,在未來(lái)的Windows版本中,這些東西是不太可能改變的。互斥保證了線程存取的同步: //*********************************************** // IPC.h //*********************************************** #ifndef _IPC_H_ #define _IPC_H_ #define IPC_SHARED_MMF _T("{34F673E0-878F-11D5-B98A-00B0D07B8C7C}") #define IPC_MUTEX _T("{34F673E1-878F-11D5-B98A-00B0D07B8C7C}") // 使用內(nèi)存映射文件進(jìn)行進(jìn)程間通訊的封裝類 class CIPC { public: CIPC(); virtual ~CIPC(); bool CreateIPCMMF(void); bool OpenIPCMMF(void); void CloseIPCMMF(void); bool IsOpen(void) const {return (m_hFileMap != NULL);} bool ReadIPCMMF(LPBYTE pBuf, DWORD &dwBufSize); bool WriteIPCMMF(const LPBYTE pBuf, const DWORD dwBufSize); bool Lock(void); void Unlock(void); protected: HANDLE m_hFileMap; HANDLE m_hMutex; }; #endif //*********************************************** // IPC.cpp //*********************************************** #include "IPC.h" //*********************************************** CIPC::CIPC() : m_hFileMap(NULL), m_hMutex(NULL) { } //*********************************************** CIPC::~CIPC() { CloseIPCMMF(); Unlock(); } //*********************************************** bool CIPC::CreateIPCMMF(void) { bool bCreated = false; try { if(m_hFileMap != NULL) return false; // Already created // Create an in-memory 4KB memory mapped // file to share data m_hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 4096, IPC_SHARED_MMF); if(m_hFileMap != NULL) bCreated = true; } catch(...) {} return bCreated; } //*********************************************** bool CIPC::OpenIPCMMF(void) { bool bOpened = false; try { if(m_hFileMap != NULL) return true; // Already opened m_hFileMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, IPC_SHARED_MMF); if(m_hFileMap != NULL) bOpened = true; } catch(...) {} return bOpened; } //*********************************************** void CIPC::CloseIPCMMF(void) { try { if(m_hFileMap != NULL) CloseHandle(m_hFileMap), m_hFileMap = NULL; } catch(...) {} } //*********************************************** bool CIPC::ReadIPCMMF(LPBYTE pBuf, DWORD &dwBufSize) { _ASSERTE(pBuf); bool bSuccess = true; try { if(m_hFileMap == NULL) return false; DWORD dwBaseMMF = (DWORD)MapViewOfFile(m_hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); _ASSERTE(dwBaseMMF); // The first DWORD in the MMF contains the size of the data DWORD dwSizeofInBuf = dwBufSize; CopyMemory(&dwBufSize, (LPVOID)dwBaseMMF, sizeof(DWORD)); if(dwSizeofInBuf != 0) { if(dwBufSize > dwSizeofInBuf) bSuccess = false; else CopyMemory(pBuf, (LPVOID)(dwBaseMMF + sizeof(DWORD)), dwBufSize); } UnmapViewOfFile((LPVOID)dwBaseMMF); } catch(...) {} return bSuccess; } //*********************************************** bool CIPC::WriteIPCMMF(const LPBYTE pBuf, const DWORD dwBufSize) { _ASSERTE(pBuf); bool bSuccess = true; try { if(m_hFileMap == NULL) return false; DWORD dwBaseMMF = (DWORD)MapViewOfFile(m_hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); _ASSERTE(dwBaseMMF); // The first DWORD in the MMF contains the size of the data CopyMemory((LPVOID)dwBaseMMF, &dwBufSize, sizeof(DWORD)); CopyMemory((LPVOID)(dwBaseMMF + sizeof(DWORD)), pBuf, dwBufSize); UnmapViewOfFile((LPVOID)dwBaseMMF); } catch(...) {} return bSuccess; } //*********************************************** bool CIPC::Lock(void) { bool bLocked = false; try { // First get the handle to the mutex m_hMutex = CreateMutex(NULL, FALSE, IPC_MUTEX); if(m_hMutex != NULL) { // Wait to get the lock on the mutex if(WaitForSingleObject(m_hMutex, INFINITE) == WAIT_OBJECT_0) bLocked = true; } } catch(...) {} return bLocked; } //*********************************************** void CIPC::Unlock(void) { try { if(m_hMutex != NULL) { ReleaseMutex(m_hMutex); CloseHandle(m_hMutex); m_hMutex = NULL; } } catch(...) {} }PasswordSpy的反向工程 上述內(nèi)容是關(guān)于通過(guò)編程途徑從其它程序“拷貝”密碼,下面的內(nèi)容我們將討論:如何防止PasswordSpy這樣的程序從你的程序中獲取密碼信息?如果你的應(yīng)用程序存儲(chǔ)并顯示密碼,你有特別關(guān)注安全問(wèn)題,你可能會(huì)考慮讓?xiě)?yīng)用堤防類似PasswordSpy這樣的程序。 參考資料
|
聯(lián)系客服