监视远程线程的创建

PsSetLoadImageNotifyRoutine loadImageNotifyRoutine 中拿全路径 PsSetLoadImageNotifyRoutine#include <ntifs.h>#include <ntddk.h>#include <Ntstrsafe.h>#include <fltKernel.h>//删除指针#define SafeFreeDelete(pData) { if(pData){ExFreePool(pData);pDa... 阅读详情

监视远程线程的创建

作者: 一块三毛钱
邮件: zhongts@163.com
日期: 2004.12.29

    远程线程技术被大量的使用在木马、蠕虫等软件当中,通过在别的进程中插入线程的方式运行代码,具有相当高的隐蔽性。比如常见的 Explorer.exe 进程中有十几个线程同时运行,在其中插入一个线程后,谁也分辨不出来哪个就是插入的远程线程。本文提供了一种方法可以监视远程线程的创建活动,记录下来远程线程的 ID 等重要数据,这样就可以方便大家查出哪个进程往哪个进程中插入了远程线程。

    下面分别是 IceSword v1.06 和本文代码所记录下来的远程线程创建的情况:
    
    
    
    
    
    由于本文需要编写驱动程序,所以不熟悉驱动程序编写的读者可以找一些驱动方面的书籍先看看,这里推荐大家到罗云彬的网站上去下载翻译的 KmdTut 来看。同时把 KmdKit 也下载下来,因为本文代码用到了这个软件包。安装好 Masm32 和 KmdKit 之后才能编译本文提供的代码。如果编译代码时提示 error LNK2001: unresolved external symbol _PsRemoveCreateThreadNotifyRoutine@4 错误,则把本文提供的 ntoskrnl.lib 复制到 lib/w2k 文件夹中覆盖原文件即可。我也是刚学驱动编程,下面提供的只是一个很简单的例子,要想实用还有很多事情要做。

    首先是监视线程的创建问题,然后再区分哪些是远程线程。要想监视线程的创建需要用到这样的一个函数 PsSetCreateThreadNotifyRoutine。通过该函数我们注册一个回调函数,每次当系统中有新的线程创建的时候就会调用我们的回调函数。在这个回调函数中我们就可以把所有的线程的创建记录下来。如果要监视进程的创建则还有另外一个函数 PsSetCreateProcessNotifyRoutine 可以完成这个功能。监视线程创建的回调函数的函数原型如下:

VOID
(*PCREATE_THREAD_NOTIFY_ROUTINE) (
    IN HANDLE  ProcessId,
    IN HANDLE  ThreadId,
    IN BOOLEAN  Create
    );
    
    ProcessId 是进程号,这里的进程号是指向包括该线程的进程,而不是创建该线程的进程。ThreadId 是将要创建的线程的线程号。Create 用来指出是创建线程还是销毁线程。监视进程创建的回调函数的函数原型如下:

VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE) (
    IN HANDLE  ParentId,
    IN HANDLE  ProcessId,
    IN BOOLEAN  Create
    );

    ParentId 是父进程号,ProcessId 是进程号,Create 表示创建还是销毁进程。
    
    有了这两个函数我们就可以监视所有的进程和线程的创建和销毁活动了。下面来看看代码,我把主要的代码都列了出来。
    
DriverEntry proc uses esi, pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
LOCAL status : NTSTATUS
LOCAL pDeviceObject : PDEVICE_OBJECT

......

mov g_dwProcessId, 0
mov g_bMainThread, FALSE
lea eax, _ProcessCallback
invoke PsSetCreateProcessNotifyRoutine, eax, FALSE
lea eax, _ThreadCallback
invoke PsSetCreateThreadNotifyRoutine, eax
mov status, eax

......

DriverEntry endp

    上面就是注册回调函数的代码部分,_ProcessCallback 和 _ThreadCallback 分别是进程和线程监视函数。在驱动程序的启动部分注册了回调函数,还需要在驱动的卸载部分移去注册的回调函数。代码如下:

_DriverUnload proc pDriverObject:PDRIVER_OBJECT

lea eax, _ProcessCallback
invoke PsSetCreateProcessNotifyRoutine, eax, TRUE
lea eax, _ThreadCallback
invoke PsRemoveCreateThreadNotifyRoutine, eax

invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
mov eax, pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
ret
_DriverUnload endp

    给 PsSetCreateProcessNotifyRoutine 函数的第二个参数传递 TRUE 就可以移去注册的进程回调函数。移去注册的线程回调函数需要调用 PsRemoveCreateThreadNotifyRoutine 函数,这个函数是一个未公开函数,从 Windows XP 以后提供,由于手边没有 Windows 2000 系统,不能验证,大家可以看看自己的 Windows 2000 系统中有没有这个函数。因为这个一个未公开函数,所以调用的时候不能直接调用,需要引入库才行。生成引入库的办法也很简单,利用 Masm32 软件包中自带的 inc2l 工具即可,使用办法大家可以参考 Masm32 自己生成引入库的方法。上文之所以提到要覆盖 ntoskrnl.lib 文件就是这个原因。

    本来监视远程线程只需要注册一个线程回调函数即可,因为要判断是否是远程线程,要根据创建线程的进程和包含线程的进程的不同才能判断是否是远程线程。所以,我们还需要注册一个进程回调函数。

_ProcessCallback proc uses esi,ParentId:DWORD, ProcessId:DWORD, bCreate:DWORD

.if bCreate
  mov eax, ProcessId
  mov g_dwProcessId, eax
  mov g_bMainThread, TRUE
.endif
ret
_ProcessCallback endp

    这个就是进程回调函数,如果新创建一个进程,则把 g_bMainThread 设置为 TRUE,把进程 ID 保存到 g_dwProcessId 中。因为一个新的进程被创建时,它的主线程不是它自己创建的,而是它的父进程创建的。这里父进程和它自己的进程肯定不是同一个进程,但这个时候创建的主线程不是远程线程。上面的代码就是记录进程的创建,那么紧接着创建的线程就不是远程线程。

_ThreadCallback proc uses ebx esi edi, ProcessId:DWORD, ThreadId:DWORD, bCreate:DWORD
LOCAL lpParentEProcess, lpEProcess
LOCAL dwParentPID, dwParentTID

cmp g_bMainThread, TRUE
je exit_0

cmp bCreate, 0
je exit_0

cmp ProcessId, 4
je exit_0

invoke PsGetCurrentProcessId
mov dwParentPID, eax
cmp eax, ProcessId
je exit_0

invoke PsGetCurrentThreadId
mov dwParentTID, eax

invoke PsLookupProcessByProcessId, dwParentPID, addr lpParentEProcess
cmp eax, STATUS_SUCCESS
jne exit_0
invoke PsLookupProcessByProcessId, ProcessId, addr lpEProcess
cmp eax, STATUS_SUCCESS
jne exit_0

mov esi, lpParentEProcess
add esi, g_dwOffset
mov edi, lpEProcess
add edi, g_dwOffset

invoke DbgPrint, $CTA0("调用方: Name=%s PID=%d TID=%d/t/t被调用方: Name=%s PID=%d TID=%d/n"), /
   esi, dwParentPID, dwParentTID, edi, ProcessId, ThreadId

exit_0:
mov g_bMainThread, FALSE
ret
_ThreadCallback endp

    这段代码是线程回调函数,也是我们的核心代码。先判断是不是一个进程的主线程创建,如果不是继续判断。是不是创建线程?如果是则继续判断。进程是否是 SYSTEM 进程?如果是则忽略。这是因为每次打开文件夹、切换文件夹 Explorer.exe 都会在 SYSTEM 进程当中创建一个远程线程,所以我们忽略它。大家可以把这两句注释掉再看看程序的输出就能明白。

    因为回调函数中只有两个参数,一个是 ProcessId 表示包含线程的进程号,另外一个是 ThreadId 表示创建的线程号。所以我们还需要找出那个创建线程的进程号,才能够比较创建线程的进程和包含线程的进程是不是同一个进程,从而判断是不是远程线程。这里就要提到一个问题,当某一个进程创建线程的时候,系统是在该进程上下文中调用我们的线程回调函数,所以我们可以通过 PsGetCurrentProcessId 函数来取得该进程号。再通过 PsGetCurrentThreadId 取得线程号,注意这个线程不是要创建的线程,而是包含创建线程代码的线程。

    代码接着又调用一个未公开函数 PsLookupProcessByProcessId 来取得某个进程的 EPROCESS 结构,EPROCESS 结构在 KmdKit 所带的 w2kundoc.inc 中有详细的说明,在 EPROCESS 结构的 ImageFileName 成员中保存着进程的名字。因为系统不同 ImageFileName 成员的偏移位置也不同,所以,根据系统的不同代码中采用了一个全局变量 g_dwOffset 来保存这个偏移。下面是判断系统的代码:

invoke PsGetVersion, NULL, addr g_dwSystemMinorVersion, NULL, NULL
.if g_dwSystemMinorVersion==0
mov g_dwOffset, 1FCh
.elseif g_dwSystemMinorVersion==1
mov g_dwOffset, 174h
.elseif g_dwSystemMinorVersion==2
mov g_dwOffset, 154h
.endif

所有的工作做完之后就是把收集到的信息输出来,通过 DbgPrint 函数可以达到这个目的。

    大家可以通过 KmdKit 自带的 KmdManager 工具注册/运行本文代码生成的 RemoteThreadMonitor.sys 文件,然后通过 DbgView 或者 SoftICE 工具查看代码的输出。知道了远程线程的线程号可以用 Process Explorer 等工具杀掉远程线程。

参考资料:
(1) sinister 编写进程/线程监视器
    http://www.xfocus.net/articles/200303/495.html
(2) DDK
(3) KmdKit
    http://www.freewebs.com/four-f/
(4) KmdTut 中文翻译
    http://asm.yeah.net

远程线程的创建步骤(附源码) (1)用VirtualAllocEx函数在远程进程的地址空间中分配一块内存。(2)用WriteProcessMemory函数反映Dll的路径名复制到第1步分配的内存中(3)用GetProcAddress函数来得到LoadLibrary W(或A)函数在Kernel32.dll的真实地址。(4)用CreateRemoteThread函数在远程进程中创建一个线程,让新线程调用正确的LoadLibrar... 阅读详情

相关推荐

QQ盗号核心编程

平台:windows xp sp2;  软件:QQ2005版。  申明:本文旨在技术交流。  一。先讲几句废话:  经常有听到有朋友QQ被盗的消息,总感觉做出这种行为的人是可鄙的,不就是对QQ窗口进行监视,然后再是记录用户输入的号码和密码,认为没什么了不起。  对于Windows核心编程,本人还是一只菜鸟,前一段时间把《Windows系统编程》粗略的看一边(当然重点地方仔细的看),由于

dkxyl666的专栏 766

基于PsSetLoadImageNotifyRoutine实现监控模块加载并卸载已加载模块(卸载DLL、EXE和sys等加载)

背景 对于内核层实现监控模块的加载,包括加载DLL模块、内核模块等。你也许会想到 HOOK 各种内核函数来实现。确定,在内核层中的 HOOK 已经给人留下太多深刻的印象了,有 SSDT HOOK、Inline HOOK、IRP HOOK、过滤驱动等等。 但是,Windows 其实给我们提供现成的内核函数接口,方便我们在内核下监控用户层上模块加载的情况,即 PsSetLoadImageNotifyRoutine 内核函数,可以设置一个回调函数,来监控监控模块加载。 现在,本文就使用 PsSetLoadI

苞米地里捉小鸡的博客 4602

扩展内核函数 PsSetCreateProcessNotifyRoutine 等的蹲坑数量

扩展内核函数 PsSetCreateProcessNotifyRoutine 等的蹲坑数量

进程挂靠后使用PsGetCurrentProcessId获取的进程ID不准

如题,在使用KeStackAttachProcess挂靠到目标进程后,又调用了一系列子函数,此时并没有把EPROCESS传进去。 PEPROCESS pProcess = NULL; KAPC_STATE apc; NTSTATUS status = PsLookupProcessByProcessId((HANDLE)pid, &pProcess); if (NT_SUCCESS(status)) { KeStackAttachProcess(pProcess, &apc);

Sven的忘却日记 2226

树莓派4B安装 ubuntu20.04 & VNC远程桌面 & 安装ROS noetic

树莓派4B安装ubuntu20.04 & VNC远程桌面1、安装ubuntu方式1:下载Imager文件。方式2:下载镜像文件。2、查询树莓派 IP 地址3、使用ssh远程登录树莓派4、更新源地址5、更新6、安装桌面环境7、允许root登陆8、登陆远程桌面9、设置中文 1、安装ubuntu 方式1:下载Imager文件。...

weixin_44415639的博客 2万+

摩尔线程GPU实战:5分钟搞定AI模型部署(含Docker避坑指南)

本文详细介绍了摩尔线程GPU在AI模型部署中的实战应用,包括环境配置、Docker避坑指南及性能优化技巧。通过5分钟快速部署指南,帮助开发者高效利用摩尔线程GPU进行AI模型推理,特别针对常见兼容性问题提供解决方案,显著提升部署效率。

weixin_28736335的博客 454

监视远程线程的创建[收藏]

监视远程线程的创建作者: 一块三毛钱邮件: zhongts@163.com日期: 2004.12.29    远程线程技术被大量的使用在木马、蠕虫等软件当中,通过在别的进程中插入线程的方式运行代码,具有相当高的隐蔽性。比如常见的 Explorer.exe 进程中有十几个线程同时运行,在其中插入一个线程后,谁也分辨不出来哪个就是插入的远程线程。本文提供了一种方法可以监视远程线程的创建活动,记录下来远

Purpleendurer@优快云 2325

大语言模型原理与工程实践:行业大语言模型的评测:以金融行业大语言模型为例

大语言模型、金融行业、模型评测、自然语言处理、深度学习、Transformer、BERT、GPT 1. 背景介绍 近年来,大语言模型(Large Language Model,LLM)在自然语言处理(Natural Language Processing,NLP)领域取得了突破性的进

AI大模型应用之禅 137

(转载)监视远程线程的创建

作者: 一块三毛钱邮件: zhongts@163.com日期: 2004.12.29    远程线程技术被大量的使用在木马、蠕虫等软件当中,通过在别的进程中插入线程的方式运行代码,具有相当高的隐蔽性。比如常见的 Explorer.exe 进程中有十几个线程同时运行,在其中插入一个线程后,谁也分辨不出来哪个就是插入的远程线程。本文提供了一种方法可以监视远程线程的创建活动,记录下来远程线程的 ID 等

Kendiv's Box 2427

看完这篇你就能讲解LLC软开关:一文秒懂 ZVS 和 ZCS 到底啥意思!

想要 MOS 管ZVS 好实现➜ 把工作频率保持在 fr1 或更高。想让整流二极管也ZCS 实现➜ 频率就别高过 fr1。设计磁性元件时,一定要计算好 Lr、Lm、Cr 的值,这直接决定你 fr、fr1 是多少!LLC 的软开关技术不是“魔法”,是电感电容+频率控制的精妙组合;fr1 就像黄金分割点,整流和开关都能“刚刚好”;不是所有软开关都能同时实现,要看你在频率曲线的哪一段!

weixin_43199439的博客 1542

Rockchip eMMC寿命监控:SMART信息读取与预防性维护

擦写计数坏块数量温度使用时间。

小灰灰的博客 766

枚举和移除进程和线程回调

进程回调可以监视进程的创建和退出,这个在前面的章节已经讲过了。 某些游戏保护的 驱动喜欢用这个函数来监视有没有黑名单中的程序运行,如果运行则阻止运行或者把游戏退 出。而线程回调则通常用来监控远程线程的建立,如果发现有远程线程注入到了游戏进程里, 则马上把游戏退出。 我们注册的进程回调,会存储在一个名为 PspCreateProcessNotifyRoutine 的数组里。 PspCreatePr...

liuhaidon1992的博客 898

pytorch搭建SSAE实现预测分类代码模板完整代码

pytorch搭建SSAE实现预测分类代码模板完整代码

325

API Hook完全手册

1 基本原理<br />API Hook是什么我就不多说了,直接进入正题。API Hook技术主要有下面的技术难点:<br />1.     如何将自己的的代码Inject到其他进程<br />2.     如何Hook到API1.1 代码的Injection<br />常用的方法有:<br />1.     使用注册表HKLM/Software/Microsoft/Windows NT/CurrentVersion/Windows/AppInit_DLLs<br /> <br />这种方法可以指定多个DL

newsony的专栏 359

RK3576 USB3.0 DWC3控制器调试:PHY初始化失败排查指南

DWC3 是 Synopsys 公司推出的 USB3.0/3.1 控制器 IP,支持双角色(DRD)模式,可配置为 Host、Device 或 OTG。

小灰灰的博客 1181

华为OD机考双机位C卷 - 简单的解压缩算法 (Java & Python & JS & GO & C++ & C)

华为OD机考双机位C卷 - 简单的解压缩算法 , 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 130

JProfiler 入门教程(提供下载PDF)

伦理片 http://www.gxuy.com/     《JProfiler 入门教程》 V1.0  适用于JProfiler 7.1.2 目录 一、JProfiler 介绍    4 二、启动JProfiler 7    4 2.1 Quick Start菜单    4 2.2 Srart Center菜单    5 2.2.1 Srart Cent

光线技术博客 986

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

API Hook

API Hook完全手册1 基本原理<br />API Hook是什么我就不多说了,直接进入正题。API Hook技术主要有下面的技术难点:<br />1.     如何将自己的的代码Inject到其他进程<br />2.     如何Hook到API1.1 代码的Injection<br />常用的方法有:<br />1.     使用注册表HKLM/Software/Microsoft/Windows NT/CurrentVersion/Windows/AppInit_DLLs<br /> <br />

emad1211的专栏 383

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

深入编程之QQ盗号核心代码

经常有听到有朋友QQ被盗的消息,总感觉做出这种行为的人是可鄙的,不就是对QQ窗口进行监视,然后再是记录用户输入的号码和密码,认为没什么了不起。 对于Windows核心编程,本人还是一只菜鸟,前一段时间把《Windows系统编程》粗略的看一边(当然重点地方仔细的看),由于对于C++有点基础,感觉学起来比较容易上手。但到了这两天真正实践的时候,遇到了各种各样的问题。即使一个小小的问题都足以让我...

java开发指南博客 【转载】 3201

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

上一篇: 查询规则表达式的网站
下一篇: stlsoft更新为1.81版本
pll621
博客等级 码龄25年 27粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值