http://blog.csdn.net/KeSummer/article/details/2455379
三两行代码实现进程防杀,免驱动,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