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

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

2014-5-19 01:09
13012
  重载内核的相关文章实在是太多了,鉴于还是有很多初学者研究这一块,本文仅作为一个引导作用,文笔不好,见谅。
  我的博客: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;
}

  重点还是KeFixRelocEx,重定位修正的是“地址的值”,希望大家能看懂,那么我就在这里做了相对比较多的判断。
  “地址”可执行,“值”可执行。
  “地址”可执行,“值”不可执行。指向原模块。如访问全局变量。
  “地址”不可执行,“值”可执行。不修改。如函数表。
  “地址”不可执行,“值”不可执行。想不出来是什么,指向原模块吧。
对于第一点,我原本是指向新模块,但测试了好半天,最后还是没有解决重载后某些程序打不开的问题。我曾尝试解析汇编,但字节组合方式太多了,我无法做出最正确的判断,既然我找不到是哪一类重定位存在问题,那么我就做没有问题的地方,如IAT,这种处理很像权限访问中的解决方式(1.我能干什么。2.我不能干什么)。最后代码变成这个样子:
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;
}

  啰嗦了那么多,非常不完美的解决了某些程序打不开的问题,如果有兴趣的朋友可以继续深入。但回头想想重载仅仅是为了防止HOOK而带来的麻烦,不妨假设HOOK没有那么猥琐,如果你发现重载内核不能绕过某些HOOK,再对症下药吧。
第三部分:获取原始地址
  重头戏来啦!一开始说过原始SSDT函数都存储在一个叫做KiServiceTable的变量里,这个变量同样没有导出,利用字节码搜索的方式效率很低且未必找的准确,所以另求出路。网上已经有大牛研究出了一种方式,那就是利用重定位来查找。
  首先来看WRK是如何做的:(KiInitSystem)
   KeServiceDescriptorTable[0].Base = &KiServiceTable[0];
    KeServiceDescriptorTable[0].Count = NULL;
    KeServiceDescriptorTable[0].Limit = KiServiceLimit;
    KeServiceDescriptorTable[0].Number = KiArgumentTable;
    for (Index = 1; Index < NUMBER_SERVICE_TABLES; Index += 1) {
        KeServiceDescriptorTable[Index].Limit = 0;
    }

    //
    // Copy the system service descriptor table to the shadow table
    // which is used to record the Win32 system services.
    //

    RtlCopyMemory(KeServiceDescriptorTableShadow,
                  KeServiceDescriptorTable,
                  sizeof(KeServiceDescriptorTable));

  再来对比Windows 7 x86中是如何做的,IDA分析如下:

  Ntoskrnl.exe的期望基址是00400000,所以第一句的RVA就是00395C12,来看一下重定位信息:

  可以发现一个特点,有两个连续的重定位00395C14与00396C18,而第一个RVA就是KeServiceDescriptorTable,第二个就是KiServiceTable了,结合IDA对附近代码的综合判断,最后的代码就是这样:
PVOID FindKiServiceTable(PVOID lpNtoskrnlAddress)
{
  PVOID lpKeServiceDescriptorTable = KeGetProcAddress(lpNtoskrnlAddress, "KeServiceDescriptorTable");
  IMAGE_DOS_HEADER *lpDosHeader = (IMAGE_DOS_HEADER*)lpNtoskrnlAddress;
  IMAGE_NT_HEADERS *lpNtHeader = (IMAGE_NT_HEADERS *)((PCHAR)lpDosHeader + lpDosHeader->e_lfanew);
  IMAGE_BASE_RELOCATION *lpRelocateTable = (IMAGE_BASE_RELOCATION*)((PCHAR)lpNtoskrnlAddress + 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 j;

    for (j = 0; j < NumberOfItems - 1; j++)
    {
      if ((lpItem[j] >> 12) == IMAGE_REL_BASED_HIGHLOW && (lpItem[j + 1] >> 12) == IMAGE_REL_BASED_HIGHLOW)
      {
        ULONG *lpFixAddress1 = (ULONG*)((PCHAR)lpNtoskrnlAddress + lpRelocateTable->VirtualAddress + (lpItem[j] & 0x0FFF));
        ULONG *lpFixAddress2 = (ULONG*)((PCHAR)lpNtoskrnlAddress + lpRelocateTable->VirtualAddress + (lpItem[j + 1] & 0x0FFF));
        //两个连续的重定位
        if ((ULONG)lpFixAddress2 - (ULONG)lpFixAddress1 == sizeof(ULONG))
        {
          //MOV DWORD PTR DS:[KeServiceDescriptorTable], XXX
          if (*(USHORT*)((PCHAR)lpFixAddress1 - sizeof(USHORT)) == 0x05C7)
          {
            //DbgPrint("lpFixAddress1:%08X\n", (ULONG)lpFixAddress1 - 2);
            if (*lpFixAddress1 == (ULONG)lpKeServiceDescriptorTable)
            {
              return (PVOID)*lpFixAddress2;
            }
          }
        }
      }
    }
    lpRelocateTable = (IMAGE_BASE_RELOCATION *)((PCHAR)lpRelocateTable + lpRelocateTable->SizeOfBlock);
  }
  return NULL;
}
PVOID BuildKeServiceTable(PVOID lpKernelAddress, PVOID lpOrgKernelAddress)
{
  PVOID lpKiServiceTable = NULL;
  PVOID lpKeServiceTable = NULL;

  if (lpKiServiceTable = FindKiServiceTable(lpKernelAddress))
  {
    lpKeServiceTable = ExAllocatePool(NonPagedPool, KeServiceDescriptorTable->NumberOfService * sizeof(PVOID));
    
    if (lpKeServiceTable)
    {
      RtlCopyMemory(lpKeServiceTable, lpKiServiceTable, KeServiceDescriptorTable->NumberOfService * sizeof(PVOID));
      DbgPrint("BuildSSDT:0x%p\n", lpKeServiceTable);
    }    
  }
  return lpKeServiceTable;
}

  而最后的DriverEntry与ServiceCallFilter则是:
PVOID ServiceCallFilter(PVOID *lppServiceTableBase, ULONG_PTR ServiceIndex)
{
  if (lppServiceTableBase == KeServiceDescriptorTable->ServiceTableBase)
  {
    return g_KeServiceTable[ServiceIndex];
  }
  return lppServiceTableBase[ServiceIndex];
}

VOID __declspec(naked) _MyKiFastCallEntryFrame()
{
  __asm
  {
    push ecx;

    push eax;
    push edi;
    call ServiceCallFilter;
    mov  edx, eax;

    pop  ecx;

    pop  eax;
    sub  esp, ecx;
    shr  ecx, 2;
    mov  edi, esp;
    jmp  eax;
  }
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
  PVOID lpHookKiFastCallEntryAddress;
  UCHAR HookCode[7];

  DbgPrint("Driver Load.\n");
  InitializePsLoadedModuleList(DriverObject);
  g_lpNtoskrnlAddress = KeGetModuleHandle(PsLoadedModuleList, "ntoskrnl.exe");
  g_lpNewNtoskrnlAddress = ReloadNtModule(PsLoadedModuleList);
  g_KeServiceTable = (PVOID*)BuildKeServiceTable(g_lpNewNtoskrnlAddress, g_lpNtoskrnlAddress);
  KeFixReloc2(g_lpNewNtoskrnlAddress, g_lpNtoskrnlAddress);
  lpHookKiFastCallEntryAddress = FindHookKiFastCallEntryAddress(GetKiFastCallEntryAddress());
  HookCode[0] = 0xE8;
  *(ULONG*)&HookCode[1] = (ULONG_PTR)_MyKiFastCallEntryFrame - (ULONG_PTR)lpHookKiFastCallEntryAddress - 5;
  HookCode[5] = 0x90;
  HookCode[6] = 0x90;
  RtlCopyMemoryEx(lpHookKiFastCallEntryAddress, HookCode, sizeof(HookCode));

  DriverObject->DriverUnload = DriverUnload;
  return STATUS_SUCCESS;
}

  来来来测试一下,就用HideToolz来看效果。


  加载驱动咯。

  好了,无视SSDT HOOK,同样无视INLINE HOOK,终于算是完成了一点像样的东西了,但这并不是全部,也不是此专题的完结,后面还有哦,我想后面应该是告诉大家如何再把SHADOW SSDT搞定。
  最后,此代码仍然不能拿到本机测试,如果你想蓝的话。对于新模块最少还有两个问题没有搞定(别喷我),后续我同样会告诉大家。嗯,先这样吧。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 4
支持
分享
最新回复 (13)
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
mark
2014-5-19 01:11
0
雪    币: 2143
活跃值: (720)
能力值: ( 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
雪    币: 2588
活跃值: (3579)
能力值: ( 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
活跃值: (429)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
楼主有没有遇到过,起始重定位表的第一个结构,virtual和sizeofblock都是零的情况,我就遇到了(内核在磁盘上的文件被修改了)。你这种方式,在这种情况下是无法实现重定位的。真的很想知道,当这种判断重定位的方式有误时,怎么处理。。。。
2014-5-20 08:34
0
雪    币: 2143
活跃值: (720)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
把文件发上来看看
2014-5-20 12:24
0
雪    币: 124
活跃值: (429)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
把文件发上来看看[/QUOTE]
这个是从虚拟机上的xp上拷贝过来的
ntkrnlpa.rar
上传的附件:
2014-5-20 16:29
0
雪    币: 2143
活跃值: (720)
能力值: ( 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
活跃值: (429)
能力值: ( 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
雪    币: 2143
活跃值: (720)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
根据名字遍历PsLoadedModuleList获取模块基址,自写函数,代码就不贴了,很简单的。
2014-6-7 11:51
0
雪    币: 206
活跃值: (117)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢分享!!
2015-4-13 21:24
0
游客
登录 | 注册 方可回帖
返回
//