安全矩阵

 找回密码
 立即注册
搜索
查看: 2778|回复: 0

windows ALPC内核拦截的方法

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2022-1-3 19:23:53 | 显示全部楼层 |阅读模式
原文链接:windows ALPC内核拦截的方法

前言ALPC这玩意挺复杂的,现在的安全软件应该都是在r3下hook services来实现的,比如
@FaEry
https://bbs.pediy.com/thread-251158.htm写的
但是r3下挂会遇到PPL问题
https://bbs.pediy.com/thread-250446.htm
所以才有了今天的文章
内核可以的挂钩方法直接内联hook -PG
找指针改地址,做DKOM -安全软件不应该这样做
由于ALPC_PORT是object回调,因此挂object 的情况下,win7可以,win8以上直接PG并且只能拦得到创建但是不能拦得到ALPC交换的过程
IO挂钩 -本文的方法
最开始我是自己逆向ALPC时候偶然发现的,后来搜了一下外网,老外
http://www.zer0mem.sk/?p=542
也找到了一个一样的方法,不过他的研究比我深入一点
为什么能挂上
NtAlpcSetInformation->AlpcpInitializeCompletionList->AlpcpAllocateCompletionPacketLookaside
中可以看到

这是一个IO回调,可以通过设置微软允许的IOComplateCallback来做一些操作
怎么挂钩首先我们要知道内核里面有个全局的双向链表是叫做nt!alpclist 根据zeromem的说法是
虽然这玩意不公开,但是有个公开结构AlpcPortObjectType是跟他在一起的,定位到AlpcPortObjectType再定位到它就行

请注意这是一个坑,因为这个方法win7好使,仅限于win8之前,win8后,这玩意就成这样的布局了:

因此我们再也无法通过公开的AlpcPortObjectType再拿到信息了,只能找特征码:
\x48\xCC\xCC\xCC\xCC\xCC\xCC\x48\xCC\xCC\xCC\xCC\xCC\xCC\x48\xCC\xCC\xCC\xCC\xCC\xCC\x48\xCC\xCC\xCC\xCC\xCC\xCC\xCC自己找,别抄.....那个alpclistlock也是一样,特征码处理
挂钩我们需要干什么:
  1. 1. 遍历alpclist
  2. 2. 找到这个ALPC是否是我们的需要挂钩的进程(比如services.exe)
  3. 3. 设置IO回调挂钩
复制代码


首先记得锁一下:
  1. if (_interlockedbittestandset64((__int64*)&gAlpcpPortListLock, 0))
  2.         ExfAcquirePushLockShared((PULONG_PTR)&gAlpcpPortListLock);
复制代码


然后是遍历这个双向链表
  1. PLIST_ENTRY pLink = NULL;
  2.     for (pLink = gAlpcpPortList->Flink; pLink != (PLIST_ENTRY)&gAlpcpPortList->Flink; pLink = pLink->Flink)
  3.     {

  4.         _ALPC_PORT* alpcPort = CONTAINING_RECORD(pLink, _ALPC_PORT, PortListEntry);
复制代码


其中ALPC_PORT结构每个版本都在变
  1. struct _ALPC_PORT
  2. {
  3.     struct _LIST_ENTRY PortListEntry;                                       //0x0
  4.     struct _ALPC_COMMUNICATION_INFO* CommunicationInfo;                     //0x10
  5.     struct _EPROCESS* OwnerProcess;                                         //0x18
  6.     VOID* CompletionPort;                                                   //0x20
  7.     VOID* CompletionKey;                                                    //0x28
  8.     struct _ALPC_COMPLETION_PACKET_LOOKASIDE* CompletionPacketLookaside;    //0x30
  9.     VOID* PortContext;                                                      //0x38
  10.     struct _SECURITY_CLIENT_CONTEXT StaticSecurity;                         //0x40
  11.     struct _LIST_ENTRY MainQueue;                                           //0x88
  12.     struct _LIST_ENTRY PendingQueue;                                        //0x98
  13.     struct _LIST_ENTRY LargeMessageQueue;                                   //0xa8
  14.     struct _LIST_ENTRY WaitQueue;                                           //0xb8
  15.     union
  16.     {
  17.         struct _KSEMAPHORE* Semaphore;                                      //0xc8
  18.         struct _KEVENT* DummyEvent;                                         //0xc8
  19.     };
  20.     struct _ALPC_PORT_ATTRIBUTES PortAttributes;                            //0xd0
  21.     struct _EX_PUSH_LOCK Lock;                                              //0x118
  22.     struct _EX_PUSH_LOCK ResourceListLock;                                  //0x120
  23.     struct _LIST_ENTRY ResourceListHead;                                    //0x128
  24.     struct _ALPC_COMPLETION_LIST* CompletionList;                           //0x138
  25.     struct _ALPC_MESSAGE_ZONE* MessageZone;                                 //0x140
  26.     struct _CALLBACK_OBJECT* CallbackObject;                                //0x148
  27.     VOID* CallbackContext;                                                  //0x150
  28.     struct _LIST_ENTRY CanceledQueue;                                       //0x158
  29.     volatile LONG SequenceNo;                                               //0x168
  30.     union
  31.     {
  32.         struct
  33.         {
  34.             ULONG Initialized : 1;                                            //0x16c
  35.             ULONG Type : 2;                                                   //0x16c
  36.             ULONG ConnectionPending : 1;                                      //0x16c
  37.             ULONG ConnectionRefused : 1;                                      //0x16c
  38.             ULONG Disconnected : 1;                                           //0x16c
  39.             ULONG Closed : 1;                                                 //0x16c
  40.             ULONG NoFlushOnClose : 1;                                         //0x16c
  41.             ULONG ReturnExtendedInfo : 1;                                     //0x16c
  42.             ULONG Waitable : 1;                                               //0x16c
  43.             ULONG DynamicSecurity : 1;                                        //0x16c
  44.             ULONG Wow64CompletionList : 1;                                    //0x16c
  45.             ULONG Lpc : 1;                                                    //0x16c
  46.             ULONG LpcToLpc : 1;                                               //0x16c
  47.             ULONG HasCompletionList : 1;                                      //0x16c
  48.             ULONG HadCompletionList : 1;                                      //0x16c
  49.             ULONG EnableCompletionList : 1;                                   //0x16c
  50.         } s1;                                                               //0x16c
  51.         ULONG State;                                                        //0x16c
  52.     } u1;                                                                   //0x16c
  53.     struct _ALPC_PORT* TargetQueuePort;                                     //0x170
  54.     struct _ALPC_PORT* TargetSequencePort;                                  //0x178
  55.     struct _KALPC_MESSAGE* volatile CachedMessage;                          //0x180
  56.     ULONG MainQueueLength;                                                  //0x188
  57.     ULONG PendingQueueLength;                                               //0x18c
  58.     ULONG LargeMessageQueueLength;                                          //0x190
  59.     ULONG CanceledQueueLength;                                              //0x194
  60.     ULONG WaitQueueLength;                                                  //0x198
  61. };
复制代码


之后判断进程合法性:
  1. if (!alpcPort->OwnerProcess ||
  2.             PsGetProcessId((PEPROCESS)alpcPort->OwnerProcess) != TargetPrcessId ||
  3.             !alpcPort->CompletionPort)
  4.             continue;
复制代码


然后就是设置回调了
  1. void* IoMiniCompletPtr = IoAllocateMiniCompletionPacket(ALPC_NotifyCallback, alpcPort);
  2.         if (IoMiniCompletPtr == NULL)
  3.         {
  4.             __debugbreak();
  5.             return;
  6.         }
  7.         IoSetIoCompletionEx(
  8.             alpcPort->CompletionPort,
  9.             alpcPort->CompletionKey,
  10.             nullptr,
  11.             NULL,
  12.             NULL,
  13.             FALSE,
  14.             IoMiniCompletPtr);
复制代码


这个IoAllocateMiniCompletionPacket和他的结构我是自己IDA逆向推导出来的,因为没公开,没任何可靠的信息
  1. struct _IO_MINI_COMPLETION_PACKET_USER
  2. {
  3.     struct _LIST_ENTRY ListEntry;                                           //0x0
  4.     ULONG PacketType;                                                       //0x10
  5.     VOID* KeyContext;                                                       //0x18
  6.     VOID* ApcContext;                                                       //0x20
  7.     LONG IoStatus;                                                          //0x28
  8.     ULONGLONG IoStatusInformation;                                          //0x30
  9.     VOID(*MiniPacketCallback)(struct _IO_MINI_COMPLETION_PACKET_USER* arg1, VOID* arg2); //0x38
  10.     VOID* Context;                                                          //0x40
  11.     UCHAR Allocated;                                                        //0x48
  12. };

  13. /*
  14. 这两玩意是我IDA逆向看的,微软也没说
  15. PAGE:00000001402C807C                                     IoAllocateMiniCompletionPacket proc near
  16. PAGE:00000001402C807C                                                     ; CODE XREF: AlpcpAllocateCompletionPacketLookaside+82↑p
  17. PAGE:00000001402C807C                                                     ; NtCreateWorkerFactory+179↓p
  18. PAGE:00000001402C807C                                                     ; DATA XREF: ...
  19. PAGE:00000001402C807C
  20. PAGE:00000001402C807C                                     arg_0           = qword ptr  8
  21. PAGE:00000001402C807C
  22. PAGE:00000001402C807C 48 89 5C 24 08                                      mov     [rsp+arg_0], rbx
  23. PAGE:00000001402C8081 57                                                  push    rdi
  24. PAGE:00000001402C8082 48 83 EC 20                                         sub     rsp, 20h
  25. PAGE:00000001402C8086 48 8B DA                                            mov     rbx, rdx
  26. PAGE:00000001402C8089 33 D2                                               xor     edx, edx
  27. PAGE:00000001402C808B 48 8B F9                                            mov     rdi, rcx
  28. PAGE:00000001402C808E 8D 4A 03                                            lea     ecx, [rdx+3]
  29. PAGE:00000001402C8091 E8 AA 9C 03 00                                      call    IopAllocateMiniCompletionPacket
  30. PAGE:00000001402C8096 48 85 C0                                            test    rax, rax ; 【rax = 分配的io包结构】
  31. PAGE:00000001402C8099 74 0C                                               jz      short loc_1402C80A7
  32. PAGE:00000001402C809B 48 89 78 38                                         mov     [rax+38h], rdi ; 【0x38 = _IO_MINI_COMPLETION_PACKET_USER->MiniPacketCallback】
  33. PAGE:00000001402C809F 48 89 58 40                                         mov     [rax+40h], rbx ; 【0x40 = _IO_MINI_COMPLETION_PACKET_USER->Context】
  34. PAGE:00000001402C80A3 C6 40 48 01                                         mov     byte ptr [rax+48h], 1
  35. PAGE:00000001402C80A7
  36. PAGE:00000001402C80A7                                     loc_1402C80A7:  ; CODE XREF: IoAllocateMiniCompletionPacket+1D↑j
  37. PAGE:00000001402C80A7 48 8B 5C 24 30                                      mov     rbx, [rsp+28h+arg_0]
  38. PAGE:00000001402C80AC 48 83 C4 20                                         add     rsp, 20h
  39. PAGE:00000001402C80B0 5F                                                  pop     rdi
  40. PAGE:00000001402C80B1 C3                                                  retn
  41. PAGE:00000001402C80B1                                     IoAllocateMiniCompletionPacket endp
  42. rax = 一个指针
  43. */
  44. typedef void(__fastcall* MINIPACKETCALLBACK)(
  45.     __in _IO_MINI_COMPLETION_PACKET_USER* miniPacket,
  46.     __inout void* context
  47.     );
  48. extern "C" {
  49.     NTKERNELAPI
  50.         void*
  51.         NTAPI IoAllocateMiniCompletionPacket(
  52.             __in MINIPACKETCALLBACK miniPacketCallback,
  53.             __in const void* context
  54.         );

  55.     NTKERNELAPI
  56.         void
  57.         NTAPI IoSetIoCompletionEx(
  58.             __inout void* completitionPort,
  59.             __in const void* keyContext,
  60.             __in const void* apcContext,
  61.             __in ULONG_PTR ioStatus,
  62.             __in ULONG_PTR ioStatusInformation,
  63.             __in bool allocPacketInfo,
  64.             __in const void* ioMiniCoompletitionPacketUser
  65.         );

  66.     NTSYSAPI
  67.         NTSTATUS
  68.         NTAPI
  69.         ZwQuerySystemInformation(
  70.             IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  71.             OUT PVOID SystemInformation,
  72.             IN ULONG SystemInformationLength,
  73.             OUT PULONG ReturnLength OPTIONAL
  74.         );

  75.     NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(
  76.         _In_ PVOID Base
  77.     );
  78.     NTKERNELAPI
  79.         void*
  80.         NTAPI IoFreeMiniCompletionPacket(
  81.             __in const void* miniPacket
  82.         );
  83. }
复制代码


挂钩后,我们顺利得到信息


解码ALPC_PORT信息ALPC这个只是一个标准协议,每个不同的服务比如 创建服务与创建账号与搜索系统信息 等的具体内容都是不同的,要自己手动解码,但是在这里如zeroman所说,这个keycontext带了一个叫做SubProcessTag的东西,这个东西就对应这个RPC所带的服务(其实不是ALPC传过来的),就可以拿到基本的,某进程发了RPC给某进程,并且RPC是关于xxx服务的,但是服务的具体信息比如名字啥的
具体解码禁止抄作业
其他的参考:
https://bbs.pediy.com/thread-268225.htm#msg_header_h1_7
https://blog.csdn.net/weixin_43787608/article/details/84555474
https://bbs.pediy.com/thread-251158.htm
http://www.zer0mem.sk/?p=542


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-23 15:21 , Processed in 0.014112 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表