------- Software debugging -- frustrated the internal mode protection mechanism of QQ.exe, -----qq.exe

Source: Internet
Author: User
Tags apc

------- Software debugging -- frustrated the internal mode protection mechanism of QQ.exe, -----qq.exe

 

------------------------------------------------------------------------

QQ is a popular instant messaging (IM) tool. During installation, two driver files will be generated under the \ .. \ windows \ system32 \ drivers path of the system partition:

QQProtect. sys and QQFrmMgr. sys, the former is the kernel mode component of QQProtect.exe (QQ security protection process, also known as Q shield), and the latter is a filter drive.

At the same time, the key of the corresponding name will be created to the Registry location HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ services \. Two important sub-keys control the loading of these two drivers.

Method: "type" and "start" -- for QQProtect. sys, the key values are 1 and 2, which means that services.exe automatically loads QQProtect. sys into the kernel

Space. For QQFrmMgr. sys, the key values are 1 and 1, which means that during kernel initialization, ntoskrnl.exe loads QQFrmMgr. sys into the kernel space.

QQFrmMgr. sys is earlier than QQProtect. sys, as shown in:

 

Although these two drivers are not Rootkit or malware, they do hook the System service scheduling table/Shadow, inject kernel threads into the System process, and note

Some notification callbacks ....

Therefore, some key data structures of the system are changed for improper activities.

This article discusses how to use the kernel debugger WinDbg.exe to check such kernel space Measures to Protect QQ processes, and then restore the system to a "clean" state.

The test environment is composed of two real computers (dual-host physical debugging): the host machine running Windows 7 (debugging machine) and the target machine running Windows 8.1 (debugged machine, QQ has been installed)

The two are connected through Ethernet cables for debugging.

Note: When you perform physical Debugging through the ethernet cable, there are no special requirements for the NIC of the Debugging machine. However, the NIC of the Debugging machine must be supported by Debugging Tools for Windows (that is, Kd.exe

And WinDbg.exe), and the operating system version on the debug machine must be windows 8 or later. The operating system on the debug machine must be windows xp or a later version.

 

One of the major advantages of using Ethernet debugging is the convenience of obtaining communication media-compared to the old serial port Line (RS-232) and the COM module which is basically eliminated on the motherboard, Cat5 standard or above

Network line can buy casually in the Computer City, and the motherboard can never have no network interface card using the RJ-45 port .... Ethernet debugging will surely become a standard in the future!

On the other hand, I have also implemented physical-Virtual Machine debugging. As a debugged machine, the virtual machine runs Windows 7 on it. In this way, the QQ driver can not only compare different kernel versions.

(Windows 7 is the kernel version 6.1; Windows 8.1 is the kernel version 6.3). The logic difference shows that the QQ driver adopts the "anti-Virtual Machine" technology and reveals whether

Actions on real machines!

 

Therefore, in the following debugging process, I will explain all the results different from those on the real machine. Before you start, let's take a look at the physical debugging parameters configured for the two servers:

1 cd "d:\Windows Kits\10\Debuggers\x86" && d: && windbg.exe -n -v -logo d:\networking_physical_host-target_debugging.txt -y SRV*E:\windows8_1_retail_symbols*http://msdl.microsoft.com/download/symbols -k net:port=60111,key=shayi.1983.gmail.com

 

 

Where,

❶ I installed the Windows Kits driver development kit under the "d: \ Windows Kits" Directory;

Outputs debugging information to the specified log file;

The token specifies the URL of the Microsoft symbol server, so that the debugger can download and parse the function symbols in a specific kernel module from the server on demand through http get requests;

