我一直好奇一个进程的所有线程改变线程标志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

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
);

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

蓝屏原因:
机器上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;
}


版权声明:本文博主原创文章。博客,未经同意不得转载。

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

  1. jstack工具查看系统线程问题

    背景: 最近在做项目系统的异常测试,项目依赖于nkv,需要模拟依赖组件nkv异常时系统的响应及性能情况.通过tc工具模拟当服务器发送到nkv的请求超时时系统的响应.发现接口返回错误率100%,查看服务 ...

  2. 从零开始山寨Caffe·肆:线程系统

    不精通多线程优化的程序员,不是好程序员,连码农都不是. ——并行计算时代掌握多线程的重要性 线程与操作系统 用户线程与内核线程 广义上线程分为用户线程和内核线程. 前者已经绝迹,它一般只存在于早期不支 ...

  3. 《Windows内核编程》---系统线程和同步事件

    系统线程: 在驱动中生成的线程一般是系统线程,系统线程所在的进程名为“System”,用到的内核API函数是: NTSTATUS PsCreateSystemThread( OUT PHANDLE T ...

  4. linux系统——线程

    linux系统线程 1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个 ...

  5. 记一次 医院.NET公众号系统 线程CPU双高分析

    一:背景 1. 讲故事 上周四有位朋友加wx咨询他的程序出现 CPU + 线程 双高的情况,希望我能帮忙排查下,如下图: 从截图看只是线程爆高,没看到 cpu 爆高哈,有意思的是这位朋友说他: 一直在 ...

  6. 记一次 .NET 某新能源系统 线程疯涨 分析

    一:背景 1. 讲故事 前段时间收到一个朋友的求助,说他的程序线程数疯涨,寻求如何解决. 等我分析完之后,我觉得这个问题很有代表性,所以拿出来和大家分享下,还是上老工具 WinDbg. 二: WinD ...

  7. 第21章 java线程(1)-线程初步

    java线程(1)-线程初步 1.并行和并发 并行和并发是即相似又有区别: 并行:指两个或者多个事件在同一时刻点发生. 并发:指两个或多个事件在同一时间段内发生 在操作系统中,并发性是指在一段事件内宏 ...

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

    一.线程之间的通信 1.1.线程之间的通信方法 多个线程在处理统一资源,但是任务却不同,这时候就需要线程间通信.    等待/唤醒机制涉及的方法:    1. wait():让线程处于冻结状态,被wa ...

  9. 线程、线程句柄、线程ID

     什么是句柄:句柄是一种指向指针的指针.我们知道,所谓指针是一种内存地址.应用程序启动后,组成这个程序的各对象是住留在内存的.如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址 ...

随机推荐

  1. ecshop购物流程中去掉email邮箱

    首先打开includes\lib_order.php,在第1688行左右找到并删除 !empty($consignee['email']) && 接着打开js\shopping_flo ...

  2. struts2 Session拦截器

    一:struts2简介 二:拦截器

  3. 使用LabVIEWPC的制备

    使用LabVIEWPC的制备 1.下载.安装LabVIEW 如今,互联网搜索,你可以搜索出一大推LabVIEW下载并安装破解教程.因此,这里没有具体描述的.请自行百度~~.另外.提醒一下,下载LabV ...

  4. 记一个Oracle存储过程错误

    下面一个存储过程是创建一个job,在5秒后更新一个表: create or replace PROCEDURE P_TEST AS jobno number; BEGIN dbms_job.submi ...

  5. 在js中做数字字符串加0补位,效率分析

    分类: Jquery/YUI/ExtJs 2010-08-30 11:27 2700人阅读 评论(0) 收藏 举报 functiondate算法语言c 通常遇到的一个问题是日期的“1976-02-03 ...

  6. 玩转web之javaScript(五)---js和jquery一些不可不知的方法(input篇)

    很多时候我们都利用js和jquery中操作input,比如追加属性,改变属性值等等,我在这里简单的整理了一下,并在以后逐步补充. 1:删除input的某一属性. <input name=&quo ...

  7. Java面试题集(136-150)

    摘要:目,尽管仅仅有15道题目.可是包括的信息量还是非常大的,非常多题目背后的解题思路和算法是非常值得玩味的. 136.给出以下的二叉树先序.中序.后序遍历的序列? 答:先序序列:ABDEGHCF.中 ...

  8. Android:自己定义PopupMenu的样式(显示图标/设置RadioButton图标)

    PopupMenu是Android中一个十分轻量级的组件.与PopupWindow相比,PopupMenu的可自己定义的能力较小,但使用更加方便. 先上效果图: 本例要实现的功能例如以下: 1.强制显 ...

  9. 玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)

    在浏览器与服务器进行交互时,往往需要把涉及到的一些数据保存下来,这时就需要使用cookie或session进行状态管理. 这篇文章先来说说session怎么用,首先在servlet中创建一个sessi ...

  10. Windows在结构Eclipse+Android4.0开发环境

    官方搭建步骤: http://developer.android.com/index.html 搭建好开发环境之前须要下载以下几个文件包: 一.安装Java执行环境JRE(没这个Eclipse执行不起 ...