首页
社区
课程
招聘
[原创]重载内核之三获取原始地址
发表于: 2014-5-19 01:09 13126

[原创]重载内核之三获取原始地址

2014-5-19 01:09
13126

  重载内核的相关文章实在是太多了,鉴于还是有很多初学者研究这一块,本文仅作为一个引导作用,文笔不好,见谅。
  我的博客:http://blog.csdn.net/sidyhe
  开发环境:VS2010 + WinDDK
  测试环境:VirtualDDK + VMware + Win7 sp1 x86
  第一部分链接:http://bbs.pediy.com/showthread.php?t=187863
  第二部分链接:http://bbs.pediy.com/showthread.php?t=187919
小结与修正
  目前已经实现了一份简单的重载内核代码,但是如果你也跟着我实现了此部分,会发现此代码根本不能使用,甚至不能拿到本机来测试,是的,新的内核还是有大量的问题,驱动加载后会导致一些程序打不开,但是并不蓝屏,有意思的现象。
  写上一篇文章的时候没有测试的那么完善,但是我拿出我之前写的重载内核代码,并没有上述问题,仔细分析代码并回忆,问题还是出在了重定位以及需要额外的处理。那么关于修复重定位的部分就需要重新写了,把修复过程分为两部分,第一次全部重定位到新模块上,第二次有选择的重定位到原模块上,为什么需要那么麻烦?这就涉及到了原始地址的获取方式问题,原始地址都存储在一个叫KiServiceTable的变量中,详见WRK。为什么要获取原始地址?因为当驱动加载的时候你无法确定当前的SSDT表是否被HOOK,所以在第一次修复重定位之后去找KiServiceTable,然后再进行第二次重定位的修复(我无法保证第二次修复不会破坏KiServiceTable中的地址)。
  重新写一份代码,当然大部分还是从原来的代码复制过来,这样有利于逻辑上的思考,先不进行HOOK,把重载部分先理顺清楚,重定位修复代码修改为这个样子:

