X64ssdt 枚举函数偏移地址

emmmmm 这个其实  和Windows x86差不多~~~~~

这里参考了 看雪论坛分享的 资料  作者是 Tesla.Angela(GDUT.HWL) 

下面是代码 

#include <ntddk.h>
#include <windef.h>
#pragma intrinsic(__readmsr)
typedef struct _SYSTEM_SERVICE_TABLE{
	PLONG  		ServiceTableBase;
	PVOID  		ServiceCounterTableBase;
	ULONGLONG  	NumberOfServices;
	PVOID  		ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
PSYSTEM_SERVICE_TABLE ssdt;
ULONGLONG GetSsdt()
{
	PUCHAR startaddr = (PUCHAR)__readmsr(0xc0000082);//这里是两个下划线
	PUCHAR Endaddr = startaddr + 0x500;
	PUCHAR i = NULL;
	UCHAR b1, b2, b3;
	ULONG temp = 0;
	ULONGLONG addr = 0;
	for (i = startaddr; i < Endaddr; i++)
	{
		b1 = *i;
		b2 = *(i + 1);
		b3 = *(i + 2);
		if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15)
		{
			memcpy(&temp, i + 3, 4);
			addr = (ULONGLONG)temp + (ULONGLONG)i + 7;
			return addr;
		}
	}
	return 0;
}
ULONGLONG GetFunctionAddress(ULONGLONG index)
{	
	LONG Temp;
	ULONGLONG temp,ret=0;
	temp = (ULONGLONG)ssdt + 4 * index;
	Temp = *(PLONG)temp;
	Temp = Temp >> 4;
	ret = (ULONGLONG)ssdt + (LONG64)Temp;
	return ret; 
}
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("goodbye"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	ULONGLONG i = 0;
	PSYSTEM_SERVICE_TABLE add=NULL;
	ULONGLONG addr = GetSsdt();
	if (addr== 0)
	{
		KdPrint(("大哥对不起 没有找到ssdt!\n"));
		return STATUS_SUCCESS;
	}
	ssdt = (PSYSTEM_SERVICE_TABLE)addr;
	KdPrint(("sstd :%d\n", ssdt->NumberOfServices));
	for (i = 0; i < ssdt->NumberOfServices; i++)
	{     
		KdPrint(("【%d】%x", i, (ssdt->ServiceTableBase[i])));
	}
	DriverObject->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

这是效果图 

然后 这里说一下 总结吧

其实这里也是一步一步调试出来的

因为x64的ssdt 表没有导出  所以需要动态导出ssdt 表 这个比较坑爹  

不过 看教程  比较厉害的是通过读取 C0000082 寄存器,能够得到 KiSystemCall64 的地址, 这个虽然不知道前辈们怎么得出来的 但是可以肯定的是,这个帮了我们的大忙 

fffff800`03cc7ff2 4c8d1547782300  lea     r10,[nt!KeServiceDescriptorTable 

然后我们的 KeServiceDescriptorTable 的特征码就是 4c8d15

而  我们换一下特征码(4c8d1d),就能获得 KeServiceDescriptorTableShadow 的地址了。 
然后 这样我们就能得出 他们的地址了 然后就可以枚举地址了

然后 至于 根据 服务号 然后推断出 地址的

 mov rax, rcx ;rcx=Native API 的 index 
 lea r10,[rdx] ;rdx=ssdt 基址 
 mov edi,eax 
 shr edi,7 
 and edi,20h 
 mov r10, qword ptr [r10+rdi] 
 movsxd r11,dword ptr [r10+rax] 
 mov rax,r11 
 sar r11,4 
 add r10,r11 
 mov rax,r10  ret

(以上代码是 作者Tesla.Angela(GDUT.HWL)  所总结)

但是驱动不支持汇编  那么只能 转化成 C或者 shellcode 了  

C的呢 我上面有  

下面shellcode 我直接放出 Tesla.Angela(GDUT.HWL) 的代码了

VOID Initxxxx()
{
	UCHAR strShellCode[36]="\x48\x8B\xC1\x4C\x8D\x12\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x4E\x8B\x14\x17\x4D\x63\x1C\x82\x49\x8B\xC3\x49\xC1\xFB\x04\x4D\x03\xD3\x49\x8B\xC2\xC3";
	/*
	mov rax, rcx ;rcx=index
	lea r10,[rdx] ;rdx=ssdt
	mov edi,eax
	shr edi,7
	and edi,20h
	mov r10, qword ptr [r10+rdi]
	movsxd r11,dword ptr [r10+rax*4]
	mov rax,r11
	sar r11,4
	add r10,r11
	mov rax,r10
	ret
	*/
	scfn=ExAllocatePool(NonPagedPool,36);
	memcpy(scfn,strShellCode,36);
}

也没有什么东西~~

猜你喜欢

转载自blog.csdn.net/qq_41071646/article/details/86482350