恋爱的犀牛 发表于 2017-6-2 13:31:21

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

一直好奇将一个进程的所有线程的线程标志改成Terminated后,这个进程会自动结束吗?还是这个进程只是被设置成了结束标志,而实际还在运行?想写个程序试验一下,但问题来了,怎么得到线程的标志呢?在PsIsSystemThread中得到线程的是否为系统线程的标志win xp 下的ntoskrnl.exe文件中的PsIsSystemThread的函数:; Attributes: bp-based frame; __stdcall PsIsSystemThread(x)public _PsIsSystemThread@4_PsIsSystemThread@4 proc neararg_0= dword ptr8mov   edi, edi      ; IoIsSystemThreadpush    ebpmov   ebp, espmov   eax, mov   eax, shr   eax, 4and   al, 1pop   ebpretn    4_PsIsSystemThread@4 endpF5一下下:char __stdcall PsIsSystemThread(int a1){return (*(_DWORD *)(a1 + 0x248) >> 4) & 1;}比较下面来自官方的声明PsIsSystemThread routineThePsIsSystemThreadroutine checks whether a given thread is a system thread.SyntaxC++BOOLEAN PsIsSystemThread(
_In_PETHREAD Thread
);

ParametersThreadPointer to the thread to be checked.Return valuePsIsSystemThreadreturnsTRUEif the specified thread is a system thread,FALSEotherwise.来源:<http://msdn.microsoft.com/zh-cn/library/ff559945(v=vs.85).aspx>可以猜测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函数的地址并不是函数的真实地址,而是jmp指令,指令的目的地才地函数的真实地址。f8be2520 ff251826bef8    jmp   dword ptr ds:问题来了,之一:为什么得到的函数地址不是真实地址,是系统本身就是JMP样子的还是被机器上的安全软件给修改成JMP的?验证方法:回复快照,看最原始的系统中这个地方是不是也是JMP?在干净的系统上,uf函数总是能看到真正的地址:lkd> uf PsIsSystemThreadnt!IoIsSystemThread:804ef8a2 8bff            mov   edi,edi804ef8a4 55            push    ebp804ef8a5 8bec            mov   ebp,esp804ef8a7 8b4508          mov   eax,dword ptr 804ef8aa 8b8048020000    mov   eax,dword ptr 804ef8b0 c1e804          shr   eax,4804ef8b3 2401            and   al,1804ef8b5 5d            pop   ebp804ef8b6 c20400          ret   4而在程序中看到的都是JMP地址:BOOLEAN PsIsSystemThread(PETHREAD Thread);dprintf("PsIsSystemThread:0X%08X\n", (PULONG)pPsIsSystemThread);看来系统本身就是JMP地址。通过x nt!PsIsSystemThread看看结果,得到函数真实地址,函数真实地址的地方是不是FF 25而函数的真实地址是804ef8a2lkd> uf PsIsSystemThreadnt!IoIsSystemThread:804ef8a2 8bff            mov   edi,edi804ef8a4 55            push    ebp804ef8a5 8bec            mov   ebp,esp804ef8a7 8b4508          mov   eax,dword ptr 804ef8aa 8b8048020000    mov   eax,dword ptr 804ef8b0 c1e804          shr   eax,4804ef8b3 2401            and   al,1804ef8b5 5d            pop   ebp804ef8b6 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:0XF8C2055CIoIsSystemThread:0XF8C20550lkd> u 0xf8c2055cf8c2055c ff259c06c2f8    jmp   dword ptr ds:f8c20562 cc            int   3f8c20563 cc            int   3f8c20564 cc            int   3f8c20565 cc            int   3f8c20566 cc            int   3f8c20567 cc            int   3f8c20568 ff25a806c2f8    jmp   dword ptr ds:lkd> u f8c20550f8c20550 ff259806c2f8    jmp   dword ptr ds:f8c20556 cc            int   3f8c20557 cc            int   3f8c20558 cc            int   3f8c20559 cc            int   3f8c2055a cc            int   3f8c2055b cc            int   3f8c2055c ff259c06c2f8    jmp   dword ptr ds: dword ptr ds: = dword ptr ds: = 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:        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; }
页: [1]
查看完整版本: 在PsIsSystemThread中得到线程的是否为系统线程的标志