PVOID ReloadNtModule(PKLDR_DATA_TABLE_ENTRY PsLoadedModuleList)
{
  PVOID lpImageAddress = NULL;
  PKLDR_DATA_TABLE_ENTRY NtLdr = (PKLDR_DATA_TABLE_ENTRY)PsLoadedModuleList->InLoadOrderLinks.Flink;
  PVOID lpFileBuffer;

  DbgPrint("Nt Module File is %wZ\n", &NtLdr->FullDllName);
  if (lpFileBuffer = KeGetFileBuffer(&NtLdr->FullDllName))
  {
    PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer;
    PIMAGE_NT_HEADERS lpNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);

    if (lpImageAddress = ExAllocatePool(NonPagedPool, lpNtHeader->OptionalHeader.SizeOfImage))
    {
      PUCHAR lpImageBytes = (PUCHAR)lpImageAddress;
      IMAGE_SECTION_HEADER *lpSection = IMAGE_FIRST_SECTION(lpNtHeader);
      ULONG i;

      RtlZeroMemory(lpImageAddress, lpNtHeader->OptionalHeader.SizeOfImage);
      RtlCopyMemory(lpImageBytes, lpFileBuffer, lpNtHeader->OptionalHeader.SizeOfHeaders);
      for (i = 0; i < lpNtHeader->FileHeader.NumberOfSections; i++)
      {
        RtlCopyMemory(lpImageBytes + lpSection[i].VirtualAddress, (PCHAR)lpFileBuffer + lpSection[i].PointerToRawData, lpSection[i].SizeOfRawData);
      }
      if (KeFixIAT(PsLoadedModuleList, lpImageAddress))
      {
        KeFixReloc1(lpImageAddress, NtLdr->DllBase);
      }
      else
      {
        ExFreePool(lpImageAddress);
        lpImageAddress = NULL;
      }
    }
    ExFreePool(lpFileBuffer);
  }
  if (lpImageAddress) DbgPrint("ImageAddress:0x%p\n", lpImageAddress);
  return lpImageAddress;
}
VOID KeFixReloc1(PVOID ImageBaseAddress)
{
  IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)ImageBaseAddress;
  IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
  IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)ImageBaseAddress + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  ULONG_PTR DifferOffset = (ULONG_PTR)ImageBaseAddress - lpNtHeader->OptionalHeader.ImageBase;

  while (lpRelocateTable->SizeOfBlock)
  {
    ULONG NumberOfItems = (lpRelocateTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
    USHORT  *lpItem = (USHORT*)((PCHAR)lpRelocateTable + sizeof(IMAGE_BASE_RELOCATION));
    ULONG i;

    for (i = 0; i < NumberOfItems; i++)
    {
      switch (lpItem[i] >> 12)
      {
      case IMAGE_REL_BASED_HIGHLOW:
        {
          ULONG_PTR *lpFixAddress = (ULONG_PTR *)((PCHAR)ImageBaseAddress + lpRelocateTable->VirtualAddress + (lpItem[i] & 0x0FFF));

          *lpFixAddress += DifferOffset;
        }
        break;
      case IMAGE_REL_BASED_ABSOLUTE://do nothing
        break;
      default:
        DbgPrint("KeFixReloc1:Found unknown type(%X).\n", (lpItem[i] >> 12));
        break;
      }
    }
    lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
  }
  lpNtHeader->OptionalHeader.ImageBase = (ULONG)ImageBaseAddress;
  return;
}
VOID KeFixReloc2(PVOID New, PVOID Old)
{
  IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)New;
  IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
  IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)New + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

  while (lpRelocateTable->SizeOfBlock)
  {
    ULONG NumberOfItems = (lpRelocateTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
    USHORT  *lpItem = (USHORT*)((PCHAR)lpRelocateTable + sizeof(IMAGE_BASE_RELOCATION));
    ULONG i;

    for (i = 0; i < NumberOfItems; i++)
    {
      switch (lpItem[i] >> 12)
      {
      case IMAGE_REL_BASED_HIGHLOW:
        {
          PVOID lpFixAddress = (PCHAR)New + lpRelocateTable->VirtualAddress + (lpItem[i] & 0x0FFF);

          KeFixRelocEx(New, Old, lpFixAddress);
        }
        break;
      case IMAGE_REL_BASED_ABSOLUTE://do nothing
        break;
      default:
        break;
      }
    }
    lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
  }
  return;
}
BOOLEAN KeIsExecutable(PVOID ImageBase, PVOID Address)
{
  IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)ImageBase;
  IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
  IMAGE_SECTION_HEADER *lpSecHdr = IMAGE_FIRST_SECTION(lpNtHeader);
  ULONG_PTR Rva = (ULONG_PTR)Address - (ULONG_PTR)ImageBase;
  USHORT i;

  for (i = 0; i < lpNtHeader->FileHeader.NumberOfSections; i++)
  {
    if (Rva >= lpSecHdr[i].VirtualAddress && Rva < lpSecHdr[i].VirtualAddress + lpSecHdr[i].SizeOfRawData)
    {
      return ((lpSecHdr[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0);
    }
  }
  return FALSE;
}

VOID KeFixRelocEx(PVOID New, PVOID Old, PVOID FixAddress)
{
  if (KeIsExecutable(New, FixAddress))
  {
    if (KeIsExecutable(New, *(PVOID*)FixAddress))
    {
      if (KeIsIAT(New, *(PVOID*)FixAddress))
      {
        NOTHING;
      }
      else
      {
        *(ULONG_PTR*)FixAddress = *(ULONG_PTR*)FixAddress - (ULONG_PTR)New + (ULONG_PTR)Old;
      }
    }
    else
    {
      *(ULONG_PTR*)FixAddress = *(ULONG_PTR*)FixAddress - (ULONG_PTR)New + (ULONG_PTR)Old;
    }
  }
  else
  {
    if (KeIsExecutable(New, *(PVOID*)FixAddress))
    {
      NOTHING;
    }
    else
    {
      *(ULONG_PTR*)FixAddress = *(ULONG_PTR*)FixAddress - (ULONG_PTR)New + (ULONG_PTR)Old;
    }
  }
  return;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 4
支持
分享
最新回复 (13)
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
mark
2014-5-19 01:11
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
BOOLEAN KeIsIAT(PVOID ImageBase, PVOID lpAddress)
{
	IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)ImageBase;
	IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
	PIMAGE_IMPORT_DESCRIPTOR lpImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)ImageBase + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

	while (lpImportDescriptor->Characteristics)
	{
		PIMAGE_THUNK_DATA lpThunk = (PIMAGE_THUNK_DATA)((PCHAR)ImageBase + lpImportDescriptor->OriginalFirstThunk);
		PVOID *lpFuncTable = (PVOID*)((PCHAR)ImageBase + lpImportDescriptor->FirstThunk);
		ULONG i;

		for (i = 0; lpThunk->u1.Ordinal; i++)
		{
			if ((lpThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0)
			{
				if (lpAddress == &lpFuncTable[i])
				{
					return TRUE;
				}
			}
			lpThunk++;
		}
		lpImportDescriptor++;
	}
	return FALSE;
}
2014-5-19 01:16
0
雪    币: 2895
活跃值: (3929)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
继续,不要停
2014-5-19 07:07
0
雪    币: 236
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5

  1 PVOID ReloadNtModule(PKLDR_DATA_TABLE_ENTRY PsLoadedModuleList)
  2 {
  3     PVOID lpImageAddress = NULL;
  4     PKLDR_DATA_TABLE_ENTRY NtLdr = (PKLDR_DATA_TABLE_ENTRY)PsLoadedModuleList->InLoadOrderLinks.Flink;
  5     PVOID lpFileBuffer;
  6 
  7     DbgPrint("Nt Module File is %wZ\n", &NtLdr->FullDllName);
  8     if (lpFileBuffer = KeGetFileBuffer(&NtLdr->FullDllName))
  9     {
 10     ┊   PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer;
 11     ┊   PIMAGE_NT_HEADERS lpNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
 12 
 13     ┊   if (lpImageAddress = ExAllocatePool(NonPagedPool, lpNtHeader->OptionalHeader.SizeOfImage))
 14     ┊   {
 15     ┊   ┊   PUCHAR lpImageBytes = (PUCHAR)lpImageAddress;
 16     ┊   ┊   IMAGE_SECTION_HEADER *lpSection = IMAGE_FIRST_SECTION(lpNtHeader);
 17     ┊   ┊   ULONG i;
 18 
 19     ┊   ┊   RtlZeroMemory(lpImageAddress, lpNtHeader->OptionalHeader.SizeOfImage);
 20     ┊   ┊   RtlCopyMemory(lpImageBytes, lpFileBuffer, lpNtHeader->OptionalHeader.SizeOfHeaders);
 21     ┊   ┊   for (i = 0; i < lpNtHeader->FileHeader.NumberOfSections; i++)
 22     ┊   ┊   {
 23     ┊   ┊   ┊   RtlCopyMemory(lpImageBytes + lpSection[i].VirtualAddress, (PCHAR)lpFileBuffer + lpSection[i].PointerToRawData, lpSection[i].SizeOfRawData);
 24     ┊   ┊   }
 25     ┊   ┊   if (KeFixIAT(PsLoadedModuleList, lpImageAddress))
 26     ┊   ┊   {
 27     ┊   ┊   ┊   KeFixReloc1(lpImageAddress, NtLdr->DllBase);
 28     ┊   ┊   }
 29     ┊   ┊   else
 30     ┊   ┊   {
 31     ┊   ┊   ┊   ExFreePool(lpImageAddress);
 32     ┊   ┊   ┊   lpImageAddress = NULL;
 33     ┊   ┊   }
 34     ┊   }
 35     ┊   ExFreePool(lpFileBuffer);
 36     }
 37     if (lpImageAddress) DbgPrint("ImageAddress:0x%p\n", lpImageAddress);
 38     return lpImageAddress;
 39 }
 40 VOID KeFixReloc1(PVOID ImageBaseAddress)
 41 {
 42     IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)ImageBaseAddress;
 43     IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
 44     IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)ImageBaseAddress + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
 45     ULONG_PTR DifferOffset = (ULONG_PTR)ImageBaseAddress - lpNtHeader->OptionalHeader.ImageBase;
 46 
 47     while (lpRelocateTable->SizeOfBlock)
 48     {
 49     ┊   ULONG NumberOfItems = (lpRelocateTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
 50     ┊   USHORT  *lpItem = (USHORT*)((PCHAR)lpRelocateTable + sizeof(IMAGE_BASE_RELOCATION));
 51     ┊   ULONG i;
 52 
 53     ┊   for (i = 0; i < NumberOfItems; i++)
 54     ┊   {
 55     ┊   ┊   switch (lpItem[i] >> 12)
 56     ┊   ┊   {
 57     ┊   ┊   ┊   case IMAGE_REL_BASED_HIGHLOW:
 58     ┊   ┊   ┊   ┊   {
 59     ┊   ┊   ┊   ┊   ┊   ULONG_PTR *lpFixAddress = (ULONG_PTR *)((PCHAR)ImageBaseAddress + lpRelocateTable->VirtualAddress + (lpItem[i] & 0x0FFF));
 60 
 61     ┊   ┊   ┊   ┊   ┊   *lpFixAddress += DifferOffset;
 62     ┊   ┊   ┊   ┊   }
 63     ┊   ┊   ┊   ┊   break;
 64     ┊   ┊   ┊   case IMAGE_REL_BASED_ABSOLUTE://do nothing
 65     ┊   ┊   ┊   ┊   break;
 66     ┊   ┊   ┊   default:
 67     ┊   ┊   ┊   ┊   DbgPrint("KeFixReloc1:Found unknown type(%X).\n", (lpItem[i] >> 12));
 68     ┊   ┊   ┊   ┊   break;
 69     ┊   ┊   }
 70     ┊   }
 71     ┊   lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
 72     }
 73     lpNtHeader->OptionalHeader.ImageBase = (ULONG)ImageBaseAddress;
 74     return;
 75 }
 76 VOID KeFixReloc2(PVOID New, PVOID Old)
 77 {
 78     IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)New;
 79     IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
 80     IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)New + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
 81 
 82     while (lpRelocateTable->SizeOfBlock)
 83     {
 84     ┊   ULONG NumberOfItems = (lpRelocateTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
 85     ┊   USHORT  *lpItem = (USHORT*)((PCHAR)lpRelocateTable + sizeof(IMAGE_BASE_RELOCATION));
 86     ┊   ULONG i;
 87 
 88     ┊   for (i = 0; i < NumberOfItems; i++)
 89     ┊   {
 90     ┊   ┊   switch (lpItem[i] >> 12)
 91     ┊   ┊   {
 92     ┊   ┊   ┊   case IMAGE_REL_BASED_HIGHLOW:
 93     ┊   ┊   ┊   ┊   {
 94     ┊   ┊   ┊   ┊   ┊   PVOID lpFixAddress = (PCHAR)New + lpRelocateTable->VirtualAddress + (lpItem[i] & 0x0FFF);
 95 
 96     ┊   ┊   ┊   ┊   ┊   KeFixRelocEx(New, Old, lpFixAddress);
 97     ┊   ┊   ┊   ┊   }
 98     ┊   ┊   ┊   ┊   break;
 99     ┊   ┊   ┊   case IMAGE_REL_BASED_ABSOLUTE://do nothing
100     ┊   ┊   ┊   ┊   break;
101     ┊   ┊   ┊   default:
102     ┊   ┊   ┊   ┊   break;
103     ┊   ┊   }
104     ┊   }
105     ┊   lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
106     }
107     return;
108 }



    // 论坛代码 可以设置高亮嘛?
