目录

CVE-2018-8120 分析

1、实验环境

1.1、操作系统

1.2、用到的分析工具

2、假如

2.1、我想提权

​ 我想使我编写的一个普通的R3的程序一运行就获得SYSTEM最高权限。一个常用的办法是: 替换当前进程_EPROCESS结构的Token成员的值为system进程的_EPROESS的Token成员值。一旦替换成功,那么从替换成功的那一刻开始一直到程序退出这段时间里,程序所做的一切操作都是以SYSTEM最高权限执行的。

​ 但是,要完成这项工作在R3层面上直接上shellcode是不行的,因为所有进程的EPROCESS结构都是位于内核空间中的,如果要对其进行读写则代码必须运行在内核空间中才行,用户空间中的代码如果对其进行读写则会产生保护性异常。

​ 所以问题就来了,怎样让我们的替换Token的shellcode(这段shellcode是怎么写的在后面会有详细解释)运行在内核空间中呢?

2.2、 有一个处于内核空间,极少被调用的函数

2.2.1、快速系统调用简介

​ 虽然用户程序不能直接访问内核空间,但是用户程序可以通过调用系统服务来间接访问系统空间中的数据或间接调用执行系统空间中的代码。当调用系统服务时,调用线程会从用户模式切换到内核模式,调用结束后再返回到用户模式,也就是所谓的模式切换,有时也被称为上下文切换(Context Switch)。模式切换是通过软中断或专门的快速系统调用(Fast System Call)指令来实现。

​ 下面我来简要介绍下Windows 7 X86 sp1 是如何通过SYSENTER指令实现快速系统调用的。举一个简单的例子。调用ReadFile()这个函数的流程为下图所示:

​ 在windows 7 sp1 x86中使用微软的亲儿子WINDBG(本地内核调试模式,具体设置百度,PS:设置完后需使用管理员权限启动WINDBG否则使用BCDEDIT设置重启后依然不能启用本地内核调试模式)查看NTDLL.DLL中导出的NtReadFile()函数的反汇编:

lkd> uf ntdll!NtReadFile
ntdll!ZwReadFile:
775762b8 b811010000 mov eax,111h ;NtReadFile的系统服务号码为 0x111
775762bd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
775762c2 ff12 call dword ptr [edx]
775762c4 c22400 ret 24h

那么当第二句 mov edx,offset SharedUserData!SystemCallStub 执行后,edx 值为0x7ffe0300。因为第三句是 call dword ptr [edx] 所以继续查看地址SharedUserData!SystemCallStub 处的值

lkd> dd SharedUserData!SystemCallStub
7ffe0300 775770b0 775770b4 00000000 00000000

​ 继续执行call dword ptr [edx] 则跳转到地址0x775770b0 处执行,继续使用神器反汇编

lkd> uf 775770b0
ntdll!KiFastSystemCall:
775770b0 8bd4 mov edx,esp
775770b2 0f34 sysenter
775770b4 c3 ret

​ 当执行sysenter指令后,进入内核模式,调用KisystemService()函数,该函数会根据服务ID从系统服务分发表(System Service Dispatch Table)中找到要调用的服务函数的函数地址和参数描述,然后调用内核中正真的NtReadFile()函数。那个服务ID就是进入SharedUserData!SystemCallStub之前那个mov eax,111h的111h。

2.2.2、SSDT表 和 ShadowSSDT 表和 HalDispatchTable硬件抽象层调度表 简介

​ 再windows NT系列操作系统中,有两种类型的系统服务,一种是实现在内核文件中,是常用的系统服务。另一种实现在win32k.sys中,是一些与图形显示及用户界面相关的系统服务。这些系统服务在系统运行期间常驻于系统内存区中,并且他们的入口地址保存在两个系统服务地址表KiServiceTable和Win32pServiceTable中.所有的系统服务地址表都保存在系统服务描述表(SDT)中。

​ 目前windows系统共有两个SDT,一个是ServiceDescriptorTable(SSDT),另一个是ServiceDescriptorTableShadow(SSDTShadow).

​ 其中ServiceDescriptorTable中只包含KiServiceTable,而ServiceDescriptorTableShadow中既包含KiServiceTable又包含Win32pServiceTbale.其中SSDT是可以访问的而SSDTShadow是不公开的。

​ 使用windbg查看SSDT和SSDTShadow如下:

lkd> dd nt!KeServiceDescriptorTable
83fad9c0 83ec1d9c 00000000 00000191 83ec23e4
83fad9d0 00000000 00000000 00000000 00000000 //SSDT中该项为空 lkd> dd nt!KeServiceDescriptorTableShadow
83fada00 83ec1d9c 00000000 00000191 83ec23e4
83fada10 955b6000 00000000 00000339 955b702c //SSDTShadow中该项不为空 SDT的表项中成员按以下数据结构组成:
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; // 0x00 系统服务地址表地址
PULONG ServiceCounterTableBase; // 0x04
PULONG NumberOfService; // 0x08 服务函数的个数
ULONG ParamTableBase; // 0x0c 该系统服务的参数表
} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE; //sizeof=0x10 那么根据SSDTShadow可以得到KiServiceTable的地址为0x83ec1d9c,包含0x191个服务函数;
可以得到Win32pServiceTable的地址为0x955b6000,包含0x339个服务函数。

​ 这时我们去看看Win32pServiceTable处的东西吧!

lkd> dds 955b6000
955b6000 95543d37 win32k!NtGdiAbortDoc
955b6004 9555bc23 win32k!NtGdiAbortPath
955b6008 953b71ac win32k!NtGdiAddFontResourceW
955b600c 95552c5d win32k!NtGdiAddRemoteFontToDC
955b6010 9555d369 win32k!NtGdiAddFontMemResourceEx
955b6014 95544554 win32k!NtGdiRemoveMergeFont
955b6018 955445e8 win32k!NtGdiAddRemoteMMInstanceToDC
955b601c 9546dad1 win32k!NtGdiAlphaBlend
955b6020 9555cb94 win32k!NtGdiAngleArc
955b6024 95421965 win32k!NtGdiAnyLinkedFonts
955b6028 95421882 win32k!NtGdiFontIsLinked
955b602c 9555eead win32k!NtGdiArcInternal
955b6030 9555d085 win32k!NtGdiBeginGdiRendering
955b6034 9555bc97 win32k!NtGdiBeginPath
955b6038 954628cb win32k!NtGdiBitBlt

​ 可以发现它的每一个成员都是一个四字节的服务函数指针!如果把这里面某个函数指针改为我们shellcode的地址,再在用户层调用它的R3对应函数,那么不就让我们的shellcode在高权限执行了吗?但是,我们需要一个更好的目标,它在我们程序的运行阶段不会被其他任何进程调用。(因为又不是你一个程序在调系统服务函数,如果其他程序调用了你改了函数指针指向的函数,就会有不可预料的事情发生,比如BSOD).

​ 另一个很好的表是硬件抽象层(HAL)调度表nt!HalDispatchTable。这里也存储了系统调用地址,不过是HAL例程的地址。用温帝霸查看如下所示:

lkd> dds nt!HalDispatchTable
83f6e3f8 00000004
83f6e3fc 83e338a2 hal!HaliQuerySystemInformation
83f6e400 83e341b4 hal!HalpSetSystemInformation

​ 注意到nt!HalDispatchTable+4那个地址指向的函数了吗?这个函数就是我们要覆盖为shellcode地址的最佳选择。因为有一个名为NtQueryIntervalProfile的未记录函数,它获取当前为给定配置文件源设置的配置文件间隔。该函数可以通过调用GetProcAddress从NTDLL.DLL中获取地址,在userland调用。该函数在内部调用KeQueryIntervalProfile函数 :

kd> u nt!NtQueryIntervalProfile + 0x62
nt!NtQueryIntervalProfile+0x62:
8414fecd 7507 jne nt!NtQueryIntervalProfile+0x6b (8414fed6)
8414fecf a1acdbf683 mov eax,dword ptr [nt!KiProfileInterval (83f6dbac)]
8414fed4 eb05 jmp nt!NtQueryIntervalProfile+0x70 (8414fedb)
8414fed6 e83ae5fbff call nt!KeQueryIntervalProfile (8410e415);调用KeQueryIntervalProfile
8414fedb 84db test bl,bl
8414fedd 741b je nt!NtQueryIntervalProfile+0x8f (8414fefa)
8414fedf c745fc01000000 mov dword ptr [ebp-4],1
8414fee6 8906 mov dword ptr [esi],eax
//本地u好像权限不够,双机调u成功

​ 继续反汇编nt!KeQueryInterValProfile

kd> u nt!KeQueryIntervalProfile+0x23
nt!KeQueryIntervalProfile+0x23:
8410e438 ff15fce3f683 call dword ptr [nt!HalDispatchTable+0x4 (83f6e3fc)]
8410e43e 85c0 test eax,eax
8410e440 7c0b jl nt!KeQueryIntervalProfile+0x38 (8410e44d)
8410e442 807df400 cmp byte ptr [ebp-0Ch],0
8410e446 7405 je nt!KeQueryIntervalProfile+0x38 (8410e44d)
8410e448 8b45f8 mov eax,dword ptr [ebp-8]
8410e44b c9 leave
8410e44c c3 ret

​ 发现了吗?nt!HalDispatchTable+0x4不就是hal!HaliQuerySystemInformation吗?所以我们可以用userland中的令牌(Token)窃取shellcode的地址覆盖这个指针,那么一旦我们调用NtQueryIntervalProfile函数的时候,就会在内核中运行我们的shellcode啦!!!

​ 但是绕来绕去,我们还是没有办法在R3直接修改内核空间中的内存。。。

CVE-2018-8120 分析的更多相关文章

  1. [uboot] (第三章)uboot流程——uboot-spl代码流程 后续2018版本分析

    board_init_f在/u-boot-2018.07-fmxx/arch/arm/mach-fmxx/spl.c中定义 board_init_f之后,和转载的部分有出入: u-boot-2018. ...

  2. 慢查询日志分析(mysql)

    开启慢查询日志之后,慢查询sql会被存到数据库系统表mysql.slow_log或是文件中,可参考.有两个工具可以帮助我们分析输出报告,分别是mysqldumpslow和pt-query-digest ...

  3. android CVE

    本文收集网上android cve的一些分析供后续学习: Android uncovers master-key:android1.6-4.0 由于ZIP格式允许存在两个或以上完全相同的路径,而安卓系 ...

  4. HDU 2018 母牛的故事 (递归入门)

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2018 思路分析: 问题分析:这道题的递推关系非常类似斐波那契数列,由题意不难得到以下函数递推式: 对于 ...

  5. 深入剖析最新IE0day漏洞

    在2018年4月下旬,我们使用沙箱发现了IE0day漏洞;自从在野外发现上一个样本(CVE-2016-0189)已经有两年多了.从许多方面来看,这个特别的漏洞及其后续的开发比较有趣.下一篇文章将分析最 ...

  6. Android安全研究经验谈

    安全研究做什么 从攻击角度举例,可以是:对某个模块进行漏洞挖掘的方法,对某个漏洞进行利用的技术,通过逆向工程破解程序.解密数据,对系统或应用进行感染.劫持等破坏安全性的攻击技术等. 而防御上则是:查杀 ...

  7. 2018-2019-2 网络对抗技术 20165236 Exp5 MSF基础应用

    2018-2019-2 网络对抗技术 20165236 Exp5 MSF基础应用 一. 实践内容(3.5分) 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要 ...

  8. MT【272】更大的视野,更好的思路.

    已知$f(x)=\sum\limits_{k=1}^{2017}\dfrac{\cos kx}{\cos^k x},$则$f(\dfrac{\pi}{2018})=$_____ 分析:设$g(x)=\ ...

  9. Debian Security Advisory(Debian安全报告) DSA-4405-1 openjpeg2

    package :openjpeg2 相关CVE ID: CVE-2017-17480 CVE-2018-5785 CVE-2018-6616 CVE-2018-14423 CVE-2018-1808 ...

  10. 关于Retrofit网络请求URL中含有可变参数的处理

    开题:在此默认各位看官对Retrofit.以及Okhttp已经有过一定的了解及应用,所以今天我们不谈基础入门的东西,今天我们谈在Retrofit请求接口管理类中URL参数含有动态参数的处理方式.一般我 ...

随机推荐

  1. Python数据分析(一): ipython 技巧!

    不一定非得使用Jupyter Notebook,试试ipython命令行 安装 ipython 我只试过Windows 10环境下的. 1.安装python安装包之后,应该就有ipython了. 2. ...

  2. Linux清空文件内容

    日志文件太多,需要清空: echo "" > mylog.log

  3. 【Storm篇】--Storm中的同步服务DRPC

    一.前述 Drpc(分布式远程过程调用)是一种同步服务实现的机制,在Storm中客户端提交数据请求之后,立刻取得计算结果并返回给客户端.同时充分利用Storm的计算能力实现高密度的并行实时计算. 二. ...

  4. 论Java访问权限控制的重要性

    人在什么面前最容易失去抵抗力? 美色,算是一个,比如说西施的贡献薄就是忍辱负重.以身报国.助越灭吴:金钱,算是另外一个,我们古人常说“钱乃身外之物,生不带来死不带去”,但我们又都知道“有钱能使鬼推磨” ...

  5. asp.net core 系列 22 EF(连接字符串,连接复原,DbContext)

    一.连接字符串 在上二篇中,ASP.NET Core 应用程序连接字符串是写死在ConfigureServices代码中,下面介绍通过配置来实现.连接字符串可以存储在 appsettings.json ...

  6. ASP.NET Core DI 手动获取注入对象

    ASP.NET Core DI 一般使用构造函数注入获取对象,比如在ConfigureServices配置注入后,通过下面方式获取: private IValueService _valueServi ...

  7. 使用mongoskin操作MongoDB

    mongoskin是一个操作MongoDB的模型工具 相当于数据库类 与之相当的还有mongoose比较出名 安装模块(特地加了版本,这里被坑过,在Ubuntu中开发的好好的,部署到线上centos中 ...

  8. PWA的探索与应用

    本文由云+社区发表 PWA(Progressive Web App)起源背景 传统的Web网页存在以下几个问题: 进入一个页面必须要记住它的url或者加入书签,入口不便捷: 没网络就没响应,不具备离线 ...

  9. Windows 花屏问题

    已经有2台电脑 Windows 10 系统出现花屏现象,表现为比较炫的界面出现花屏.文字显示不全.移位.闪烁等,如果点击“设置”.“开始”,Chrome浏览器等:比较平素的界面显示正常,比如资源管理器 ...

  10. Python并发编程之消息队列补充及如何创建线程池(六)

    大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...