目录

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. Spring mvc参数类型转换

    1,需求 有时候我们接收到的参数为String类型的,但是我们需要将它们转化为其他类型的如:date类型,枚举类型等等,spring mvc为我们提供了这样的功能. 2,配置文件 在springmvc ...

  2. 1.python简介

    简介 1.python语言介绍 python的创始人:Guido Van Rossum 2.python是一门什么样的语言 编程语言主要从以下几个角度进行分类:编译型,静态型,动态性,强类型定义语言和 ...

  3. .NET Core实战项目之CMS 第四章 入门篇-Git的快速入门及实战演练

    写在前面 上篇文章我带着大家通过分析了一遍ASP.NET Core的源码了解了它的启动过程,然后又带着大家熟悉了一遍配置文件的加载方式,最后引出了依赖注入以及控制反转的概念!如果大家把前面几张都理解了 ...

  4. .NET Core中的验证组件FluentValidation的实战分享

    今天有人问我能不能出一篇FluentValidation的教程,刚好今天在实现我们的.NET Core实战项目之CMS的修改密码部分的功能中有用到FluentValidation,所以就以修改用户密码 ...

  5. .NET跨平台开发之Xamarin.Android介绍与生命周期【2】

    前言 不同于IOS,Xamarin在Visual Studio中针对Android,可以很直接的去设计使用者界面,在本系列中,子浩会针对Android目录结构以及基本控制项进行介绍,包括TextVie ...

  6. Java 多线程(五)—— 线程池基础 之 FutureTask源码解析

    FutureTask是一个支持取消行为的异步任务执行器.该类实现了Future接口的方法. 如: 取消任务执行 查询任务是否执行完成 获取任务执行结果(”get“任务必须得执行完成才能获取结果,否则会 ...

  7. 我的2017OKR - 年中回顾

    自从订阅了吴军老师的<硅谷来信>之后,对其中一篇介绍Google的目标管理方法OKR的文章记忆犹新.想到自己喜欢在每年年初的时候给自己定制一些规划,于是乎了解了一下OKR并重构了一下我的2 ...

  8. plsql可视化文件夹解释

    function:一般是存储函数或者方法 procedures:一般是存放存储过程 Table:一般是存放建的表 packages:包(头) package bodies:包体types:类型 typ ...

  9. angr进阶(4)从任意位置开始

    从程序的任意位置开始可以大大的减少测试的时间,使用的方法是控制程序运行到某时刻的寄存器的值来进行的.asisctffinals2015_fake p = angr.Project("fake ...

  10. [五]基础数据类型之Short详解

      Short 基本数据类型short  的包装类 Short 类型的对象包含一个 short 类型的字段      原文地址:[五]基础数据类型之Short详解   属性简介   值为  215-1 ...