-
-
[求助]如何遍历内核空间内存地址的可读性问题
-
发表于:
2017-6-23 14:18
3910
-
本人在写自己的反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;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)