2014-5-19 08:51
0
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mark
2014-5-19 11:32
0
雪    币: 124
活跃值: (469)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
楼主有没有遇到过,起始重定位表的第一个结构,virtual和sizeofblock都是零的情况,我就遇到了(内核在磁盘上的文件被修改了)。你这种方式,在这种情况下是无法实现重定位的。真的很想知道,当这种判断重定位的方式有误时,怎么处理。。。。
2014-5-20 08:34
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
把文件发上来看看
2014-5-20 12:24
0
雪    币: 124
活跃值: (469)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
把文件发上来看看[/QUOTE]
这个是从虚拟机上的xp上拷贝过来的
ntkrnlpa.rar
上传的附件:
2014-5-20 16:29
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
10
[QUOTE=topofall;1286059]把文件发上来看看
这个是从虚拟机上的xp上拷贝过来的
ntkrnlpa.rar[/QUOTE]

我看了一下,你也仔细看看,我是用的C32ASM
VirtualAddress是0,SizeofBlock不是0
那么函数可以改为:
VOID KeFixReloc1(PVOID ImageBaseAddress)
{
	IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)ImageBaseAddress;
	IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
	IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)ImageBaseAddress + lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	ULONG_PTR ExpectBaseAddress = lpNtHeader->OptionalHeader.ImageBase;

	while (lpRelocateTable->SizeOfBlock)
	{
		if (lpRelocateTable->VirtualAddress)
		{
			ULONG NumberOfItems = (lpRelocateTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
			USHORT  *lpItem = (USHORT*)((PCHAR)lpRelocateTable + sizeof(IMAGE_BASE_RELOCATION));
			ULONG i;

			for (i = 0; i < NumberOfItems; i++)
			{
				switch (lpItem[i] >> 12)
				{
				case IMAGE_REL_BASED_HIGHLOW:
					{
						ULONG_PTR *lpFixAddress = (ULONG_PTR *)((PCHAR)ImageBaseAddress + lpRelocateTable->VirtualAddress + (lpItem[i] & 0x0FFF));
						ULONG_PTR Rva = *lpFixAddress - ExpectBaseAddress;

						*lpFixAddress = (ULONG_PTR)ImageBaseAddress + Rva;
					}
					break;
				case IMAGE_REL_BASED_ABSOLUTE://do nothing
					break;
				default:
					DbgPrint("KeFixReloc1:Found unknown type(%X).\n", (lpItem[i] >> 12));
					break;
				}
			}
		}
		lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
	}
	lpNtHeader->OptionalHeader.ImageBase = (ULONG_PTR)ImageBaseAddress;
	return;
}

    同理KeFixReloc2、FindKiServiceTable以及后面文章的PatchKeFlushCurrentTb也多添加一个判断。
    谢谢指点。
2014-5-20 16:41
0
雪    币: 124
活跃值: (469)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
驱动重新加载了一下,验证了一下确实是Virtual:0x00000000         SizeOfBlock:192
昨天加载的时候,不知道为什么老是显示为零。。。。我说嘛,奇了怪了peload能识别,我写的不能识别。搞得我还以为是那个有其他方法判断呢。
2014-5-20 23:24
0
雪    币: 46
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
KeGetModuleHandle在哪
2014-6-6 18:02
0
雪    币: 2161
活跃值: (750)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
根据名字遍历PsLoadedModuleList获取模块基址,自写函数,代码就不贴了,很简单的。
2014-6-7 11:51
0
雪    币: 206
活跃值: (117)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢分享!!
2015-4-13 21:24
0
游客
登录 | 注册 方可回帖
返回
//