Hook swapcontext enumeration of hidden processes (learning notes 4)

Source: Internet
Author: User
Tags apc
Author: bzhkl
Time: 2008-12-11,12: 01
Chain: http://bbs.pediy.com/showthread.php? T = 78464

Previously, I tried to detect a hidden process and then solved it with the method of brute force enumeration. But the hook swapcontext didn't see complete code. So I collected some useful modules on the Internet and integrated them to implement support. xp3, xp2 should be supported even if it is not tested.
Complete project code

Difficulty: there are still some details about obtaining the swapcontext address ~
Principle: When kiswapcontext calls swapcontext, ESI stores the context of the thread to be swapped in. EDI stores the context of the thread to be swapped out. Then, it intercepts ESI, that is, the ETHREAD, to obtain the corresponding eprocess, and then collects
Disadvantages: it has a great impact on the system performance. Because the system thread scheduling is very frequent, wrk's kiswapcontext compilation can reflect high efficiency requirements ~.

Another interesting question
Kiswapcontext is the fastcall call method, which is to use ECx edX to upload more data by stdcall.
Wrk is annotated in this way.
; Boolean
; Kiswapcontext (
; In pkthread oldthread
; In pkthread newthread
;)
But let's look at the code in wrk.
MoV EDI, ECx; set old thread address
MoV ESI, EDX; set next thread address
Movzx ECx, byte PTR [EDI]. thwaitirql; Set APC interrupt bypass disable
Call swapcontext; Swap Context
It is indeed two parameters.

View with windbg
80545975 8bf1 mov ESI, ECx
80545977 8bbb24010000 mov EDI, dword ptr [EBX + 124 h]
8054597d 89b324010000 mov dword ptr [EBX + 124 h], ESI
80545983 8a4f58 mov Cl, byte PTR [EDI + 58 h]
80545986 e8f5000000 call nt! Swapcontext (80545a80)
It is found that kiswapcontext is a parameter, and ESI is the thread context to be swapped in. It is obtained through ECx (obtained by the first parameter) EDI, but not
Therefore, it is concluded that the parameters of kiswapcontext are now one. Maybe I have not updated the old version of wrk ..

Wrk kiswapcontext code
Cpublicfastcall kiswapcontext, 2
. FPO (0, 0, 0, 4, 1, 0)

;
; N. B. The following registers must be saved such that EBP is saved last.
; This is done so the debugger can find the saved EBP for a thread
; That is not currently in the running state.
;

Sub ESP, 4*4
MoV [esp + 12], EBX; save registers
MoV [esp + 8], ESI;
MoV [esp + 4], EDI;
MoV [esp + 0], EBP;
MoV EBX, PCR [pcselfpcr]; Set address of PCR
MoV EDI, ECx; set old thread address
MoV ESI, EDX; set next thread address
Movzx ECx, byte PTR [EDI]. thwaitirql; Set APC interrupt bypass disable

Call swapcontext; Swap Context
MoV EBP, [esp + 0]; restore registers
MoV EDI, [esp + 4];
MoV ESI, [esp + 8];
MoV EBX, [esp + 12];
Add ESP, 4*4;
Fstret kiswapcontext;

Fstendp kiswapcontext

Kiswapcontext code obtained by windbg
Lkd> UF kiswapcontext
NT! Kiswapcontext:
8054595c 83ec10 sub ESP, 10 h
8054595f 895c240c mov dword ptr [esp + 0ch], EBX
80545963 89742408 mov dword ptr [esp + 8], ESI
80545967 897c2404 mov dword ptr [esp + 4], EDI
8054596b 892c24 mov dword ptr [esp], EBP
8054596e 648b1d1c000000 mov EBX, dword ptr fs: [1ch]
80545975 8bf1 mov ESI, ECx
80545977 8bbb24010000 mov EDI, dword ptr [EBX + 124 h]
8054597d 89b324010000 mov dword ptr [EBX + 124 h], ESI
80545983 8a4f58 mov Cl, byte PTR [EDI + 58 h]
80545986 e8f5000000 call nt! Swapcontext (80545a80)
8054598b 8b2c24 mov EBP, dword ptr [esp]
8054598e 8b7c2404 mov EDI, dword ptr [esp + 4]
80545992 8b742408 mov ESI, dword ptr [esp + 8]
80545996 8b5c240c mov EBX, dword ptr [esp + 0ch]
8054599a 83c410 add ESP, 10 h
8054599d C3 RET

After the driver runs, the effect is:

The collected process is
0x81fe7768 svchost.exe
0x81ec6478 alg.exe
0x81f5e990 svchost.exe
0x81fe83e0 drvloader.exe
0x81ca7020 taskmgr.exe
0x81595d70 vmwareservice. e
0x815c6608 vmwaretray.exe
0x815d9c08 svchost.exe
0x8159c528 ctfmon.exe
0x8158eb60 visualtasktips.
0x815e5da0 winlogon.exe
0x81e96418 drvloader.exe
0x815f8bd8 lsass.exe
0x81fe5020 msdev. exe
0x81ec0b28 mdm.exe
0x81ee0500 assumer.exe
0x81f13020 msdev. exe
0x815523a8 dbgview. exe
0x81f74020 csrss.exe
0x821507c0 System
0x82009830 vmwareuser.exe
0x81f66da0 services.exe
0x81f07b88 svchost.exe

The collected process must be incomplete because some processes do not collect = when there is no thread scheduling at rest.

The following is the main code:

DWORD gthreadsprocessoffset = 0x220; // ETHREAD offset in eprocess
/*

+ 0x218 toplevelirp: uint4b
+ 0x21c devicetoverify: ptr32 _ device_object
+ 0x220 threadsprocess: ptr32 _ eprocess
*/

Ulong processnameoffset = 0X174; // the file name of the process is offset in eprocess.
/*
+ 0x170 session: ptr32 void
+ 0X174 imagefilename: [16] uchar
+ 0x184 joblinks: _ list_entry
*/

Pprocesslist wlastitem = NULL;
Int beterminate = 0; // 1 indicates that the thread must be stopped. 3. The thread is not in pending state. 0 indicates that the thread can run normally.

Void _ stdcall collectprocess (peprocess) // collects eprocess
{
If (! Isadded (wlastitem, peprocess) additem (& wlastitem, peprocess );
Return;
}

Void _ stdcall threadcollect (puchar pethread) // obtain the eprocess Based on ETHREAD and call collectprocess to collect
{
Peprocess = * (peprocess *) (pethread + gthreadsprocessoffset );
If (peprocess) collectprocess (peprocess );
Return;
}

DWORD outpethread = 0;
Void _ stdcall processdata (DWORD pinethread, DWORD poutethread)
{
Dword pid, eprocess;
Char * pname;
If (mmisaddressvalid (pvoid (pinethread + 0x220) // you need to determine whether it is a real
The ETHREAD struct of sometimes seems to call swapcontext, but it is not the ETHREAD struct. Then, the blue screen will not be blue if we do not go into further investigation and add a judgment ~
{
Eprocess = * (DWORD *) (pinethread + 0x220 );

If (mmisaddressvalid (pvoid (eprocess )))
{
Threadcollect (puchar) pinethread );
}

}
}

Pbyte gobackaddr = NULL;
Pbyte changaddr = NULL;

DWORD callcontextoffset = 0;

_ Declspec (naked) void hookswap ()
{

_ ASM
{
Pushad
Pushfd
CLI
}

_ ASM
{
// EDI is the thread Context
Push EDI
// ESI is the thread context of the switch.
Push ESI
Call processdata // collection process
}

_ ASM
{
STI
Popfd
Popad
}
_ Asm jmp dword ptr [gobackaddr]
}

/*
The principle of obtaining the swapcontext address is:
Use pslookupthreadbythreadid to get the kthread of idle system
Res = (pchar) (thread-> TCB. kernelstack );
Swapaddr = * (DWORD *) (RES + 0x08 );
*/
Pchar getswapaddr ()
{
Pchar res = 0;
Ntstatus status;
Pethread thread;

If (* ntbuildnumber <= 2195)
Status = pslookupthreadbythreadid (pvoid) 4, & (pethread) thread );
Else
Status = pslookupthreadbythreadid (pvoid) 8, & (pethread) thread );

If (nt_success (Status ))
{
If (mmisaddressvalid (thread ))
{
Res = (pchar) (thread-> TCB. kernelstack );

}
If (mmisaddressvalid (RES + 8 ))
{
_ ASM
{
MoV eax, res
Add eax, 8
MoV eax, [eax]
MoV res, eax
}
}
Else
{
Res = 0;
Return NULL;
}
}
_ ASM
{
MoV eax, res
Sub eax, 5
MoV changaddr, eax
MoV edX, [eax + 1]
MoV callcontextoffset, EDX
Add eax, EDX
Add eax, 5
MoV gobackaddr, eax
MoV res, eax
}
Return res;
}

