• 64位操作系统Hook内核函数NtQuerySystemInformation遇到的坑


    最近做个东西,修改某程序通过调用GetSystemInfo得到CPU内核数目的目的,起初想在进程内Hook GetSystemInfo 这个API来达到效果,但是这样HOOK还得向进程注入一个DLL,比较麻烦。后来得知GetSystemInfo 这个函数内部调用内核NtQuerySystemInformation来达到效果的。于是想直接Hook 内核NtQuerySystemInformation来达到效果。

     

    HOOK的过程还算顺利,我是判断参数为SystemBasicInformation的时候就直接修改NtQuerySystemInformation返回的CPU数目来达到这个目的。

     

    但是,实际测试发现,并不能达到修改CPU数目的效果。调试了两三个小时无果,最后在网上查发现问题所在。

    In 32-bit Windows, the structure is filled exactly the same for all three information classes. The x64 builds treat SystemEmulationBasicInformation differently. This allows WOW64.DLL, executing 64-bit code in a 32-bit process, to get basic information that’s suited to the 32-bit caller.

    于是修改HOOK函数条件为SystemEmulationBasicInformation 时总算解决了这个问题。

     

    最终Hook函数代码如下:

    NTSTATUS __fastcall FakeNtQuerySystemInformation(
    	IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    	OUT PVOID                   SystemInformation,
    	IN ULONG                    SystemInformationLength,
    	OUT PULONG                  ReturnLength
    )
    {
    	if ((SystemBasicInformation == SystemInformationClass ||
    		SystemEmulationBasicInformation == SystemInformationClass) && gGetProcessImageFileName != 0 && g_config_processor_count > 0) {
    		PCHAR pImageName = gGetProcessImageFileName(PsGetCurrentProcess());
    		if (NULL != pImageName)
    		{
    			CHAR buffer[100];
    			strncpy(buffer, pImageName,100);
    			int len = strlen(buffer);
    			for (int i = 0; i < len && i < 100; i++)
    				buffer[i] = (char)tolower((int)buffer[i]);
    
    			if (strstr(buffer, "asktao") != NULL) {
    				memset(SystemInformation, 0, SystemInformationLength);
    				DbgPrint("[FakeCpuCount]FakeNtQuerySystemInformation pid: %s 
    ", pImageName);
    				NTSTATUS status = NtQuerySystemInformation(SystemInformationClass,
    					SystemInformation, SystemInformationLength, ReturnLength);
    				if (SystemInformationClass == SystemEmulationBasicInformation) {
    					if (NT_SUCCESS(status)) {
    						(*(BYTE*)((ULONGLONG)SystemInformation + 0x38)) = (BYTE)g_config_processor_count;
    					}
    				}
    				else
    				{
    					if (NT_SUCCESS(status)) {
    						(*(BYTE*)((ULONGLONG)SystemInformation + 0x38)) = (BYTE)g_config_processor_count;
    					}
    				}
    				return status;
    			}
    		}
    	}
    	return NtQuerySystemInformation(SystemInformationClass,
    		SystemInformation, SystemInformationLength, ReturnLength);
    }
    

      

     

  • 相关阅读:
    PHP 连接oracle
    PHP 简易导出excel 类解决Excel 打开乱码
    Linux下Apache网站目录读写权限的设置
    PHP behavior 机制简单实现
    RewriteCond和13个mod_rewrite应用举例Apache伪静态
    PHP event 事件机制
    PHP 函数引用传值
    django数据库连接快速配置
    解决Django项目数据库无法迁移问题
    生成uuid唯一标识符
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/13416104.html
Copyright © 2020-2023  润新知