首页
社区
课程
招聘
[分享]内核下获取SSDT信息
发表于: 2016-4-13 10:24 10661

[分享]内核下获取SSDT信息

2016-4-13 10:24
10661
获取信息包括函数序号,当前地址,原始地址,函数名,内核模块完整路径,内核模块基址。支持WinAll x86。

#include "ntddk.h"
#include <WinDef.h>
#include "ntimage.h"

int NtosVersion;  //判断操作系统内核标志
wchar_t NtosVersionName[4][128]={L"\\??\\C:\\WINDOWS\\system32\\ntoskrnl.exe",L"\\??\\C:\\WINDOWS\\system32\\ntkrnlpa.exe",L"\\??\\C:\\WINDOWS\\system32\\ntkrnlmp.exe",L"\\??\\C:\\WINDOWS\\system32\\ntkrpamp.exe"};
char NtosVersionNameA[4][128]={"C:\\WINDOWS\\system32\\ntoskrnl.exe","C:\\WINDOWS\\system32\\ntkrnlpa.exe","C:\\WINDOWS\\system32\\ntkrnlmp.exe","C:\\WINDOWS\\system32\\ntkrpamp.exe"};
ULONG SSDTNumber=0;
KIRQL Irql;
BOOLEAN IsGetSSDT=false;

typedef struct _SSDTInformation
{
	ULONG index;
	ULONG CurrentAddress;
	ULONG OriginalAddress;
	char FunctionName[16];  //函数名
	char KernelMouduleName[64];  //内核模块名
	ULONG KernelMouduleBase;  //内核模块基址
}SSDTInformation,*PSSDTInformation;
PSSDTInformation SSDT;
//SSDT= (PSSDTInformation)ExAllocatePool(NonPagedPool,sizeof(SSDTInformation)*512);

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
	unsigned int *ServiceTableBase;
	unsigned int *ServiceCounterTableBase; 
	unsigned int NumberOfServices;
	unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

extern"C" __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;

ServiceDescriptorTableEntry_t  *pNewSSDT;

ULONG OldImageBase=0;  //当前内核在内存中的地址
ULONG ImageBase=0;  //文件中的基址

//恢复内存保护  
void PageProtectOn()
{
	__asm{
		mov  eax,cr0
			or   eax,10000h
			mov  cr0,eax
			sti
	}
}

//去掉内存保护
void PageProtectOff()
{
	__asm{
		cli
			mov  eax,cr0
			and  eax,not 10000h
			mov  cr0,eax
	}
}

typedef enum _SYSTEM_INFORMATION_CLASS
{
	SystemModuleInformation = 11,
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_MODULE_INFORMATION
{
	ULONG Reserved[2];
	PBYTE Base;
	ULONG Size;
	ULONG Flags;
	USHORT Index;
	USHORT Unknown;
	USHORT LoadCount;
	USHORT ModuleNameOffset;
	CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef struct _SYSTEM_MODULE_INFO_LIST
{
	ULONG ulCount;
	SYSTEM_MODULE_INFORMATION smi[1];
} SYSTEM_MODULE_INFO_LIST, *PSYSTEM_MODULE_INFO_LIST;

typedef struct _MY_IMAGE_BASE_RELOCATION {
	ULONG   VirtualAddress;
	ULONG   SizeOfBlock;
	USHORT  TypeOffset[1];
} MY_IMAGE_BASE_RELOCATION;


extern"C"  NTSTATUS __stdcall ZwQuerySystemInformation(
	SYSTEM_INFORMATION_CLASS SystemInformationClass,
	PVOID SystemInformation,
	ULONG SystemInformationLength,
	PULONG ReturnLength
	);



VOID SetNewSSDT(PVOID pNewImage)
{

	ULONG              uIndex;
	ULONG              uNewKernelInc,uOffset;
	//新内核地址-老内核地址,得到相对偏移
	uNewKernelInc = (ULONG)pNewImage -OldImageBase;

	//老内核的ssdt指针加上相对偏移,得到新内核的ssdt指针
	pNewSSDT = (ServiceDescriptorTableEntry_t *)((ULONG)&KeServiceDescriptorTable + uNewKernelInc);

	if (!MmIsAddressValid(pNewSSDT))
	{
		KdPrint(("pNewSSDT is unaviable!"));
		return;
	}
	//由于数量是一个数值,因此不必作相对偏移
	pNewSSDT->NumberOfServices = KeServiceDescriptorTable.NumberOfServices;
	//计算相对函数地址
	uOffset = (ULONG)KeServiceDescriptorTable.ServiceTableBase -OldImageBase;
	//得到新的ssdt函数表地址
	pNewSSDT->ServiceTableBase = (unsigned int*)((ULONG)pNewImage + uOffset);
	if (!MmIsAddressValid(pNewSSDT->ServiceTableBase))
	{
		KdPrint(("pNewSSDT->ServiceTableBase: %X",pNewSSDT->ServiceTableBase));
		return;
	}

	//依次遍历
	for (uIndex = 0;uIndex<pNewSSDT->NumberOfServices;uIndex++)
	{  //新的函数地址再加上相对加载地址,得到现在的ssdt函数地址
		pNewSSDT->ServiceTableBase[uIndex] = pNewSSDT->ServiceTableBase[uIndex]-ImageBase+OldImageBase;
		//DbgPrint("%d->%08x\n",uIndex,pNewSSDT->ServiceTableBase[uIndex]);  //打印SSDT索引号和地址
	}

	//
	//保存SSDT信息
	//
	SSDT= (PSSDTInformation)ExAllocatePool(NonPagedPool,sizeof(SSDTInformation)*pNewSSDT->NumberOfServices);
	if(SSDT==NULL)
	{
		DbgPrint("申请内存失败\n");
		return;
	}
	else
	{
		IsGetSSDT=true;
	}
	for (uIndex = 0;uIndex<pNewSSDT->NumberOfServices;uIndex++)
	{  
		SSDT[uIndex].index = uIndex;  //序号
		SSDT[uIndex].OriginalAddress=pNewSSDT->ServiceTableBase[uIndex];  //原始地址
		SSDT[uIndex].CurrentAddress=KeServiceDescriptorTable.ServiceTableBase[uIndex];
	}
	SSDTNumber=pNewSSDT->NumberOfServices;  //有多少项
}

BOOLEAN LoadKernel()
{
	NTSTATUS          status;
	UNICODE_STRING        uFileName;
	HANDLE            hFile;
	OBJECT_ATTRIBUTES      ObjAttr;
	IO_STATUS_BLOCK        IoStatusBlock;
	LARGE_INTEGER        FileOffset;
	ULONG            retsize;
	PVOID            lpVirtualPointer;
	ULONG            uLoop;
	ULONG            SectionVirtualAddress,SectionSize;
	PIMAGE_DOS_HEADER      ImageDosHeader;
	PIMAGE_NT_HEADERS      ImageNtHeader;
	PIMAGE_SECTION_HEADER    lpImageSectionHeader;

	InitializeObjectAttributes(&ObjAttr,\
		&uFileName,\
		OBJ_CASE_INSENSITIVE,\
		NULL,\
		NULL);
	RtlInitUnicodeString(&uFileName,NtosVersionName[NtosVersion]);
	//打开文件
	status = ZwCreateFile(\
		&hFile,\
		FILE_ALL_ACCESS,\
		&ObjAttr,\
		&IoStatusBlock,\
		0,\
		FILE_ATTRIBUTE_NORMAL,\
		FILE_SHARE_READ,\
		FILE_OPEN,\
		FILE_NON_DIRECTORY_FILE,\
		NULL,\
		0);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("CreateFile Failed!\n"));
		return false;
	}

	//读取DOS头
	FileOffset.QuadPart = 0;
	ImageDosHeader=(PIMAGE_DOS_HEADER)ExAllocatePool(NonPagedPool, sizeof(IMAGE_DOS_HEADER));  //记得释放
	status = ZwReadFile(hFile,\
		NULL,\
		NULL,\
		NULL,\
		&IoStatusBlock,\
		ImageDosHeader,\
		sizeof(IMAGE_DOS_HEADER),\
		&FileOffset,\
		0);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("Read ImageDosHeader Failed!"));
		ZwClose(hFile);
		return false;
	}



	//读取NT头
	ImageNtHeader=(PIMAGE_NT_HEADERS)ExAllocatePool(NonPagedPool, sizeof(IMAGE_NT_HEADERS));  //记得释放
	FileOffset.QuadPart = ImageDosHeader->e_lfanew;
	status = ZwReadFile(hFile,\
		NULL,\
		NULL,\
		NULL,\
		&IoStatusBlock,\
		ImageNtHeader,\
		sizeof(IMAGE_NT_HEADERS),\
		&FileOffset,\
		0);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("Read ImageNtHeaders Failed!"));
		ZwClose(hFile);
		return false;
	}
	ImageBase=ImageNtHeader->OptionalHeader.ImageBase;
	//读取区表
	lpImageSectionHeader = (PIMAGE_SECTION_HEADER)ExAllocatePool(NonPagedPool,sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader->FileHeader.NumberOfSections);
	FileOffset.QuadPart += sizeof(IMAGE_NT_HEADERS);
	status = ZwReadFile(hFile,\
		NULL,\
		NULL,\
		NULL,\
		&IoStatusBlock,\
		lpImageSectionHeader,\
		sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader->FileHeader.NumberOfSections,\
		&FileOffset,\
		0);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("Read ImageSectionHeader Failed!"));
		ExFreePool(lpImageSectionHeader);
		ZwClose(hFile);
		return false;
	}

	//COPY数据到内存
	lpVirtualPointer = ExAllocatePool(NonPagedPool,\
		ImageNtHeader->OptionalHeader.SizeOfImage);
	if(lpVirtualPointer == 0)
	{
		KdPrint(("lpVirtualPointer Alloc space Failed!"));
		ZwClose(hFile);
		return false;
	}
	memset(lpVirtualPointer,0,ImageNtHeader->OptionalHeader.SizeOfImage);
	//COPY DOS头
	RtlCopyMemory(lpVirtualPointer,\
		ImageDosHeader,\
		sizeof(IMAGE_DOS_HEADER));

	//COPY NT头
	RtlCopyMemory((PVOID)((ULONG)lpVirtualPointer+ImageDosHeader->e_lfanew),\
		ImageNtHeader,\
		sizeof(IMAGE_NT_HEADERS));
	//COPY 区表
	RtlCopyMemory((PVOID)((ULONG)lpVirtualPointer+ImageDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS)),\
		lpImageSectionHeader,\
		sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader->FileHeader.NumberOfSections);
	//依次COPY 各区段数据
	for(uLoop = 0;uLoop < ImageNtHeader->FileHeader.NumberOfSections;uLoop++)
	{
		SectionVirtualAddress = lpImageSectionHeader[uLoop].VirtualAddress;//对应区段相对偏移
		if(lpImageSectionHeader[uLoop].Misc.VirtualSize > lpImageSectionHeader[uLoop].SizeOfRawData)
			SectionSize = lpImageSectionHeader[uLoop].Misc.VirtualSize;//取最大的占用空间
		else
			SectionSize = lpImageSectionHeader[uLoop].SizeOfRawData;
		FileOffset.QuadPart = lpImageSectionHeader[uLoop].PointerToRawData;//对应区段的超始地址
		status = ZwReadFile(hFile,\
			NULL,\
			NULL,\
			NULL,\
			&IoStatusBlock,\
			(PVOID)((ULONG)lpVirtualPointer+SectionVirtualAddress),\
			SectionSize,\
			&FileOffset,\
			0);
		if(!NT_SUCCESS(status))
		{
			KdPrint(("SectionData Read Failed!"));
			ExFreePool(lpImageSectionHeader);
			ExFreePool(lpVirtualPointer);
			ZwClose(hFile);
			return false;
		}
	}

	SetNewSSDT(lpVirtualPointer);

	ExFreePool(lpImageSectionHeader);//释放区段内存空间
	ExFreePool(ImageNtHeader);
	ZwClose(hFile);//关闭句柄
	return true;
}

// 获取kernel模块的信息
NTSTATUS GetKernelModuleInfo()
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	PSYSTEM_MODULE_INFO_LIST pSysModInfoList = NULL;
	ULONG ulLength = 0;

	status = ZwQuerySystemInformation(SystemModuleInformation, pSysModInfoList, ulLength, &ulLength);
	if(status != STATUS_INFO_LENGTH_MISMATCH)
	{
		return STATUS_UNSUCCESSFUL;
	}

	pSysModInfoList = (PSYSTEM_MODULE_INFO_LIST)ExAllocatePool(NonPagedPool, ulLength);
	if(NULL == pSysModInfoList)
	{
		return STATUS_UNSUCCESSFUL;
	}

	status = ZwQuerySystemInformation(SystemModuleInformation, pSysModInfoList, ulLength, &ulLength);
	if(!NT_SUCCESS(status))
	{
		ExFreePool(pSysModInfoList);
		return STATUS_UNSUCCESSFUL;
	}

	OldImageBase=(ULONG)pSysModInfoList->smi[0].Base;  //得到当前内核的基址

	if(strstr(pSysModInfoList->smi[0].ImageName,"ntoskrnl.exe"))
	{
		NtosVersion=0;
	}
	if(strstr(pSysModInfoList->smi[0].ImageName,"ntkrnlpa.exe"))
	{
		NtosVersion=1;
	}
	if(strstr(pSysModInfoList->smi[0].ImageName,"ntkrnlmp.exe"))
	{
		NtosVersion=2;
	}
	if(strstr(pSysModInfoList->smi[0].ImageName,"ntkrpamp.exe"))
	{
		NtosVersion=3;
	}
	ExFreePool(pSysModInfoList);

	return STATUS_SUCCESS;
}

NTSTATUS Status;
HANDLE FileHandle;
IO_STATUS_BLOCK ioStatus;
FILE_STANDARD_INFORMATION FileInformation;
BOOLEAN GetSSDTName()
{


	if (KeGetCurrentIrql() > PASSIVE_LEVEL)
	{
		return STATUS_UNSUCCESSFUL;
	}
	//设置NTDLL路径
	UNICODE_STRING uniFileName;
	RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntdll.dll");

	//初始化打开文件的属性
	OBJECT_ATTRIBUTES objectAttributes;
	InitializeObjectAttributes(&objectAttributes, &uniFileName,
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
	////创建文件

	Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,
		&ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,
		NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
	if (!NT_SUCCESS(Status))
	{
		DbgPrint("IoCreateFile failed!status:0x%08x\n", Status);
		return false;
	}
	//获取文件信息

	Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,
		sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwQueryInformationFile failed!status:0x%08x\n", Status);
		ZwClose( FileHandle );
		return false;
	}
	//判断文件大小是否过大
	if (FileInformation.EndOfFile.HighPart != 0)
	{
		DbgPrint("File Size Too High");
		ZwClose(FileHandle);
		return false;
	}
	//取文件大小
	ULONG uFileSize = FileInformation.EndOfFile.LowPart;
	//分配内存
	PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize, (ULONG)"NTDLL");
	if (pBuffer == NULL)
	{
		DbgPrint("ExAllocatePoolWithTag() == NULL");
		ZwClose(FileHandle);
		return false;
	}
	//从头开始读取文件
	LARGE_INTEGER byteOffset;
	byteOffset.LowPart = 0;
	byteOffset.HighPart = 0;
	Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);
	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwReadFile failed!status:0x%08x\n", Status);
		ZwClose(FileHandle);
		return false;
	}
	//取出导出表
	PIMAGE_DOS_HEADER  pDosHeader;
	PIMAGE_NT_HEADERS  pNtHeaders;
	PIMAGE_SECTION_HEADER pSectionHeader;
	ULONG     FileOffset;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory;
	//DLL内存数据转成DOS头结构
	pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	//取出PE头结构
	pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)pBuffer + pDosHeader->e_lfanew);
	//判断PE头导出表表是否为空
	if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
	{
		DbgPrint("VirtualAddress == 0");
		return false;
	}
	//取出导出表偏移
	FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

	//取出节头结构
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
	PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
	//遍历节结构进行地址运算
	for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
	{
		if (pSectionHeader->VirtualAddress <= FileOffset &&
			FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
		{
			FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
		}
	}
	//导出表地址
	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pBuffer + FileOffset);
	//取出导出表函数地址
	PULONG AddressOfFunctions;
	FileOffset = pExportDirectory->AddressOfFunctions;
	//遍历节结构进行地址运算
	pSectionHeader = pOldSectionHeader;
	for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
	{
		if (pSectionHeader->VirtualAddress <= FileOffset &&
			FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
		{
			FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
		}
	}
	AddressOfFunctions = (PULONG)((ULONG)pBuffer + FileOffset);

	//取出导出表函数名字
	PUSHORT AddressOfNameOrdinals;
	FileOffset = pExportDirectory->AddressOfNameOrdinals;
	//遍历节结构进行地址运算
	pSectionHeader = pOldSectionHeader;
	for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
	{
		if (pSectionHeader->VirtualAddress <= FileOffset &&
			FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
		{
			FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
		}
	}
	AddressOfNameOrdinals = (PUSHORT)((ULONG)pBuffer + FileOffset);
	//取出导出表函数序号
	PULONG AddressOfNames;
	FileOffset = pExportDirectory->AddressOfNames;
	//遍历节结构进行地址运算
	pSectionHeader = pOldSectionHeader;
	for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
	{
		if (pSectionHeader->VirtualAddress <= FileOffset &&
			FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
		{
			FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
		}
	}
	AddressOfNames = (PULONG)((ULONG)pBuffer + FileOffset);
	//分析导出表
	ULONG uNameOffset;
	ULONG uOffset;
	LPSTR FunName;
	PVOID pFuncAddr;
	ULONG uServerIndex;
	ULONG uAddressOfNames;
	for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++)
	{
		uAddressOfNames = *AddressOfNames;
		pSectionHeader = pOldSectionHeader;
		for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
		{
			if (pSectionHeader->VirtualAddress <= uAddressOfNames &&
				uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
			{
				uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
			}
		} 
		FunName = (LPSTR)((ULONG)pBuffer + uOffset);

		if (FunName[0] == 'Z' && FunName[1] == 'w')
		{
			pSectionHeader = pOldSectionHeader;
			uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];
			for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
			{
				if (pSectionHeader->VirtualAddress <=  uOffset&&
					uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
				{
					uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
				}
			} 
			pFuncAddr = (PVOID)((ULONG)pBuffer + uNameOffset);
			uServerIndex = *(PULONG)((ULONG)pFuncAddr + 1);
			FunName[0] = 'N';
			FunName[1] = 't';
			//KdPrint(("序列号为:%d,函数名为: %s\n", uServerIndex, FunName));
			RtlCopyMemory(SSDT[uServerIndex].FunctionName,FunName,sizeof(char)*15);  //保存函数名
			SSDT[uServerIndex].KernelMouduleBase=OldImageBase;  //保存内核模块基址
			RtlCopyMemory(SSDT[uServerIndex].KernelMouduleName,NtosVersionNameA[NtosVersion],sizeof(char)*63);  //保存内核模块名

		}

	}
	ExFreePoolWithTag(pBuffer , (ULONG)"NTDLL");
	ZwClose(FileHandle);
	return true;
}

void DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	if(IsGetSSDT)
	{
		ExFreePool(SSDT);
	}
	DbgPrint("Driver Unload...\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegsiterPath)
{
	int i=0;
	pDriverObject->DriverUnload = DriverUnload;
	if(NT_SUCCESS(GetKernelModuleInfo()))  //获取当前内核信息
	{
		if(LoadKernel())  //加载内核
		{
			if(GetSSDTName())
			{
				for(int i=0;i<SSDTNumber;i++)
				{
					DbgPrint("序号:%d 当前地址:%08x 原始地址:%08x 函数名:%s 内核模块:%s 模块基址:%08x\n",SSDT[i].index,SSDT[i].CurrentAddress,SSDT[i].OriginalAddress,SSDT[i].FunctionName,SSDT[i].KernelMouduleName,SSDT[i].KernelMouduleBase);
				}
			}
			else
			{
				DbgPrint("GetSSDTName failed!\n");
			}
		}
		else
		{
			DbgPrint("LoadKernel failed!\n");
		}
		
	}
	else
	{
		DbgPrint("GetKernelModuleInfo failed!\n");
	}
	
	DbgPrint("Driver Onload...\n");
	return STATUS_SUCCESS;
}




大量参考了论坛其他人的代码,
无图无真相,上!

XP:




Windows 10






Windows10比较坑,内核文件会被进程占用,如果你直接打开会失败。关于这个我在http://www.netfairy.net/?post=232 第五点提到。解决的办法之一:CopyFileEx把内核文件复制到临时目录,用完再删除。最近写内核代码蓝屏多多,惊喜多多!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (16)
雪    币: 300
活跃值: (2477)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark,
2016-4-13 11:14
0
雪    币: 346
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
先mark。
2016-4-13 12:21
0
雪    币: 11096
活跃值: (17617)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
很具参考价值的学习资料,楼主辛苦了
2016-4-13 13:39
0
雪    币: 2938
活跃值: (18)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
5
顶,顶.
2016-4-13 15:57
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
大牛们    现在要发 应该直接发解析文件格式 读内核文件了      
这样不但稳定  安全  而且WINDOWS通用    也没有RING3  RING0   线程级别    文件占用  这些乱七八糟的问题

补充一句

印象里  NT系列函数  返回缓冲区需求长度   应该是从XP才有的    2K下的NT函数 是没有这个功能的
所以上面代码的两次QuerySystemInformation   在2K下 应该都是失败的。
2016-5-9 12:51
0
雪    币: 441
活跃值: (1060)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
7
mark
2016-5-19 13:37
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
KeServiceDescriptorTable.ServiceTableBase - PSYSTEM_MODULE_INFORMATION->Module[0].Base
= NEWSSDT.ServiceTableBase - pBuff(ntoskrnl.exe读入该内存)

原始地址 = *(NEWSSDT.ServiceTableBase + i*4) - pBuff.PIMAGE_NT_HEADERS.ImageBase + PSYSTEM_MODULE_INFORMATION->Module[0].Base;

是这样的关系吗?

虚拟机XpX86试了一下,就第一个函数地址相同,其他都不同,虚拟机没有被HOOK的,这是什么情况?
-----------------------------------------------------
特么写错了...
2016-9-26 17:50
0
雪    币: 18
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
原来可以编辑呀...
2016-9-26 22:17
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
10
怎么感觉有我的代码的影子?我感觉有一部分很像我以前发给一个网友的代码(帮他做一个windows管理软件)
2016-11-17 20:36
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习了一波,尝试在虚拟机win7 32运行了代码,发现无法打开内核文件ntkrnlpa.exe的情况。目测是打开文件status = ZwCreateFile(&hFile, FILE_ALL_ACCESS, &ObjAttr, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0)这句话给的权限太大导致失败,改成status = ZwCreateFile(&hFile, GENERIC_READ, &ObjAttr, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);申请权限改成只读就成功了。
2017-3-21 22:21
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
不过还是感谢分享,给我等菜鸟学习。
2017-3-21 22:22
0
雪    币: 7
活跃值: (333)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
13

你创建系统线程去打开,应该没这个限制。

2017-3-22 09:20
0
雪    币: 29
活跃值: (184)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
感谢分享
2017-7-12 15:21
0
雪    币: 20
活跃值: (146)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
请问一下,SetNewSSDT那个传入的地址不是你刚才读取的地址么,为什么就是新的内核地址了呢。。。。
2017-7-25 10:57
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
不错
2017-9-2 22:18
0
雪    币: 57
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢大佬
2020-2-6 23:53
0
游客
登录 | 注册 方可回帖
返回
//