隐匿与追踪:Rootkit检测与绕过技术分析

Rootkit是一种高隐蔽性恶意软件,广泛用于网络攻击和高级持续性威胁(APT),通过隐藏进程、文件和网络连接等实现持久化控制。随着操作系统和安全技术的发展,Rootkit的实现和检测技术持续演进。本文通过探讨Rootkit的实现原理、检测方法、绕过策略及案例分析,为安全从业者提供技术参考。 一、Rootkit基础概念 1.1 定义 Rootkit是一种恶意软件,能够隐藏自身及相关活动(如进程、文件、网络连接),规避安全检测工具。根据运行环境,Rootkit主要分为: 用户态Rootkit:运行在用户空间,通过劫持库函数或注入进程实现隐藏。 内核态Rootkit:运行在内核空间,修改内核数据结构或代码,隐蔽性更高。 1.2 典型功能 隐藏进程:修改进程链表或系统调用结果,隐藏恶意进程。 隐藏文件:篡改文件系统接口,隐藏恶意文件。 隐藏网络连接:伪造网络状态,隐藏恶意流量。 提权后门:提供持久化高权限访问。 数据窃取:窃取敏感信息,传输至C2服务器。 自我保护:通过反调试技术阻止分析。 二、Rootkit实现技术 2.1 用户态Rootkit 用户态Rootkit运行在用户空间,部署简单但隐蔽性较低,适合快速攻击。 2.1.1 LD_PRELOAD劫持 通过设置LD_PRELOAD加载自定义动态库,覆盖标准库函数。例如,劫持readdir隐藏特定文件: struct dirent *readdir(DIR *dir) { static struct dirent *(*real_readdir)(DIR *) = NULL; if (!real_readdir) { real_readdir = dlsym(RTLD_NEXT, "readdir"); } struct dirent *entry = real_readdir(dir); while (entry && strstr(entry->d_name, "malicious")) { entry = real_readdir(dir); // 跳过包含"malicious"的文件 } return entry; } 它的原理是通过设置LD_PRELOAD环境变量,加载一个恶意共享库,覆盖标准库函数,比如readdir,用于隐藏恶意文件或目录。技术上,LD_PRELOAD利用Linux动态链接器的优先加载机制,将恶意函数置于标准库之前。实际用途包括隐藏恶意文件的目录列表,或伪装恶意进程的活动。优势是实现简单,只需编写少量代码并设置环境变量;但局限是依赖LD_PRELOAD变量,容易被检测,比如通过检查环境变量或LD_DEBUG日志。 2.1.2 进程注入 通过将恶意代码注入合法进程(如systemd),隐藏行为。例如,使用ptrace注入代码: void inject_code(pid_t pid, unsigned char *code, size_t len) { void *mem = mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mem == MAP_FAILED) { perror("mmap失败"); return; } memcpy(mem, code, len); if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { perror("ptrace失败"); return; } struct user_regs_struct regs; ptrace(PTRACE_GETREGS, pid, NULL, &regs); regs....

2025年05月14日 · 7 分钟 · finley

二进制混淆对抗技术研究

一、前言 在软件安全领域,二进制混淆与逆向工程始终处于动态对抗的两端。恶意软件利用混淆技术逃避检测,而安全研究人员则必须突破这些屏障,分析恶意行为或验证程序安全性。本文将从实战角度简述主流混淆技术的实现并给出可能的对抗方案。 二、对抗可执行文件变异 静态分析软件 IDA pro/Ghidra 等,直接以可执行文件 (PE, ELF, …) 作为输入。软件开发者为阻止逆向分析工程师使用相关软件进行分析,可以对编译生成的可执行文件进行变异以干扰静态分析软件加载目标程序, 常见的编译方式有: 加壳 压缩/加密原始可执行文件,并在运行时解压/解密 导入表隐藏 如 PE 的 IAT 表用户导入程序需要使用的外部函数,逆向工程师常常借助外部函数符号推断程序功能 头文件修改 修改如 PE 文件头等加载时必要的数据结构,以阻止静态分析工具加载程序内存DUMP 典型的加壳软件有 UPX,此类软件一般会设法将原始程序A 保存在新构造的程序 B 中,随后 B 在运行时会解压并释放执行原始程序 A,由于原始程序被压缩,静态分析软件无法直接从 B 中开始分析。 对抗此类加壳保护时, 我们有所谓的 “ESP 定律脱壳”: 其假设大部分此类壳采用栈的方式保存程序入口点时的CPU上下文,如 x86 下使用 pushad 之类的指令 在加壳后的程序完成解压或者解密动作后,其可能会为了模拟原始程序刚进入口点时的上下文效果从栈中恢复先前保存的上下文 逆向工程师可以利用硬件访问断点,在开始保存有上下文的栈中地址处设置硬件读断点,如果按预想触发,随后不久就可能看到代码跳转至原始程序的入口点处执行 脱壳的方式主要还是取决于加壳器的做法,有些壳可能只会加密部分代码段,此时他可能利用一些系统API提供的函数来提前在用户代码被执行前完成解密,比如 Windows 下的 TLSCallback,或 C Runtime 提供的init数组等。 二进制加壳使用的主要技术实际上源于静态二进制修改,一般来说你很难对代码段进行修补,会出现很多指令大小,占用空间的问题,所以一般的做法很多都是拷贝代码到另外一处,修补相关偏移等,所以他仍然需要在原始代码区域布置 jmp 等跳转,另外有些加密壳任然会保留原始代码的内存区域,只是将数据加密,所以可以简单通过布置执行断点完成脱壳。 总结来说逆向此类目标应该是利用各种方式接近代码解密完成后,真实程序刚好开始执行的位置,但实际上也不一定需要这么严谨,从分析的角度来看,如果不是需要成功脱壳并将其转化成无壳并可以执行的状态,则无需刻意分析其 OEP 等位置,只要将内存镜像 DUMP 下来后修正其 Header,保证 IDA 能加载分析即可。 DUMP 镜像的修复主要需要考虑的是 Header 的映射字段部分,需要将其Raw Addr调整至符合内存镜像的 Virtual Addr 处。...

2025年04月30日 · 2 分钟 · s0duku

WordPress插件认证绕过与权限提升漏洞实例分析

一、前言 管理员权限用户能够执行更多敏感操作,也更容易导致RCE(远程代码执行)。在 WordPress 中,管理员拥有安装任意插件的权限,因此用户如果拥有管理员权限,几乎等同于获得RCE。 下面从 diff 漏洞修复的角度,介绍 WordPress 插件中出现的 认证绕过和权限提升漏洞是如何导致获取管理员权限的。其中大部分漏洞与 WordPress 插件相关,也有小部分来自其他PHP项目。 二、认证绕过 2.1 CVE-2024-6695 USER PROFILE BUILDER <= 3.11.8 2.1.1 漏洞成因 漏洞成因是自动登录和用户注册流程对用户邮箱的字符串处理不一致。用户注册时未清除邮箱字符串中的空格字符,而自动登录流程会清除空格。攻击者可通过注册带空格的仿冒管理员邮箱(如admin@example.com )来利用此漏洞。利用前提是需要知道管理员邮箱地址且系统启用了自动登录功能。 function wppb_check_email_value( $message, $field, $request_data, $form_location ){ ... $user_signup = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . $wpdb->base_prefix . "signups WHERE user_email = %s AND active=0", $request_data['email'])); ... $users = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->users} WHERE user_email = %s", $request_data['email'])); 注册邮箱的检查逻辑是通过数据库查询判断用户输入的邮箱是否已存在,若不存在则允许注册。 在 wppb_check_email_value​ 函数中,程序未对注册邮箱进行规范化处理就直接执行数据库查询。 例如,若管理员邮箱是 admin@test.com​,攻击者可尝试注册 admin@test.com (尾部加一个空格)。由于程序未清理空格,数据库查询会将其视为新邮箱,从而绕过检查并成功注册。 function wppb_log_in_user( $redirect, $redirect_old ) { if( is_user_logged_in() ) { return; } ....

