拆解iOS自动抢红包插件:从dylib注入到防撤回原理
简介面向iOS越狱环境下微信功能增强的实际需求这份插件包集成自动抢红包与消息防撤回两大能力既适合普通用户直接安装体验也适合越狱插件开发人员研究实现原理尤其适合经常参与群聊抢红包或关注消息撤回场景的用户。压缩包共30个文件整体体积仅817KB内含8张png功能截图主要包含5个deb安装包、2个dylib动态库、5个plist配置以及Xcode工程源码、头文件和说明文档。目前已有519人学习下载。包内提供ConfigForWeChatRedEnvelop等配置项配合截图演示、ReadMe与README文档可快速掌握参数含义、部署流程和不同版本deb的差异对于想深入学习越狱插件开发的人xcodeproj工程、xm与mm源文件、plist配置及dylib动态库相互参照能清晰呈现从源码编写、编译打包到动态注入的完整链路方便对照调试、二次开发或按需查阅。1. 这个iOS插件包到底拆出来是什么从一次抢红包延迟说起过年群里抢红包手速再快也拼不过秒抢的后来发现是有人挂了iOS自动抢红包插件。这份资源包标称支持某信iOS端自动抢红包和消息防撤回拆开以后其实是两个核心模块一个是注入到某信进程的dylib动态库另一个是配套的配置文件。本文不讨论该不该用只从逆向工程角度把它的原理、实现路径和踩坑点讲透。适合对iOS逆向、越狱开发、tweak编写有基本概念但还没完整拆过类似包的开发者也适合想评估这类插件风险、决定值不值得自己研究源码的人。2. 先理解自动抢红包的技术前提消息通知与代码注入2.1 抢红包的三种常见实现路径自动抢红包在iOS上有三种典型路线资源包选的是第三种。第一种是模拟通知栏点击。通过监听系统推送检测到“红包”关键词后利用辅助功能或者后台唤起某信再模拟点击进入会话。这种方案最容易被系统限制因为iOS对后台唤起和自动点击的权限卡得很严而且某信客户端本身对通知栏跳转做了限制经常点进去却不是红包消息。第二种是网络抓包后直接构造请求。在越狱环境下挂钩网络层拦截某信与服务器之间的通信看到红包消息后直接伪造领取请求。这种方案技术门槛高因为某信的协议加密和签名校验一直在升级但一旦成功效率极高。资源包里没有看到网络库排除这种。第三种是注入进程后调用内部方法。利用MobileSubstrate或类似框架把dylib注入某信进程hook住消息管理器和视图展示方法监听到红包消息后直接调用客户端内部的开红包方法。这个方案的难点在于找到正确的类和方法名以及处理红包消息的异步回调。这份资源包的实现根据文件命名和代码特征判断就是这一种。2.2 为什么iOS上必须走注入沙盒与签名机制不做越狱的话常规第三方App根本没法修改另一个App的行为。iOS普通App运行在沙盒里进程隔离不能读写别的App的内存空间也没有权限加载外部动态库。某信自己的签名只覆盖其官方二进制系统不认非官方的代码签名。所以这类插件通常要求设备已越狱。越狱后系统代码签名验证被绕过或者说被patch掉了这样才有机会把dylib塞进某信进程。注入方式一般有两种一种是修改某信的可执行文件的Load Commands加入一个LC_LOAD_DYLIB另一种是利用动态库注入工具比如使用Substrate的SubstrateLoader在App启动时提前加载第三方插件。资源包里的dylib文件如果直接用file命令查看能看到它是arm64架构编译的里面包含了对某信私有类的引用。但要让它真正加载还需要一个plist文件里面声明了该dylib的Bundle Filter即要注入的目标进程。这个plist通常放在动态库安装包的Library/MobileSubstrate/DynamicLibraries目录下或者在zip内以独立配置形式存在。2.3 资源包里应该有哪些文件tweak结构速览我拆过好几个类似的tweak包这份资源包的内部结构比较典型。先解压zip你会看到大致如下的目录# 解压后目录结构 AutoRedPacketTweak/ ├── Library/ │ └── MobileSubstrate/ │ └── DynamicLibraries/ │ ├── RedPacketTweak.dylib # 抢红包主逻辑 │ ├── AntiRevokeTweak.dylib # 防撤回逻辑 │ ├── RedPacketTweak.plist # 注入配置 │ └── AntiRevokeTweak.plist ├── DEBIAN/ │ └── control # 包管理信息描述依赖关系 ├── usr/ │ ├── bin/ │ │ └── unpack_rp.sh # 安装后触发脚本 │ └── lib/ │ └── libsubstrate.dylib # 运行时依赖库部分包会带 └── README.md这段目录是常见的动态库插件打包格式。其中dylib是编译产物包含所有hook逻辑plist决定注入到哪个进程格式大概是这样的!-- RedPacketTweak.plist -- ?xml version1.0 encodingUTF-8? !DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd plist version1.0 dict keyBundle/key stringcom.wechat.app/string keyFilter/key dict keyExecutable/key stringWeChat/string /dict /dict /plist解读一下参数Bundle指定目标App的Bundle ID这里用了某信的标准IDExecutable是目标可执行文件名。如果没有这个plist系统不知道把dylib加载到哪个进程也不会生效。DEBIAN目录是为方便用包管理器安装而做的如果你只是手动拷贝可以忽略。3. 拆包实战用class-dump和Hopper还原功能逻辑3.1 把zip解包后先做静态检查拿到包别急着装先做静态分析。我一般先在macOS上解压用file命令看二进制架构再跑class-dump导出头文件最后用Hopper或IDA看关键方法的伪代码。# 解压后查看dylib基本信息 file RedPacketTweak.dylib # 输出: Mach-O 64-bit dynamically linked shared library arm64 # 检查签名信息 codesign -dv RedPacketTweak.dylib 21 | head -20 # 如果输出code object is not signed at all说明未签名安装到越狱设备后需要额外签名或依赖越狱环境。 # 用class-dump导出ObjC头文件 class-dump -S -H RedPacketTweak.dylib -o ./headers_rp # 导出后可以看到字符串和方法名比如对应红包消息的关键类 ls ./headers_rpclass-dump是逆向iOS二进制最常用的工具它能把Objective-C类的接口信息还原出来。从输出的头文件里你能看到插件里声明了哪些类比如某信的消息管理类、会话列表类等。注意class-dump只能还原接口不能还原实现所以接下来要进Hopper看汇编和伪代码。3.2 从二进制里找红包消息入口抢红包的核心逻辑第一步是找到红包消息到达时客户端内部会触发的回调方法。在class-dump出来的头文件里搜“RedEnvelope”或“RedPacket”关键字通常会定位到几个可疑的类比如消息模型类MMMessage、服务类等。我一般会先用Hopper打开dylib搜索字符串# 在Hopper里用字符串搜索 # 搜索 redPacketred_publicopenRedPacket 等 # 比如看到类似这样的内部方法调用 -[MMMsgXmlParser parseRedPacketContent:] -[RedPacketOpenManager openRedPacket:fromSession:completion:]这里说明插件hook了消息解析方法目的是在收到的xml内容中提取红包字段。当你看到parseRedPacketContent:就可以判断插件是在消息到达的第一时间介入抢在红包过期前触发。参数说明时间窗口很关键如果插件在消息解析阶段就直接调用开红包方法那么它不需要等UI刷新速度最快但这样做也可能导致消息还没显示就开红包造成界面错乱。所以很多插件会加一个延迟比如0.1到0.5秒让消息先落库。3.3 防撤回的黑匣子替换消息展示方法防撤回插件原理相对简单大部分做法是hook住撤回消息的通知方法。某信撤回消息时会调用一个类似revokeMsg:的方法把消息内容标记为撤回然后从界面上移除。防撤回插件只需要两个动作一个是拦截撤回消息的XML改成不执行删除另一个是把消息内容重新插入到数据库。用class-dump查看头文件你会看到类似这样的方法签名# class-dump输出示例 - (void)revokeMsg:(id)arg1; - (void)onRevokeMsg:(id)arg1;在Hopper里看实现插件通常是这样做的# 伪代码展示 - (void)revokeMsg:(id)msg { // 判断是否开启防撤回 if (isAntiRevokeEnabled) { // 不调用原始方法或者把原始消息的撤回标记置空 originalRevokeMsg MSHookMessage(self, selector(revokeMsg:), _original_revokeMsg); // 直接return什么都不做 return; } originalRevokeMsg(self, msg); // 正常撤回 }如果资源包还支持“对方撤回后自己仍能看到”它多半是修改了消息列表的数据源让已撤回的消息不被过滤掉。注意防撤回只能防自己的客户端对方那边依然会显示已撤回。群里如果有人撤回别人还是看不到只有装了插件的你能看到内容。4. 自动抢红包的触发逻辑从监听消息到模拟点击4.1 监听消息回调的hook点选择抢红包的启动点是消息回调。某信收到新消息后通常会有个统一入口比如消息通知中心的onNewMsg:方法。插件要先hook住这个方法判断消息类型是不是红包。选哪个hook点直接决定成功率。有的插件hook的是聊天界面刷新方法比如[MessageView reloadData]那么只有你正好打开某个聊天界面时才能触发实用性很差。好的插件会hook全局消息推送处理类比如某信的消息管理器这样即使你在后台也能在消息到达瞬间触发。代码层面的hook写法类似这样这里用常见tweak语言示例%hook NewMessageManager - (void)onNewMsg:(id)msg { %orig(msg); // 先调用原始方法保证消息正常落库 if ([msg hasRedEnvelope]) { // 延迟0.2秒后执行抢红包 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2*NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [self openRedEnvelope:msg]; }); } } %end这段代码的关键点是%orig(msg)它在hook之后先执行原逻辑避免因为拦截导致消息丢失。抢红包操作放在另一个线程或者延迟执行是为了避开主线程阻塞。0.2秒的延迟是很多tweak作者权衡后的经验值太短容易拿不到完整的红包数据太长会被别人抢走。4.2 红包检测与延迟参数调整红包检测怎么实现主要是解析消息的xml内容。某信的红包消息在xml里会有一个字段比如redEnvelope标签插件通过正则表达式或者字符串匹配来识别。检测到红包后下一步是自动点击。两种做法一种直接调用红包控制器的方法比如[RedPacketController openWithMessage:]另一种是遍历UI找到红包气泡的视图然后模拟一次触摸事件。资源包里通常会有配置文件让你调整是否只抢指定群的红包、是否延迟、是否过滤特定金额。比如一个简单的配置项# 配置文件常见格式 (AutoRedPacket.conf) [General] enabled true delay 0.2 # 秒 blacklist # 群名关键词过滤逗号分隔 whitelist # 只抢这些群不填表示所有群 maxAmount 0 # 0表示不限制 onlyFirst false # 只抢手气最佳参数含义delay越短抢到概率越大但容易触发某信风控。blacklist和whitelist都是字符串匹配注意如果群名是动态的用关键词匹配容易误判。maxAmount设置为非0时一般通过对红包消息的金额字段做判断但很多情况下金额是加密的这个选项不一定生效。4.3 防撤回的原理为什么撤回只是屏蔽很多用户误以为防撤回是拦截服务器数据实际上客户端根本控制不了服务器。某人撤回消息后某信服务器会向所有接收方客户端下发一条“撤回指令”接收方的App收到指令后把本地消息隐藏。所以防撤回插件做的事情就是让客户端不要执行这条隐藏指令。它看起来像“阻止撤回”但实际上只是把撤回指令忽略了。对方撤回的消息在你的设备上还在但你无法阻止对方在别人设备上撤回也无法让自己看到历史消息里已经被彻底删除的那些。从技术上说hook撤回指令的方法后插件两个选择要么完全忽略要么把撤回消息标记为已撤回但保留内容。有些防撤回插件同时支持“撤回后显示已撤回”的样式这需要额外修改消息状态字段代码复杂度更高。5. 避坑/常见问题安装崩溃、失效、封号风险排查5.1 现象装上插件后某信启动闪退原因基本是dylib依赖的某个类方法在新版某信中不存在了。比如某信从8.x升级后内部类名和方法签名改了一大批老插件直接调用旧方法就会崩。解决用class-dump导出当前某信版本的头文件比对插件引用的方法是否可以找到如果找不到说明插件没有兼容新版。另一个隐蔽原因是plist里Filter写错了比如可执行文件名大小写错误或者Bundle ID不对导致注入失败或注入到错误进程。5.2 现象自动抢红包从来没抢到过原因没有给某信开启通知权限或者后台刷新被关闭消息根本没有到达客户端。很多插件依赖系统推送来唤醒某信如果推送关闭插件只在你打开某信时才有机会生效。解决检查通知权限是否开启并把某信的后台刷新打开。另外确认插件延迟参数是否过大有些配置项被误改成5秒那基本没戏。我遇到过最尴尬的一次是配置文件里delay写成了整数5结果相当于5秒后执行红包早没了。5.3 现象某信升级后插件失效原因某信改了类名和方法偏移而tweak是通过方法名绑定的一旦方法不存在就会失效。这是iOS tweak的通病每次App版本大更新后都需要重新适配。解决先不升级某信等待插件更新再升级。或者自己用Frida动态看一下新版里对应方法变成了什么再重新编译dylib。如果你不懂怎么改最简单的办法是锁某信版本把自动更新关掉。5.4 现象设备出现莫名耗电或者有网络回传原因有些插件会收集用户数据并回传到作者服务器比如你绑定的账号、群列表、红包金额记录等。这类插件通常把网络代码藏在一个看似无关的类里不上报时看着一切正常。解决在越狱设备上用抓包工具检查插件是否有外联或者用lsof命令看该进程连接的网络地址。对于来历不明的zip包我会先在隔离环境里跑一遍插件看它有没有动态请求。另外自动抢红包本身就可能触发某信的风控机制轻则禁抢红包重则暂时封号。做技术分析可以装到主力机上需要自己权衡。5.5 现象安装后不生效但越狱环境显示正常原因越狱环境是否是rootless模式。现在新的越狱工具默认启用rootless动态库目录变成了/var/jb/usr/lib/...老插件还写在/usr/lib下系统不会加载。解决确认越狱类型如果是rootless需要把dylib放到/var/jb/Library/MobileSubstrate/DynamicLibraries并且修改动态库的install name。这个细节很容易被忽略很多插件失效不是代码问题而是安装路径不对。6. 验证和进阶如何让插件在iOS 17上继续工作iOS 17越狱后的环境变化不小。传统MobileSubstrate在部分新系统上兼容性不如以前你需要确认插件使用的依赖是Substrate还是ElleKit两者在rootless环境下的行为有差异。要验证dylib是否有效最直接的方式是动态调试。安装Frida然后运行frida-trace观察某信启动时是否加载了你的dylib# 在逻辑设备上执行 frida-trace -U -m *RedPacket* WeChat # 如果输出了相关调用说明插件被成功注入并且hook点被触发。如果没有任何输出说明dylib没有加载先排查路径和plist。另外可以用Frida列出所有模块确认动态库是否出现在进程内存中# 用Frida列出模块 frida -U -n WeChat -e Module.enumerateModules().forEach(m { if(m.name.includes(RedPacket)) console.log(m.name) })这段命令会告诉我们动态库是否真的在进程里。很多时候你觉得自己装了但是系统根本没加载它。自己写tweak的现代方案我推荐使用Theos ElleKit。Theos编译时生成dylib和plistElleKit负责注入兼容性比Substrate好。编译参数要注意# Theos编译一个arm64的tweak make package THEOS_DEVICE_SIMULATOR0 # 生成的包会包含deb安装到设备后自动部署如果你是初学者我更建议先从理解这份资源包的结构开始不要急着装到真实设备上。把class-dump导出的头文件对着Hopper逐条看熟悉某信消息链路的常见类和调用顺序比直接用别人的插件有价值得多。那以后我拆任何一款tweak包都会强制走一遍“file → class-dump → Hopper字符串搜索 → Frida验证”这条流程。插件是不是真的值那个价钱、有没有后门、版本兼容性如何半小时就能判断个大概。希望这次拆包笔记对你也有参考价值也希望你只把技术留在学习层面。本文还有配套的精品资源点击获取

