在PsIsSystemThread中得到线程的是否为系统线程的标志



一直好奇将一个进程的所有线程的线程标志改成 Terminated后,这个进程会自动结束吗?还是这个进程只是被设置成了结束标志,而实际还在运行?
想写个程序试验一下,但问题来了,怎么得到线程的标志呢?

在PsIsSystemThread中得到线程的是否为系统线程的标志

win xp 下的ntoskrnl.exe文件中的PsIsSystemThread的函数:
 
    
; Attributes: bp-based frame
; __stdcall PsIsSystemThread(x)
public _PsIsSystemThread@4
_PsIsSystemThread@4 proc near
arg_0= dword ptr 8
mov edi, edi ; IoIsSystemThread
push ebp
mov ebp, esp
mov eax, [ebp+arg_0]
mov eax, [eax+248h]
shr eax, 4
and al, 1
pop ebp
retn 4
_PsIsSystemThread@4 endp
F5一下下:
 
    
char __stdcall PsIsSystemThread(int a1)
{
return (*(_DWORD *)(a1 + 0x248) >> 4) & 1;
}
比较下面来自官方的声明

PsIsSystemThread routine

The PsIsSystemThread routine checks whether a given thread is a system thread.

Syntax

C++
BOOLEAN PsIsSystemThread(
  _In_  PETHREAD Thread
);

Parameters

Thread [in]

Pointer to the thread to be checked.

Return value

PsIsSystemThread returns TRUE if the specified thread is a system thread, FALSE otherwise.


来源: >

可以猜测 a1 + 0x248就是线程权限的标识。
我们在xp系统上看一下:
 
      
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x1c0 CreateTime : _LARGE_INTEGER
+0x1c0 NestedFaultCount : Pos 0, 2 Bits
+0x1c0 ApcNeeded : Pos 2, 1 Bit
+0x1c8 ExitTime : _LARGE_INTEGER
+0x1c8 LpcReplyChain : _LIST_ENTRY
+0x1c8 KeyedWaitChain : _LIST_ENTRY
+0x1d0 ExitStatus : Int4B
+0x1d0 OfsChain : Ptr32 Void
+0x1d4 PostBlockList : _LIST_ENTRY
+0x1dc TerminationPort : Ptr32 _TERMINATION_PORT
+0x1dc ReaperLink : Ptr32 _ETHREAD
+0x1dc KeyedWaitValue : Ptr32 Void
+0x1e0 ActiveTimerListLock : Uint4B
+0x1e4 ActiveTimerListHead : _LIST_ENTRY
+0x1ec Cid : _CLIENT_ID
+0x1f4 LpcReplySemaphore : _KSEMAPHORE
+0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
+0x208 LpcReplyMessage : Ptr32 Void
+0x208 LpcWaitingOnPort : Ptr32 Void
+0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
+0x210 IrpList : _LIST_ENTRY
+0x218 TopLevelIrp : Uint4B
+0x21c DeviceToVerify : Ptr32 _DEVICE_OBJECT
+0x220 ThreadsProcess : Ptr32 _EPROCESS
+0x224 StartAddress : Ptr32 Void
+0x228 Win32StartAddress : Ptr32 Void
+0x228 LpcReceivedMessageId : Uint4B
+0x22c ThreadListEntry : _LIST_ENTRY
+0x234 RundownProtect : _EX_RUNDOWN_REF
+0x238 ThreadLock : _EX_PUSH_LOCK
+0x23c LpcReplyMessageId : Uint4B
+0x240 ReadClusterSize : Uint4B
+0x244 GrantedAccess : Uint4B
+0x248 CrossThreadFlags : Uint4B
+0x248 Terminated : Pos 0, 1 Bit
+0x248 DeadThread : Pos 1, 1 Bit
+0x248 HideFromDebugger : Pos 2, 1 Bit
+0x248 ActiveImpersonationInfo : Pos 3, 1 Bit
+0x248 SystemThread : Pos 4, 1 Bit
+0x248 HardErrorsAreDisabled : Pos 5, 1 Bit
+0x248 BreakOnTermination : Pos 6, 1 Bit
+0x248 SkipCreationMsg : Pos 7, 1 Bit
+0x248 SkipTerminationMsg : Pos 8, 1 Bit
+0x24c SameThreadPassiveFlags : Uint4B
+0x24c ActiveExWorker : Pos 0, 1 Bit
+0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit
+0x24c MemoryMaker : Pos 2, 1 Bit
+0x250 SameThreadApcFlags : Uint4B
+0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit
+0x250 LpcExitThreadCalled : Pos 1, 1 Bit
+0x250 AddressSpaceOwner : Pos 2, 1 Bit
+0x254 ForwardClusterOnly : UChar
+0x255 DisablePageFaultClustering : UChar
果然,那么我们可以通过在 PsIsSystemThread函数中查找特征码的方法来取得线程的标识。如果要保护进程,我们可以将进程的所有线程的线程标志都设置成 SystemThread

1. PsIsSystemThread是导出但未声明的函数,只需要声明一下就可以使用了。
声明:
 
      
BOOLEAN PsIsSystemThread(
_In_ PETHREAD Thread
);

