系统回调介绍

目的:

遍历系统中的回调

类型:

与Xuetr遍历到的类型相同

如有雷同,还望见谅。。。有错误或者不恰当的地方请指正。

附件中代码大量冗余,可以将相同的部分写成一个函数,一开始没注意,懒得改了。。。

详细实现见代码

环境:

WIN XP SP3   大量使用硬编码,本次仅在于实现我的虚拟机环境下的遍历,没有考虑寻找通用方法。

参考资料:1、WRK 1.2

2、React OS

3、标 题:替换进程创建监视函数

作 者:鹿剑

链 接:http://bbs.pediy.com/showthread.php?t=93759

将包括:

1.创建进程、创建线程、加载模块回调

2.注册表回调

3.错误检测回调

4.Lego回调

5.关机回调

6.注销回调

7.文件系统改变回调

8.即插即用回调(还未完成,忘大家给些提示,我好补充完整)

8.已经完成,见下面:(从2000里面抄抄捡捡,大牛莫笑。。。

其实实现起来都差不多,一个链表头串起来,好几种只是结构不同而已

1、创建进程、创建线程、加载模块回调

(1)创建进程回调

注册创建进程回调使用函数 PsSetCreateProcessNotifyRoutine,调用这个函数会将注册的信息保存到一个数组里面。

反汇编这个函数,会发现以下片段:

代码:

805d0c27 56              push    esi
805d0c28 57              push    edi
805d0c29 7464            je      nt!PsSetCreateProcessNotifyRoutine+0x73 (805d0c8f)
805d0c2b bf404a5680      mov     edi,offset nt!PspCreateProcessNotifyRoutine (80564a40)   
805d0c30 57              push    edi

PspCreateProcessNotifyRoutine (80564a40)即这个数组的地址,这个数组是以下结构:
ypedef struct _EX_FAST_REF
{
    union
    {
        PVOID Object;
        ULONG_PTR RefCnt:3;
        ULONG_PTR Value;
    };
} EX_FAST_REF, *PEX_FAST_REF;

低三位RefCnt是引用指针,Value指向一个结构,如下:
typedef struct _EX_CALLBACK_ROUTINE_BLOCK
{
    EX_RUNDOWN_REF RundownProtect;
    PEX_CALLBACK_FUNCTION Function;
    PVOID Context;
} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

可以看到保存了回调函数的地址

因而采用搜索数组的方式在进行遍历即可,因为在WIN XP SP3中数组元素为8个,所以遍历的时候就按八个来的,WIN 7就不是了

(2)创建线程和加载模块分别是PsSetCreateThreadNotifyRoutine,PsSetLoadImageNotifyRoutine函数 其原理一样,略过。。。

(3)卸载方法参考 http://blog.csdn.NET/whatday/article/details/13354031

2、注册表回调

一开始真不知道哪个函数是注册注册表回调,尝试着在MSDN以cm(Xuetr回调类型里就是cmpCallBack)开头看到了CmRegisterCallback,大致看了一下,跟上面的原理一样。。不过是不是八个元素没注意,按八个处理的

3、错误检测回调

函数是:

KeRegisterBugCheckCallback

KeRegisterBugCheckReasonCallback

反汇编KeRegisterBugCheckCallback :

代码:

804fa138 c7400458d75580  mov     dword ptr [eax+4],offset nt!KeBugCheckCallbackListHead (8055d758)

又一个链表头,查看WRK ,这里没有考虑WRK与WIN XP 在该函数上可能的差异。。。得到以下信息:

/

代码:

*
NTKERNELAPI
BOOLEAN
KeRegisterBugCheckCallback (
    __out PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
    __in PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
    __in PVOID Buffer,
    __in ULONG Length,
    __in PUCHAR Component
    )
typedef struct _KBUGCHECK_CALLBACK_RECORD {
    LIST_ENTRY Entry;
    PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine;
    PVOID Buffer;
    ULONG Length;
    PUCHAR Component;
    ULONG_PTR Checksum;
    UCHAR State;
} KBUGCHECK_CALLBACK_RECORD, *PKBUGCHECK_CALLBACK_RECORD;

LIST_ENTRY KeBugCheckCallbackListHead;
LIST_ENTRY KeBugCheckReasonCallbackListHead;

结构类型就很清楚了,得到链表头,按照双向链表便利即可

4、Lego回调

刚从XUETR里面看到这个还真不知道是什么,搜索一番后,得到了MJ的一些说明:

ULONG PsSetLegoNotifyRoutine(PVOID notifyroutine)

notifyroutine为需要设置的回调函数地址

返回值是_ETHREAD->Tcb->LegoData的偏移量

调用此函数,系统会将一个未导出的全局变量_PspLegoNotifyRoutine设置为你设定的回调函数地址

当一个线程的_ETHREAD->Tcb->LegoData不为空,且_PspLegoNotifyRoutine不为空,那么当这个线程调用PspExitThread退出时,会调用PspLegoNotifyRoutine中的回调函数

系统中只允许设置一个这样的回调函数

有人跟着给出具体结构和定义:

代码:

typedef VOID (*PLEGO_NOTIFY_ROUTINE)( PKTHREAD Thread );
ULONG PsSetLegoNotifyRoutine( PLEGO_NOTIFY_ROUTINE LegoNotifyRoutine ) 
{ 
    PAGED_CODE(); 
    PspLegoNotifyRoutine = LegoNotifyRoutine; 
    return FIELD_OFFSET(KTHREAD,LegoData); 
} 

硬编码搜索到这个全局变量,查看地址是否为0即可(不知是否有误,或者加上地址有效检测?)

代码:

nt!PsSetLegoNotifyRoutine:
805d299a 8bff            mov     edi,edi
805d299c 55              push    ebp
805d299d 8bec            mov     ebp,esp
805d299f 8b4508          mov     eax,dword ptr [ebp+8]
805d29a2 a3c0d26780      mov     dword ptr [nt!PspLegoNotifyRoutine (8067d2c0)],eax//这里
805d29a7 b8d0000000      mov     eax,0D0h
805d29ac 5d              pop     ebp
805d29ad c20400          ret     4

5、关机回调

有两个函数:

IoRegisterShutdownNotification

IoRegisterLastChanceShutdownNotification

来看第一个:

相关结构和定义也是参考了WRK。。。。

代码:

LIST_ENTRY IopNotifyShutdownQueueHead;
LIST_ENTRY IopNotifyLastChanceShutdownQueueHead;

typedef struct _SHUTDOWN_PACKET {
    LIST_ENTRY ListEntry;
    PDEVICE_OBJECT DeviceObject;
} SHUTDOWN_PACKET, *PSHUTDOWN_PACKET;

要得到回调函数地址,需要得到设备对象,回调函数地址即IRP_MJ_SHUTDOWN的例程地址

//#define IRP_MJ_SHUTDOWN                 0x10

代码如下:

代码:

ULONG GetNotifyAddr(PDEVICE_OBJECT Device_Object)
{
  ULONG Addr;
  PDRIVER_OBJECT Driver_Object;
  Driver_Object=Device_Object->DriverObject;
  Addr=*(ULONG*)((ULONG)Driver_Object+0x38+0x40);
  return Addr;
}

6、注销回调

搜了N久也不知道是哪个函数,于是看了看Xuetr,只有mrxsmb.sys注册了注销回调,查看其导入表看看有没有跟注册相关的字眼,于是找到了SeRegisterLogonSessionTerminatedRoutine

,查了一下,果然是。

也是一个链表头的形式,相关结构和定义:

代码:

typedef NTSTATUS (*PSE_LOGON_SESSION_TERMINATED_ROUTINE) (
  IN PLUID LogonId
  );
typedef struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION {
    struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION *Next;
    PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine;
} SEP_LOGON_SESSION_TERMINATED_NOTIFICATION, *PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION;

NTSTATUS
SeRegisterLogonSessionTerminatedRoutine(
    IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
    );

7、文件系统改变回调

相关的注册函数是:IoRegisterFsRegistrationChange

结构:

代码:

typedef struct _NOTIFICATION_PACKET 
{
    LIST_ENTRY ListEntry;
    PDRIVER_OBJECT DriverObject;
    ULONG NotificationRoutine;
} NOTIFICATION_PACKET, *PNOTIFICATION_PACKET;

8、即插即用回调

(1)注册的函数应该是IoRegisterPlugPlayNotification(由于搞不定,我都开始怀疑了。。。)

一开始想用上面的方法找到链表头,遍历链表即可,但是发现结果不对。。。

我找的是IopDeferredRegistrationList,是不是找错了?

WRK里面没有这个函数的实现,于是翻了翻React OS,找到参考的代码有这么几句:

代码:

InsertHeadList(&PnpNotifyListHead, &Entry->PnpNotifyList);
KeReleaseGuardedMutex(&PnpNotifyListLock);
DPRINT("IoRegisterPlugPlayNotification() returns NotificationEntry %p\n",
        Entry);
*NotificationEntry = Entry;

其中相关结构:

代码:

typedef struct _PNP_NOTIFY_ENTRY
{
    LIST_ENTRY PnpNotifyList;
    IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
    PVOID Context;
    UNICODE_STRING Guid;
    PFILE_OBJECT FileObject;
    PDRIVER_NOTIFICATION_CALLBACK_ROUTINE PnpNotificationProc;
} PNP_NOTIFY_ENTRY, *PPNP_NOTIFY_ENTRY;

结果完全对不上。。。。。从ntoskrnl.exe中找到这个函数,无奈逆向太烂看不出来将注册信息保存到哪了。。。貌似是一个常量指向的地址。。。

(2)从函数实现来看,注册成功后,将相关结构的地址返回了,如果按照React OS的做法,这个结构是在整个链表里面的,结果自己注册了一个回调打算进行遍历,还是不行。。。。

还望大家指点。。。

其余结果都能和Xuetr对得上

8.即插即用回调

今天下了一份2000源代码回来,找到了IoRegisterPlugPlayNotification函数的实现部分,发现了一个链表IopDeviceClassNotifyList,用Windbg查看这个链表,得到如下信息:

|------------------------|

1.8067d080 -> e1dd7698 ->--^

8067d080 <- e1dd7698 <----

|________________________|

|------------------------------------------------|

2.e1336d98 -> e1036468 -> e1307548 -> 8067d090 ->--^

e1307548 <- 8067d090 <- e1336d98 <- e1036468 <----

|________________________________________________|

|------------------------------------------------|

4.e1000888 -> e1f58478 -> e1bc04a0 -> 8067d0a0 ->--^

e1bc04a0 <- 8067d0a0 <- e1000888 <- e1f58478 <----

|________________________________________________|

|------------------------|

5.e1537858 -> 8067d0a8 ->--^

e1537858 <- 8067d0a8 <----

|________________________|

|------------------------|

6.e156e7c8 -> 8067d0b0 ->--^

e156e7c8 <- 8067d0b0 <----

|________________________|

|------------------------|

10.e1315d60 -> 8067d0d0 ->--^

e1315d60 <- 8067d0d0 <----

|________________________|

|------------------------------------------------|

11.e1002ad8 -> e156fc48 -> e1301258 -> 8067d0d8 ->--^

e1301258 <- 8067d0d8 <- e1002ad8 <- e156fc48 <----

|________________________________________________|

|------------------------------------------------------------|

12.e1023c40 -> e131ae08 -> e101ea20 -> e1f752c8 -> 8067d0e0 ->--^

e1f752c8 <- 8067d0e0 <- e1023c40 <- e131ae08 <- e101ea20 <----

|____________________________________________________________|

一共17个,正好跟Xuetr对应上

而参照2000代码,IopDeviceClassNotifyList是一个具有13个(XP也是)元素的数组,每个都是一个链表,数据格式:

代码:

typedef struct _SETUP_NOTIFY_DATA
 {
    LIST_ENTRY ListEntry;
    IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
    PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
    PVOID Context;
    PDRIVER_OBJECT DriverObject;
    USHORT RefCount;
    BOOLEAN Unregistered;
    PFAST_MUTEX Lock;
} SETUP_NOTIFY_DATA, *PSETUP_NOTIFY_DATA;

但是偏移跟实际的对不上。。。应该有所更改了

通过计算注册时提供的ClassGuid得到不同的hash值,hash值相同的串在一个链表里

但是技术太烂,WinDbg在u IoRegisterPlugPlayNotification里面没看到IopDeviceClassNotifyList数组,但是发现还有一个函数:IopInitializePlugPlayNotification   这个函数没有导出,我用了最烂的方法,遍历内核模块空间,根据特征码得到函数地址

代码:

/*
nt!IopInitializePlugPlayNotification:
8058a5b4 6a0d            push    0Dh
8058a5b6 b880d06780      mov     eax,offset nt!IopDeviceClassNotifyList (8067d080)  
8058a5bb 59              pop     ecx
8058a5bc 894004          mov     dword ptr [eax+4],eax
*/

再得到IopDeviceClassNotifyList 数组地址,遍历即可。。。

另外有一个问题:

其中的一个PCALLBACK_RECORD:

代码:

0: kd> dd e1dd7698
e1dd7698  8067d080 8067d080 00000002 00000000
e1dd76a8  00000000 b2884fcc 00000000 81c26b10

  kd> dt _driver_object 81c26b10
nt!_DRIVER_OBJECT
   +0x000 Type             : 4
   +0x002 Size             : 168
   +0x004 DeviceObject     : 0x81b332d0 _DEVICE_OBJECT
   +0x008 Flags            : 0x10
   +0x00c DriverStart      : 0xf8ba4000 
   +0x010 DriverSize       : 0x1100
   +0x014 DriverSection    : 0x81f317c0 
   +0x018 DriverExtension  : 0x81c26bb8 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\swenum"
   +0x024 HardwareDatabase : 0x8067e260 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null) 
   +0x02c DriverInit       : 0xf8ba48dd     long  swenum!GsDriverEntry+0
   +0x030 DriverStartIo    : (null) 
   +0x034 DriverUnload     : 0xf8ba432a     void  swenum!DriverUnload+0
   +0x038 MajorFunction    : [28] 0xf8ba4768     long  swenum!DispatchCreate+0

而用XUETR得到的结果是属于sysaudio.sys模块。。。。。:

最后附代码,硬编码:

代码:

NTSTATUS GetPlugPlayCallBack(ULONG KernelAddress)
{

  //未导出
  UCHAR* Base=KernelAddress;
  ULONG i=0;
  ULONG NotifyAddr;//回调函数地址
  PSETUP_NOTIFY_DATA pPnpNotifyPack;
  PLIST_ENTRY pListEntry;
  PLIST_ENTRY pListNext;
  PULONG Address;
  int count;
  Address=0;
  
  if(KernelAddress!=0)
  {
     for(i=0;i<0x20D000;i++)//内核大小硬编码了
     {
       
      if((*(UCHAR*)Base==0x6a)&&(*(UCHAR*)(Base+1)==0x0d)&&(*(UCHAR*)(Base+2)==0xb8)&&(*(UCHAR*)(Base+7)==0x59)&&(*(UCHAR*)(Base+8)==0x89))
      {
       DbgPrint("找到IopInitializePlugPlayNotification地址%x\n",Base);
       Address=*(ULONG*)(Base+3);
       break;
      }
      Base++;
     }
  }
  
  if(Address==0)
    {
     DbgPrint("获取PlugPlay回调数组失败\n");
       return STATUS_UNSUCCESSFUL;
    }
  DbgPrint("PlugPlay回调数组地址%x\n",(ULONG)Address);
  //13个元素
  for(count=0;count<NOTIFY_DEVICE_CLASS_HASH_BUCKETS*2;count+=2)
  {
    //DbgPrint("PlugPlay回调数组元素%x\n",Address[count]);
        {
      pListEntry=Address[count];
      pListNext=pListEntry;
      if(pListNext->Flink!=pListEntry)
      {
         DbgPrint("回调入口:%X  类型:PlugPlay  包地址:%X\n",*(ULONG*)((PULONG)pListNext+5),pListNext);
         PlugPlayNum++;
      }
      pListNext=pListNext->Flink;
      while(pListNext->Flink!=pListEntry)
      {
        if(pListNext<KernelAddress+0x20D000)
        {  
          pListNext=pListNext->Flink;

            DbgPrint("回调入口:%X  类型:PlugPlay  包地址:%X\n",*(ULONG*)((PULONG)pListNext+5),pListNext);
          pListNext=pListNext->Blink;
        }
        else
        {
          DbgPrint("回调入口:%X  类型:PlugPlay  包地址:%X\n",*(ULONG*)((PULONG)pListNext+5),pListNext);
        }
        PlugPlayNum++;
        pListNext=pListNext->Flink;
      }
    }
  }
   
}

jpg改rar

				
时间: 2024-10-09 10:04:18

系统回调介绍的相关文章

微铺子点单系统详细介绍 - 争做国内最专业的微信商店平台,微信外卖订餐系统!

什么是微铺子? 微铺子是国内专业的微信点单系统,集成了外卖.点餐.订座等众多功能.通过微铺子,店家可以在微信上建立店铺,消费者只需关注店家的帐号,即可浏览商品与店家的信息,消费者关注到商家后,根据提示,进行点击点单,简单三步,15秒内,即可完成订餐.店家可以通过电脑后台.电子邮件.短信或无线打印机多种方式即时查看订单,并提供相应的服务. 微铺子系统适用于:餐饮.酒店.水果店.蛋糕店.花店.零售.超市等. 微铺子从创立到与合作商家的长期测试,再到正式投入商用,期间不断根据客户的需求完善产品,不断开

微信游戏《全民炫舞》公司的引擎开发和布料系统技术介绍

微信<全民炫舞>上线了. 整理了一下过去技术开发历史,还有技术ppt,有兴趣看下: 公司游戏引擎技术介绍: http://www.h3d.com.cn/hr/hr.htm 布料系统技术介绍: 2012 China Game Developer Conference大会演讲资料下载: http://www.h3d.com.cn/hr/downlond/QQX52_CGDC.ppt NVIDIA QQ炫舞2 布料技术演示录像地址: http://www.h3d.com.cn/hr/donnlond

一些开源的统计机器翻译系统简要介绍

最近打算深入了解一下机器翻译系统的具体功能模块,以东北大学的Niutrans为蓝本,其用户手册里有一些对其他开源的统计机器翻译系统的介绍,觉得也不错,就简要地记一下发在这里. Moses:Edinburgh大学SMT小组开发.最新版本的同时支持基于短语的以及基于句法的模型(从短语,规则的提取到解码).提供了分解的翻译模型,使得信息在不同层之间利用.还有混淆网络以及词格作为输入的使用,减弱了在ambiguous upstream 系1-best输出的错误.此外Moses的package提供了很多有

最新最全的Cleanflight 无人机开源代码的系统列介绍

Cleanflight can be used on multirotor aircraft and fixed-wing aircraft, it supports a variety for shapes and motor counts, not limited to quadcopters, hexacopters, octocopters, tricopters and planes. Cleanflight is Open-Source flight controller softw

IOS常用的系统文件目录介绍

iOS常用目录整理说明是本文要介绍的内容,虽然不同API全面,也算是在编程中常用到的存放目录,所以是必备文档,不多说,来看详细内容讲解. 1.[/Applications] 常用软件的安装目录 内建软体及JB软体存放位置 2. [/private /var/ mobile/Media /iphone video Recorder] 录像文件存放目录 3.[/private /var/ mobile/Media /DCIM] 相机拍摄的照片文件存放目录 4.[/private/var/ mobil

微铺子点单系统具体介绍 - 争做国内最专业的微信商店平台,微信外卖订餐系统!

什么是微铺子? 微铺子是国内专业的微信点单系统,集成了外卖.点餐.订座等众多功能.通过微铺子,店家能够在微信上建立店铺,消费者仅仅需关注店家的帐号,就可以浏览商品与店家的信息,消费者关注到商家后,依据提示,进行点击点单,简单三步,15秒内,就可以完毕订餐.店家能够通过电脑后台.电子邮件.短信或无线打印机多种方式即时查看订单,并提供对应的服务. 微铺子系统适用于:餐饮.酒店.水果店.蛋糕店.花店.零售.超市等. 微铺子从创立到与合作商家的长期測试,再到正式投入商用,期间不断依据客户的需求完好产品,

vpay钱包系统开发介绍

vpay钱包系统开发介绍 找 182^00*99^0522 vpay钱包交易系统开发 vpay区块链系统搭建 区块链技术注定会改变世界: 虽然区块链技术"只不过是一个不可篡改的数据库技术",但它注定会改变世界,因为他记录的,不仅是数据,还有人,还有事,乃至整个世界.它承载的,最重要的其实并不是自由,而是希望.面对区块链,你别无选择,只有赤身已对. 区块链可以与人工智能.大数据互相促进发挥更大价值 区块链浪潮的来临并不是要取代互联网,而是让互联网发展得更好,区块链可以作为价值互联网的重要

Hadoop 学习笔记五 ---Hadoop系统通信协议介绍

本文约定: DN: DataNode TT: TaskTracker NN: NameNode SNN: Secondry NameNode JT: JobTracker 本文介绍Hadoop各节点和Client之间通信协议. Hadoop的通信是建立在RPC的基础上,关于RPC的详解介绍大家可以参照 "hadoop rpc机制 && 将avro引入hadoop rpc机制初探" Hadoop中节点之间的通信是比较复杂的一个网络,若可以把它们之间的通信网络了解清楚,那么

PKI系统深入介绍

公钥基础设施(Public Key Infrastructure,简称PKI)是眼下网络安全建设的基础与核心,是电子商务安全实施的基本保障,因此,对PKI技术的研究和开发成为眼下信息安全领域的热点.本文对PKI技术进行了全面的分析和总结,当中包含PKI组成.证书认证机构CA.PKI应用.应用编程接口和PKI标准等,并对CA的开发做了简要分析.本文对PKI,特别是CA的开发.应用和普及具有一定的促进作用. 1 前言 随着网络技术和信息技术的发展,电子商务已逐步被人们所接受,并在得到不断普及.但因为