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: 0148DirBase: 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: 0148DirBase: 3fe820a0  ObjectTable: 99218a60  HandleCount:  88.Image: wininit.exeTHREAD 8e49c290  Cid 0180.0184  Teb: 7ffdf000 Win32Thread: ffb53978 WAIT: (Executive) KernelMode Non-Alertable95472958  SynchronizationEvent95472930  Semaphore Limit 0x12Win32 Start Address wininit!WinMainCRTStartup (0x0032f0cd)Stack Init 95472ed0 Current 95472708 Base 95473000 Limit 95470000 Call 0Priority 15 BasePriority 15 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5ChildEBP 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+0x39495472780 82a5bda6 8e49c290 8e49c350 00000000 nt!KiCommitThreadWait+0x461954728f8 83203019 00000002 95472974 00000001 nt!KeWaitForMultipleObjects+0x6d295472980 83202d32 00000011 9762e350 00000004 nt!PopSleepDeviceList+0xe9954729d8 83202af3 95472a70 00000001 00000006 nt!PoBroadcastSystemState+0x23695472a00 83203d98 95472ad4 95472b58 8320398e nt!PopSetDevicesSystemState+0x6395472ac0 82ba3173 00000006 00000004 c0000004 nt!NtSetSystemPowerState+0x40a95472ac0 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+0xe295472c28 82ba3173 00000002 0019f8e8 76fea364 nt!NtShutdownSystem+0x3295472c28 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任意加载/执行(漏洞)相关推荐

  1. java代码从编译到加载执行的过程

    代码编译 在刚接触java时,我们都知道通过javac命令将java源码文件编译成.class字节码文件,这是由编译器来完成的. 包括泛型擦除属于编译时期的语法糖. .class字节码文件是跨平台的, ...

  2. win7或win10控制面板加载页面失败解决方案

    win7或win10控制面板出现加载页面失败 平时我们使用系统都好好的,没出啥篓子,突然心血来潮打开控制面板或者说系统属性出现以下如图坑爹状况(由于本人已解决放张网上搜到的图-win7). 尼玛出现也 ...

  3. 一加3t运行linux,【漏洞分析】获取已锁定的OnePlus 3/3T:引导加载程序漏洞

    翻译:胖胖秦 预估稿费:120RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 前言 在这篇博文中,我公开了OnePlus 3/3T引导加载程序中的两个漏洞.第一个CVE- ...

  4. php定时执行代码漏洞_【漏洞风险提示】Drupal任意PHP代码执行漏洞通告

    漏洞描述 Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成. 2020年11月25日,Drupal发布了Drupa ...

  5. .net DLL(exe)加载时间

    项目引用其他dll文件或exe文件时: 编译时,引用的dll或exe文件必须存在, 执行时,当函数调用了dll或exe文件内容,才加载此dll或exe文件:否则dll或exe可以不存在,更不会加载.

  6. 今天仔细学习了html加载执行的顺序

    页面上通常会有三个标签,html,head,body,这三个之间的关系是,html包含整个页面代码,head主要用于引入一些js,css文件,body用来包含页面代码和js代码 浏览器加载页面的顺序为 ...

  7. js页面加载前执行_做一名合格的前端开发工程师:Javascript加载执行问题探索

    做前端开发少不了各种利器.比如我习惯用的还是Google浏览器和重型武器Fiddller. 一:原始情况 首先大家看看如下的代码: 估计90%的程序员都会把js文件放在head中,但是大家有没有深究过 ...

  8. 加载执行预编译的Sql :prepareStatement

    1.获得连接:Connection con = null; con = DBUtil.getConnection(); 2.写sql语句:String sql=""; 3.用连接加 ...

  9. 不加载执行js_这些你不知道的前端隐藏加载执行JavaScript

    浏览器加载一个js脚本,会在devtools中留下各种痕迹,elements中的script元素,console中的日志,source中的代码,network中的网络请求等 前端30K面试准备,最完整 ...

最新文章

  1. 安装vue脚手架创建项目
  2. Spring-AOP @AspectJ进阶之绑定连接点方法入参
  3. Swift-binary search tree
  4. SQL Server 2008中的代码安全(四):主密钥
  5. django 性能优化_优化Django管理员
  6. PHP文件下载过滤类
  7. Java面试宝典————基础篇
  8. 易混淆知识点(1):word-wrap和word-break傻傻分不清楚
  9. 并发编程(二)线程并发工具类
  10. Confluence 6 导入 Active Directory 服务器证书 - UNIX
  11. 【Codeforces Round #422 (Div. 2) C】Hacker, pack your bags!(hash写法)
  12. java提取日志sql,通过Java程序抽取日志中的sql语句
  13. mysql全量备份命令_linux下进行定时mysql数据库全量备份
  14. 重回童年的经典系列 |《保卫萝卜》来了,你还记得它吗?复刻 源码+解析 @怀旧的你
  15. 征途2s 服务器文件,征途2 部分服务器更新内容介绍!
  16. 大学计算机考试不挂科秘诀,在大学,考试想不挂科,学渣的4个锦囊妙计,最后一点看笑了!...
  17. 面向对象C#初级入门精讲(1)C#开发入门-徐照兴-专题视频课程
  18. 指向数组的指针的理解
  19. Python_OpenCV调用摄像头完成人脸识别
  20. HackerRank初级篇之Between Two Sets

热门文章

  1. Unity3D 2D射击小游戏瞄准线的实现
  2. 查看 class 文件
  3. 没有预算的新媒体运营如何启动?
  4. cesium-接入监控视频
  5. linux 配置使用ftp 使用账号密码登陆失败
  6. python 画出决策边界_python 画出使用分类器得到的决策边界
  7. 2021阿里云服务器购买攻略-618年中大促专场
  8. 大数据相加_c 大数据相加 class
  9. 什么是m叉树_品读 | 记忆深处那些树
  10. mysql server mirro_Docker下安装MySQL Server镜像