在PsIsSystemThread中得到线程的是否为系统线程的标志_第1张图片
蓝屏原因:
机器上 PsIsSystemThread函数的地址并不是函数的真实地址,而是jmp指令,指令的目的地才地函数的真实地址。
f8be2520 ff251826bef8 jmp dword ptr ds:[0F8BE2618h]
 
 
在PsIsSystemThread中得到线程的是否为系统线程的标志_第2张图片

问题来了,之一:为什么得到的函数地址不是真实地址,是系统本身就是JMP样子的还是被机器上的安全软件给修改成JMP的?
验证方法:
回复快照,看最原始的系统中这个地方是不是也是JMP?
在干净的系统上,uf函数总是能看到真正的地址:
 
     
lkd> uf PsIsSystemThread
nt!IoIsSystemThread:
804ef8a2 8bff mov edi,edi
804ef8a4 55 push ebp
804ef8a5 8bec mov ebp,esp
804ef8a7 8b4508 mov eax,dword ptr [ebp+8]
804ef8aa 8b8048020000 mov eax,dword ptr [eax+248h]
804ef8b0 c1e804 shr eax,4
804ef8b3 2401 and al,1
804ef8b5 5d pop ebp
804ef8b6 c20400 ret 4


而在程序中看到的都是JMP地址:
 
     
BOOLEAN PsIsSystemThread(PETHREAD Thread);
dprintf("PsIsSystemThread:0X%08X\n", (PULONG)pPsIsSystemThread);
看来系统本身就是JMP地址。


通过x nt!PsIsSystemThread看看结果,得到函数真实地址,函数真实地址的地方是不是FF 25
而函数的真实地址是804ef8a2
 
     
lkd> uf PsIsSystemThread
nt!IoIsSystemThread:
804ef8a2 8bff mov edi,edi
804ef8a4 55 push ebp
804ef8a5 8bec mov ebp,esp
804ef8a7 8b4508 mov eax,dword ptr [ebp+8]
804ef8aa 8b8048020000 mov eax,dword ptr [eax+248h]
804ef8b0 c1e804 shr eax,4
804ef8b3 2401 and al,1
804ef8b5 5d pop ebp
804ef8b6 c20400 ret 4


而程序得到的地址为JMP地址
 
     
BOOLEAN PsIsSystemThread(PETHREAD Thread);  
BOOLEAN IoIsSystemThread(PETHREAD Thread);
dprintf("PsIsSystemThread:0X%08X\n", (PULONG)pPsIsSystemThread);
dprintf("IoIsSystemThread:0X%08X\n", (PULONG)pIoIsSystemThread);

这两个函数的地址分别为:
 
     
PsIsSystemThread:0XF8C2055C
IoIsSystemThread:0XF8C20550
lkd> u 0xf8c2055c
f8c2055c ff259c06c2f8 jmp dword ptr ds:[0F8C2069Ch]
f8c20562 cc int 3
f8c20563 cc int 3
f8c20564 cc int 3
f8c20565 cc int 3
f8c20566 cc int 3
f8c20567 cc int 3
f8c20568 ff25a806c2f8 jmp dword ptr ds:[0F8C206A8h]
lkd> u f8c20550
f8c20550 ff259806c2f8 jmp dword ptr ds:[0F8C20698h]
f8c20556 cc int 3
f8c20557 cc int 3
f8c20558 cc int 3
f8c20559 cc int 3
f8c2055a cc int 3
f8c2055b cc int 3
f8c2055c ff259c06c2f8 jmp dword ptr ds:[0F8C2069Ch]
dword ptr ds:[0F8C2069Ch] = dword ptr ds:[0F8C20698h] = 804ef8a2

http://bbs.pediy.com/showthread.php?t=93742
这里的代码好像没有处理FF25
所以看雪上楼主的这个程序会蓝屏。
改后代码:
 
     
ULONG GetCrossThreadFlagOffset()
{
ULONG Offset = 0;
PUCHAR pPsIsSystemThread;
PULONG pFuncAddr;
PUCHAR pFeature;
if(Offset == 0)
{
pPsIsSystemThread = (PUCHAR)PsIsSystemThread;
}
dprintf("PsIsSystemThread:0X%08X\n", (PULONG)pPsIsSystemThread);
//判断是不是FF 25
if ((*pPsIsSystemThread) != 0xFF || *(pPsIsSystemThread+1) != 0X25)
{
dprintf("pProc is not ff 25.\n");
return Offset;
}
//ff25 9806c2f8 jmp dword ptr ds:[0F8C20698h]
pFuncAddr = (*(PULONG)(pPsIsSystemThread+2));
dprintf("pFuncAddr:0X%08X\n", (PULONG)pFuncAddr);
pFuncAddr = (PULONG)*pFuncAddr;
dprintf("pFuncAddr:0X%08X\n", (PULONG)pFuncAddr);
pFeature = (PUCHAR)pFuncAddr;
while( *pFeature!=0x8B || *(pFeature+1)!=0x80 )
pFeature++;
dprintf("Instruction found in address:0X%08X\n",(PULONG)pFeature);
Offset = *(PULONG)(pFeature+2);
dprintf("Offset:0X%08X\n",Offset);
return Offset;
}
 
      

你可能感兴趣的:(内核开发)