作者: combojiang
相信曾经写过shellcode的人都会记得,shellcode的开头是寻找kernel32.dll模块的内存加载地址。
同样,如果要编写类似东东的内核,第一步是找到ntoskrnl.exe模块的内存加载位置。 这里大致说明一下,有三种常用的方法。
1。 查找使用ZwQuerySystemInformation加载的模块,然后从加载模块中查找ntoskrnl.exe模块。 例如http://BBS.pediy.com/showthread.PHP? t=58199
第一部分利用ZwQuerySystemInformation检查给定ntoskrnl.exe模块的内存加载位置。
2。 它通过驱动程序对象,这是驱动驱动程序条目函数的第一个参数。 驱动程序对象结构包括
驱动程序安全成员指向LDR_DATA_TABLE_ENTRY结构,通过遍历该表得到ntoskrnl的基地址和大小。 例如http://BBS.pediy.com/showthread.PHP? t=56042
3。 通过驱动DriverEntry函数的返回地址,根据系统布局图,如下所示。
因此,可以在距离80000000h的位置搜索ntosknrl。 我们的驱动程序被加载在系统布局图的80000000h到a0000000h区间。
完整的代码如下所示。
. 386
. modelflat,stdcall
optioncasemap:none
includeGetKernelBase.inc
. code
getkernelbaseprocusesesiediebxdwsomewhereinkernel : dword
xoredi,edi; 资产错误
moveax,MmSystemRangeStart
moveax,[eax]
moveax,[eax]; eax=80000000h
; #definePAGE_SHIFT12
; #definepage_size(1ulpage_shift ) 4k单位
. ifdwSomewhereInKernel=eax
movesi,dwSomewhereInKernel
andesi,not(page_size-1; 开始下载-搜索框架
movebx,esi
subebx,eax; -MmSystemRangeStart
shrebx,PAGE_SHIFT; Numberofpagestosearch
. whileebx
invokeMmIsAddressValid,esi
. break.ifal==FALSE; bad
moveax,[esi]
. ifeax==00905A4Dh; MZsignature
movedi,esi
. break
. endif
subesi,PAGE_SIZE; 下一页下载
decebx; nextpage
. endw
. endif
moveax,edi
回复
GetKernelBaseendp
driverentryprocpdriverobject : pdriver _ object,pusregistrypath : p unicode _ string
leaecx,[ebp][4]; 获取驱动程序条目的回复地址
推式ecx
invokeMmIsAddressValid,ecx
popecx
. ifal
movecx,[ecx]; getreturnaddress框架堆栈
invokeGetKernelBase,ecx
. ifeax!=0
invokeDbgPrint,$ CTA0(getkernelbase : ntoskrnl.exe base=x/n ),eax
. else
invokeDbgPrint,$ CTA0(getkernelbase : couldn ' tfindntoskrnl.exe base/n ' ) )
. endif
. endif
moveax,status _ device _ configuration _ error
回复
驱动程序条目结束
最终驱动程序条目