CVE-2014-4113本地提权漏洞分析
By Netfairy

前言

2014年10月14日, Crowdstrike和FireEye发表了一篇文章, 描述了一个新的针对Windows的提权漏洞. Crowdstrike的文章表明:这一新漏洞是在追踪一个高度先进攻击团队飓风熊猫(HURRICANE PANDA)发现的, 这之前, 飓风熊猫利用此漏洞进行攻击已至少五个月了.原文http://www.crowdstrike.com/blog/crowdstrike-discovers-use-64-bit-zero-day-privilege-escalation-exploit-cve-2014-4113-hurricane-panda/. 通用漏洞发布平台随后披露了这个漏洞的部分细节, 该漏洞的CVE编号为CVE-2014-4113. 报告指出:Microsoft Windows下的 win32k.sys是Windows子系统的内核部分,是一个内核模式设备驱动程序,它包含有窗口管理器、后者控制窗口显示和管理屏幕输出等。如果Windows内核模式驱动程序不正确地处理内存中的对象,则存在一个特权提升漏洞。成功利用此漏洞的攻击者可以运行内核模式中的任意代码。攻击者随后可安装程序;查看、更改或删除数据;或者创建拥有完全管理权限的新帐户。

环境
操作系统:windows XP SP3
漏洞文件:Win32k.sys 5.1.2600.6514
调试器:Windbg 6.11.1.404 && Olldbg &&IDA6.6
漏洞验证
我在网上拿到了POC, 这个POC包含了两个文件:Win32.exe和Win64.exe
 
先验证漏洞是否存在, 打开控制台, 直接执行calc.exe
 
Calc.exe进程属于用户netfairy,然后在转到Win32.exe所在目录,,执行Win32.exe calc.exe
 

再看此时的calc.exe进程,是以SYSTEM权限运行的,所以这个win32.exe在XP SP3 下提权成功.

漏洞分析
粗略分析Win32.exe执行流
在调试机器用OD载入win32.exe并添加参数calc.exe. 程序进入主函数后调用的第一个函数是
 
OD对符号的识别不太好,用IDA反汇编这个函数
 
蓝色部分是程序的执行流程。程序先调用
GetVersionExA
获取系统版本信息,下面就cmp     [ebp+VersionInformation.dwMajorVersion], 5 等等进行一系列的比较。所以可以看看出这个函数的作用就是获取目标系统版本并比较决定是否进行下一步的攻击。接着main函数调用的第二个函数是
 
这个函数有点大,就不全贴出来了。总之这个函数首先调用LoadLibraryA加载ntdll.dll,接着调用GetProcAddress得到QuerySystemInformation地址函数的地址,接着调用LoadLibraryA得到ntkrnlpa.exe的地址,接着调用GetProcAddress得到LookupProcessByProcessId的地址,最后调用GetCurrentProcessId获得当前进程的PID。
继续执行,main函数调用的第三个函数是
 
一开始我就猜想这个函数创建的线程应该就是触发漏洞提权的用的。因为Main在这之后就是一个CreateProcessA调用,显然是执行shellcode的。跟进CreateThread看看,这个线程调用函数次序如下:
 
现在我们还不清楚漏洞是怎么触发的,继续往下执行,main函数调用CreateProcessA
 
通过传入的命令行参数创建一个新的进程,该进程和win32.exe有相同的权限。如果前面一步提权成功,那么新创建的进程将拥有system权限。总结一下main函数执行流程以及每个函数的作用如下
 

要分析这个漏洞,只需要分析call    ds:CreateThread ; //触发漏洞,提权 就好。

IDA&&Windbg漏洞详细分析
静态分析
先设置加载win32.exe时调试器中断下来
 
然后bp $exentry断在模块入口点,如图
 
但这里不是main函数入口点,继续单步
 
这个就是main函数了。然后跟进main函数。下面不一一说。直接来到关键函数
 
 
继续往下执行,TrackPopupMenu执行前
 
TrackPopupMenu执行后
 
可见是由TrackPopupMenu最终触发了漏洞,这是从用户层看到的,下面跟踪TrackPopupMenu对应的内核函数win32k!xxxTrackPopupMenuEx
 
1. 在win32k!xxxTrackPopupMenuEx中进行一些列处理后,最终会调用win32k! xxxMNLoop
 
2. 跟进win32k! xxxMNLoop,函数又会调用win32k!xxxHandleMenuMessages
 
3. 继续跟进win32k!xxxHandleMenuMessages,其会事先调win32k! xxxMNFindWindowFromPoint得到win32k! xxxSendMessage需要的菜单窗口对象指针ptagWND,之后再调用win32k! xxxSendMessage给菜单窗口发送消息。
4. 跟进wn32k! xxxMNFindWindowFromPoint,函数首先调用win32k! xxxSendMessage给菜单窗口发送0x1EB(MN_FINDWINDOWFROMPOINT)消息
 
在应用层,程序调用SetWindowsHookExA安装了一个一个钩子类型为4,也就是WH_CALLWNDPROC类型的钩子(SetWindowsHookExA与钩子类型见:https://msdn.microsoft.com/en-us/library/ms644990%28VS.85%29.aspx?f=255&MSPPError=-2147217396),应用层会拦截内核发来的0x1EB消息,钩子处理函数如下
 
跟进SetWindowLongA处理函数,函数最终会调用EndMenu销毁菜单窗口并返回0xFFFFFFFB
 
应用层代码返回0xFFFFFFFB,执行流返回到内核win32k! xxxMNFindWindowFromPoint上下文
 
此时的eax应该为0xFFFFFFFB(一会我们调试的时候会看到),函数接着往下执行,最终0xFFFFFFFB会做为win32k! xxxMNFindWindowFromPoint的返回值
5. win32k! xxxMNFindWindowFromPoint执行完返回到win32k!xxxHandleMenuMessages上下文,对于前边win32k! xxxMNFindWindowFromPoint的返回值0xFFFFFFB,程序没有严格校验它的返回值ptagWND,导致后边把0xFFFFFFFB作为ptagWND传给win32k! xxxSendMessage
 
而不幸的是win32k! xxxSendMessage又会调用ptagWND+0x60处的函数,也就是
call [0xFFFFFFB+0x60],即call [0x5B]。并且应用层会事先调用ZwAllocateVirtualMemory在0地址分配内存并在0x5B处写入shelllcode的地址。
 
最后,结合前面的分析。给出一份直观的程序流程图

动态调试
动态调试需要在应用程和内核层同时下断:
应用层:
004012E2 call    dword_40EBCC    ; ntdll!ZwAllocateVirtualMemory
004015FE call    ds:TrackPopupMenu
 
内核层:
BF938E11 call    xxxMNFindWindowFromPoint@12
BF9392F6 call    xxxSendMessage@16
 
其中poi(poi(poi(fs:0x124)+0x44)+0x84)代表当前执行进程的pid(win32.exe的pid为0xba4),要进行pid判断是否为win32.exe进程,不然调试器老是断在别的进程。
1. 调用ZwAllocateVirtualMemory前
 
调用后执行完
004012fb e876050000      call    image00400000+0x1876 (00401876)
 
可以看到0x5b保存了提权的shellcode的 地址
……
00401830 55              push    ebp
00401831 8bec            mov     ebp,esp
00401833 83ec08          sub     esp,8
00401836 60              pushad
……
2. 继续运行到
 
控制权转到内核
3. 转到内核层,程序断在win32k! xxxMNFindWindowFromPoint
 
4. win32k! xxxMNFindWindowFromPoint又会调用win32k! xxxSendMessage

 
5. 最终win32k! xxxMNFindWindowFromPoint的返回值是0xFFFFFFFB
 
6. 最终程序会转到0x5B保存的0x00401830执行
 
记住,此时处于内核层,所以程序可以执行所有特权指令。当然,你完全可以直接在这里执行shellcode。Win32.exe把提权代码放到这里,可以把程序的权限提升至system,然后转到用户层
004017EE call    ds:CreateProcessA  
由CreateProcess创建的calc.exe自然也是system权限了。

 

总结

有对函数返回值进行进一步利用的,如call [retn+0xXX],一定要严格校验返回值。以免攻击者构造恶意的代码控制返回值,进行进一步的漏洞利用。

参考
Windows内核提权漏洞CVE-2014-4113分析报告:http://drops.wooyun.org/papers/3324
CVE-2014-4113漏洞利用过程分析:http://drops.wooyun.org/papers/3331

CrowdStrike Discovers Use of 64-bit Zero-Day Privilege Escalation Exploit (CVE-2014-4113):http://www.crowdstrike.com/blog/crowdstrike-discovers-use-64-bit-zero-day-privilege-escalation-exploit-cve-2014-4113-hurricane-panda/

CVE-2014-4113本地提权测试的更多相关文章

  1. CVE¬-2020-¬0796 漏洞复现(本地提权)

    CVE­-2020-­0796 漏洞复现(本地提权) 0X00漏洞简介 Microsoft Windows和Microsoft Windows Server都是美国微软(Microsoft)公司的产品 ...

  2. MySQL-based databases CVE -2016-6663 本地提权

    @date: 2016/11/3 @author: dlive 0x01 漏洞原文 翻译水平不高求轻喷 感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程 0x ...

  3. 基于RedHat发行的Apache Tomcat本地提权漏洞

    描述 Tomcat最近总想搞一些大新闻,一个月都没到,Tomcat又爆出漏洞.2016年10月11日,网上爆出Tomcat本地提权漏洞,漏洞编号为CVE-2016-5425.此次受到影响的主要是基于R ...

  4. iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权

    iOS冰与火之歌(番外篇) 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权 蒸米@阿里移动安全 0x00 序 这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用 ...

  5. Linux Kernel ‘perf’ Utility 本地提权漏洞

    漏洞名称: Linux Kernel ‘perf’ Utility 本地提权漏洞 CNNVD编号: CNNVD-201309-050 发布时间: 2013-09-09 更新时间: 2013-09-09 ...

  6. Linux Kernel ‘kvm_set_memory_region()’函数本地提权漏洞

    漏洞名称: Linux Kernel ‘kvm_set_memory_region()’函数本地提权漏洞 CNNVD编号: CNNVD-201306-343 发布时间: 2013-06-20 更新时间 ...

  7. kali权限提升之本地提权

    kali权限提升之本地提权 系统账号之间权限隔离 操作系统的安全基础 用户空间 内核空间 系统账号: 用户账号登陆时候获取权限令牌 服务账号无需用户登录已在后台启动服务 windows用户全权限划分: ...

  8. CVE-2017-16995 Ubuntu16.04本地提权漏洞复现

    0x01 前言 该漏洞由Google project zero发现.据悉,该漏洞存在于带有 eBPF bpf(2)系统(CONFIG_BPF_SYSCALL)编译支持的Linux内核中,是一个内存任意 ...

  9. Potato家族本地提权分析

    原文来自SecIN社区-作者:Zeva 0x00 前言 在实际渗透中,我们用到最多的就是Potato家族的提权.本文着重研究Potato家族的提权原理以及本地提权细节 0x01 原理讲解 1.利用Po ...

随机推荐

  1. 浅析XSS与XSSI异同

    浅析XSS与XSSI异同 这篇文章主要介绍了XSS与XSSI异同,跨站脚本(XSS)和跨站脚本包含(XSSI)之间的区别是什么?防御方法有什么不同?感兴趣的小伙伴们可以参考一下 Michael Cob ...

  2. 大规模实时流处理平台架构-zz

    随着不同网络质量下接入终端设备种类的增多,服务端转码已经成为视频点播和直播产品中必备的能力之一.直播产品讲究时效性,希望在一定的时间内让所有终端看到不同尺寸甚至是不同质量的视频,因此对转码的实时性要求 ...

  3. 洛谷 P3835: 【模板】可持久化平衡树

    题目传送门:洛谷P3835. 题意简述: 题面说的很清楚了. 题解: 考虑建立一棵每个节点都表示一个版本的树. 以初始版本 \(0\) 为根.对于第 \(i\) 个操作,从 \(v_i\) 向 \(i ...

  4. Linux查看用户密码修改时间

    在/etc/shadow文件里面,第三个字段标识表示密码修改日期:这个是表明上一次修改密码的日期与1970-1-1相距的天数.如果账户自创建后,没有修改过密码,就可以使用这个字段来查找账号创建日期. ...

  5. Floyd_Warshall算法

    Floyd_Warshall算法主要用于求解所有节点对的最短路径,代码如下: #include<iostream> using namespace std; #define Inf 655 ...

  6. Python Webdriver 重新使用已经打开的浏览器实例

    因为Webdriver每次实例化都会新开一个全新的浏览器会话,在有些情况下需要复用之前打开未关闭的会话.比如爬虫,希望结束脚本时,让浏览器处于空闲状态.当脚本重新运行时,它将继续使用这个会话工作.还就 ...

  7. 并行运行多个python虚拟机

    之前遇到一个问题,需要将场景服务这个模块拆分出来,用独立的一个线程去执行.使用独立的线程好处就是,逻辑写的可以相对简单粗暴点,不必考虑到大量的场景服务逻辑卡主线程的情况. 由于我们服务器之前是使用py ...

  8. haproxy支持的负载均衡算法详解

    目前haproxy支持的负载均衡算法有如下8种: 1.roundrobin 表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法.该算法是动态的,对于实 ...

  9. CentOS7 修改网卡名称

    vi /etc/sysconfig/grub 增加net.ifnames=0 biosdevname=0 执行:grub2-mkconfig -o /boot/grub2/grub.cfg

  10. getch与getchar区别

    getch(): 所在头文件:conio.h 函数用途:从控制台读取一个字符,但不显示在屏幕上 getchar(): 所在头文件:stdio.h getch与getchar基本功能相同,差别是getc ...