在 winlogon 和 csrss 进程中具有 RWX 权限的 VAD

逆向工程 视窗 数字取证
2021-06-11 08:18:49

在 VirtualBox VM 内运行的干净的 Windows XP SP2 安装中vboxmangage debugvm --dumpguestcore,在使用 Volatility进行快照和分析时,我总是发现 9 个 VADPAGE_EXECUTE_READWRITE正在winlogon.exe处理权限,1 个 VAD 正在csrss.exe处理相同权限有时也有一个正在explorer.exe处理中。

这对于两台不同的机器是一样的,一台安装了 VirtualBox 工具,另一台没有。

这些是从哪里来的?写权限有什么用?任何帮助都非常感谢,谢谢!

2个回答

以下所有陈述均基于 xp-sp3

WinDbg中也可以用来分析在VadTree RWX页面
复制粘贴以下几行**.txt and run the script $$>a< path to **.txt

脚本内容需要在路径中使用 grep 进行文本解析

aS  proc        @#Process ;
aS  procname    @@c++( (char *)(((nt!_EPROCESS *) @#Process ))->ImageFileName )  ;
aS  procvad     @@c++( (((nt!_EPROCESS *) @#Process ))->VadRoot )  ;
.block { !for_each_process ".printf \"%20ma\t%p\t%p\n\n\",${procname}, ${proc} , ${procvad}; .echo \n;.shell  -ci  \"!vad ${procvad}\"  grep  \"EXECUTE_READWRITE\"" } ;
ad *

然后设置进程上下文以适应进程并检查从 StartVpn 到 EndVpn 的内存

iirc Winlogon 和 csrss 总是有几个 RWX 页面
csrss RWX 页面似乎总是包含大量初始化 _UNICODE_STRING
大多数页面将无法查看您可能需要在 Phase1Init 阶段进行实时调试

sxe ibp;.reboot  

在重新启动设置bp NtCreateProcessEx直到 csrss 即将创建
bc * ; gu ;!vad on csrss _EPROCESS csrss 进程此时不会有 RWX 页面
只有 4 个 vads 将存在于 csrss VadTree
您可能需要从这里开始并捕获分配/写入和执行

           csrss.exe    86acebe0    86d62660  
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped       EXECUTE_READWRITE  Pagefile-backed section

此 oneliner 将获取该页面中的大部分字符串

.foreach (place { s -[1]b 7f6f0000 l?7000 0x7f } ) { r $t0 = place ; dS @$t0-7}

上面一行的输出

7f6f2170  "C:\WINDOWS"
7f6f2190  "C:\WINDOWS\system32"
7f6f21c0  "\BaseNamedObjects"
7f6f2208  ".罯...罯"
7f6f22b0  ".罯...罯"
7f6f221c  "Autorun.inf"
7f6f2300  ".罯02.罯Software\Microsoft\Clock"
7f6f226c  "DoesNotExist"
7f6f2260  ".罯"
7f6f2368  "ヘ罯...罯.罯"
7f6f22c4  "Clock.ini"
7f6f23d8  ".罯68.罯Control Panel\Color Scheme"
7f6f2418  "s"
7f6f230c  "Software\Microsoft\Clock"

winlogon RWX 页面将包含 Executble 代码,其中大多数将以push cx push ax序列开头, 并以对 somehwre 的间接调用结束,jmp eax 一些对不可见/不存在位置的中间调用可能需要实时分析

从未在 clean explorer / iexplore / services.exe 进程中观察到 rwx 页面,它们仅在安装了某些防病毒软件等后才存在

请参阅下面的Avasted RWXexplorer.exe 页面,修补RtlSetCurrentDirectory_U和加载snxhk.dll using LdrLoadDll()相同的补丁也可以在 iexplore.exe 中观察到

.shell dir /b scan*vad*
scanvad4rwx.txt    
lkd> $$>a< scanvad4rwx.txt
              System    86fc6830    86fbfa90     
            smss.exe    86b0e020    86dfd008      
           csrss.exe    86acebe0    86f4e4d0  
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE  Pagefile-backed section    
        winlogon.exe    86d7b918    86d58930  
86ae8ee0 ( 8)       9550     9553         4 Private      EXECUTE_READWRITE 
86340690 ( 7)      29c90    29c93         4 Private      EXECUTE_READWRITE 
86f370d0 ( 6)      2a4f0    2a4f3         4 Private      EXECUTE_READWRITE 
86b13a38 ( 5)      46580    46583         4 Private      EXECUTE_READWRITE 
86da2a00 ( 6)      497c0    497c3         4 Private      EXECUTE_READWRITE 
        services.exe    86b0a020    86ec15c8  
86da7c20 (12)        380      380         1 Private      EXECUTE_READWRITE 
               lsass.exe    86b2a6b8    86b21110  
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        explorer.exe    86241260    86b86768  
86b13d28 (13)         90       90         1 Private      EXECUTE_READWRITE 
86545e50 (11)        2b0      2b0         1 Private      EXECUTE_READWRITE 
86aa6878 (12)        2c0      2ca        11 Private      EXECUTE_READWRITE 
86b056a0 (10)        2d0      2da        11 Private      EXECUTE_READWRITE 
86b3b9c8 (12)        2e0      2ea        11 Private      EXECUTE_READWRITE 
             AvastUI.exe    86315a00    860fc008  
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        iexplore.exe    86aaf020    861b3f00  
862ae9f8 (16)        150      150         1 Private      EXECUTE_READWRITE 

在重读时,我注意到以下输出来自不同的会话,因此拆分

and examine the memory  using  lkd> .process /p /r 862543e8 &   lkd> uf 150000
00150000 50              push    eax
00150001 60              pushad
00150002 bd42001500      mov     ebp,150042h
00150007 8b7d10          mov     edi,dword ptr [ebp+10h]
0015000a 8b4518          mov     eax,dword ptr [ebp+18h]
0015000d 8b5d1c          mov     ebx,dword ptr [ebp+1Ch]
00150010 8907            mov     dword ptr [edi],eax
00150012 895f04          mov     dword ptr [edi+4],ebx
00150015 897c2420        mov     dword ptr [esp+20h],edi
00150019 8d454c          lea     eax,[ebp+4Ch]
0015001c 50              push    eax
0015001d ff7548          push    dword ptr [ebp+48h]
00150020 8d4550          lea     eax,[ebp+50h]
00150023 50              push    eax
00150024 8d4540          lea     eax,[ebp+40h]
00150027 50              push    eax
00150028 6aff            push    0FFFFFFFFh
0015002a ff5508          call    dword ptr [ebp+8]
0015002d 85c0            test    eax,eax
0015002f 750f            jne     00150040    
00150031 33c9            xor     ecx,ecx
00150033 8d4538          lea     eax,[ebp+38h]
00150036 50              push    eax
00150037 8d4528          lea     eax,[ebp+28h]
0015003a 50              push    eax
0015003b 51              push    ecx
0015003c 51              push    ecx
0015003d ff5500          call    dword ptr [ebp]    
00150040 61              popad
00150041 c3              ret

将命令放在一行中

? @$t1+10 ; ? poi(@$t1+10) ; ln poi(@$t1+10); db (@$t1+18) l8; u (@$t1+18)  l3;
? poi(@$t1+4c) ; ? poi(@$t1+48) ; ? poi(@$t1+50) ;? poi(@$t1+40) ;  lm m ntdll* ;
ln poi(@$t1+8) ; ? poi(@$t1+38); db  (@$t1+28) l8; du /c 40 poi(@$t1+2c) ;
? poi(@$t1); ln poi(@$t1);.echo patches RtlSetCurwith pattern and sets return 
address    [esp+20]to patched instruction calls ntvirtproct for a pagein ntdll 
on successloads a dll using LdrLoadDll;   

Evaluate expression: 1376338 = 00150052
Evaluate expression: 2089936810 = 7c91e7aa
(7c91e7aa)       Exact matches: ntdll!RtlSetCurrentDirectory_U
0015005a  6a 6c 68 78 e9 91 7c e8                          jlhx..|.
0015005a 6a6c            push    6Ch
0015005c 6878e9917c      push    offset ntdll!`string'+0x34 (7c91e978)
00150061 e81501ffff      call    0014017b
Evaluate expression: 64 = 00000040
Evaluate expression: 32 = 00000020
Evaluate expression: 4096 = 00001000
Evaluate expression: 2089934848 = 7c91e000
start    end        module name
7c900000 7c9b2000   ntdll      (pdb symbols)          f:\symbols\ntdll.pdb
(7c90d6ee)   Exact matches: ntdll!NtProtectVirtualMemory
Evaluate expression: 1691353088 = 64d00000
0015006a  60 00 60 00 9a 00 15 00                          `.`.....
0015009a  "C:\Program Files\Alwil Software\Avast5\snxhk.dll"
Evaluate expression: 2089903043 = 7c9163c3
(7c9163c3)      Exact matches:    ntdll!LdrLoadDll = <no type information>
patches RtlSetCurwith pattern and sets return address    
[esp+20] to patched instruction calls ntvirtproct for     
a page in ntdll on success loads a dll using LdrLoadDll

更新

CSRSRV 初始化期间正在创建 csrss.exe 中的 rwx 页面似乎是堆

我在 NtAllocateVirtualMemory 上创建 csrss.exe 后设置了一个条件中断,以在每次分配时打印 VadTree
,我看到在 CSRSRV init 时插入了 rwx 页面,并且在调用堆栈中观察到了 CreateSharedSection

sxe ibp;.reboot

在重新启动bp NtCreateprocessEx and hit g;kb直到 csrss.exe 即将创建时,
您可以通过查看传递给 RtlCreateUserProcess api 的 unicode_string 在打印的
dS 应打印的调用堆栈中收集正在创建的进程..................... ...../csrss.exe
回车gu以允许创建进程将进程
!process 0 1 csrss.exe 保存到便笺簿
!vad VadRoot
你应该在 csrss vad 树中观察 4 个 vad

现在设置这个条件断点(substitute the saved eprocess inplace of 0x81160020注意use 0x notation
bp

bp nt!NtAllocateVirtualMemory "!vad @@c++(((nt!_EPROCESS *) 0x81160020)->VadRoot);kb;.echo \n;dd poi(@esp+8);"

如果您坚持访问断点,您可以在将 rwx 页面添加到 ProcessHeapList 时捕获

见下文

ntdll!RtlCreateHeap+0x5b9: 001b:7c9253de e8a6000000 调用 ntdll!RtlpAddHeapToProcessList(7c925489)

kd> !heap HEAPEXT:无法获取 *ntdll!RtlpGlobalTagHeap 的地址。索引地址名称调试选项已启用
1:00160000
2:00260000
kd>

p  step over the call

ntdll!RtlCreateHeap+0x5be: 001b:7c9253e3 8b45e4 mov eax,dword ptr [ebp-1Ch]

kd> !heap

索引地址名称 调试选项已启用
1:00160000
2:00260000
3: 7f6f0000

kd> `!process 0 1 csrss.exe`
PROCESS `81160020`  SessionId: 0  Cid: 01c4    Peb: 7ffde000  ParentCid: 014c
    DirBase: 06e30000  ObjectTable: e14a7f38  HandleCount:  10.
    Image: csrss.exe
    VadRoot `812275c0 Vads 13` 

转储瓦德特里

kd> `!vad 812275c0`
VAD     level      start      end    commit
812201d8 ( 1)          0       ff         0 Private      READWRITE         
812280e8 ( 2)        100      100         1 Private      READWRITE         
81229dd0 ( 3)        110      110         1 Private      READWRITE         
81222a88 ( 4)        120      15f         4 Private      READWRITE         
811f30b8 ( 5)        160      25f         3 Private      READWRITE         
81223b80 ( 6)        260      26f         6 Private      READWRITE         
812275c0 ( 0)      4a680    4a684         2 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\csrss.exe
811f4fd8 ( 2)      75b40    75b4a         2 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\csrsrv.dll
811cced0 ( 1)      7c900    7c9b1         5 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\ntdll.dll
8121f440 ( 3)      `7f6f0    7f7ef         0 Mapped       EXECUTE_READWRITE`  Pagefile-backed section
81167108 ( 2)      7ffb0    7ffd3         0 Mapped       READONLY           Pagefile-backed section
811e1d30 ( 4)      7ffdd    7ffdd         1 Private      READWRITE         
811e21b0 ( 3)      7ffde    7ffde         1 Private      READWRITE         

Total VADs:    13  average level:    3  maximum depth: 6

转储调用堆栈

kd> kb
ChildEBP RetAddr  Args to Child              
0015fda4 75b437b8 00007008 7f6f0000 00100000 ntdll!RtlCreateHeap+0x5be
0015fe28 75b42f9a 001626dd 00000000 00000000 CSRSRV!CsrSrvCreateSharedSection+0x23f
0015ff74 75b430f3 0000000a 001624f0 7c90dc9e CSRSRV!CsrParseServerCommandLine+0x255
0015ff88 4a68115d 0000000a 001624f0 00000005 CSRSRV!CsrServerInitialization+0x95
0015ffa8 4a6818d7 0000000a 001624f0 0016251c csrss!main+0x4f
0015fff4 00000000 7ffde000 000000c8 00000166 csrss!NtProcessStartup+0x1d2

断点列表

kd> bl
 0 e 8058124c     0001 (0001) nt!NtCreateProcessEx
 1 e 805691ea     0001 (0001) nt!NtAllocateVirtualMemory "!vad @@c++(((nt!_EPROCESS *) 0x81160020)->VadRoot);kb;.echo \n;dd poi(@esp+8);"
 2 e 7f6f0000 w 1 0001 (0001)

您可以在链的下方进一步使用 winlogon 来遵循此方法

更新以回答评论

断点@NtAllocateVirtualMemory 没有捕捉到vad 12 的分配,
这是来自vad11 的RWX 分配,我的断点只有在分配vad 13
并打印vadtree 时才击中,我发现vad 增加了2,其中一个是7f6f0000 rwx 页面,所以也许另一种方法用于将 vad 添加到 NtAllocateVirtualMemory 的 vad 树中,有可能需要重置 rwx 而未重置需要调查

我只能确认该页面确实是 HEAP 并且似乎在几乎每个进程中都映射了对所有进程 vad 具有 EXECUTE_READ 权限的进程,除了在它是 RWX 的 csrss 中

lkd> .logopen c:\check7f6f0page.txt
Opened log file 'c:\check7f6f0page.txt'
lkd> !for_each_process ".process /p /r @#Process ; !grep -c \"!vad @@c++( ( ( nt!_EPROCESS *) @#Process )->VadRoot)\" -e \"7f6f0\""
lkd> .logclose
Closing open log file c:\check7f6f0page.txt

结果显示此页面已映射到所有进程

lkd> .shell grep "7f6f0    7f7ef         0 Mapped" c:\check7f6f0page.txt
<.shell waiting 1 second(s) for process>
86d39250 ( 4)      7f6f0    7f7ef         0 Mapped       EXECUTE_READWRITE  Pagefile-backed section
86d39250 ( 4)      7f6f0    7f7ef         0 Mapped       EXECUTE_READWRITE  Pagefile-backed section
86e87fd8 ( 4)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86e87fd8 ( 4)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86b96d10 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86b96d10 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86abfe80 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86abfe80 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86eaf3a8 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86eaf3a8 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86b3fda8 ( 4)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section
86e77b20 ( 2)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ       Pagefile-backed section

并确认构造_HEAP

lkd> dt -r nt!_HEAP 0x7f6f0000
   +0x000 Entry            : _HEAP_ENTRY
      +0x000 Size             : 0xc8
      +0x002 PreviousSize     : 0
      +0x000 SubSegmentCode   : 0x000000c8 Void
      +0x004 SmallTagIndex    : 0x1e ''
      +0x005 Flags            : 0x1 ''
      +0x006 UnusedBytes      : 0 ''
      +0x007 SegmentIndex     : 0 ''
   +0x008 Signature        : 0xeeffeeff
   +0x00c Flags            : 0x7008
   +0x010 ForceFlags       : 8
   +0x014 VirtualMemoryThreshold : 0xfe00
   +0x018 SegmentReserve   : 0x100000

7f6f0000 的转储

lkd> dd 7f6f0000 l1c/4
7f6f0000  000000c8 0000011e eeffeeff 00007008
7f6f0010  00000008 0000fe00 00100000

如果您查看 ntdll!RtlCreateHeap,您可以确认此模式确实是堆

lkd> !grep -c "uf ntdll!RtlCreateHeap" -e "ebp-24h"
7c925dcd c745dc88050000  mov     dword ptr [ebp-24h],588h
7c925de7 c745dcc0050000  mov     dword ptr [ebp-24h],5C0h
7c925e87 8145dc80000000  add     dword ptr [ebp-24h],80h
7c925eb1 8b75dc          mov     esi,dword ptr [ebp-24h]
7c93c079 0145dc          add     dword ptr [ebp-24h],eax

在使用地址的地方反汇编

lkd> u 7c925eb1
ntdll!RtlCreateHeap+0x421:
7c925eb1 8b75dc          mov     esi,dword ptr [ebp-24h]
7c925eb4 83c607          add     esi,7
7c925eb7 83e6f8          and     esi,0FFFFFFF8h
7c925eba 8bc6            mov     eax,esi
7c925ebc c1e803          shr     eax,3
7c925ebf 8b4de4          mov     ecx,dword ptr [ebp-1Ch]
7c925ec2 668901          mov     word ptr [ecx],ax

评估表达式

lkd> ? ((588 + 80 >> 3) + 7)  & 0x0fffffff8 
Evaluate expression: 200 = 000000c8

更新

csrss 中的 RWX 页面是_CsrSrvSharedSectionHeap==_CsrSrvSharedSectionBase
从注册表查询特定值并映射到 NtMapViewOfSection
或使用 NtCreateSection 创建的部分所有这些都发生在
csrss!main ->csrsrv.dll ->CsrsrvCreateSharedSection

reg query "hklm\system\currentcontrolset\control\session manager\subsystems\csrss"
! REG.EXE VERSION 3.0    
HKEY_LOCAL_MACHINE\system\currentcontrolset\control\session manager\subsystems\csrss
        CsrSrvSharedSectionBase     REG_DWORD       0x7f6f0000

PAGE_EXECUTE_READWRITE(RWX) 内存通常用于分配注入的进程。权限允许代码执行。扫描 RWX 的内存转储是一种检测注入进程的方法。以下是一些注入恶意软件的内存权限示例。

拉姆尼特内存:Svchost.exe1

Private (Commit), 0x20010000, 52 kB, RWX, MZ
Private (Commit), 0x2001d000, 4 kB, R,  
Private (Commit), 0x2001e000, 12 kB, RW, DS
Private (Commit), 0x20021000, 4 kB, R, 

内存:Svchost.exe2

Private (Commit), 0x20010000, 4 kB, RWX, MZ 
Private (Commit), 0x20011000, 28 kB, RX
Private (Commit), 0x20018000, 4 kB, R
Private (Commit), 0x20019000, 4 kB, RW
Private (Commit), 0x2001a000, 4 kB, R
Free, 0x2001b000, 84 kB, NA

平点

Private (Commit), 0x2460000, 160 kB, RWX, MZ 

上面的输出是使用我自己的工具(不是波动率)创建的。explorer.exe 或其他进程将内存块标记为 RWX 的情况并不少见。它的大小通常为 4k(取决于进程)。RWX 内存的存在并不意味着存在问题,但它是一个很好的调查起点。可以在开发人员 (Michael Hale Ligh) 的网站之一上找到有关使用 Volatility 检测进程注入的很好的读物