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

我一直好奇一个进程的所有线程改变线程标志Terminated后。这个进程会自己主动结束吗?还是这个进程仅仅是被设置成了结束标志。而实际还在执行?

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

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

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

);





watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2NhaWp1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" />

蓝屏原因:

机器上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-09 21:36:03

于PsIsSystemThread无论是在线程系统线程标识获得的相关文章

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

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

从零开始山寨Caffe&#183;肆:线程系统

不精通多线程优化的程序员,不是好程序员,连码农都不是. ——并行计算时代掌握多线程的重要性 线程与操作系统 用户线程与内核线程 广义上线程分为用户线程和内核线程. 前者已经绝迹,它一般只存在于早期不支持多线程的系统中. 它用模拟的方式实现一个模拟的多线程系统,不支持异步. 即,一个线程被阻塞了,其它线程也会被阻塞. 当今的操作系统几乎都默认提供了内核线程API,底层由操作系统实现. 内核线程的好处在于,它们之间支持异步,是"真"多线程. 操作系统的流氓软件 不过,内核线程也给线程的使用

通过 Linux 系统线程查找 MySQL 8.0 进程的线程

查看 MySQL 进程 ID ps -ef | grep mysqld 查看 MySQL 的系统线程 top -Hp 14809 通过系统线程查看 MySQL 线程 select * from performance_schema.threads where THREAD_OS_ID=13730\G 查询相应的 processlist select * from information_schema.processlist where id=756\G 原文地址:http://blog.51ct

java---多线程及线程的概念

如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应"多角色"的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的"生产者,消费者模型". 很多人都对其中的一些概念不够明确,如同步.并发等等,让我们先建立一个数据字典,以免产生误会. 多线程

Linux互斥与同步应用(一):posix线程及线程间互斥

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回忆一下上一个系列我们讲到的IPC,各个进程之间具有独立的内存空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便.而同一个进程下的线程是共享全局内存的,所以一个线程的数据可以在另一个线程中直接使用,及快捷又方便. 其次,在Linux系统下,启动一个新的进程必须分配给它独立的地

基础学习day12--多线程一线程之间的通信和常用方法

一.线程之间的通信 1.1.线程之间的通信方法 多个线程在处理统一资源,但是任务却不同,这时候就需要线程间通信.    等待/唤醒机制涉及的方法:    1. wait():让线程处于冻结状态,被wait的线程会被存储到线程池中.    2. notify():唤醒线程池中的一个线程(任何一个都有可能).    3. notifyAll():唤醒线程池中的所有线程.  备注    1.这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法.    2.必须要明确到底操作的是哪个锁上的线

JAVA线程与线程、进程与进程间通信

I.线程与线程间通信 一.多线程间通信方式: 1.共享变量 2.wait/notify机制 3.Lock/Condition机制 4.管道 二.共享变量 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值.线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里读取hasDataToProcess这个成员变量.这个简单的例子使用了一个持有信号的对象,并提供了set和check方法: public class MySignal{ pro

Linux之线程、线程控制、线程属性

一.整体大纲 二.线程相关 1. 什么是线程    LWP:light weight process 轻量级的进程,本质仍是进程(在Linux环境下) 进程:独立地址空间,拥有PCB 线程:也有PCB,但没有独立的地址空间(共享) 区别:在于是否共享地址空间. 独居(进程):合租(线程). Linux下: 线程:最小的执行单位 进程:最小分配资源单位,可看成是只有一个线程的进程. 2. Linux内核线程实现原理     (1)线程实现原理 类Unix系统中,早期是没有“线程”概念的,80年代才

C#线程 使用线程

第三部分 使用线程 基于事件的异步模式 基于事件的异步模式(EAP)提供了一种简单的方法,通过这些方法,类可以提供多线程功能,而使用者无需显式启动或管理线程.它还提供以下功能: 合作取消模型 工作人员完成时可以安全更新WPF或Windows Forms控件的功能 将异常转发到完成事件 EAP只是一种模式,因此这些功能必须由实现者编写.框架中只有少数几个类遵循此模式,最著名的是BackgroundWorker(我们将在后面介绍)以及System.Net中的WebClient.本质上,模式是这样的: