目录

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. ThinkPHP 数据库操作(六) : 查询事件、事务操作、监听SQL

    查询事件 查询事件(V5.0.4+) 从 5.0.4+ 版本开始,增加了数据库的CURD操作事件支持,包括: 查询事件仅支持 find . select . insert . update 和 del ...

  2. Mysql篇--Linux中安装Mysql

    一.前述 由于Windows安装Mysql非常麻烦,所以分享一篇Linux中对MySQL的搭建,废话不多说,来,come on. 二.步骤 2.1 yum安装 yum install mysql-se ...

  3. Linux(2)---记录一次线上服务 CPU 100%的排查过程

    Linux(2)---记录一次线上服务 CPU 100%的排查过程 当时产生CPU飙升接近100%的原因是因为项目中的websocket时时断开又重连导致CPU飙升接近100% .如何排查的呢 是通过 ...

  4. C# 8中的范围类型(Range Type)

    C# 8.0中加入了一个新的范围类型(Range Type). 这里我们首先展示一些代码,并一步一步为代码添加一些不同的东西, 为大家展示一下范围类型的功能和用法. 我们最原始的代码如下: stati ...

  5. 使用Spring Cloud搭建服务注册中心

    我们在之前的博客中已经介绍过阿里的分布式服务框架dubbo[Linux上安装Zookeeper以及一些注意事项][一个简单的案例带你入门Dubbo分布式框架],但是小伙伴们应该也看到了,阿里的dubb ...

  6. 洛谷:P1182:数列分段`Section II`

    题目描述 对于给定的一个长度为N的正整数数列 A-iA−i ,现要将其分成 M(M≤N)M(M≤N) 段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列 4 2 4 5 1424 ...

  7. C#线程安全使用(一)

    关于Task的使用,一直都是半知半解,最近终于有时间详细的看了一遍MSDN,作为备忘录,将心得也记录下来和大家分享. 首先,根据MSDN的描述,Task是FrameWork4引进的新功能,他和ConC ...

  8. Spring拓展接口之BeanFactoryPostProcessor,占位符与敏感信息解密原理

    前言 开心一刻 一只被二哈带偏了的柴犬,我只想弄死隔壁的二哈 what:是什么 BeanFactoryPostProcessor接口很简单,只包含一个方法 /** * 通过BeanFactoryPos ...

  9. Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  10. c# Task 篇幅二

    上面一篇https://i.cnblogs.com/EditPosts.aspx?postid=10444773我们介绍了Task的启动,Task的一些方法以及应用,今天我们着重介绍一下Task其它概 ...