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

一直好奇将一个进程的所有线程的线程标志改成Terminated后,这个进程会自动结束吗?还是这个进程只是被设置成了结束标志,而实际还在运行?

想写个程序试验一下,但问题来了,怎么得到线程的标志呢?

win xp 下的ntoskrnl.exe文件中的PsIsSystemThread的函数:


; Attributes: bp-based frame



; __stdcall PsIsSystemThread(x)

public [email protected]

[email protected] 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

[email protected] 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.

来源: <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:[0F8BE2618h]

问题来了,之一:为什么得到的函数地址不是真实地址,是系统本身就是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; 

}






时间: 2024-10-07 01:40:34

在PsIsSystemThread中得到线程的是否为系统线程的标志的相关文章

于PsIsSystemThread无论是在线程系统线程标识获得

我一直好奇一个进程的所有线程改变线程标志Terminated后.这个进程会自己主动结束吗?还是这个进程仅仅是被设置成了结束标志.而实际还在执行? 想写个程序试验一下.但问题来了,怎么得到线程的标志呢? 在PsIsSystemThread中得到线程的是否为系统线程的标志 win xp 下的ntoskrnl.exe文件里的PsIsSystemThread的函数: ; Attributes: bp-based frame ; __stdcall PsIsSystemThread(x) public [

Android中Handler的使用方法——在子线程中更新界面

本文主要介绍Android的Handler的使用方法.Handler可以发送Messsage和Runnable对象到与其相关联的线程的消息队列.每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联. Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器.2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Han

boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。

1.实现多线程方法: 其实就是多个线程同时调用io_service::run for (int i = 0; i != m_nThreads; ++i)        {            boost::shared_ptr<boost::thread> pTh(new boost::thread(                boost::bind(&boost::asio::io_service::run,&m_ioService)));            m_l

C#中只使用Invokerequired来判断是不是UI线程可靠吗?

博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:C#中只使用Invokerequired来判断是不是UI线程可靠吗?.

java中线程通信(传统的线程通信)

假设现在系统有两个线程,这两个线程分别代表存款者和取钱者——现在假设系统有一种特殊的要求,系统要求存款者和取钱者不断地重复存款.取钱的动作.而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱.不允许存款者连续两次存钱,也不允许取钱者连续两次取钱. 为了实现这种功能,可以借助Object类提供的wait().notify().notifyAll() 3 个方法,这3个方法并不属于Thread类,而是属于Object类.但这3 个方法必须由同步监视器对象来调用,这可分以下两种情况: 1.对

python-多线程:调用thread模块中的start_new_thread()函数来产生新线程

Python 多线程 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度 程序的运行速度可能加快 在一些等待的任务实现上如用户输入.文件读写和网络收发数据等,线程就比较有用了.在这种情况下我们可以释放一些珍贵的资源如内存占用等等. 线程在执行过程中与进程还是有区别的.每个独立的线程有一个程序运行的入口.顺序执行序列和程序的出口.

记录一次线程池的在项目中的实际应用,讲解一下线程池的配置和参数理解。

前言:最近项目中与融360项目中接口对接,有反馈接口(也就是我们接收到请求,需要立即响应,并且还要有一个接口推送给他们其他计算结果),推送过程耗时.或者说两个接口不能是同时返回,有先后顺序. 这时我想到了把自己Controller立即返回接受成功,中间添加一个新的线程去做其他耗时的操作(线程池配置和参数测试讲解请阅读第5步). 1.Controller代码如下: @Autowiredprivate CallThreadDemo worker; @RequestMapping("/bandBank

在线程中显示一个窗口(多个UI线程)

多数耗时操作可以异步执行,推荐async/await. 但和UI相关的部分仅能在UI线程执行,这时UI线程的耗时操作,导致界面卡死,不够友好. 我们可以创建一个单独的UI线程显示一个正在加载的窗口,可以在窗口显示一些动画之类的. 如果是WinForms那么很容易做到. Application.Run(new LoadingForm()); WPF没有提供这样简单的方式,官方文档中有示例<多窗口.多线程>,官方例子 ExceptionHandlingSecondaryUIThread 经过简化后

[Java Performance] 线程及同步的性能 - 线程池/ThreadPoolExecutors/ForkJoinPool

线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自客户端的请求.Java中对于线程池的支持,来自ThreadPoolExecutor.一些应用服务器也确实是使用的ThreadPoolExecutor来实现线程池. 对于线程池的性能调优,最重要的参数就是线程池的大小. 对于任何线程池而言,它们的工作方式几乎都是相同的: 任务被投放到一个队列中(队列的