如何获取Windows 系统的内核变量

如何获取Windows 系统的内核变量,第1张

PsLoadedModuleList等重要内核变量并未被ntoskrnlexe导出,也没有公开的函

数可以获取。而这些内核变量对于Rootkit、Anti-Rootkit 以及内核溢出的利用等都

是至关重要的。

下面我们以PsLoadedModuleList、PsActiveProcessHead 等为例,介绍得到这些

变量的方法。

对于Windows NT 40和Windows 2000,尚没有“温柔”的办法可以获取这些变量,

比较理想的办法也就是特征代码搜索,这种方法虽然暴力,但通常都很有效,一般也

不会出问题;对于Windows XP和Windows 2003,我们找到了一些更加优雅的选择。

下面首先介绍特征代码搜索的方法。

[DWORD KernelBase]

要进行特征代码搜索,首先要定位ntoskrnlexe在内核的加载地址KernelBase。

这个地址可以通过ZwQuerySystemInformation Class 10的SystemModuleInformation

来得到。参考资源[1]中给出了相关代码。事实上,KernelBase 这个值对同一 *** 作系

统来说非常固定,可以作为常量来用:

Windows NT: 0x80100000

Windows 2000:0x80400000

Windows XP: 0x804d1000

Windows 2003: 0x804e0000

Windows NT 40 ntoskrnlexe 的OptionalHeader->ImageBase = 0x80100000,

ntldr 也会按照这个值来加载内核,但是从Windows 2000开始就不是这样了。可能基

于这个历史原因,各系统的(DWORD )PsNtosImageBase始终初始化为0x80100000。

另外,内核变量PsNtosImageBase、KdpNtosImageBase等也指向KernelBase:

KernelBase = (DWORD )PsNtosImageBase

KernelBase = (DWORD )KdpNtosImageBase

[LIST_ENTRY PsLoadedModuleList]

PsLoadedModuleList这个全局变量指向一个保存着所加载驱动信息的双向链表。

通过它可以枚举系统中所有的驱动模块。

虽然很多内核函数都用到了PsLoadedModuleList,但是大部分并没有被导出,而

从基址开始搜会很花时间。对于Windows 2000来说,从下面这个地方入手是个好主意:

nt!MmGetSystemRoutineAddress+0x66:

804f0ed0 8b35f0e84680 mov esi,[nt!PsLoadedModuleList (8046e8f0)]

804f0ed6 81fef0e84680 cmp esi,0x8046e8f0

流程如下:

1、ImageBase = LoadLibraryA("ntoskrnlexe")

2、GetProcAddress(ImageBase,"MmGetSystemRoutineAddress")

3、搜索特征代码:

(WORD )(MmGetSystemRoutineAddress + i) = 0x358b && \

(WORD )(MmGetSystemRoutineAddress + i + 6) = 0xfe81

&&

(DWORD )(MmGetSystemRoutineAddress + i + 2) == \

(DWORD )(MmGetSystemRoutineAddress + i + 8)

4、定位内核中的地址:

PsLoadedModuleList = \

(DWORD )(MmGetSystemRoutineAddress + i + 2) + (KernelBase - ImageBase)

从SP0到SP4,i值并不相同,但是肯定不大于0x100。

对Windows NT来说,就没这么好运气了,没有理想的可用于定位的API,只能从头

开始搜索。下面这段代码至少对SP1~SP6a的来说都具有很好的稳定性和唯一性:

801CEB1C: 8B 4D 08 mov ecx,dword ptr [ebp+8]

801CEB1F: 89 01 mov dword ptr [ecx],eax

801CEB21: 8B 45 0C mov eax,dword ptr [ebp+0Ch]

801CEB24: 89 10 mov dword ptr [eax],edx

801CEB26: 8B 36 mov esi,dword ptr [esi]

801CEB28: 81 FE 70 0B 15 80 cmp esi,80150B70h //PsLoadedModuleList

如果是用驱动做这件事情,就不必暴力搜索了,fuzen_op(fuzen_op@yahoocom)

在FU_Rootkit20(参考资源[2])中使用了一段比较巧妙的代码:

DWORD FindPsLoadedModuleList (IN PDRIVER_OBJECT DriverObject)

{

PMODULE_ENTRY pm_current;

if (DriverObject == NULL)

return 0;

pm_current = ((PMODULE_ENTRY)((DWORD)DriverObject + 0x14));

if (pm_current == NULL)

return 0;

gul_PsLoadedModuleList = pm_current;

while ((PMODULE_ENTRY)pm_current->le_modFlink != gul_PsLoadedModuleList)

{

if ((pm_current->unk1 == 0x00000000) && \

(pm_current->driver_PathLength == 0))

{

return (DWORD) pm_current;

}

pm_current = (MODULE_ENTRY)pm_current->le_modFlink;

}

return 0;

}

[LIST_ENTRY PsActiveProcessHead]

理论上PsActiveProcessHead 也可以用搜索代码的方法来取,但是还有更简单的

方法。

ntoskrnlexe导出的PsInitialSystemProcess 是一个PEPROCESS,指向system进

程的EPROCESS。这个EPROCESS的结构成员EPROCESSActiveProcessLinksBlink 就是

PsActiveProcessHead:

kd> dt _EPROCESS ActiveProcessLinksBlink poi(PsInitialSystemProcess)

+00 ActiveProcessLinks : [ 0x81356900 - 0x8046e728 ]

+0x004 Blink : 0x8046e728 [ 0x81a2fb00 - 0xff5a4ce0 ]

kd> PsActiveProcessHead

Evaluate expression: -2142836952 = 8046e728

EPROCESS这个结构在不同的 *** 作系统上各不相同,需要分别对待。

[struct _KDDEBUGGER_DATA64 KdDebuggerDataBlock]

Windows 2000 开始,系统引入了变量KdDebuggerDataBlock。其中包含了大量的

内核变量。如果能够获取到的话,可以解决许多问题。遗憾的是,Windows NT上没有

这个变量。WinDBG SDK的wdbgextsh中包含了它的结构:

typedef struct _KDDEBUGGER_DATA64

因为比较长,这里就不引用了。

从对5021956902版本ntoskrnlexe 的逆向工程结果来看,只有两个函数使用

了该变量,并且,两个函数都未导出,且代码前后没有明显特征,无法靠直接搜索代

码来获取。

但是,我们发现,ntoskrnlexe导出了KdEnableDebugger,KdEnableDebugger会

调用KdInitSystem,而KdInitSystem 中引用了KdDebuggerDataBlock:

n < 100

Windows 2000:

KdEnableDebugger + n:

6A 00 push 0

6A 00 push 0

C6 05 28 41 48 00 01 mov _PoHiberInProgress, 1

E8 1C DC 10 00 call _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:

68 70 02 00 00 push 270h // sizeof(KdDebuggerDataBlock)

B9 50 D1 54 00 mov ecx, offset _KdpDebuggerDataListHead

68 D8 FA 46 00 push offset KdDebuggerDataBlock

8B 40 18 mov eax, [eax+18h]

68 4B 44 42 47 push 4742444Bh // "KDBG",可以用作搜索的定位标志

A3 3C D1 54 00 mov ds:_KdpNtosImageBase, eax

89 0D 54 D1 54 00 mov ds:dword_54D154, ecx

89 0D 50 D1 54 00 mov ds:_KdpDebuggerDataListHead, ecx

Windows XP

KdEnableDebugger + n:

6A 00 push 0

6A 00 push 0

C6 05 8C 98 47 00 01 mov _PoHiberInProgress, 1

E8 2B 17 13 00 call _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:

68 90 02 00 00 push 290h

68 E0 9D 46 00 push offset KdDebuggerDataBlock

BE 74 96 59 00 mov esi, offset _KdpDebuggerDataListHead

68 4B 44 42 47 push 4742444Bh

89 35 78 96 59 00 mov ds:dword_599678, esi

89 35 74 96 59 00 mov ds:_KdpDebuggerDataListHead, esi

Windows 2003

KdEnableDebugger + n:

56 push esi

56 push esi

C6 05 0C 08 49 00 01 mov PoHiberInProgres, 1

E8 CB AD 15 00 call _KdInitSystem@8 ; KdInitSystem(x,x)

KdInitSystem + n:

68 18 03 00 00 push 318h

68 D0 A3 47 00 push offset KdDebuggerDataBlock

BE 18 10 5D 00 mov esi, offset _KdpDebuggerDataListHead

68 4B 44 42 47 push 4742444Bh

89 35 1C 10 5D 00 mov ds:dword_5D101C, esi

89 35 18 10 5D 00 mov ds:_KdpDebuggerDataListHead, esi

可以看出,上面代码特征的唯一性很好。用于搜索是没有问题的。我在上面同时

列出了三个系统的代码,仅仅只是为了比较,事实上,对Windows XP和Windows 2003

是完全没有必要采取如此暴力手段的。

刚开始的时候,每次循环是获取不到ajax中的值的,在ajax中,如果想获取到变量I,那么也是有问题了。

解决了半小时,终于明白了问题的所在:

for 循环是一个单线程的东西,而ajax是多线程的,之所以称之为异步同步,是因为执行到ajax的时候去后台开启了一个线程,但是for循环本身就是一个单线程的东西,那么执行到ajax的时候,ajax开启了一个线程,for

循环是没有等他的,知道for循环结束的时候,才会把ajax返回的数据拿回来,所以会出问题

解决办法:只需要把ajax改成同步的就可以了,每次for循环,都要去加载ajax方法,并且拿到他返回的数据,只需要在ajax中间加一个代码就可以搞定了。async: false,//设置成同步

确定了目标之后你成功了10%,但是剩下的90%之中,多数是坚持不懈的努力,你会遇到迷茫、遇到挫折,此时不要放弃,回忆你立定目标的决心,成功就在你眼前!习惯很容易养成,一件事情,只要你能咬牙坚持10天,它自然就成了习惯! 现代人变得越来越浮躁,不妨静下心来用音乐洗礼你的心灵!

以上就是关于如何获取Windows 系统的内核变量全部的内容,包括:如何获取Windows 系统的内核变量、js用不了ajax提示没有该变量、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9557348.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存