三两行代码实现进程防杀,免驱动,IceSword,WSysCheck等无效.

其实这个已经是一个很老的技巧了,今天挖出来写到blog上。windows在强制结束进程的时候会先结束掉所有的线程,而结束线程调用的是:PspTerminateThreadByPointer,这个函数很有意思。看看就知道了。

 它判断ETHREAD里面的CrossThreadFlags;的值,如果这个值等于PS_CROSS_THREAD_FLAGS_SYSTEM ,即是一个系统线程,那么直接返回拒绝访问,那么进程就无法结束了。所以我们把程序的线程改成系统线程,那么就可以达到防杀的目的。当然要杀还是很快的,把值修改回去或者投递一个ExitThread的APC就OK了。当然,觉得不够刺激可以改成PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION,那么结束线程的时候,系统会中断下来,一般是因为没有调试器附加而产生一个bugcheck,即蓝屏。

 

NTSTATUS
PspTerminateThreadByPointer(
    IN PETHREAD Thread,
    IN NTSTATUS ExitStatus,
    IN BOOLEAN DirectTerminate
    )

/**/ /*++

Routine Description:

    This function causes the specified thread to terminate.

Arguments:

    ThreadHandle - Supplies a referenced pointer to the thread to terminate.

    ExitStatus - Supplies the exit status associated with the thread.

    DirectTerminate - TRUE is its ok to exit without queing an APC, FALSE otherwise

--
*/


...
{
    NTSTATUS Status;
    PKAPC    ExitApc
=NULL;
    ULONG    OldMask;

    PAGED_CODE();

    
if (Thread->CrossThreadFlags
    
& PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION) ...{
      PspCatchCriticalBreak(
"Terminating critical thread 0x%p (in %s) ",
                Thread,
                THREAD_TO_PROCESS(Thread)
->ImageFileName);
    }


    
if (DirectTerminate && Thread == PsGetCurrentThread()) ...{

        ASSERT (KeGetCurrentIrql() 
< APC_LEVEL);

        PS_SET_BITS (
&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_TERMINATED);

        PspExitThread (ExitStatus);

        
//
        
// Never Returns
        
//

    }
 else ...{
        
//
        
// Cross thread deletion of system threads won't work.
        
//
        if (IS_SYSTEM_THREAD (Thread)) ...{//如果这个是一个系统线程,直接返回拒绝访问。
            return STATUS_ACCESS_DENIED;
        }


        Status 
= STATUS_SUCCESS;

        
while (1) ...{
            ExitApc 
= (PKAPC) ExAllocatePoolWithTag (NonPagedPool,
                                                     
sizeof(KAPC),
                                                     
'xEsP');
            
if (ExitApc != NULL) ...{
                
break;
            }

            KeDelayExecutionThread(KernelMode, FALSE, 
&ShortTime);
        }


        
//
        
// Mark the thread as terminating and call the exit function.
        
//
        OldMask = PS_TEST_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_TERMINATED);

        
//
        
// If we are the first to set the terminating flag then queue the APC
        
//

        
if ((OldMask & PS_CROSS_THREAD_FLAGS_TERMINATED) == 0) ...{

            KeInitializeApc (ExitApc,
                             PsGetKernelThread (Thread),
                             OriginalApcEnvironment,
                             PsExitSpecialApc,
                             PspExitApcRundown,
                             PspExitNormalApc,
                             KernelMode,
                             ULongToPtr (ExitStatus));

            
if (!KeInsertQueueApc (ExitApc, ExitApc, NULL, 2)) ...{
                
//
                
// If APC queuing is disabled then the thread is exiting anyway
                
//
                ExFreePool (ExitApc);
                Status 
= STATUS_UNSUCCESSFUL;
            }
 else ...{
                
//
                
// We queued the APC to the thread. Wake up the thread if it was suspended.
                
//
                KeForceResumeThread (&Thread->Tcb);

            }

        }
 else ...{
            ExFreePool (ExitApc);
        }

    }


    
return Status;
}

 

