one_gadget实战:攻防世界babystack从栈溢出到getshell
1. 从一道栈溢出题说起one_gadget 到底解决什么问题如果你打过一段时间的 CTF pwn 题大概率会遇到这样一种情况题目给了栈溢出程序里也有现成的 system 函数或者后门函数但偏偏没有给你一个干净的/bin/sh字符串或者调用 system 之前寄存器状态不对导致你明明控制了返回地址却拿不到 shell。这时候很多人第一反应是去找pop rdi; ret这样的 gadget然后手动拼 ROP 链。但还有一种更省事的思路——直接找一个执行到某条指令时只要满足几个约束条件就能自动 execve(/bin/sh, ...)的地址跳过去就完事了。这个地址就是 one_gadget 要找的东西。one_gadget 是 Ruby 写的一个小工具专门用来在 libc 里搜索那些能一步 getshell 的指令片段。它的核心价值在于当你已经能控制程序执行流、并且知道 libc 基址的时候不需要再费劲去构造完整的 ROP 链只要满足某个 gadget 的约束条件直接跳到那个地址就能拿到 shell。这在堆题、格式化字符串题、以及一些栈溢出但空间受限的场景里特别有用。攻防世界 pwn 进阶区的 babystack 就是一道非常典型的适合用 one_gadget 来打的题。它本身逻辑不复杂但如果你只会用传统的 ret2libc 手法可能会在找/bin/sh和布置参数上卡住。而用 one_gadget整个利用过程会变得非常直接。这篇文章我会从这道题的实际利用出发把 one_gadget 的安装、用法、约束条件的判断方法、以及实战中容易踩的坑全部讲清楚。不管你是刚接触 pwn 的新手还是已经打过一些题但没用过 one_gadget 的选手都能从里面拿到可以直接复用的东西。2. babystack 的题目结构与我第一次分析时的判断2.1 拿到题目后的第一轮信息收集拿到 babystack 这道题第一步永远是看保护。用checksec跑一下典型的输出大概是Partial RELRO、No Canary found、NX enabled、No PIE。这个组合意味着什么没有 Canary说明栈溢出可以直接覆盖返回地址而不触发检测No PIE说明程序本身的代码段地址是固定的我们可以直接用程序里的 gadgetNX enabled说明栈上不可执行不能直接往栈上写 shellcode 然后跳过去。接下来用file看一下架构一般是 64 位 ELF。然后用 IDA 或者 objdump 看主逻辑。babystack 的主函数通常长这样读入一段内容到栈上的缓冲区缓冲区大小比如是 0x10 或者 0x20但 read 或者 gets 读入的长度远大于缓冲区大小典型的栈溢出。程序里可能还会有一个已经调用过的函数比如read、puts、printf之类这些函数的 GOT 表项里存着 libc 里的真实地址可以用来泄漏 libc 基址。我第一次分析的时候习惯性地先找有没有现成的后门函数。很多 babystack 类的题目会藏一个system(/bin/sh)或者execve(/bin/sh)的函数如果有那直接覆盖返回地址跳过去就结束了。但这道题没有。程序里只有普通的输入输出逻辑没有任何直接 getshell 的代码路径。这就意味着必须走 libc 泄漏加 ROP 的路线。2.2 为什么这道题适合用 one_gadget 而不是传统 ROP传统 ret2libc 的思路是先泄漏 libc 基址然后计算 system 和/bin/sh的地址构造pop rdi; ret/bin/shsystem的 ROP 链。这个思路本身没问题但在这道题上会遇到两个实际困难。第一个困难是 gadget 的可用性。64 位程序里要调用 system 需要把/bin/sh的地址放到 rdi 寄存器里。如果程序里恰好有pop rdi; ret这个 gadget那还好办。但有些 babystack 版本里程序本身很小gadget 数量有限可能找不到干净的pop rdi; ret。这时候你就得去 libc 里找但 libc 里的 gadget 地址需要先知道 libc 基址而泄漏 libc 基址又需要先构造一次 ROP这就变成了一个鸡生蛋蛋生鸡的问题。第二个困难是栈空间和调用约定。即使找到了pop rdi; ret构造 ROP 链的时候还需要考虑栈对齐问题。64 位下调用 system 时如果栈没有 16 字节对齐可能会在 system 内部的 movaps 指令处崩溃。这个坑非常隐蔽很多人第一次打的时候会莫名其妙地 segfault排查半天才发现是栈对齐问题。one_gadget 的好处就在于它绕过了这两个困难。你不需要找pop rdi; ret也不需要手动布置/bin/sh参数只要 libc 基址已知直接跳到 one_gadget 的地址它内部已经帮你把 execve 的参数准备好了。当然代价是你需要满足它的一些约束条件比如某个寄存器必须为 NULL或者栈上某个位置必须是可写的。这些约束条件在实战中通常是可以满足的尤其是当你能控制程序执行流的时候。3. one_gadget 的安装与基础用法详解3.1 安装过程中容易忽略的依赖问题one_gadget 是 Ruby gem 包安装命令很简单gem install one_gadget但实际安装的时候很多人会卡在依赖上。首先你的系统里得有 Ruby 环境而且版本不能太老。其次one_gadget 依赖elftools这个 gem它会自动安装但如果你的网络环境访问 RubyGems 比较慢可能会超时。我的经验是如果gem install卡住不动可以先换一下 gem 源或者直接用系统包管理器装一个预编译版本。安装完之后用one_gadget --version验证一下。如果提示找不到命令说明 gem 的 bin 目录没有加到 PATH 里。Ruby gem 的可执行文件通常放在~/.gem/ruby/x.x.x/bin或者/usr/local/bin下面你需要把这个路径加到环境变量里。这个坑很基础但确实有不少人第一次装完之后发现命令用不了就是因为 PATH 没配好。还有一个常见问题是 libc 版本不匹配。one_gadget 是直接分析你指定的 libc 文件所以你必须用题目实际使用的那个 libc。如果你随便拿一个本机的 libc 去跑找到的 gadget 地址和约束条件可能和题目环境完全不一样。babystack 这类题目通常会提供一个 libc 文件或者你需要根据泄漏出来的函数地址去 libc 数据库里查对应的版本。这一步千万不能偷懒libc 版本错了后面全错。3.2 基本命令与输出解读one_gadget 最基本的用法就是直接跟一个 libc 文件路径one_gadget ./libc-2.23.so输出通常是这样几行0x45216 execve(/bin/sh, rsp0x30, environ) constraints: rax NULL 0x4526a execve(/bin/sh, rsp0x30, environ) constraints: [rsp0x30] NULL 0xf02a4 execve(/bin/sh, rsp0x30, environ) constraints: [rsp0x30] NULL 0xf1147 execve(/bin/sh, rsp0x30, environ) constraints: [rsp0x30] NULL每一块包含两部分第一行是 gadget 的地址相对于 libc 基址的偏移以及它实际执行的 execve 调用形式下面 constraints 是使用这个 gadget 必须满足的条件。这里需要重点解释一下 constraints 的含义。rax NULL意思是跳转到这个 gadget 的时候rax 寄存器的值必须是 0。[rsp0x30] NULL意思是栈指针往上偏移 0x30 的那个内存位置里面存的值必须是 0。这些条件看起来有点奇怪但理解之后就会发现它们其实是 execve 调用时对参数寄存器的要求。execve 的第一个参数是 filename第二个参数是 argv第三个参数是 envp。one_gadget 找到的这些片段通常是在 libc 内部某些函数的执行路径上此时 rdi 已经指向了/bin/sh字符串rsi 和 rdx 可能已经满足条件但 rax 或者栈上某个位置需要是 NULL 才能让 execve 正常执行。3.3 如何选择最合适的 gadget面对多个 gadget怎么选我的原则是优先选约束条件最容易满足的。[rsp0x30] NULL这种条件在栈溢出场景下通常比较好满足因为你可以控制栈上的内容。而rax NULL这种寄存器条件就需要看你在跳转之前 rax 的值是什么有时候可以通过前面的函数调用来控制。还有一个技巧是用one_gadget -l参数列出所有 gadget 的详细信息包括它们所在的函数和更完整的约束。有时候默认输出只显示部分约束用-l可以看到更全面的条件避免选了一个看起来简单但实际上还有其他隐藏约束的 gadget。另外one_gadget 还支持--raw参数只输出地址方便脚本直接读取。在写 exp 的时候我通常会先用 one_gadget 手动跑一遍把候选地址记下来然后在脚本里硬编码或者用正则解析。如果题目环境经常变也可以把 one_gadget 集成到 exp 脚本里动态获取但这样会让脚本依赖 Ruby 环境不太适合分享给别人。4. babystack 的完整利用链路从泄漏到 getshell4.1 第一次栈溢出泄漏 libc 基址babystack 的利用分两步。第一步是泄漏 libc 基址。由于程序有栈溢出我们可以构造一个 ROP 链调用puts或者write函数把某个 libc 函数的 GOT 表项内容打印出来。比如from pwn import * p process(./babystack) elf ELF(./babystack) libc ELF(./libc-2.23.so) pop_rdi 0x4007c3 # 假设程序里有这个 gadget puts_plt elf.plt[puts] puts_got elf.got[puts] main_addr elf.symbols[main] payload bA * 0x10 bB * 8 # 填充到返回地址 payload p64(pop_rdi) payload p64(puts_got) payload p64(puts_plt) payload p64(main_addr) p.sendline(payload) leaked u64(p.recvline().strip().ljust(8, b\x00)) libc_base leaked - libc.symbols[puts]这里有几个细节需要注意。填充长度必须算准0x10是缓冲区大小8是 saved rbp 的大小加起来才是返回地址的偏移。这个偏移如果算错了整个 ROP 链就会错位程序会直接崩溃。我一般会在 IDA 里仔细看栈帧布局确认缓冲区起始位置到返回地址的距离。泄漏的时候puts会打印 GOT 表里的地址直到遇到\x00才停止。所以接收的时候要用recvline然后手动补齐 8 字节。有时候puts打印出来的地址只有 6 字节有效高位是\x00所以ljust(8, b\x00)这一步不能省。拿到泄漏地址后减去puts在 libc 里的偏移就得到了 libc 基址。然后用libc.address libc_base设置一下后面就可以直接用libc.symbols[system]这样的方式获取地址了。4.2 第二次栈溢出用 one_gadget 完成利用拿到 libc 基址之后第二次栈溢出就简单了。我们再次触发溢出这次直接跳到 one_gadget 的地址one_gadget_offset 0xf1147 # 从 one_gadget 输出里选一个 one_gadget_addr libc_base one_gadget_offset payload bA * 0x10 bB * 8 payload p64(one_gadget_addr) p.sendline(payload) p.interactive()看起来很简单但实际打的时候十有八九第一次不会成功。原因就是约束条件没有满足。比如你选的 gadget 要求[rsp0x30] NULL但你在跳转的时候栈上那个位置恰好不是 NULLexecve 就会失败程序崩溃。这时候就需要在 payload 里做文章。你可以在跳转到 one_gadget 之前先布置一下栈上的内容让[rsp0x30]变成 NULL。具体怎么做可以在 payload 里多填充一些\x00或者调整填充长度让栈指针的位置刚好落在你控制的全零区域上。这个需要根据实际情况调试没有固定公式。我的经验是先用 gdb 附加到进程在跳转到 one_gadget 的地址之前下断点然后看 rsp 的值和[rsp0x30]的内容。如果[rsp0x30]不是 NULL就调整 payload 的填充或者换一个约束条件不同的 gadget。有时候换一个 gadget 比硬调栈布局更省事。4.3 栈对齐问题与 one_gadget 的兼容性前面提到过栈对齐问题这里再展开说一下。64 位下调用函数时栈指针必须是 16 字节对齐的。one_gadget 内部的 execve 调用同样遵循这个规则。如果你跳转到 one_gadget 的时候rsp 没有对齐execve 内部的某些指令可能会触发 SIGSEGV。怎么判断是否对齐在 gdb 里看 rsp 的值如果 rsp 的末位是 0说明是 16 字节对齐如果是 8说明没有对齐。如果不对齐可以在 payload 里加一个retgadget 来调整。ret指令会让 rsp 增加 8从而改变对齐状态。这个技巧在传统 ROP 里很常用用 one_gadget 的时候同样适用。不过 one_gadget 的约束条件里通常不会直接写栈对齐因为它是从 libc 内部某个调用点开始的那个调用点的栈对齐状态是固定的。你跳过去的时候只要保证你的 rsp 和那个调用点的 rsp 对齐状态一致就行。实际调试的时候如果发现跳过去就崩可以先试试加一个ret调整一下。5. 实战中那些文档不会告诉你的坑5.1 libc 版本识别错误导致的连锁反应这是最致命的坑。babystack 题目提供的 libc 文件和你本机系统的 libc 很可能不是一个版本。如果你用本机的 libc 去跑 one_gadget找到的 gadget 偏移和约束条件都是错的exp 打过去必然失败。怎么确认 libc 版本最可靠的方法是用泄漏出来的函数地址去 libc 数据库里查。比如你泄漏了puts的地址就用这个地址的低 12 位因为页对齐低 12 位不受基址影响去匹配。或者用libc-database这类工具输入几个函数的地址它会帮你找到对应的 libc 版本。还有一个细节有些题目给的 libc 文件名字是改过的比如libc.so.6但实际版本可能和文件名暗示的不一样。不要相信文件名要用工具验证。我一般会用strings libc.so.6 | grep GNU C Library看一下版本号然后再用 one_gadget 跑。5.2 one_gadget 约束条件的动态验证方法one_gadget 输出的约束条件是静态分析的结果但实际运行时寄存器和栈的状态是动态的。有时候静态分析说某个条件必须满足但实际上因为执行路径不同那个条件可能已经被满足了或者根本不重要。我的做法是在 gdb 里跳到 one_gadget 地址之前先手动检查一遍所有约束条件。比如 gadget 要求rax NULL我就在 gdb 里p/x $rax看一下。如果确实是 0那就可以放心跳。如果不是就看看能不能通过前面的 ROP 链把 rax 清零。清零 rax 的方法有很多比如调用一个返回值为 0 的函数或者用xor eax, eax; ret这样的 gadget。还有一种情况是约束条件互相冲突。比如 gadget A 要求rax NULLgadget B 要求[rsp0x30] NULL但你当前的栈布局只能满足其中一个。这时候就要权衡看哪个更容易调整。通常来说栈上的条件比寄存器条件更容易满足因为栈是你直接控制的。5.3 从 babystack 延伸出的通用利用思路babystack 只是一个例子但它的利用思路可以迁移到很多类似的题目上。核心逻辑是先通过一次泄漏拿到 libc 基址然后第二次溢出直接用 one_gadget getshell。这个套路适用于所有有栈溢出、有输出函数、没有现成后门的题目。变种情况也有。比如有些题目只能溢出一次那就需要把泄漏和 getshell 合并到一次 ROP 链里。这时候 one_gadget 可能不太适用因为你需要先泄漏再跳转而 one_gadget 是直接 getshell 的。这种情况下还是得用传统的 ret2libc。所以 one_gadget 不是万能的它最适合的是可以多次溢出或者已经知道 libc 基址的场景。还有一种情况是题目开了 PIE但给了泄漏。这时候程序本身的 gadget 地址也是随机的但 libc 的 gadget 地址只依赖于 libc 基址。所以用 one_gadget 反而比找程序本身的 gadget 更方便因为程序本身的 gadget 需要先泄漏程序基址而 one_gadget 只需要 libc 基址。6. 把 one_gadget 用得更顺手的几个进阶技巧6.1 批量筛选 gadget 的脚本化方法当 libc 里有十几个 one_gadget 的时候手动一个个试很浪费时间。我通常会写一个小脚本把 one_gadget 的输出解析成列表然后依次尝试每个 gadget直到成功 getshell。脚本的大致逻辑是import subprocess import re def get_one_gadgets(libc_path): result subprocess.run([one_gadget, libc_path], capture_outputTrue, textTrue) gadgets [] for line in result.stdout.split(\n): match re.match(r(0x[0-9a-f]), line) if match: gadgets.append(int(match.group(1), 16)) return gadgets gadgets get_one_gadgets(./libc-2.23.so) for offset in gadgets: try: # 构造 payload 并尝试 payload bA * 0x10 bB * 8 p64(libc_base offset) p.sendline(payload) p.interactive() break except: continue这个脚本的关键是异常处理。如果某个 gadget 失败程序会崩溃你需要重新启动进程再试下一个。实际写的时候要把进程启动放在循环内部每次尝试都重新开一个进程。6.2 结合 gdb 插件加速调试gdb 有一些插件可以显示 one_gadget 的信息比如 pwndbg 和 gef。pwndbg 里有一个one_gadget命令可以直接在调试的时候列出当前 libc 的所有 gadget 和约束条件。这样你就不用来回切换终端了。用法很简单在 gdb 里输入one_gadget它会输出和命令行工具一样的结果。然后你可以结合vmmap查看 libc 基址直接计算出 gadget 的绝对地址。调试的时候我通常会在跳转指令处下断点然后单步执行到 one_gadget 地址观察寄存器和栈的变化确认约束条件是否满足。6.3 约束条件不满足时的补救手段如果所有 gadget 的约束条件都不满足怎么办这时候可以考虑用 ROP 链先调整寄存器和栈然后再跳到 one_gadget。比如某个 gadget 要求rax NULL你可以先找一个xor eax, eax; ret的 gadget把 rax 清零然后再跳到 one_gadget。或者你可以用pop rsi; ret和pop rdx; ret这样的 gadget手动设置 execve 的参数然后直接调用 execve。这其实就退化成传统的 ROP 了但有时候比硬凑 one_gadget 的条件更简单。还有一种情况是 one_gadget 的地址包含\x00或者\n这样的坏字符导致 payload 被截断。这时候要么换一个 gadget要么用编码的方式绕过。babystack 这类题目通常没有坏字符限制但如果是字符串输入函数就要注意\n和\x00的问题。7. 关于 one_gadget 和 babystack 的一些个人体会打 babystack 这道题的时候我最大的感受是one_gadget 确实能省很多事但它不是银弹。它的价值在于给你多一个选择而不是替代传统的 ROP 技术。很多时候传统 ROP 更可控因为你知道每一步在做什么而 one_gadget 更像是一个黑盒你只知道跳过去可能 getshell但具体能不能成功取决于一堆约束条件。我的建议是先把传统的 ret2libc 练熟理解 ROP 链的构造原理和栈对齐这些底层细节。然后再学 one_gadget把它当成一个加速工具。这样即使 one_gadget 用不了你也有备选方案。另外one_gadget 的约束条件一定要动态验证不要只看静态输出。gdb 是你最好的朋友多在里面观察寄存器和栈的状态比盲目试错效率高得多。还有libc 版本一定要确认清楚这是所有利用的前提。版本错了后面全白搭。最后说一个实用的小技巧如果你在打远程的时候本地能通但远程不通大概率是 libc 版本不一致。这时候不要怀疑自己的 exp先去确认远程环境的 libc 版本。很多 CTF 题目会在题目描述里给出 libc 文件或者你可以通过泄漏多个函数的地址来精确匹配版本。这个排查思路能帮你省下大量时间。

相关新闻

从简历海啸到智能初筛:我用 ModelEngine Nexent 零代码搭建了一个招聘 Agent

从简历海啸到智能初筛:我用 ModelEngine Nexent 零代码搭建了一个招聘 Agent

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

2026/10/12 23:31:25 阅读更多 →
Anaconda+Jupyter数据分析环境配置与实战指南

Anaconda+Jupyter数据分析环境配置与实战指南

1. 为什么数据分析老手都绕不开Anaconda这套组合刚接触Python做数据分析的人,十有八九会在环境配置这一步卡住。你可能只是想跑个pandas读CSV,结果装完Python发现缺numpy,装完numpy又提示scipy版本不兼容,好不容易凑齐了&#xff…

2026/10/12 23:31:25 阅读更多 →
数据链路层真题避坑指南:HDLC、CRC与滑动窗口的比特级验证

数据链路层真题避坑指南:HDLC、CRC与滑动窗口的比特级验证

简介:本资源是《计算机网络原理》课程第四章‘数据链路层’的权威试题汇编PPT,专为高校计算机类专业学生、考研备考者及教师命题参考设计,聚焦HDLC协议、PPP协议、CRC循环冗余校验、流量控制(停止等待/滑动窗口)、差错…

2026/10/12 23:30:25 阅读更多 →

最新新闻

IIS管理器打开全攻略:本机启动、远程连接与排错实战

IIS管理器打开全攻略:本机启动、远程连接与排错实战

搞Windows服务器的同学都清楚,IIS管理器这个窗口,看着不起眼,却是撑起大量Web业务的关键工具。很多人以为它就是个“打开就能用”的图形界面,但在实际运维里,光是怎么把它顺利打开、正常连上远程站点,就能筛…

2026/10/13 5:33:32 阅读更多 →
从compose到组合上下文:函数组合的工程化实战复盘

从compose到组合上下文:函数组合的工程化实战复盘

函数组合不是新东西,但真正把它做到"极致"和"优雅",我用了将近一年的时间反复打磨。这篇文章是我对这段时间的完整复盘。我不打算讲枯燥的范畴论,也不打算罗列一堆库的API,我想说的是:我如何从一个…

2026/10/13 5:33:32 阅读更多 →
充电器空载发热、待机功耗异常怎么办?温度保险电阻排查维修实战

充电器空载发热、待机功耗异常怎么办?温度保险电阻排查维修实战

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

2026/10/13 5:33:32 阅读更多 →
fio-3.8完整指南:从解压编译到IOPS与延迟分析实战

fio-3.8完整指南:从解压编译到IOPS与延迟分析实战

简介:FIO(Flexible I/O Tester)3.8 版本完整源代码压缩包,面向存储性能测试工程师、系统运维与内核/驱动开发者,用于在 SSD、HDD、RAID、NVMe 等场景下评估读写吞吐、IOPS 与延迟,并开展压力测试与瓶颈定位…

2026/10/13 5:33:32 阅读更多 →
python -v 和 python -V 的区别:命令行参数大小写敏感与解释器启动排查

python -v 和 python -V 的区别:命令行参数大小写敏感与解释器启动排查

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

2026/10/13 5:33:32 阅读更多 →
目标类型new表达式:现代编程语言的类型推断演进

目标类型new表达式:现代编程语言的类型推断演进

1. 目标类型new表达式的前世今生第一次看到var list new List<string>();这种写法时&#xff0c;我还在用Java写ArrayList<String> list new ArrayList<String>();。这种重复的类型声明总让我觉得像在说废话——明明右边已经写了类型&#xff0c;为什么左边…

2026/10/13 5:32:32 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →