某Nginx后门分析复现与改写
2020-07-27 19:01:37 Author: bbs.pediy.com(查看原文) 阅读量:705 收藏

活跃值: 活跃值 (67)

能力值:

( LV2,RANK:10 )

在线值:

[讨论]InfinityHook在19041小版本间的兼容性问题

4小时前 276

[讨论]InfinityHook在19041小版本间的兼容性问题

本文参考:

剖析InfinityHook原理 掀起一场更激烈的攻与防恶战

Windows 10 19041版本的无限挂钩原理

Github项目InfinityHook

Github项目infhook19041

尝试过程:

为了技术储备,尝试在19041上进行稳定的InfinityHook

Windows19041 更新到最近的小版本 10.0.19041.388,下载对应的符号文件

直接编译大佬的项目Github项目infhook19041,运行,蓝屏,

调试发现 

在没有获取到函数 KeQueryPerformanceCounter 中 mov rdi, cs:HalpPerformanceCounter 地址的情况下

访问了地址+3的位置去获取变量HalpPerformanceCounter所在的偏移

IDA 加上符号文件

简单修改了查找的特征码

再次编译,没有蓝屏,但是Hook没有生效

继续调试

发现是在被替换了的 keQueryPerformanceCounter 中,在栈中查找存储系统调用的地址,之前的偏移已经无效

最终效果:

Github项目infhook19041,这份代码大佬可能只是用来测试,所以卸载的不完整,系统不重启的情况下,停止再重启驱动后,获取到的 circularKernelContextLogger 的值为1,而本应该获取到circularKernelContextLogger的地址。

简单修改代码

声明一个变量来保存 GetCpuClock 的索引值,在将WMI_LOGGER_CONTEXT的GetCpuClock成员设置为1前,保存

std::uintptr_t OriginalGetCpuClock		   {};/* 原GetCpuClock的索引值 */ 
OriginalGetCpuClock = *reinterpret_cast<std::uint64_t*>(circularKernelContextLogger + Offsets::wmiGetCpuClock);

在卸载驱动时,还原 GetCpuClock

bool UnhookSystemCall() {

	if (halpPerformanceCounter && halCounterQueryRoutine) {
		*reinterpret_cast<std::uintptr_t*>(halpPerformanceCounter + Offsets::counterQueryRoutine) = halCounterQueryRoutine;
		return true;
	}

	*reinterpret_cast<std::uint64_t*>(circularKernelContextLogger + Offsets::wmiGetCpuClock) = OriginalGetCpuClock;
	
	if (!NT_SUCCESS(modifyCKCL(EtwStopLoggerCode, EVENT_TRACE_FLAG_SYSTEMCALL))) {
		return false;
	}

	return false;
}

还发现了另外一个小问题,在事件跟踪控制中,ExAllocatePool 申请的内存,没有释放,简单改了下代码

NTSTATUS modifyCKCL(ETWTRACECONTROLCODE functionCode, std::uint32_t enableFlags) {
	PCKCL_TRACE_PROPERTIES properties = reinterpret_cast<PCKCL_TRACE_PROPERTIES>(ExAllocatePool(NonPagedPool, PAGE_SIZE));
	if (!properties)
		return STATUS_INSUFFICIENT_RESOURCES;

	memset(properties, 0, PAGE_SIZE);

	properties->Wnode.BufferSize    = PAGE_SIZE;
	properties->Wnode.Guid          = {0x54DEA73A, 0xED1F, 0x42A4, {0xAF, 0x71, 0x3E, 0x63, 0xD0, 0x56, 0xF1, 0x74}};
	properties->Wnode.ClientContext = 0x1;
	properties->Wnode.Flags         = 0x20000;
	properties->BufferSize          = sizeof(std::uint32_t);
	properties->MinimumBuffers      = 2;
	properties->MaximumBuffers      = 2;
	properties->LogFileMode         = 0x400;
	properties->EnableFlags         = enableFlags;
	properties->ProviderName        = RTL_CONSTANT_STRING(L"Circular Kernel Context Logger");

	std::uint32_t returnSize {};

	NTSTATUS Status = ZwTraceControl(functionCode, properties, PAGE_SIZE, properties, PAGE_SIZE, reinterpret_cast<PULONG>(&returnSize));
	ExFreePool(properties);
	return Status;
}

小版本之间的兼容问题

存储系统调用的栈地址,我们可以通过遍历栈,替换所有储存了系统调用函数指针的地址。

halpPerformanceCounter可以通过加载符号文件,获取符号信息;

但是符号文件以国内的网络很多时候都会下载失败,除非我们提前下载好所有版本的符号文件,但是这样一来只能向前兼容,不能向后兼容。

看雪的大佬们,有什么好的解决方法?

附件:

1.   版本 10.0.19041.388 的 ntoskrnl.exe 与其符号文件

2.   修改后Infinityhook

[公告]看雪论坛2020激励机制上线了!发帖不减雪币了!如何获得积分快速升级?

最后于 42分钟前 被随风行编辑 ,原因: 新增了发现的问题

上传的附件:
  • win10.19041程序文件+符号文件.zip (7.78MB,3次下载)
  • Infinityhook.zip (262.93kb,5次下载)

文章来源: https://bbs.pediy.com/thread-260962.htm
如有侵权请联系:admin#unsafe.sh