Bool hookswapfunction (bool flag)
{
If (flag = true)
{
Kirql oldirql = 0;
DWORD newoffset; // HookSwap-ChangAddr-5;
_ ASM
{
MoV eax, hookswap
MoV edX, changaddr
Sub eax, EDX
Sub eax, 5
MoV newoffset, eax
}

Paged_code ()
Assert (kegetcurrentirql () <= dispatch_level );
Keraiseirql (2, & oldirql); // high_level
_ ASM
{
CLI
MoV eax, Cr0
And eax, not 10000 h // disable WP bit
MoV Cr0, eax
}
_ ASM
{
MoV eax, changaddr
Push newoffset
Pop dword ptr [eax + 1]

}

_ ASM
{
MoV eax, Cr0
Or eax, 10000 h // enable WP bit
MoV Cr0, eax
STI
}


Kelowerirql (oldirql );

}
// Bug check 0xd1: driver_irql_not_less_or_equal

Else
{
Kirql oldirql = 0;
Keraiseirql (2, & oldirql); // high_level
_ ASM
{
CLI
MoV eax, Cr0
And eax, not 10000 h // disable WP bit
MoV Cr0, eax
}

_ ASM
{
MoV eax, changaddr
Push callcontextoffset
Pop dword ptr [eax + 1]
}


_ ASM
{
MoV eax, Cr0
Or eax, 10000 h // enable WP bit
MoV Cr0, eax
STI
}
Kelowerirql (oldirql );
// Dbuplint ("hookswapfunctionfalse"); // jution
}

}

Peprocess processobject (pethread ETHREAD ){
Return (peprocess) (ETHREAD-> TCB. apcstate. process );
}

Void klisterunload (in pdriver_object pdriverobject)
{
Beterminate = 1;
While (beterminate! = 3) // = 3 it indicates that the created thread is not in pending state and will end immediately. At this time, it can be unloaded. Otherwise, the thread will be directly blue in pending state.
{

}

If (gobackaddr) // pbyte gobackaddr = NULL;
Hookswapfunction (false );
}

Void showprocess ()
{

Pprocesslist temp;
Dword count = 0;
Puchar pfilename;
Temp = wlastitem;

While (temp) // a time series table
{
If (temp-> peprocess)
{
Count ++;
Pfilename = (puchar) (unsigned INT) (temp-> peprocess) + 0X174 );
Dbuplint ("0x % 08x % s/n", (unsigned INT) (temp-> peprocess), pfilename );
}
Temp = pprocesslist (temp-> nextitem );
}

Dbuplint ("% d processes in total", count );
}

Void workthread (in pvoid pcontext)
{
Large_integer timeout;

While (true)
{
If (mmisaddressvalid (& beterminate) // because beterminate is set in unload, this variable cannot be accessed after the driver is uninstalled, so use mmisaddressvalid to determine
{
If (beterminate = 0)
{

// The wait unit is 100ns //-10. The value is converted to microseconds. // 2000000 microseconds = 2 seconds.
Timeout = rtlconvertlongtolargeinteger (-10*2000000 );

Kedelayexecutionthread (kernelmode, false, & timeout );
Dbuplint ("the process collected is ");
Showprocess ();
}
Else
{
Beterminate = 3;
Psterminatesystemthread (STATUS_SUCCESS );
Goto _ end;
}
}
Else
{
Beterminate = 3;
Psterminatesystemthread (STATUS_SUCCESS );
Goto _ end;
}
}
_ End :;
}

// Call the DriverEntry routine when the driver is loaded.
Ntstatus DriverEntry (
In pdriver_object pdriverobject,
In punicode_string pregistrypath
)
{
Ntstatus dwstatus;
Handle hthread;

Pdriverobject-> driverunload = klisterunload;

Dwstatus = pscreatesystemthread (& hthread,
(Access_mask) 0,
Null,
(Handle) 0,
Null,
Workthread,
Null
);


Getswapaddr ();
If (gobackaddr ){
Hookswapfunction (true );
}
Return STATUS_SUCCESS;
}

Uploaded attachment

Hookswapcontext.rar (, 105.1 kb, 122 times

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.