主题:获取内核ntoskrnl.exe基地址的几种常见办法
标 题: 【总结】获取内核ntoskrnl.exe基地址的几种常见办法
作 者: xcode
网 站: http://edu.teamsourcing.com.cn
如果大家写过shellcode一定还记得,shellcode中开头要找kernel32.dll模块的内存加载地址。
同样,如果大家要写一个内核的类似东东的话,第一步也是要找出ntoskrnl.exe模块的内存加载位置。有三种常见办法在这里咱们大体描述下:
1。利用ZwQuerySystemInformation 来检索加载的模块,从加载模块里面搜索出ntoskrnl.exe模块。例子如:http://bbs.pediy.com/showthread.php?t=58199
在开头部分就是利用ZwQuerySystemInformation 来检所ntoskrnl.exe模块的内存加载位置。
2。通过驱动DriverEntry函数的第一个参数,即DriverObject。在DriverObject结构体中有一项
DriverSection成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历这张表得到ntoskrnl的基址和大小。例子如:http://bbs.pediy.com/showthread.php?t=56042
3。通过驱动DriverEntry函数的返回地址,根据系统布局图,如下:
未命名.JPG
因此,我们可以在从80000000h开始的位置搜索ntosknrl。我们的驱动程序就是加载在系统布局图的80000000h到a0000000h的区间中。
完整代码如下:
.386
.model flat, stdcall
option casemap:none
include GetKernelBase.inc
.code
GetKernelBase proc uses esi edi ebx dwSomewhereInKernel:DWORD
xor edi, edi ; assume error
mov eax, MmSystemRangeStart
mov eax, [eax]
mov eax, [eax] ; eax = 80000000h
; #define PAGE_SHIFT 12
; #define PAGE_SIZE (1UL << PAGE_SHIFT) 4k为单位
.if dwSomewhereInKernel >= eax
mov esi, dwSomewhereInKernel
and esi, not (PAGE_SIZE-1) ; start down-search from here
mov ebx, esi
sub ebx, eax ; - MmSystemRangeStart
shr ebx, PAGE_SHIFT ; Number of pages to search
.while ebx
invoke MmIsAddressValid, esi
.break .if al == FALSE ; bad
mov eax, [esi]
.if eax == 00905A4Dh ; MZ signature
mov edi, esi
.break
.endif
sub esi, PAGE_SIZE ; next page down
dec ebx ; next page
.endw
.endif
mov eax, edi
ret
GetKernelBase endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT,pusRegistryPath:PUNICODE_STRING
lea ecx, [ebp][4] ; 得到DriverEntry返回地址
push ecx
invoke MmIsAddressValid, ecx
pop ecx
.if al
mov ecx, [ecx] ; Get return address from stack
invoke GetKernelBase, ecx
.if eax != 0
invoke DbgPrint, $CTA0("GetKernelBase: ntoskrnl.exe base = %08X\n"), eax
.else
invoke DbgPrint, $CTA0("GetKernelBase: Couldn't find ntoskrnl.exe base\n")
.endif
.endif
mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
end DriverEntry
声明:
本文的目的纯粹是一种技术交流,使用本文所演示的技术所造成的一切影响都与本人无关.
网站:http://edu.teamsourcing.com.cn
作 者: xcode
网 站: http://edu.teamsourcing.com.cn
如果大家写过shellcode一定还记得,shellcode中开头要找kernel32.dll模块的内存加载地址。
同样,如果大家要写一个内核的类似东东的话,第一步也是要找出ntoskrnl.exe模块的内存加载位置。有三种常见办法在这里咱们大体描述下:
1。利用ZwQuerySystemInformation 来检索加载的模块,从加载模块里面搜索出ntoskrnl.exe模块。例子如:http://bbs.pediy.com/showthread.php?t=58199
在开头部分就是利用ZwQuerySystemInformation 来检所ntoskrnl.exe模块的内存加载位置。
2。通过驱动DriverEntry函数的第一个参数,即DriverObject。在DriverObject结构体中有一项
DriverSection成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历这张表得到ntoskrnl的基址和大小。例子如:http://bbs.pediy.com/showthread.php?t=56042
3。通过驱动DriverEntry函数的返回地址,根据系统布局图,如下:
未命名.JPG
因此,我们可以在从80000000h开始的位置搜索ntosknrl。我们的驱动程序就是加载在系统布局图的80000000h到a0000000h的区间中。
完整代码如下:
.386
.model flat, stdcall
option casemap:none
include GetKernelBase.inc
.code
GetKernelBase proc uses esi edi ebx dwSomewhereInKernel:DWORD
xor edi, edi ; assume error
mov eax, MmSystemRangeStart
mov eax, [eax]
mov eax, [eax] ; eax = 80000000h
; #define PAGE_SHIFT 12
; #define PAGE_SIZE (1UL << PAGE_SHIFT) 4k为单位
.if dwSomewhereInKernel >= eax
mov esi, dwSomewhereInKernel
and esi, not (PAGE_SIZE-1) ; start down-search from here
mov ebx, esi
sub ebx, eax ; - MmSystemRangeStart
shr ebx, PAGE_SHIFT ; Number of pages to search
.while ebx
invoke MmIsAddressValid, esi
.break .if al == FALSE ; bad
mov eax, [esi]
.if eax == 00905A4Dh ; MZ signature
mov edi, esi
.break
.endif
sub esi, PAGE_SIZE ; next page down
dec ebx ; next page
.endw
.endif
mov eax, edi
ret
GetKernelBase endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT,pusRegistryPath:PUNICODE_STRING
lea ecx, [ebp][4] ; 得到DriverEntry返回地址
push ecx
invoke MmIsAddressValid, ecx
pop ecx
.if al
mov ecx, [ecx] ; Get return address from stack
invoke GetKernelBase, ecx
.if eax != 0
invoke DbgPrint, $CTA0("GetKernelBase: ntoskrnl.exe base = %08X\n"), eax
.else
invoke DbgPrint, $CTA0("GetKernelBase: Couldn't find ntoskrnl.exe base\n")
.endif
.endif
mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
end DriverEntry
声明:
本文的目的纯粹是一种技术交流,使用本文所演示的技术所造成的一切影响都与本人无关.
网站:http://edu.teamsourcing.com.cn