Region and the path of the pre-stored local symbol file (which can be downloaded from the MSDN site. The overall MSI package size is about five or six hundred MB;

(Note: Because the kernel versions on the host are different, you need to download the corresponding symbol files and specify them as debugging parameters)

Listener specifies that the debugging port is UDP 60111 on the host machine through Ethernet debugging (net;

The last key of the shard can be specified at will, but the four subdomains must be separated by dots.

For more information about the configurations on the target machine, see the MSDN document.

----------------------------------------------------------

First, the System thread in the System Process is browsed through Process Explorer on the Windows 8.1 target machine. One of the QQ kernel threads is

Created by QQFrmMgr. sys, the startup address of this thread is offset from the base address loaded to the module as 0x5e34:

 

Our goal is to end the execution of this thread. The general practice is to use the built-in APC (asynchronous process call) mechanism. APC is run in a specific thread context.

.

From a programming perspective, call KeInitializeApc () to initialize an nt! _ KAPC structure, and associate it with the nt of the QQ kernel thread! _ KTHREAD structure, Set

The APC routine calls back to PspExitThread (), and then uses KeInsertQueueApc () to pass through this nt! _ KTHREAD structure to be imported into the QQ kernel thread

APC queue. In this way, when the APC is delivered, PspExitThread () is called in the execution context of the QQ kernel thread to terminate

Core Thread.

In the debugging environment, there is no corresponding kernel API available. Therefore, we must manually construct APC, specify callback functions, associate threads, and queue.

Description:

Step 1: query the nt of the System process! _ EPROCESS structure address;

Step 2: locate the Thread two-way linked list header and traverse every nt in the linked list! _ ETHREAD structure to locate the startup addresses

Threads in the space of the QQFrmMgr. sys module:

 

 

The corresponding WinDbg command is as follows:

1 !list "-t nt!_LIST_ENTRY.FLink -e -x \"r @$t3=@$extret-@$t1; 2 r @$t4= @$t3+@$t2;3 r @$t5=poi(@$t4);4 .if(@@((unsigned long)@$t5>(unsigned long)0x82000000 && (unsigned long)@$t5<(unsigned long)0x82017b00)){r @$t3;dt -b nt!_ETHREAD Cid. @$t3; dds @$t4 l1;}; 5 \" 8565e5c0+@$t0"

 

 

Step 3: Create an nt manually! _ KAPC structure, specifying the callback function, associated thread, and queue:

(3-1): query the section information in the QQFrmMgr. sys module. Note that the. data section is followed by the INIT section:

 

 

We can see that the starting RVA of. data section is 11800, the size is 3C80, And the ending RVA is 15480, which is the starting RVA of INIT section.

In the attributes of the INIT section, "Discardable" and "Execute Read Write" perfectly match the Write attributes required for manual construction of APC, And the callback function needs

So it is the ideal target section.

(3-2): initializes 0x200 bytes of memory from the start address of the INIT section. This region is used for nt! _ KAPC structure and callback function (nt! _ KAPC's

KernelRoutine field ). As shown in,

The callback function constructed at address 82015480 calls PspExitThread () to end the running of the current thread, and constructs

Nt! _ KAPC structure;

 

 

 1 r @$t0=82015500;  2 r @$t1=8b9ccbc0;  3 r@$t2=82015480; 4 ?? ((nt!_KAPC*)@$t0)->Type=18; 5 ?? ((nt!_KAPC*)@$t0)->Size=sizeof(nt!_KAPC); 6 ?? ((nt!_KAPC*)@$t0)->Thread=@$t1; 7 ?? ((nt!_KAPC*)@$t0)->KernelRoutine=@$t2; 8 ?? ((nt!_KAPC*)@$t0)->Inserted=1; 9 r @$t3=@@(&(((nt!_ETHREAD*)@$t1)->Tcb.ApcState.ApcListHead[0]));10 r @$t4=@@(&(((nt!_KAPC*)@$t0)->ApcListEntry));11 r @$t5=@@(((nt!_LIST_ENTRY*)@$t3)->Flink);12 ?? ((nt!_LIST_ENTRY*)@$t4)->Flink=@$t5;13 ?? ((nt!_LIST_ENTRY*)@$t4)->Blink=@$t3;14 ?? ((nt!_LIST_ENTRY*)@$t5)->Blink=@$t4;15 ?? ((nt!_LIST_ENTRY*)@$t3)->Flink=@$t4;16 ?? ((nt!_ETHREAD*)@$t1)->Tcb.ApcState.KernelApcPending=1;

 

 

The value of the variable "t1" is the nt of the QQ kernel thread found earlier! _ ETHREAD structure;

The variable t3 is used to locate nt! _ The first APC queue header (Tcb. ApcState. ApcListHead [0]) in the ethread structure;

"Flink" field (pointing to the next nt! _ KAPC structure) is stored by the variable "t5;

The variable "t4" is the constructed nt! The "ApcListEntry" field in the _ KAPC structure, which is used to initialize the "t5 ";

The initialization logic is similar to the following C code:

1  KTHREAD.ApcState.ApcListHead[0]->Flink = KAPC->ApcListEntry;

 

Verify that our operations are correct:

 

The entire process is illustrated in the following figure:

To understand the mechanism of APC delivery, we set a breakpoint at the entrance of the callback function, and then we can learn how the callback is called through stack tracing information.

Run the "g" key to restore the execution of the target machine. When the APC is delivered, the breakpoint is triggered:

 

 

As you can see, this APC delivery mechanism is actually not mysterious-the first parameter passed to PspSystemThreadStartup () is QQFrmMgr. sys

The startup address of the QQ kernel thread, indicating that it is scheduled to run; after a series of calls, KiSwapThread () receives the first parameter from it

(0x8b9ccbc0, that is, nt of the QQ kernel thread! _ ETHREAD structure address), locate its APC queue header, and then call the first nt in the linked list! _ KAPC

The structure's "KernelRoutine" Callback triggers the previously set breakpoint.

Press the "g" key to continue running. As a result, PspExitThread () terminates the QQ kernel thread and returns the result. Now, the target machine is browsed through Process Explorer,

The System threads in the System process cannot find the QQFrmMgr. sys + 0x5e34 thread. On the other hand, you can also verify it on the debugging machine:

 

1 r @$t0=@@(#FIELD_OFFSET(nt!_EPROCESS, ThreadListHead));2 r @$t1= @@(#FIELD_OFFSET(nt!_ETHREAD, ThreadListEntry));3 r @$t2=@@(#FIELD_OFFSET(nt!_ETHREAD, StartAddress));4 !list "-t nt!_LIST_ENTRY.FLink -e -x \"r @$t3=@$extret-@$t1; 5 r @$t4= @$t3+@$t2; 6 r @$t5=poi(@$t4);7 .if(@@((unsigned long)@$t5>(unsigned long)0x82000000 && (unsigned long)@$t5<(unsigned long)0x82017b00)){r @$t3;dt -b nt!_ETHREAD Cid. ExitStatus @$t3; dt -b nt!_KTHREAD Header. @$t3; }; 8 \" 8565e5c0+@$t0"

 

 

----------------------------------------------------------------------------------

Summary: This article discusses how to use the infrastructure provided by the kernel-APC-to defeat the executable code injected into the kernel space by the QQ filter driver, and

Core)This article introduces how to detect and restore other kernel data structures modified by the QQ driver and how to clear hook routines installed by the QQ driver!

 

----------------------------------------------------------------------------------

 

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.