windbg获取函数指针

文章详细描述了如何在Windows系统中使用FindWindowW和FindWindowExW函数,通过动态链接库和windbg调试工具追踪函数指针,以及在不同环境下查找并使用私有函数如Query_PrivateExW的过程。
摘要由CSDN通过智能技术生成
先写一个demo,查看FindWindowW FindWindowExW的函数指针
HMODULE hModule = LoadLibrary(L"user32.dll");
	if (hModule != NULL)
	{		
		while (true)
		{			
			FUN_FindWindowW FindWindowWFunc = (FUN_FindWindowW)GetProcAddress(hModule, "FindWindowW");
			if (FindWindowWFunc != NULL)
			{
				printf("FindWindowW 函数指针地址:%p\r\n", FindWindowWFunc);
				HWND hWnd = FindWindowWFunc(L"123", NULL);
			}
			FUN_FindWindowExW FindWindowExWFunc = (FUN_FindWindowExW)GetProcAddress(hModule, "FindWindowExW");
			if (FindWindowExWFunc != NULL)
			{
				printf("FindWindowExW 函数指针地址:%p\r\n", FindWindowExWFunc);
				HWND hWnd = FindWindowExWFunc(NULL,NULL, L"DingtalkMsgComming", NULL);
				int  n = (BYTE*)FindWindowExWFunc - (BYTE*)FindWindowWFunc;
				printf("指针偏移:%d 0X%X\r\n",n,n);

				FUN_FindWindowExW TextFun = (FUN_FindWindowExW)((BYTE*)FindWindowWFunc + n);
				printf("TextFun 函数指针地址:%p\r\n", TextFun);
				hWnd = TextFun(NULL, NULL, L"DingtalkMsgComming", NULL);
				int wjr = 0;

			}
			Sleep(5000);
		}
		FreeLibrary(hModule);
	}

windbg调试该程序 设置断点

bu USER32!FindWindowW

可以看到函数指针地址和打印出来的都一样的 都是**68483650

当函数命中时,地址也一致

按F8(t)一直往下走,耐心走

可以看到他掉用了FindWindowExW函数 地址 00007ffc68485f50 和demo程序打印出来的一致

我们继续按F8还可以看到 他内部会调用USER32!InternalFindWindowExW函数,这个函数是未公开的函数地址是68485f6c

用idea工具查看下FindWindowExW函数,他调用一个sub_180025F6C函数

在点进去看

我们尝试定义InternalFindWindowExW函数原型指针

typedef HWND(WINAPI* FUN_InternalFindWindowExW)(HWND hWndParent, HWND hWndChildAfter, LPCWSTR lpClassName, LPCWSTR lpWindowName,int code);

用InternalFindWindowExW 减去 00007ffc68485f6c - FindWindowExW地址 00007ffc68485f50

= 0x1C

此时我们修改下源码

HMODULE hModule = LoadLibrary(L"user32.dll");
	if (hModule != NULL)
	{		
		while (true)
		{			
			FUN_FindWindowW FindWindowWFunc = (FUN_FindWindowW)GetProcAddress(hModule, "FindWindowW");
			if (FindWindowWFunc != NULL)
			{
				printf("FindWindowW 函数指针地址:%p\r\n", FindWindowWFunc);
				HWND hWnd = FindWindowWFunc(L"123", NULL);
			}
			FUN_FindWindowExW FindWindowExWFunc = (FUN_FindWindowExW)GetProcAddress(hModule, "FindWindowExW");
			if (FindWindowExWFunc != NULL)
			{
				printf("FindWindowExW 函数指针地址:%p\r\n", FindWindowExWFunc);				
				HWND hWnd = FindWindowExWFunc(NULL,NULL, L"DingtalkMsgComming", NULL);
				int  n = (BYTE*)FindWindowExWFunc - (BYTE*)FindWindowWFunc;
				printf("指针偏移:%d 0X%X\r\n",n,n);

				FUN_FindWindowExW TextFun = (FUN_FindWindowExW)((BYTE*)FindWindowWFunc + n);
				printf("TextFun 函数指针地址:%p\r\n", TextFun);
				HWND hWnd1 = TextFun(NULL, NULL, L"DingtalkMsgComming", NULL);
				//int wjr = 0;

				HWND hWnd2 = 0;
				FUN_InternalFindWindowExW InternalFindWindowExWFunc = (FUN_InternalFindWindowExW)((BYTE*)FindWindowExWFunc + 0x1c);
				if (InternalFindWindowExWFunc != NULL)
				{
					hWnd2 = InternalFindWindowExWFunc(NULL, NULL, L"DingtalkMsgComming", NULL,0);
				}
				int wjr = 0;
			}
			Sleep(5000);
		}
		FreeLibrary(hModule);
	}

