转帖一篇:截取密码(VC++)学习消息VC++的好处
要截獲QQ密碼,大家一定想到鍵盤鉤子,2006版以前的QQ用這種方法的確可以截獲到QQ密碼,我也曾經(jīng)用這種方法將我女朋友的QQ密碼給弄過來了,~~,但2007版以后的QQ在密碼輸入框里做了大量的手腳,即使用spy++也無法截取到任何消息,鍵盤鉤子也失效了。我們總是幸運的,QQ登錄窗口的消息還是可以獲取到,既然鉤子不能用了,那我們何不換種思維方式走走捷徑呢?修改登錄窗口的回調(diào)函數(shù)地址,截取其所有消息,并創(chuàng)建一個虛假的密碼輸入框來到達截取密碼的目的,就好比在復(fù)寫紙上寫字,字跡會留下痕跡。
?
騰訊為了保護聊天內(nèi)容的安全性,防止QQ尾巴的干擾,對聊天的文字輸入框用額外的控件做了特殊處理,同樣不能截取到任何消息,也不能用WM_GETTEXT和WM_CHAR消息來取得其中的文字內(nèi)容。其實這個問題好解決,只要用模擬鍵盤程序模擬“Ctrl+A”->“Ctrl+C”就可以得到聊天內(nèi)容了。
?
去QQ廣告就更容易了,只要找到廣告顯示的子窗口,將它隱藏起來,然后在相同位置放一個自己的子窗口就可以了,如果獲取到IP地址或?qū)Ψ降牡乩砦恢玫刃畔⒁部梢燥@示在這里。
?
說到這里,還有一個非常重要的問題,那就是我們的程序必須執(zhí)行在QQ空間,因為Windows系統(tǒng)進程是受系統(tǒng)保護的,每個進程有自己獨立的內(nèi)存空間,很多API函數(shù)只對同一個進程有效,我們必須解決這個問題。
?
進入QQ進程
?
要將我們自己寫的代碼執(zhí)行在QQ進程空間中才能實現(xiàn)我們上面的的分析思路,我想到了兩種方法:
?
第一種方法還是鉤子,我們的代碼寫到一個dll動態(tài)鏈接庫里,然后啟動系統(tǒng)鉤子,當任何一個進程啟動時,我們的dll將會被加載到該進程中,我們判斷是否為QQ進程,如果不是,我們的dll就立即卸載,否則我們就順利地進入到QQ進程空間了。這種方法有個缺點,就是任何進程啟動時我們的dll都會被加載,嚴重影響到系統(tǒng)性能,我們在學習鉤子的時候書本上也確實講過,系統(tǒng)鉤子最好少用,如果程序代碼執(zhí)行效率不高的情況下,將影響系統(tǒng)性能,再好用的軟件也將變成垃圾而被用戶清除出去的。
?
第二種方法就是遠程dll注入,即用創(chuàng)建遠程線程的方法在QQ進程空間中注入一個我自己的線程,這種方法針對性很強,只對QQ進程進行操作,不操作其他進程,不影響系統(tǒng)性能,而且靈活性好,我們隨時可以將線程注入,也可以隨時撤銷,而第一種方法是系統(tǒng)鉤子內(nèi)部控制的,我們無法干預(yù)。
?
遠程注入Dll
?
我們的程序分為兩個部分,一部分是exe執(zhí)行程序,可以控制Dll的注入,另一部分就是我們要注入的Dll。
?
首先我們要找到系統(tǒng)中的QQ進程,這里要用到ToolHelp32系列函數(shù),以下函數(shù)能枚舉出系統(tǒng)所有的進程:
?
BOOL CProcessManage::EnumSystemProcess (
OUT CStringArray *pStrAry_ProcessName/*=NULL*/,
OUT CUIntArray *pUIntAry_ProcessID/*=NULL*/,
OUT CStringArray *pStrAry_ProcessPriority/*=NULL*/,
OUT CUIntArray *pUIntAry_ThreadNum/*=NULL*/,
OUT CStringArray *pStrAry_ProcessPath/*=NULL*/
)
{
HANDLE hProcess = NULL;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
if ( hProcessSnap == INVALID_HANDLE_VALUE )
return FALSE;
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
while ( bMore )
?
{
hProcess = OpenProcess(PROCESS_ALL_Access,FALSE,pe32.th32ProcessID);
if ( pStrAry_P
rocessName ) pStrAry_ProcessName->Add ( pe32.szExeFile );
if ( pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( pe32.th32ProcessID );
if ( pUIntAry_ThreadNum ) pUIntAry_ThreadNum->Add ( pe32.cntThreads );
if ( pStrAry_ProcessPriority ) pStrAry_ProcessPriority->Add ( GetProcessPriority(hProcess) );
if ( pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( GetProcessPath(pe32.th32ProcessID) );
bMore = ::Process32Next(hProcessSnap,&pe32);
}
::CloseHandle(hProcessSnap);
return TRUE;
}
從枚舉出的所有進程中找到QQ進程,如下代碼:
?
//
// 枚舉出 “QQ.exe”的進程
//
int EnumQQProcess ( CStringArray *pStrAry_ProcessName/*=NULL*/,
CUIntArray *pUIntAry_ProcessID/*=NULL*/,
CStringArray *pStrAry_ProcessPath/*=NULL*/ )
{
CStringArray StrAry_ProcessName;
CUIntArray UIntAry_ProcessID;
CStringArray StrAry_ProcessPath;
if ( !CProcessManage::EnumSystemProcess (
&StrAry_ProcessName,
&UIntAry_ProcessID,
NULL,
NULL,
&StrAry_ProcessPath
) )
{
return -1;
}
ASSERT ( StrAry_ProcessName.GetSize() == UIntAry_ProcessID.GetSize() );
ASSERT ( StrAry_ProcessName.GetSize() == StrAry_ProcessPath.GetSize() );
int nCount = 0;
for ( int i=0; i<StrAry_ProcessName.GetSize(); i++ )
{
CString csProcessName = StrAry_ProcessName.GetAt ( i );
TRACE ( _T("%sn"), csProcessName );
csProcessName.MakeLower ();
if ( csProcessName == _T("qq.exe") )
{
nCount ++;
if ( pStrAry_ProcessName ) pStrAry_ProcessName->Add ( csProcessName );
if ( pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( UIntAry_ProcessID.GetAt(i) );
if ( pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( StrAry_ProcessPath.GetAt(i) );
}
}
return nCount;
}
?
接下來我們使用函數(shù)VirtualAllocEx()/WriteProcessMemory()函數(shù)在QQ進程中申請內(nèi)存空間,將我們的數(shù)據(jù)參數(shù)寫入到QQ進程內(nèi)存空間里,然后用CreateRemoteThread()函數(shù)在QQ進程空間中啟動一個遠程線程,將我們的dll執(zhí)行在QQ進程空間中,如下函數(shù)既是:
?
typedef void (WINAPI *FUNC_SetRemoteParameter) ( LPVOID pParaAddrss, HWND hWndInvoker );
?
總結(jié)
以上是生活随笔為你收集整理的转帖一篇:截取密码(VC++)学习消息VC++的好处的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Winsock开发网络通信程序的经典入门
- 下一篇: VC/MFC中常用宏的含义