2025年04月23日 · 4 分钟 · cynault

Connexion API内存马植入研究

一、前言 Connexion 是一个现代 Python Web 框架, 使用 OpenAPI 规范直接驱动 Python Web API 开发,兼容同步(WSGI)和异步(ASGI)场景。本文将通过一个Connexion框架下一个代码执行的例子,探索这2种场景的内存马植入方式。 二、一个简单的Connexion API应用 Connexion API可以通过FlaskApp(同步)和AsyncApp(异步)两种方式创建,通过FlaskApp创建的代码如下: from connexion import FlaskApp app = FlaskApp(__name__) app.add_api('openapi.yml') if __name__ == '__main__': app.run(host='0.0.0.0', port=8888) 或者通过AsyncApp创建(官方推荐): from connexion import AsyncApp app = AsyncApp(__name__) app.add_api('openapi.yml') if __name__ == '__main__': app.run(host='0.0.0.0', port=8888) 启动前需要编写一个openapi.yml来定义API 的结构,包括接口对应的处理方法 openapi: 3.0.0 info: title: Simple Connexion API version: 1.0.0 paths: /eval: post: operationId: api.eval.run requestBody: content: application/x-www-form-urlencoded: schema: type: object required: - data properties: data: type: string responses: '200': description: OK content: text/plain: schema: type: string operationId定义的是api....

2025年04月09日 · 3 分钟 · p0melo

编码问题引起的RCE分析

一、前言 CVE-2024-12356命令注入漏洞影响BeyondTrust的Privileged Remote Access和Remote Support系列产品,并实际上依赖于PostgreSQL的CVE-2025-1094漏洞。本文从BeyondTrust的CVE-2024-12356为场景入口,逐步分析到PostgreSQL的CVE-2025-1094,解释引起命令注入的核心编码问题。 二、关键点分析 CVE-2024-12356命令注入漏洞通过WebSocket访问BeyondTrust认证前路由/nw,将HTTP中的Sec-WebSocket-Protocol子协议头设定为ingredi support desk customer thin(以及设定一些其它类似Host的必需参数),即可访问到thin-scc-wrapper脚本。 2.1 thin-scc-wrapper分析(CVE-2024-12356) thin-scc-wrapper文件补丁前后主要变化: ## ... omit if [[ "$authType" == "0" ]]; then ## read a normal sdcust gskey + blog "reading gskey" read -t 30 gskey || exit 1 + blog "read gskey as [$gskey]" ## ... omit - quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote) + quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo "$gskey" | $ingrediRoot/app/dbquote) if [[ $(echo "SELECT COUNT(1) FROM gw_sessions WHERE session_key = $quoted AND session_type = 'sdcust' AND (expiration IS NULL OR expiration>NOW())" | $db) !...

2025年04月02日 · 13 分钟 · tiangong

探索 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