首页
社区
课程
招聘
[原创]OD插件之重载内核(高清有码)
发表于: 2015-5-29 21:56 45921

[原创]OD插件之重载内核(高清有码)

2015-5-29 21:56
45921

写这个插件其实主要是因为现在32位下各种内核钩子,用一些调试工具畏首畏尾的,一会挂钩这里,一会挂钩那里,遂干脆一了百了,直接写个内核重载插件,虽说是OD插件,也可以支持其他软件。此插件名字就叫ReloadKernel V1.0吧,贴切一点:(支持2003,XP,WIN7)请避免和360,QQ管家,百度杀毒等一同使用,对于没有DebugPort清零的保护应该是可以秒的,比如HS(亲测),当然你要处理R3的反调试,对于有调试权限清零的自己恢复,端口清零的自己改下偏移也就OK了,不会改的话再不济用这个插件也可以读写内存吧!,请别瞎想,本人写这个插件主要是为了学习交流,请大家不要用于非法用途,先来个图


首先内核重载插件我分成以下几个步骤完成
1,        获取当前系统下的内核文件
2,        按PE格式加载硬盘中的内核文件,修复重定位表,导入导出表
3,        挂钩KiFastCallEntry
4,        实现过滤框架
5,        R3,R0通信
6,        OD插件GUI与逻辑部分
  
1,因为在单核,多核处理器等不同情况下,微软会加载不同的内核文件,所以我们需要知道当前系统所加载的是哪一个内核文件,之后获取到它的全路径,并Copy到内存中,已便操作
下面这个函数是获取系统加载的内核模块基址,没什么好说的,原理就是ZwQuerySystemInformation的11号功能,查询内核模块

PVOID 
GetKernelFileBase()
{
	DWORD dwsize = 0;
	PVOID pKernelBase = NULL;
	PVOID pSysInfo = NULL;
	__try
	{

		
		ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&dwsize);


	    pSysInfo = ::ExAllocatePool(NonPagedPool,dwsize);
		if(pSysInfo)
		{	
			memset(pSysInfo,0,dwsize);

			if(NT_SUCCESS(ZwQuerySystemInformation(SystemModuleInformation,pSysInfo,dwsize,&dwsize)))
			{
				PSYSTEM_MODULE_INFORMATION_ENTRY psmi = (PSYSTEM_MODULE_INFORMATION_ENTRY)((PBYTE)pSysInfo + 4);	
				pKernelBase = (PVOID)psmi->Base;
				
	
			}
			else
			{
				KdPrint(("GetKernelFileBase.ZwQuerySystemInformation error\n"));
			}
		}

	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		KdPrint(("GetKernelFileBase异常\n"));
	}
	if(pSysInfo) 
	{
		ExFreePool(pSysInfo);
		pSysInfo = NULL;
	}
	return pKernelBase ;
}

bool 
GetKernelFileFullPath(
					  OUT PUNICODE_STRING pUnicodeStr 
					  )
{
	bool bResult = FALSE;
	DWORD dwsize = 0;
	PVOID pSysInfo = NULL;
	_try
	{
		ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&dwsize);

		pSysInfo = ::ExAllocatePool(NonPagedPool,dwsize);

		if(pSysInfo)
		{	
			memset(pSysInfo, 0, dwsize);

			if(NT_SUCCESS(ZwQuerySystemInformation(SystemModuleInformation,pSysInfo,dwsize,&dwsize)))
			{


				PSYSTEM_MODULE_INFORMATION_ENTRY psmi = (PSYSTEM_MODULE_INFORMATION_ENTRY)((char*)pSysInfo + 4);

				char *szKernelModuleName = psmi->ImageName + psmi->PathLength;
				KdPrint(("模块 %s\n",szKernelModuleName));

				char szKernelModuleFullPath[255];
				ANSI_STRING asModuleName;

				//"\\Device\\HarddiskVolume1\\Windows\\System32\\"


				char szSystemPath[] = "\\??\\c:\\Windows\\System32\\";
				strcpy(szKernelModuleFullPath,(char*)szSystemPath);
				strcat(szKernelModuleFullPath,szKernelModuleName);

				::RtlInitAnsiString(&asModuleName,szKernelModuleFullPath);
				::RtlAnsiStringToUnicodeString(pUnicodeStr,&asModuleName,TRUE);

				bResult = TRUE;

			}
			else
			{
				KdPrint(("GetKernelFileFullPath.ZwQuerySystemInformation error"));
			}
		}

	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		KdPrint(("GetKernelFileFullPath.异常"));
	}
	if(pSysInfo) 
	{
		ExFreePool(pSysInfo);
		pSysInfo = NULL;
	}

	return bResult;
}
PVOID 
CreateImageFromFile( 
					IN PUNICODE_STRING ImageFile)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	HANDLE FileHandle = NULL;
	OBJECT_ATTRIBUTES ObjAttributes = {0};
	IO_STATUS_BLOCK IoStatusBlock = {0};

	InitializeObjectAttributes(
		&ObjAttributes,
		ImageFile,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL);

	Status =  ZwCreateFile(
		&FileHandle,
		GENERIC_READ, 
		&ObjAttributes,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);

	if(NT_SUCCESS(Status))
	{

		FILE_STANDARD_INFORMATION fsi = {0};
		IO_STATUS_BLOCK iostatus = {0};

		Status = ZwQueryInformationFile(
			FileHandle,
			&iostatus, 
			&fsi,
			sizeof(FILE_STANDARD_INFORMATION),
			FileStandardInformation);
		if(NT_SUCCESS(Status))
		{

			PVOID pBuffer  = ExAllocatePool(PagedPool,(LONG)fsi.EndOfFile.QuadPart);
			if(pBuffer)
			{
				memset(pBuffer,0,(LONG)fsi.EndOfFile.QuadPart);


				Status = ZwReadFile(FileHandle, NULL, NULL, NULL,&iostatus, pBuffer, (LONG)fsi.EndOfFile.QuadPart, NULL, NULL);

				if(NT_SUCCESS(Status))
				{
					KdPrint(("Read %x bytes\n", iostatus.Information));

					ZwClose(FileHandle);

					return pBuffer;
				}
				else
				{
					KdPrint(("CreateImageFromFile.读取文件失败 %x",Status));
					return 0;
				}
			}
			else
			{
				KdPrint(("CreateImageFromFile.申请非分页内存失败"));
			}
			
		}
		else
		{
			KdPrint(("CreateImageFromFile.获取文件尺寸失败"));
			return 0;
		}


	}
	else
	{
		KdPrint(("CreateImageFromFile.打开文件失败"));
		return 0;
	}

	return 0;
}
ULONG 
CreatePeStructFromMem(
					  IN ULONG ulFileAddress,
					  IN ULONG ntKernelAddress)
{

	__try
	{
		PIMAGE_DOS_HEADER pIMAGE_DOS_HEADER =  (PIMAGE_DOS_HEADER)ulFileAddress;
		PIMAGE_NT_HEADERS	pIMAGE_NT_HEADERS = (PIMAGE_NT_HEADERS)(ulFileAddress + pIMAGE_DOS_HEADER->e_lfanew);
		PIMAGE_FILE_HEADER	pIMAGE_FILE_HEADER = &pIMAGE_NT_HEADERS->FileHeader;
		PIMAGE_OPTIONAL_HEADER32	pIMAGE_OPTIONAL_HEADER = &pIMAGE_NT_HEADERS->OptionalHeader;
		KdPrint(("DOS 头 %x \n",pIMAGE_DOS_HEADER));
		KdPrint(("NT 头 %x \n",pIMAGE_NT_HEADERS));
		KdPrint(("文件 头 %x \n",pIMAGE_FILE_HEADER));
		KdPrint(("可选 头 %x \n",pIMAGE_OPTIONAL_HEADER));


		if(!pIMAGE_NT_HEADERS || !pIMAGE_FILE_HEADER || !pIMAGE_OPTIONAL_HEADER) return 0;


		ULONG pMy_ImageBase = (ULONG)ExAllocatePool(NonPagedPool,pIMAGE_OPTIONAL_HEADER->SizeOfImage); 

		if(pMy_ImageBase)
		{
		
			memset((PVOID)pMy_ImageBase,0,pIMAGE_OPTIONAL_HEADER->SizeOfImage);

			//复制头加段表
			RtlCopyMemory((PVOID)pMy_ImageBase,(PVOID)ulFileAddress,pIMAGE_OPTIONAL_HEADER->SizeOfHeaders );

			//节表展开
			PIMAGE_SECTION_HEADER pSectionHeadTmp = (PIMAGE_SECTION_HEADER)((ULONG)pIMAGE_OPTIONAL_HEADER + sizeof(IMAGE_OPTIONAL_HEADER32));
			for(int i = 0;i < pIMAGE_NT_HEADERS->FileHeader.NumberOfSections;i ++)
			{

				RtlCopyMemory((PVOID)(pSectionHeadTmp->VirtualAddress + (ULONG)pMy_ImageBase),//计算VA
					(PVOID)(pSectionHeadTmp->PointerToRawData + (ULONG)ulFileAddress),//文件偏移
					pSectionHeadTmp->SizeOfRawData);//计算尺寸

				pSectionHeadTmp ++;
			}

			//导入表处理


			for(
				PIMAGE_IMPORT_DESCRIPTOR pImportDescriptorTmp = (PIMAGE_IMPORT_DESCRIPTOR)(pIMAGE_OPTIONAL_HEADER->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (ULONG)pMy_ImageBase);
				!IsStructEmpty<IMAGE_IMPORT_DESCRIPTOR>(pImportDescriptorTmp);
			pImportDescriptorTmp++
				)
			{
				KdPrint(("导入模块 %s\n",(char*)(pImportDescriptorTmp->Name + (ULONG)pMy_ImageBase)));

				PVOID pModule = KernelGetModuleBase(((char*)(pImportDescriptorTmp->Name + (ULONG)pMy_ImageBase)));

				if(pModule) 
				{
					for(
						PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA)(pImportDescriptorTmp->FirstThunk + (ULONG)pMy_ImageBase); 
						!IsStructEmpty<IMAGE_THUNK_DATA>(pThunkData); 
					pThunkData++
						)
					{

						PVOID pFunctionTmp = 
							pThunkData->u1.AddressOfData & IMAGE_ORDINAL_FLAG32 ?

							KernelGetProcAddress(pModule,(PCHAR)(pThunkData->u1.AddressOfData & 0xffff))
							:
						KernelGetProcAddress(pModule,(PCHAR)((PIMAGE_IMPORT_BY_NAME)(pThunkData->u1.AddressOfData + (ULONG)pMy_ImageBase))->Name);


						if(!pFunctionTmp)
						{
							if(pThunkData->u1.AddressOfData & IMAGE_ORDINAL_FLAG32)
							{
								KdPrint(("有函数没找到,序号 %d",(PCHAR)(pThunkData->u1.AddressOfData & 0xffff)));
							}

							else
							{
								KdPrint(("有函数没找到,名字%s",(PCHAR)((PIMAGE_IMPORT_BY_NAME)(pThunkData->u1.AddressOfData + (ULONG)pMy_ImageBase))->Name));
							}
						}
						else
						{
							if(pThunkData->u1.AddressOfData & IMAGE_ORDINAL_FLAG32)
							{
								KdPrint(("已经修复函数,序号 %d",(PCHAR)(pThunkData->u1.AddressOfData & 0xffff)));
							}

							else
							{
								KdPrint(("已经修复函数,名字%s",(PCHAR)((PIMAGE_IMPORT_BY_NAME)(pThunkData->u1.AddressOfData + (ULONG)pMy_ImageBase))->Name));
							}

							pThunkData->u1.Function  = (DWORD)pFunctionTmp;
						}


					}
				}
				else
				{
					KdPrint(("获取模块 %s失败\n",(char*)(pImportDescriptorTmp->Name + (ULONG)pMy_ImageBase)));
				}

			}

			int nRelocNum = 0;

			ULONG ulR = ntKernelAddress - pIMAGE_OPTIONAL_HEADER->ImageBase;

			KdPrint(("重定位偏移 ulR =  %x",ulR));
			for(
				PIMAGE_BASE_RELOCATION pLoc = (PIMAGE_BASE_RELOCATION)(pIMAGE_OPTIONAL_HEADER->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (ULONG)pMy_ImageBase);
				!IsStructEmpty<IMAGE_BASE_RELOCATION>(pLoc); 
			pLoc = (PIMAGE_BASE_RELOCATION)((DWORD)pLoc + pLoc->SizeOfBlock)
				)
			{
				nRelocNum ++;
				for(PWORD pHandleAddress = (PWORD)((DWORD)pLoc + sizeof(IMAGE_BASE_RELOCATION));pHandleAddress < (PWORD)((DWORD)pLoc + pLoc->SizeOfBlock);pHandleAddress ++)
				{
					if((*pHandleAddress & 0xf000) == IMAGE_REL_BASED_HIGHLOW * 0X1000)//x86重定位标记
					{

						*(PDWORD((*pHandleAddress & 0xfff) + pLoc->VirtualAddress +  (ULONG)pMy_ImageBase)) += ulR;




					}
				}

			}

			KdPrint(("重定位块 =  %d个",nRelocNum));

			return pMy_ImageBase;

		}
		else
		{
				KdPrint(("CreatePeStructFromMem.申请内存失败"));
		}
	

	}

	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		KdPrint(("CreatePeStructFromMem.执行异常"));
	}
	return 0;
}
int nRelocNum = 0;

			ULONG ulR = ntKernelAddress - pIMAGE_OPTIONAL_HEADER->ImageBase;

			KdPrint(("重定位偏移 ulR =  %x",ulR));
			for(
				PIMAGE_BASE_RELOCATION pLoc = (PIMAGE_BASE_RELOCATION)(pIMAGE_OPTIONAL_HEADER->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (ULONG)pMy_ImageBase);
				!IsStructEmpty<IMAGE_BASE_RELOCATION>(pLoc); 
			pLoc = (PIMAGE_BASE_RELOCATION)((DWORD)pLoc + pLoc->SizeOfBlock)
				)
			{
				nRelocNum ++;
				for(PWORD pHandleAddress = (PWORD)((DWORD)pLoc + sizeof(IMAGE_BASE_RELOCATION));pHandleAddress < (PWORD)((DWORD)pLoc + pLoc->SizeOfBlock);pHandleAddress ++)
				{
					if((*pHandleAddress & 0xf000) == IMAGE_REL_BASED_HIGHLOW * 0X1000)//x86重定位标记
					{

						*(PDWORD((*pHandleAddress & 0xfff) + pLoc->VirtualAddress +  (ULONG)pMy_ImageBase)) += ulR;


					}
				}

			}
template <class T>
bool IsStructEmpty(
				   IN T *Mystruct)
{
	bool bIsEmpty = true;
	__try
	{
		for(PBYTE p = (PBYTE)Mystruct;p < (PBYTE)((DWORD)Mystruct + sizeof(T)) ;p++)
		{
			if((*p) != 0 )
			{
				bIsEmpty = false;
				break;
			}
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{

		KdPrint(("IsStructEmpty Exception"));
	}
	return bIsEmpty;
}
ULONG GetAddressOfKiFastCallEntry()
{
	ULONG dwAddress = 0;
	BYTE vgdtr[8] = {0};
	__asm
	{
	
		push eax
			push ebx
			push ecx
			push edx
			mov ecx, 0x174
			rdmsr
			mov ebx, eax		//Selector offset

			sgdt vgdtr
			//	mov edx, vgdtr
			lea edx,vgdtr
			add edx, 0x02
			mov eax, [edx]		//GDT base
		add ebx, eax		//Selector base

			mov edx, ebx
			add edx, 0x07
			mov eax, [edx]
		shl eax, 24;
		mov edx, ebx
			add edx, 0x02
			mov ecx, [edx]
		and ecx, 0x00FFFFFF
			add eax, ecx		//Address CodeSegment
			mov ebx, eax

			mov ecx, 0x176
			rdmsr
			add eax, ebx

			mov dwAddress, eax

			pop edx
			pop ecx
			pop ebx
			pop eax
	}

	return dwAddress;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 4
支持
分享
最新回复 (97)
雪    币: 682
活跃值: (826)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
把编译出来的  发上来  没安装VS
2015-5-29 22:23
0
雪    币: 70
活跃值: (37)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
插件也一并上传了
2015-5-29 22:30
0
雪    币: 47
活跃值: (359)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错不错,楼主有心了
2015-5-29 22:47
0
雪    币: 83
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好东西呀,谢谢分享~~
2015-5-29 22:49
0
雪    币: 2324
活跃值: (5138)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
不懂驱动啊·!!
2015-5-29 22:59
0
雪    币: 291
活跃值: (934)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
对第二个插件比较感兴趣
2015-5-29 23:02
0
雪    币: 967
活跃值: (1138)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
MARK 一下说不定哪天要用到
2015-5-29 23:10
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2015-5-29 23:53
0
雪    币: 39
活跃值: (264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享
2015-5-30 00:34
0
雪    币: 12864
活跃值: (4494)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
感谢分享~
2015-5-30 00:39
0
雪    币: 49
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
MARK一下,很好的教程。谢谢。
2015-5-30 09:58
0
雪    币: 244
活跃值: (454)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
致谢,火钳刘明
2015-5-30 10:05
0
雪    币: 2443
活跃值: (499)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
up  好文!
2015-5-30 10:10
0
雪    币: 8
活跃值: (190)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
设备打开失败?
2015-5-30 10:19
0
雪    币: 12548
活跃值: (5293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
只能说强大哟
2015-5-30 10:57
0
雪    币: 6124
活跃值: (4726)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
17
楼主6的不行
2015-5-31 03:14
0
雪    币: 13
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
这个插件 无敌了 赞
2015-5-31 08:42
0
雪    币: 163
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
Mark
2015-5-31 11:02
0
雪    币: 25
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
为啥没设精呢
2015-5-31 11:21
0
雪    币: 249
活跃值: (197)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
21
谢谢楼主分享
2015-5-31 12:39
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
谢谢分享 好东西 mark
2015-5-31 13:00
0
雪    币: 7942
活跃值: (2372)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
不错的文章,感谢分享。。。
2015-5-31 15:52
0
雪    币: 130
活跃值: (427)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
马克~~
2015-6-1 18:25
0
雪    币: 50161
活跃值: (20670)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
25
感谢分享!
2015-6-1 18:39
0
游客
登录 | 注册 方可回帖
返回
//