首页
社区
课程
招聘
[求助]如何遍历内核空间内存地址的可读性问题
发表于: 2017-6-23 14:18 3909

[求助]如何遍历内核空间内存地址的可读性问题

2017-6-23 14:18
3909

本人在写自己的反rootkit工具,需要枚举整个内存空间来寻找DriverObject特征,为了保险起见,起始地址为ntoskrnl.exe文件的基址,结束地址为0xffffffffffffffff。现在,有这么个问题,我需要判断指向内存的可读性,如果内存是不可读的,判断是否为驱动也就没有意义,具体代码如下:

ULONG IsValidAddr(ULONG64 pAddr)//这个函数怎么写?
{
	
	return TRUE;
}
BOOLEAN IsRealDriver(ULONG64 pAddr)
{
	PDRIVER_OBJECT pTempDriver = NULL;
	pTempDriver = (PDRIVER_OBJECT)pAddr;
	if ((pTempDriver->Type == 4) && (pTempDriver->Size == 0x150))
	{
		if (pTempDriver->DriverSize == 0)
		{
			return FALSE;
		}
		else
		{
			if (((ULONG64)(pTempDriver->DriverStart)) < 0xfffff80000000000)    //判断DriverStart是否处于低端内存,如果是,则返回FALSE
			{
				return FALSE;
			}
			else
			{
				if (((ULONG64)(pTempDriver->DriverSection)) < 0xfffff80000000000)
				{
					return FALSE;
				}
				else
				{
					return TRUE;
				}
			}
		}
	}
	else
	{
		return FALSE;
	}
}
VOID SearchTheAddress()
{
	PDRIVER_OBJECT  TempDriverObject=NULL;
	PKLDR_DATA_TABLE_ENTRY  Ldr = NULL;
	char * KernelBaseName = "ntoskrnl.exe";
	ULONG64 StartAddress=GetSystemModuleBase(KernelBaseName);       //获取内核空间的基址
//	StartAddress = 0xfffffa8019990000;
	ULONG count = 0;           //搜索到的所有驱动数目
	for (; StartAddress < (ULONG64)(0xffffffffffffffff); StartAddress = StartAddress + 8)
//	for (; StartAddress < (ULONG64)(0xfffffa8019e1d140);StartAddress=StartAddress+8)          //用来测试的代码
	{
		if (IsValidAddr(StartAddress))
		{
			if (IsRealDriver(StartAddress))
			{
				DbgPrint("DriverObjectAddress:0x%I64X\n", StartAddress);
				TempDriverObject = (PDRIVER_OBJECT)StartAddress;
				Ldr = (PKLDR_DATA_TABLE_ENTRY)(TempDriverObject->DriverSection);
				//If no page fault would occur from reading or writing at the given virtual address, MmIsAddressValid returns TRUE.
				//Even if MmIsAddressValid returns TRUE, accessing the address can cause page faults unless the memory has been locked down or the address is a valid nonpaged pool address.
				if (MmIsAddressValid(Ldr))//这个函数只能判断非分页的情况
				{
					DbgPrint("DriveName : %S\n", Ldr->FullDllName.Buffer);
					DbgPrint("ImageBase : 0x%I64X\n", Ldr->DllBase);
					DbgPrint("ImageSize : 0x%I64X\n", Ldr->SizeOfImage);
					DbgPrint("EntryPoint : 0x%I64X\n", Ldr->EntryPoint);
					DbgPrint("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
					count++;
				}
				//	count++;                                                        //驱动数目加1
				StartAddress = StartAddress + sizeof(DRIVER_OBJECT);            //寻找下一个地址
			}
		}
		
	}
	DbgPrint("%d\n", count);
}


算法参照的是http://bbs.pediy.com/thread-109819.htm这个地址中的帖子,但这个帖子提供的是32位操作系统和内嵌汇编的算法,64位应该怎么办?请各路大神指示:

//以下这个函数抄的网上的,直接拿来主义....

#define  VALID_PAGE 1
#define  INVALID_PAGE 0
#define  PDEINVALID 2
#define  PTEINVALID 3
ULONG IsValidAddr( ULONG uAddr )
{
  ULONG uInfo;
  ULONG uCr4;
  ULONG uPdeAddr;
  ULONG uPteAddr;
  _asm
  {
    cli
    push eax
    _emit 0x0F
    _emit 0x20
    _emit 0xE0//mov eax,cr4
    mov [uCr4], eax
    pop eax
  }
  _asm sti
  uInfo = uCr4 & 0x20;
  if( uInfo != 0 )
  {
    uPdeAddr = (uAddr>>21)*8+0xC0600000;
  }
  else
    uPdeAddr = (uAddr>>22)*4+0xc0300000;
  if( (*(PULONG)uPdeAddr & 0x1) != 0 )
  {
    if( (*(PULONG)uPdeAddr & 0x80) != 0 )
    {
      return VALID_PAGE;
    }
    else
    {
      if( uInfo != 0 )
      {
        uPteAddr = (uAddr>>12)*8+0xc0000000;
      }
      else
      {
        uPteAddr = (uAddr>>12)*4+0xc0000000;
      }
      if( (*(PULONG)uPteAddr & 0x1) != 0 )
        return VALID_PAGE;
      else
        return PTEINVALID;
    }
  }
  else
    return PDEINVALID;
}



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

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 35
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
求各位指教!!
2017-6-23 16:43
0
雪    币: 256
活跃值: (48)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
参考ce开源代码~
2017-6-23 16:51
0
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
4
MmIsAddressValid?
2017-6-25 19:39
0
游客
登录 | 注册 方可回帖
返回
//