可以发现InternalFindWindowExWFunc 返回值和 FindWindowExW 一致

今天发现win7下从win10拷贝的windgb.exe不能用,后来查资料

Windows下调试工具Windbg入门_windbg core解析-CSDN博客

需要从微软官网下载win7 sdk ,其他都是win10版本

https://www.microsoft.com/en-us/download/details.aspx?id=8279

win7下如何查找Query_PrivateExW函数指针,一定要下好符号表pdb

#define WIN32_LEAN_AND_MEAN		// 从 Windows 头中排除极少使用的资料
#include <windows.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")

void main()
{
	WSADATA wsaData = { 0 };
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	HMODULE hModule = LoadLibrary(L"DNSAPI.dll");
	if (hModule == NULL)
	{
		printf("加载DNSAPI.dll失败\r\n");
		return;
	}

	FARPROC DnsApiAlloc = GetProcAddress(hModule, "DnsApiAlloc");
	if (DnsApiAlloc != NULL)
	{
		printf("DnsApiAlloc 函数地址: %p\r\n", DnsApiAlloc);
	}
	else
	{
		printf("DnsApiAlloc 函数地址没有找到\r\n");
	}

	struct addrinfoW hints;
	struct addrinfoW* res, * cur;
	memset(&hints, 0, sizeof(addrinfo));
	res = NULL;
	cur = NULL;

	//初始化 hints
	memset(&hints, 0, sizeof(addrinfo));
	hints.ai_family = AF_UNSPEC;		//IPv4/IPV6
	hints.ai_flags = AI_PASSIVE;		//匹配所有 IP 地址
	hints.ai_protocol = 0;			    //匹配所有协议
	hints.ai_socktype = SOCK_STREAM;    //流类型
	hints.ai_flags = AI_ALL;
	GetAddrInfoW(L"www.baidu.com", NULL, &hints, &res);
}

写一个测试demo 调用获取dns函数

使用x64dbg调试下

先在符号 ws2_32.dll GetAddrInfoW 按F2下个断点

选择dnsapi.dll 点击右键 弹出菜单 选择下载符号,一定要下载好符号


Downloading symbol dnsapi.pdb
  Signature: 70BE754EAC24444F93D3381A96404BBE2
  Destination: C:\mysymbol\dnsapi.pdb\70BE754EAC24444F93D3381A96404BBE2\dnsapi.pdb
  URL: https://msdl.microsoft.com/download/symbols/dnsapi.pdb/70BE754EAC24444F93D3381A96404BBE2/dnsapi.pdb
InternetOpenUrl failed ()...

如果出现下载失败,手动复制连接

https://msdl.microsoft.com/download/symbols/dnsapi.pdb/70BE754EAC24444F93D3381A96404BBE2/dnsapi.pdb

会下载一个blob文件 其实就是pdb

改个名字dnsapi.pdb然后拷贝到对应的目录下

此时从新来一遍调试

此时就可以看到符号表了

000007FEFC3E19AC - 000007FEFC3E1408 = 0x5A4 此时就可以知道

Query_PrivateExW 距离DnsApiAlloc 的便宜量是0x5A4了

在用windgb调试下,先设置好符号表

设置断点 bu WS2_32!GetAddrInfoW

但运行到断点时,查询命令x DNSAPI!Query_PrivateExW

就看到query_privateExW的函数地址了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值