相关新闻

DeepSeek本地部署:显存估算与量化优化实战指南

DeepSeek本地部署:显存估算与量化优化实战指南

简介:针对DeepSeek开源大模型的本地部署需求,这份PDF为开发者与企业技术团队提供了从硬件选型到环境配置的完整参考。文档按应用场景分级,覆盖个人开发测试(如7B参数以下)与生产级部署(32B以上GPU集群&…

2026/10/11 10:22:09 阅读更多 →
从“工具过载”到“精准调用”:用 TaoToken 统一 Key 打通 AgentScope Java 的 MCP 语义检索链路

从“工具过载”到“精准调用”:用 TaoToken 统一 Key 打通 AgentScope Java 的 MCP 语义检索链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:22:09 阅读更多 →
屏幕显示故障排查指南:黑屏花屏闪屏背后的显示链路真相

屏幕显示故障排查指南:黑屏花屏闪屏背后的显示链路真相

前面几篇都在聊电脑故障的排查思路,这次把屏幕显示问题单独拎出来讲。干这行久了,我发现一个很有意思的现象:大部分人遇到黑屏,第一反应是重装系统;看到花屏,就准备换显卡;屏幕闪两下&#xff0…

2026/10/11 10:21:09 阅读更多 →

最新新闻

Linux C++符号混淆实战:从符号泄露到崩溃还原

Linux C++符号混淆实战:从符号泄露到崩溃还原

上个月处理一个发布版Linux软件被逆向的排查,第一次动手就发现一个很扎心的现象:那个C项目没做任何符号层面的处理,对手一条nm命令下来,整个项目的内部函数名、类名、全局变量全部原样躺在那里。软件里有一块自研的核心算法&#…

2026/10/11 13:08:48 阅读更多 →
MFC下载器开发实战:WinInet、进度条与自绘界面

MFC下载器开发实战:WinInet、进度条与自绘界面

简介:这是一份MFC单文档/对话框框架下的文件下载工程源码包,面向Win32桌面应用初学者与需要实现HTTP下载、进度反馈和自定义界面的C开发者。包内包含完整的工程文件、界面位图资源、说明文档及编译生成文件,涵盖CInternetSession/CHttpFile的…

2026/10/11 13:08:48 阅读更多 →
VS2019 MFC双人五子棋实战:编译环境配置与核心代码解析

VS2019 MFC双人五子棋实战:编译环境配置与核心代码解析

简介:基于MFC框架的双人五子棋完整工程,已配好VS2019编译环境,适合有一定C基础、正在学习Windows界面编程或博弈算法实现的开发者。程序使用纯图形界面,支持黑白双方轮流落子、自动判断胜负、悔棋,以及棋局的保存与打开…

2026/10/11 13:08:48 阅读更多 →
BWO-KELM预测:白鲸优化调参提升KELM泛化能力

BWO-KELM预测:白鲸优化调参提升KELM泛化能力

简介:本资源是一套基于MATLAB实现的智能优化算法与机器学习融合的回归预测方案,面向高校研究生、科研人员及工程技术人员,解决小样本非线性回归建模中模型参数调优难、泛化能力弱等实际问题。压缩包共6个文件(4个核心m脚本、1个加…

2026/10/11 13:08:48 阅读更多 →
商品评论情感分析毕业设计:Python数据清洗到GUI模型部署全流程

商品评论情感分析毕业设计:Python数据清洗到GUI模型部署全流程

简介:一套基于Python的机器学习商品评论情感分析毕业设计完整项目,采用SVM与LSTM算法,并提供GUI可视化界面,适合计算机相关专业学生完成大作业、毕业设计及项目实战练习。项目经导师指导并评审通过,评分98分&#xff0…

2026/10/11 13:08:48 阅读更多 →
ImageJ Windows版从闪退到批量出图:内存设置、宏批处理与插件安装全攻略

ImageJ Windows版从闪退到批量出图:内存设置、宏批处理与插件安装全攻略

简介:这款ImageJ Windows版本采用64位Java 8捆绑,开箱即用,适合生物医学、材料科学等领域研究人员进行图像分析与测量。资源共430个文件,压缩包约47.72MB,以ijm宏、dll动态库、jar插件和java源码为主,同时内…

2026/10/11 13:07:48 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →