探索 Intel Processor Trace:在 Windows 上的技术解析与应用实践

一、前言 本文介绍了Intel CPU Processor Trace这个特性,介绍Windows平台如何使用Intel PT这一特性,这里主要参考了这个开源项目:(https://github.com/intelpt/WindowsIntelPT)。在最后,结合Intel PT这一技术探讨其使用场景。 二、什么是CPU跟踪技术? Intel Process Trace(以下称为Intel PT)是Intel处理器中的一项拓展功能,这个功能可以使用处理器中专用的硬件设施捕获软件的执行信息。在开启了Intel PT功能时,CPU处于软件执行流信息捕获的状态下,捕获执行流的操作只会对被捕获的软件性能干扰很小。相比于通过动态插桩的方式进行执行流信息收集,Intel PT对性能的影响很小,这一个优势在复现或者挖掘某些需要竞争的漏洞时会凸显出来,往往一些竞争类漏洞的复现会和代码执行的时机相关,那么代码插桩或者开启一些调试参数或者调试器时,对于漏洞的复现都会有影响,Intel PT技术就可以在这个时候背后"默默"观察执行流。 Intel PT生成的跟踪数据流中包含了多种的数据包,这些数据包直接由CPU硬件生成,并且"实时"写入到物理内存中,并且这些数据经过压缩,无法直接通过读取数据得到执行流的跟踪信息。如果我们要读取Intel PT生成的实时跟踪数据的话,不光要对CPU生成的数据包进行解码,还要获取到被跟踪的二进制文件中的信息才能恢复出当前生成的实时执行流的虚拟地址。关于数据包的格式会在下文中介绍。 那么,Intel PT具体有哪些能力呢? Intel PT功能中可以针对特定CR3寄存器的值进行代码执行流跟踪,这个功能是CPU中的硬件实现的,不需要我们在使用时进行人为过滤。我们可以在Intel PT功能中设置不同的CR3寄存器数值,实现跟踪指定进程的能力。并且我们可以设置Intel PT功能的控制寄存器来选择让Intel PT是否跟踪特定权限下的代码流,这样便可以实现只跟踪用户态的代码流,或者只跟踪内核态的代码流,或者不限CPL全部跟踪,同样地,这个能力也是CPU硬件实现的,我们只需配置好控制寄存器就可以了。 Intel PT还可以设置虚拟地址过滤,可以通过配置Intel PT控制寄存器来让CPU在执行特定的IP范围内的代码时生成跟踪数据流。这个功能在使用Intel PT功能跟踪驱动时非常有用,我们可以设置要跟踪的驱动的地址范围来让Intel PT生成要跟踪的驱动的代码流数据。 我们还可以配置Intel PT控制寄存器生成TSC(Time Stamp Counter)数据包,这个TSC数据包可以用来分析各个事件或者组件之间的在某一个时刻的运行的代码流,分析出在某一个时刻不同事件的关联,有助于发现程序中的并发问题或者竞争问题。这个TSC数据包还可以用于分析软件性能,用于找出编码中的性能瓶颈。 Intel PT算不上是新技术,但是这个功能在Intel 7代以后的CPU才被完整的支持。所以本文用作示例的CPU型号为:Intel Pentium 4405U。下面我们来具体看看Intel PT的技术细节&配置。 三、Intel PT 数据包 下面简单介绍下Intel PT生成的常用的数据包。 a) 执行流基本信息的数据包: PSB(Packet Stream Boundary)数据包: PSBEND数据包: PSB和PSBEND数据包全部都是固定编码,PSB数据包被pt解码器用作寻找数据流中的数据包的边界,当解码跟踪数据时,解码器要先找到PSB数据包,它的作用更像是边界。 在PSB和PSBEND数据包之间的数据被解码器理解成"status only"数据包,例如:TSC(时间戳),TMA(时间戳MTC对齐),PIP(分页信息),CBR(核心总线速率),MODE.TSX,MODE.Exec(运行在多少bit模式下),FUP这些数据包。 PIP数据包: PIP数据包是用来记录对CR3寄存器修改的数据包。 TSC数据包: TSC是生成时间戳数据包,这个数据包对多线程多组件之间同步有大用处。 OVF数据包: OVF会在处理器内部发生缓冲区溢出时生成,标志着当前有数据包丢失的情况。 b) 控制流信息数据包: TNT数据包: TNT数据包可不是什么炸药,它的全称是:Taken/Not-taken Packet。这个数据包指示着最近的1到6个或者1到47个条件分支是否执行,执行就是taken(用1表示),没执行就是not-taken(用0表示),其中的B1到Bn代表着最后N个条件分支的结果,B1代表最旧的分支结果,Bn代表最新的,不过这里有一个特殊的地方是,如果开启了ret压缩,也会增加一个已经置1的taken位到TNT数据包中。 TNT数据包分两种长度的,一种是1字节版本的,可以代表最多6个的分支跳转结果。一种是8字节版本的,最多可以代表47个分支跳转的结果。 TIP数据包: TIP数据包就是Target IP数据包,顾名思义,在Intel PT开启跟踪时遇到例如:没有开启ret压缩的ret指令,间接跳转指令(例如JMP rax),中断,异常,VMEntry/VMExit等等指令时会产生一个TIP数据包记录当前的执行流IP跑到了哪里。...

2025年03月26日 · 9 分钟 · hongzhenhao

使用破壳平台自动化漏洞挖掘实践

一、前言 本文主要是讲述用静态分析平台——破壳平台进行批量漏洞快速挖掘和扫描的思路分享。 破壳平台在近日提交了TP-Link,TENDA,D-Link,Linksys,Edimax,Netgear等系列设备六十余个漏洞点,并已经获得30个CVE的批复。 CVE-2024-57357,CVE-2025-22900,CVE-2025-22903,CVE-2025-22904,CVE-2025-22905,CVE-2025-22906,CVE-2025-22907,CVE-2025-22911,CVE-2025-22912,CVE-2025-22913,CVE-2025-22916,CVE-2025-25456,CVE-2025-25458,CVE-2025-25453,CVE-2025-25455,CVE-2025-25454,CVE-2025-25457,CVE-2024-57536,CVE-2024-57537,CVE-2024-57538,CVE-2024-57539,CVE-2024-57540,CVE-2024-57541,CVE-2024-57542,CVE-2024-57543,CVE-2024-57544,CVE-2024-57545,CVE-2024-42520,CVE-2025-25579 后面我们会从三个方面来讲一下查询的策略: 边界二进制寻找 漏洞模式分析及规则编写 平台使用 二、边界二进制寻找 所谓边界二进制就是用户可以访问到的二进制,一般我们进行漏挖也是主要针对这些程序进行针对性,无需对固件中所有的程序都进行分析。 而对于静态分析来说,上传的文件越多那么分析速度和查询速度就会相应的越慢。因此需要有一个初步的文件过滤的步骤来帮助我们初步筛选一些边界二进制。根据平时的漏洞挖掘经验对于常见的路由器,摄像头,nvr等设备,其http服务及相关cgi是漏洞出现的重灾区。 上传平台后平台会自动对压缩包,固件进行解压。同时平台可以设置正则表达式进行过滤: \b(?:\w*httpd\w*|\w*.cgi|\w*onvif\w*|\w*boa\w*|\w*webs\w*|\w*goahead\w*)\b 个人平时在漏洞挖掘时也习惯使用下面的方式来大致确定一些具有网络服务的边界二进制: cd usr grep -r "bind" . | grep Binary 主要是因为值得分析的二进制一般会位于usr目录下,根目录下的bin和sbin一般是linux系统自己的系统服务。且边界二进制必然会监听端口,因此存在bind字符串的很大概率是边界二进制。 三、漏洞模式分析及规则编写 在物联网漏洞挖掘中,命令注入和缓冲区溢出是最为常见的高危漏洞类型。在我初期的自动化工作中也先以这两种漏洞模式进行查询。下面介绍这两种漏洞类型中我所使用的常见漏洞模式。 2.1 命令注入漏洞模式 大部分命令注入漏洞都会经过字符串拼接函数。 edimax CVE-2025-22905 下图是平台漏洞个查询结果,可以看到这个漏洞就是从websGetVar中获取到了对应字段,然后经过了字符串拼接后传递给了system函数,造成了命令注入漏洞。 tplink-8630 CVE-2024-57357 这个漏洞其实从调用流程上来说比较复杂,首先他会使用aes解密用户传入的数据为json,然后从json中拿取一个字符串,然后根据这个字符串去一个虚标中调用对应的函数,然后再经过一个虚表调用后再经过一个假鉴权最终达到命令注入,但是核心漏洞点就是字符串拼接后执行了system 在sub_424ab0函数中会将v20这个变量直接传递给system函数作为参数。 查询规则 针对于大部分命令注入漏洞都会经过字符串拼接函数这个漏洞模式,,使用正则进行字符串匹配或者单纯直接寻找sprintf和system函数作为危险函数点总体来说误报还是比较多的,而且不支持跨函数的情况。 因此个人采用的是使用snprintf,sprintf函数的参数作为source点,常见的命令执行函数作为sink点,然后使用平台进行污点分析,相对来说误报较少,能查到的很大概率是会存在漏洞的。 MATCH (n:identifier)<-[:ast*2]-(code:code_line) WHERE n.callee in ["snprintf","sprintf"] and n.index in [2,3,4,5,6] and code.name contains "%s" WITH collect(id(n)) as sourceSet MATCH (m:identifier{index:0}) WHERE m.callee in ['system', '_system', '_popen', 'popen', 'wpopen', '_wpopen', 'spawn', '_wexecl', '_wspawnv', 'eval', '_wsystem', 'spawnve', '_wspawnlp', '_spawnl', 'execle', '_wspawnve', '_texeclp', '_wexeclp', '_spawnlpe', '_execvp', '_exec', 'COMM_SystemEx', '_wspawnl', '_wspawnvp', 'execlp', 'system_en', '_wspawnvpe', '_wexecv', 'WinExec', '_wspawnle', '_texecvp', 'CreateProcessW', 'twsystem_nowait', '_texecle', '_execv', '__system', '_spawn', 'spawnvp', '_tspawnl', 'doSystemCmd', 'callSystemCmd', '_tspawnlpe', 'CreateProcess', '_spawnve', '_tspawnv', 'spawnlp', 'spawnlpe', 'g_spawn_command_line_async', '_wexecle', 'spawnl', '_spawnvp', '_tspawnlp', '_tspawnle', '_execl', '_wexec', '_wexeclpe', '_tspawnve', 'spawnv', '_tspawn', 'twsystem', '_spawnle', '_execle', 'execvp', '___system', '_wspawn', '_texecl', '_tspawnvp', '_eval', '_texecv', '_spawnlp', '_spawnvpe', 'spawnle', '_execlp', 'execl', '_execlpe', 'CreateProcessA', '_spawnv', '_tspawnvpe', '_texec', '_wexecvp', 'bstar_system', 'prctl_runCommandInShellBlocking', 'execv', 'spawnvpe', '_wspawnlpe', '_texeclpe', 'execlpe', 'jhl_system', 'ATP_UTIL_ExecCmdNoHang', 'j_ATP_UTIL_ExecCmdNoHang', 'bs_SetCmd', 'ExeShell','doSystemCmd','lxmldbc_system'] WITH sourceSet,collect(id(m)) as sinkSet CALL VQL....

2025年03月19日 · 2 分钟 · w00d

Windows RPC服务漏洞挖掘之旅

在当今的网络安全领域,Windows操作系统的漏洞挖掘一直是研究者们关注的焦点之一。其中,RPC(Remote Procedure Call,远程方法调用)服务作为Windows系统的核心组件,因其广泛的使用和潜在的安全风险,成为了漏洞挖掘的重要目标,历史上出了非常多的漏洞。 一、Windows RPC介绍 1.1 RPC是什么? RPC是Windows系统里最基础的组件之一,很多服务都是基于此开发。RPC是Remote Procedure Call的缩写,即远程方法调用。简单来说,客户端可以通过RPC远程调用服务端已注册的接口内的方法并取得执行结果,而无需关心具体实现。这种机制使得不同进程之间的通信变得高效且透明。 1.2 RPC工作原理 RPC的工作过程可以分为以下几个步骤,参考微软官方文档: 客户端将参数和要调用的方法按约定序列化成NDR(Network Data Representation)格式。 通过网络或管道将数据发送给服务端。 服务端接收数据后将数据反序列化,并调用对应的接口中的方法,反序列化的数据按约定作为各参数。 服务端方法执行结束后,将返回结果序列化。 再次通过网络或管道将数据发送给客户端。 客户端接收数据后将数据反序列化,从而获得服务端执行结果。 1.3 为什么关注RPC? RPC作为Windows系统的核心组件,具有以下特点使其成为漏洞挖掘的重要目标,并且历史上也出现了非常多的漏洞: 丰富的攻击面:由于RPC是许多服务的基础,因此它提供了大量的潜在攻击点。 高权限运行:RPC服务通常以高权限(如SYSTEM权限)运行,或者至少具备SeImpersonatePrivilege权限。这意味着一旦被利用,攻击者可以利用RPC服务进行提权操作。 二、Windows RPC Demo 为了更好地理解RPC的工作机制,我们可以通过一个简单的Demo来展示RPC的基本操作。以下是Windows官方教程的Windows RPC服务端和客户端代码示例: 2.1 服务端代码 //file hello.idl [ uuid(7a98c250-6808-11cf-b73b-00aa00b677a7), version(1.0) ] interface hello { void HelloProc([in, string] unsigned char * pszString); void Shutdown(void); } /* file: hellos.c */ #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include "hello.h" #include <windows.h> void HelloProc(char * pszString) { printf("%s\n", pszString); } void Shutdown(void) { RPC_STATUS status; status = RpcMgmtStopServerListening(NULL); if (status) { exit(status); } status = RpcServerUnregisterIf(NULL, NULL, FALSE); if (status) { exit(status); } } void main() { RPC_STATUS status; unsigned char * pszProtocolSequence = "ncacn_np"; unsigned char * pszSecurity = NULL; unsigned char * pszEndpoint = "\\pipe\\hello"; unsigned int cMinCalls = 1; unsigned int fDontWait = FALSE; status = RpcServerUseProtseqEp(pszProtocolSequence, RPC_C_LISTEN_MAX_CALLS_DEFAULT, pszEndpoint, pszSecurity); if (status) exit(status); status = RpcServerRegisterIf(hello_ServerIfHandle, NULL, NULL); if (status) exit(status); status = RpcServerListen(cMinCalls, RPC_C_LISTEN_MAX_CALLS_DEFAULT, fDontWait); if (status) exit(status); } 初始化 RPC 服务 通过 RpcServerUseProtseqEp 指定通信协议和端点。 通过 RpcServerRegisterIf 注册 RPC 接口(hello_ServerIfHandle 是由 MIDL 编译器对interface hello生成的接口句柄,表示服务端的 RPC 接口)。 进入监听状态 调用 RpcServerListen,服务端开始监听客户端的 RPC 调用请求。 处理客户端请求 当客户端通过 RPC 调用服务器端的远程过程时,RPC 运行时会调用相应的服务器存根代码,进而执行实际的远程方法(HelloProc和Shutdown)。 2....

2025年03月05日 · 3 分钟 · lm0963

IoT小设备HTTP漏洞挖掘研究:BOA篇

BOA是IoT小设备上常见的HTTPD之一。本文将从源码分析、漏洞挖掘、真实漏洞分析三个部分总结BOA的相关特性。其中,源码分析部分涉及到Linux网络编程,漏洞挖掘部分主要关注于如何快速恢复请求结构体、了解数据包处理逻辑以及CGI如何传递数据,真实漏洞分析部分则是分析了三个典型的BOA认证前漏洞,其中两个能够导致认证前任意代码执行,一个认证前信息泄漏。 一、BOA简介 BOA是一个单任务的HTTPD,简单说,BOA不像常见的HTTPD,为每一个连接使用fork创建子进程进行处理,也不会提前创建一个进程池、线程池用于同时处理多个连接。它在内部采用了多路复用和请求链表来处理所有来自客户端的连接,并且仅仅针对CGI程序、自动目录生成和自动文件压缩采用fork子进程的形式进行处理。简而言之,BOA是一个轻量级的HTTP服务器,主要设计用于嵌入式系统,以高效的性能和小巧的代码体积著称,通常被应用于资源受限的设备,例如路由器、智能家居或者其他的嵌入式环境。 BOA具有如下的一些特点: 单线程架构:BOA采用了单线程、事件驱动的架构来处理多个HTTP请求。传统的WEB服务器会为每一个请求使用fork创建子进程进行处理,每次请求都会造成进程创建的开销。BOA的架构避免了这种操作,从而节省了系统资源。但是,只能说BOA适合嵌入式这种请求速度慢、并发少的情景。 资源占用低:BOA的代码体积非常小,内存和CPU的使用效率高,适用于资源受限的嵌入式设备。 配置简单:BOA的配置文件简单明了,容易调整和优化,可以快速进行部署。 快速响应:单线程事件驱动模型使得在轻负载情况下响应迅速,适用于处理少量并发连接。 BOA的源码和官方文档都可以在Boa Webserver处找到。 二、BOA源码分析(TL;DR) 本章节从源码分析BOA,主要从常规分析HTTPD源码的角度,例如信号量处理、socket从创建到复用、CGI数据传递等,帮助更好理解BOA的运行特性。该部分篇幅过长,对Linux网络编程已经较为熟悉的师傅可以跳过到2.4节BOA的请求结构体说明部分和2.5节状态机处理数据包示意图部分。 2.1 信号量处理 HTTPD服务器会处理一些常见的信号量,以免HTTPD发生异常终止。在BOA中也是如此,main函数中调用函数init_signals,收到指定的信号时,执行预先设定的处理函数。 信号量的处理一般是如下流程: 创建信号量处理相关的结构体变量。 初始化清空信号量集合。 将需要关注的信号量以及对应信号量的处理函数加入到信号量集合中。 当HTTPD接收到相应的信号量时,执行预先设定的处理函数。 BOA源码中,对信号量的处理也是满足如上的流程。 /* * Name: init_signals * Description: Sets up signal handlers for all our friends. */ void init_signals(void) // 初始化信号处理函数,收到指定信号的时候,执行预定义的处理函数 { struct sigaction sa; // 不使用任何特殊标志 sa.sa_flags = 0; // 初始化信号屏蔽集sa_mask // 将如下的几个信号量,添加到sa_mask中 sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGSEGV); // 段错误 sigaddset(&sa.sa_mask, SIGBUS); // 总线错误 sigaddset(&sa.sa_mask, SIGTERM); // 终止信号 sigaddset(&sa.sa_mask, SIGHUP); // 挂起信号 sigaddset(&sa....

2025年02月26日 · 6 分钟 · OneShell

探索协程世界:原理、现实与漏洞模式(下)

在本文的上篇关于协程相关理论的介绍后,相信读者已经对协程有了大致的认识,所以接下来将会介绍在过去发生过的与协程相关的安全问题。因为协程在不同语言的实现差异,会导致其呈现的形式也会有所差异。本篇将选取几个比较有特征的案例介绍。 一、anyio - Race Condition 这个问题并没有获得CVE编号,是用户进行测试的时候发现的。anyio是一个 Python 异步网络并发库,可以在trio或者asyncio上运行。其完美的兼容了asyncio和trio,可以很方便的让代码进行重构。 然而这个库存在一个奇怪的问题,当尝试使用多线程访问这个库的时候,有概率触发一个库未初始化的问题。经过开发者定位,错误的代码位置如下: def get_async_backend(asynclib_name: str | None = None) -> AsyncBackend: if asynclib_name is None: asynclib_name = sniffio.current_async_library() modulename = "anyio._backends._" + asynclib_name try: module = sys.modules[modulename] except KeyError: module = import_module(modulename) return getattr(module, "backend_class") 这段代码的逻辑本质上为取出anyio中视线的另一个module对象并返回。实际上,在普通程序中他也被这样使用: async def sleep(delay: float) -> None: """ Pause the current task for the specified duration. :param delay: the duration, in seconds """ return await get_async_backend().sleep(delay) 可以看到,其取出来的库是提供支持协程异步函数的库。然而,这种写法其实存在一定的迷惑性。例如: async def func(d): await asy()....

2025年02月19日 · 10 分钟 · l1nk

探索协程世界:原理、实现与漏洞模式(上)

一、前言 在操作系统中,每当谈及异步,通常都是使用多线程/多进程来实现多任务的执行。然而在现代开发过程中,往往会听到一个新的概念:协程。这是一种更轻量化的并发处理模型,协程被广泛集成到诸如 Go、JavaScript、Rust 和 Python 等主流语言中,成为异步编程的核心工具。为了更好地理解协程,从而探究协程中可能存在的相关的安全问题,文章将简要介绍协程的起源与基本概念,然后通过分析协程模型的特点揭示潜在的安全风险,最后结合真实的漏洞案例,展示协程可能引发的安全隐患,并讨论如何更有效地规避这些问题。 由于内容较多,文章将分为上下两篇。在本文上篇中,会介绍协程的定义,包括常见的协程的用途以及协程在代码中的形式,接下来会给大家一个直观的感受,推断协程是如何诞生的。 二、什么是协程 关于协程的定义,这里直接摘自AI: 协程与传统函数调用的主要区别在于控制权的转移和状态的保存,这使得协程可以在中途挂起并在稍后恢复。 总结来看,协程具有如下的特征: 它不是一个由操作系统提供的特性,它是基于语言层面模拟的一个效果; 调度需要显示的声明起转换过程。 这里需要注意的是,协程于线程并非是同一个层级的概念,协程是一个用户态模拟的概念,而线程属于操作系统的原生概念。 通常,协程挂起的时候,会保存当前的上下文,包括栈堆以及寄存器等等。 由于协程非一个存在于操作系统的概念,所以对于操作系统而言,它并非真实存在,这就导致传统的调试器无法直接看到它,也就不存在直接观察它的办法。为了能对其有一个比较感性的认知,我们可以尝试先从编程语言中感受它的存在形式。在不同于语言中,协程的呈现形式也不同。比如在python中,协程的函数一般长成这样: import asyncio async def my_coroutine(): print("Start coroutine") await asyncio.sleep(1) print("End coroutine") async def main(): print("Start main") await my_coroutine() print("End main") ## Run the main function asyncio.run(main()) 其输出如下: Start main Start coroutine End coroutine End main 可以看到有几个关键点: 程序以异步的形式运行; 存在async/await关键字,被声明的函数才具有协程异步的能力; 需要使用asyncio.run将其包裹。 在协程使用更加广泛的go语言中,协程的代码如下所示: package main import ( "fmt" "time" ) func asyncTask(done chan string) { time.Sleep(2 * time....

2025年02月12日 · 6 分钟 · l1nk

Java XStream 反序列化:Gadget 挖掘思路分享

0x01 前言 Java语言中最常见的一类漏洞就是反序列化漏洞,在各种数据格式到Java对象的转化过程中,常常存在这类漏洞。常见的数据类型例如jdk提供的原生序列化数据、json、yaml、xml等等。针对这类漏洞存在一种特别的漏洞挖掘方式—Gadget挖掘,这种漏洞挖掘不需要去寻找特定的外部入口漏洞入口,入口往往是公开的,应用通过对传入的数据内容进行过滤和检查。XStream是一款针对XML和Java对象转换而开发的工具库,由于其本身的一些特点,成为了这类漏洞挖掘里一个很典型的例子,因此本文针对XStream进行Gadget挖掘分析。本文更多的是分享Gadget挖掘时的思路,进而可以在其他类型的序列化中进行类似的思考和尝试。 0x02 XStream简介 XStream是一个常用的Java对象和XML相互转换的Java库。 从java对象到XML: 从XML到Java对象: XStream在1.4.18版本以前是存在许多CVE的,核心原因在于的它使用类的黑名单进行防御,因此层出不穷的绕过,在1.4.18版本以后默认为白名单,用户需要自行根据需要使用的类进行配置,到这个版本XStream才没有继续爆出高危的反序列化漏洞。 值得一提的是,XStream中有CVE编号的利用链都是不依赖任何第三方库,纯利用JDK中的类进行利用,由此可见XStream对于反序列化的宽泛程度。 0x03 历史漏洞 简单介绍一下XStream反序列的特点。反序列化漏洞的本质是,基于可以利用的Java类:序列化数据流→Source→Gadget→Sink。 对于原生的Java反序列化来说,可以利用的Java类是任意实现了Serializable的类,入口是ObjectInputStream的readObject方法。 对于XStream来说,可以利用的Java是任意类,入口是XStream的fromXML方法。 以一个经典的CVE-2013-7285来说,poc如下,执行的sink是ProcessBuilder.start() XStream中有一系列的Converter,用于对不同的标签进行转化。 这里sorted-set标签对应的是TreeSetConverter,它的代码逻辑中会调用TreeMap的put方法,而TreeMap的put方法会调用方法的compare方法对传入Map的对象进行判断对象应该存放的位置 public V put(K key, V value) { ... // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t !...

2025年01月22日 · 4 分钟 · yyhy

Android保护机制及利用技巧总结

一、前言 本文总结了在Android上利用漏洞时遇到的一些新的保护机制以及在真机上的内核漏洞利用和调试技巧。虽然Android底层为Linux内核,但是相比较下Android内核更加难利用,主要体现在真机不能实时调试,可能开启了BTI保护、PAC保护和CFI保护,同时在近年新出的一些手机,如Pixel 10开启了内存标记访问保护Memory Tagging Extension(MTE)。本文还将介绍MTE保护在用户态时的一个特殊的绕过方法,通过探讨这些新的保护机制及其应对策略,我们希望能够帮助读者更好地理解当前Android安全环境,并为未来的漏洞研究提供新的思路和技术手段。 二、真机内核利用适配 对于一个真机内核,在编写漏洞利用程序期间可以编译一个版本一样的Linux内核用qemu模拟运行,便于掌握数据的处理过程。还可以使用Android模拟器,目前高版本的Android模拟器无法在x86/x64架构下模拟AARCH64的镜像,可以在AARCH64架构下的主机,如树莓派等下面运行模拟器。在模拟的内核中利用成功后,就是如何将其移植到真机上的问题。虽然真机不能实时调试,但是可以通过查看/sys/fs/pstore/目录下的日志文件以及dmesg来获取内核最后崩溃时的寄存器值。根据寄存器信息来定位漏洞利用程序中需要适配的位置。 root@apalis-imx8:~$ cat /sys/fs/pstore/dmesg-ramoops-0 Panic#1 Part1 <6>[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034] <5>[ 0.000000] Linux version 5.4.77-5.1.0-devel+git.a2f08dfd79ae (eichest@eichest-laptop) (gcc version 10.2.0 (Ubuntu 10.2.0-8ubuntu1)) #19 SMP PREEMPT Tue Apr 6 17:18:18 CEST 2021 <6>[ 0.000000] Machine model: Toradex Apalis iMX8QM V1.1 on Apalis Evaluation Board ... <6>[ 64.111102] sysrq: Trigger a crash <0>[ 64.114539] Kernel panic - not syncing: sysrq triggered crash <4>[ 64....

2025年01月15日 · 3 分钟 · ha1vk

CVE-2024-38054 Windows ksthunk.sys驱动提权漏洞分析

0x00 前言 最近,windows的Kernel Streaming框架出现了许多漏洞,本文通过分析CVE-2024-38054来了解一下Kernel Streaming这个攻击面。 CVE-2024-38054由 Angelboy提交给微软,在今年7月份修补的一个堆溢出漏洞。该漏洞在ksthunk.sys。驱动的作用是将WOW64(Windows 32-bit on Windows 64-bit)程序对使用Kernel Streaming框架的设备发起irp请求转化为64位的irp请求。以便后续处理无需区分wow64程序和正常64位程序。 目前由Fr0st1706编写的CVE-2024-38054的poc已经在GitHub公开。 0x01 Kernel Streaming框架简介 Kernel Streaming框架主要为windows中的音频、视频等设备提供支持。Kernel Streaming框架提供三种多媒体类驱动模型: port类, stream类和 AVStream类。 port 类是指用于 PCI 和基于 DMA 的音频设备。 stream类是指视频类设备。 AVStream 是 Microsoft 提供的多媒体类驱动程序,支持纯视频流和集成音频/视频流。 kernel steam架构如下所示: 由于音视频类的驱动大多是pnp类型的驱动,在windows中的设备不是类似\Devcie\NamedPipe的形式。而是类似下面形式: \\?\root#system#0000#{cf1dda2c-9743-11d0-a3ee-00a0c9223196}\{cfd669f1-9bc2-11d0-8299-0000f822fe8a}&{cf1dda2c-9743-11d0-a3ee-00a0c9223196} 如果想枚举pnp设备的路径的话,比较方便的方式是使用windows自带的工具: pnputil /enum-interfaces 也可以使用WDK提供的工具KsStudio来查看使用Kernel Streaming框架的驱动,我目前在win10下面测试正常,win11 ksmon.sys加载不上去。以wdk 10.0.26100.0为例,该程序的位置在:C:\Program Files (x86)\Windows Kits\10\Tools\10.0.26100.0\x64 中。该工具显示信息比较详细,对于某一项还是会有缺失。 另外一个缺点是筛选的种类有限,例如mskssrv.sys的类别是KSSTRING_Server 类别是{3C0D501A-140B-11D1-B40F-00A0C9223196}就没有在列表中。 在Kernel Streaming框架中有两个比较重要的内核对象种类:KS Filters 和 KS Pins ks filters是由微型端口驱动提供的filter factory创建的,用户态程序可以发起irp请求基于filter实例创建ks pin,然后使用ks pin实现向filter提交nodes 或者读取经过filter的数据。 0x02 pnp设备注册逻辑 以mskssrv.sys为例,可以在C:\Windows\INF\ks.inf中DeviceRegistration节中找到注册逻辑 可以看到在DeviceRegistration节中对HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 写入 rundll32.exe streamci,StreamingDeviceSetup {96E080C7-143C-11D1-B40F-00A0C9223196},{3C0D501A-140B-11D1-B40F-00A0C9223196},{3C0D501A-140B-11D1-B40F-00A0C9223196} 这个表示只会执行一次,执行streamci....

2025年01月08日 · 3 分钟 · pwnht

WSGI中的请求走私问题研究

一、WSGI介绍 WSGI是一种规范,描述了web server如何与web application通信的规范。 WSGI规范是为python生态定义的,符合WSGI接口的server如下所示: def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return '<h1>Hello, web!</h1>' environ:一个包含所有HTTP请求信息的dict对象; start_response:一个发送HTTP响应的函数。 WSGI server负责完成http请求解析到environ的映射过程,这样python的Web框架可以专注于业务逻辑,直接使用解析好的http请求对象。 二、请求走私 2.1 keep-alive 与 pipeline 为了缓解源站的压力,一般会在用户和后端服务器(源站)之间加设前置服务器,用以缓存、简单校验、负载均衡等,而前置服务器与后端服务器往往是在可靠的网络域中,ip 也是相对固定的,所以可以重用 TCP 连接来减少频繁 TCP 握手带来的开销。这里就用到了 HTTP1.1 中的 Keep-Alive 和 Pipeline 特性: 所谓 Keep-Alive,就是在 HTTP 请求中增加一个特殊的请求头 Connection: Keep-Alive,告诉服务器,接收完这次 HTTP 请求后,不要关闭 TCP 链接,后面对相同目标服务器的 HTTP 请求,重用这一个 TCP 链接,这样只需要进行一次 TCP 握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。这个特性在 HTTP1.1 中是默认开启的。 有了 Keep-Alive 之后,后续就有了 Pipeline,在这里呢,客户端可以像流水线一样发送自己的 HTTP 请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。现如今,浏览器默认是不启用 Pipeline 的,但是一般的服务器都提供了对 Pipleline 的支持。 http消息处理过程中出现两次http解析就可能出现走私,常见的情景里,容易出现在Content-Length 和 Transfer-Encoding 的处理差异中。而WSGI中进行了一次http请求解析,并且经常置于nginx等中间件后使用,所以也容易出现请求走私问题。 三、WSGI server中的走私问题 3....

2024年12月25日 · 5 分钟 · m4yfly