现在我们要修改CrossThreadFlags,那么首先要找到线程对应的ETHREAD,如果是驱动来做的话,几行代码就OK了。但是在ring3也是几行代码。我们先用OpenThread打开自己,这时会产生一个handle,然后我们把这个handle遍历出来,以查找到对应的Object的地址,也就是ETHREAD的地址。查找handle可以使用ZwQuerySystemInformation去获得。这时就剩下修改内存了,因为ETHREAD是在内核内存的,不能直接访问,我们可以通过NtSystemDebugControl去修改内核内存。下面是核心代码:

 

 

    ZWQUERYSYSTEMINFORMATION        ZwQuerySystemInformation  =  NULL;
    NTSYSTEMDEBUGCONTROL            NtSystemDebugControl 
=  NULL;
    HANDLE hThread 
=  NULL;
    DWORD    dwPID 
=  GetCurrentProcessId();
    DWORD    dwTID 
=  GetCurrentThreadId();
    PSYSTEM_HANDLE_INFORMATION        pHandleInfo 
=  NULL;
    ULONG    uObjCnt 
=   0 ;
    NTSTATUS    status;
    DWORD    dwBufLen 
=   1024 * 800 ;
    DWORD    dwRetLen 
=   1024 * 800 ;
    DWORD    dwETHREAD 
=   0 ;
    BOOL    bRet 
=  FALSE;

    EnableDebugPrivilege(TRUE);

    ZwQuerySystemInformation 
=  (ZWQUERYSYSTEMINFORMATION)GetProcAddress(LoadLibrary( " ntdll.dll " ), " ZwQuerySystemInformation " );
    NtSystemDebugControl 
=  (NTSYSTEMDEBUGCONTROL)GetProcAddress(LoadLibrary( " ntdll.dll " ), " NtSystemDebugControl " );

    
// 先创建一个线程对象
    GetProcAddress(LoadLibrary( " kernel32.dll " ), " OpenThread " );

    __asm
    ...
{//SDK居然不包含OpenThread的声明,只能用汇编,简单很多。
        push dwTID
        push 
0
        push THREAD_ALL_ACCESS
        call eax
        mov hThread,eax
    }


    
// 获得线程对象的地址
    BYTE  *  pBuf  =   new  BYTE[dwBufLen];
    ZeroMemory(pBuf,dwBufLen);
    status 
=  ZwQuerySystemInformation(SystemHandleInformation,pBuf,dwBufLen, & dwRetLen); // 列举系统所有句柄
    
    uObjCnt 
=  (ULONG) * (ULONG * )pBuf; // 获得句柄的个数

    pHandleInfo 
=  (PSYSTEM_HANDLE_INFORMATION)(pBuf + sizeof (ULONG));
    
    
if (NT_SUCCESS(status))
    ...
{
        
        
for(int i=0;i<uObjCnt;i++)
        ...
{
            
if(pHandleInfo->ProcessId==dwPID//如果句柄的拥有者并且句柄是之前打开的。
                &&pHandleInfo->Handle==(USHORT)hThread)
            ...
{
                dwETHREAD 
= (DWORD)pHandleInfo->Object;//保存下来
                break;
            }

            pHandleInfo
++;
        }

        
        
//patch 内核
        
        MEMORY_CHUNKS datas;
        datas.Address 
= dwETHREAD+0x248;//CrossThreadFlags的偏移
        datas.Data = &m_dwFixData;
        datas.Length 
= 4;

        status 
= NtSystemDebugControl(0x9,&datas,sizeof(MEMORY_CHUNKS),NULL,0,&dwRetLen);

    
//    status = NtSystemDebugControl(0x8,&datas,sizeof(MEMORY_CHUNKS),NULL,0,&dwRetLen);

        
if(NT_SUCCESS(status))
            bRet 
= TRUE;

    }

    delete [] pBuf;
    CloseHandle(hThread);

 

当然上面的代码只在XP下有效,并且是管理员。为什么?自己去看资料吧。呵呵。

我晕,这文章我发表了5次才成功,CSDN可不是一般的烂.

完整代码:http://download.csdn.net/source/458567

你可能感兴趣的:(三两行代码实现进程防杀,免驱动,IceSword,WSysCheck等无效.)