Carregando Drivers e Aplicações do Kernel, sem tocar no Resgistro (Inglês)

Started by HadeS, 22 de May , 2007, 10:06:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

HadeS

"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, \Registry\Machine\System\CurrentControlSet\Services\DriverName, 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
;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!



Desculpem-me ae por não traduzir, pois já está meio tarde pra mim e amanhã tenho que acordar muito cedo. Mas espero que tenha ajudado alguém.

Fonte: NVLabs

HadeS