<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>非尝咸鱼贩</title>
    <link>https://wechat2rss.xlab.app/feed/255746ce1fb5befc63e2be00eb25795409048fcb.xml</link>
    <description>临渊羡鱼，不如在家咸鱼&#xA;(wechat feed made by @ttttmr https://wechat2rss.xlab.app)</description>
    <managingEditor> (非尝咸鱼贩)</managingEditor>
    <image>
      <url>https://wx.qlogo.cn/mmhead/FiaIW3HsXzg5UColAniaWHMy6xarn7gJRiakyctAXxxhWqIRxZBROp1LFrag0IjwfUgYK51F7bibHgA/0</url>
      <title>非尝咸鱼贩</title>
      <link>https://wechat2rss.xlab.app/feed/255746ce1fb5befc63e2be00eb25795409048fcb.xml</link>
    </image>
    <item>
      <title>好像躲过了一次噶腰子</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486081&amp;idx=1&amp;sn=d5900c8ffd1a36e29172c1a4c91393cf</link>
      <description>欧陆奇葩历险记</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-06-28 03:26</span> <span style="display: inline-block;">瑞士</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=ab2119fc&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpkUkqibNp0c4Rv5teicOlAh2nfP2ms4SVhS5cG6ibVOSYMicLKA9cF9wE2Zuf7UQfS5q6icwUCVPkoOTiaoYS7WyeiaL7kHacg1scxiajk%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>欧陆奇葩历险记</p>
  <p><span leaf="">分享今天非常莫名其妙、略带惊悚的经历。也是想听听评论区有没有什么合理的解释。说来我在这几年遇到的奇葩事也够多了，干脆给自己整个艺名叫传奇哥吧。Fish Legend。</span></p><p><span leaf="">大伙或多或少有看到欧洲这几天的热浪导致空调危机大爆发的新闻。虽然互联网短视频难免夸大其词，但确实真有这么回事。博主虽然没有首当其冲在 40 度区，但也是受害者之一。</span></p><p><span leaf="">更令人破防的是空调实际上已经到货了，愣是排不上师傅预约安装。这几晚干脆出去住酒店——大学生行为。这样一来当然得选预算便宜点的。酒店比较偏，离市中心大约 3 公里，公交和共享滑板车都能到。那边全是工业区和做各种产业的老中，治安不太好倒也不至于很夸张。</span></p><p><span leaf="">今天我吃完早饭找共享单车回市中心，突然有人背后喊我帮忙。一看是个移民，不是本地人也不是亚洲人。在这里只是为了提供更多上下文，不要过多渲染种族的意味。</span></p><p><span leaf="">由于在这边经历过一些事情，去年甚至和路怒症路人大打出手进了局子，对方没占到便宜破防叫我滚回我的国家。所以现在我挺冷血的，陌生人无论是求助还是乞讨我能躲就躲。冤有头债有主，没钱吃饭可以找布鲁塞尔要救济拨款。</span></p><p><span leaf="">光天化日的，我还是下意识攥紧了手机。他先问我火车站在哪，我就给他指了公交车的路线。一番解释之后他掏出手机给我看说要去一个地方，</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">他还特地说是个老中的商店。</span></p><p><span leaf="">手机界面是 WhatsApp 的聊天记录，有人发了个定位。我一点开那个定位 Google 地图就弹出来了，45 公里之外。</span></p><p><span leaf="">首先有地图 app 为什么要问路，目的地还那么远？前后不一致的说辞，还专门提老中套近乎。就差脸上写着坏人了。</span><span style="letter-spacing: 0.034em;">这时候他又提出了一个请求把我吓坏了，说能不能带我上车给他带路。</span></p><p><span leaf="">我当然直接拒绝，跟他说那个定位压根就不在这个城市，然后赶紧溜了。他说声谢谢然后好像有点失望地走了。</span></p><p><span leaf="">我没想明白这个到底是骗局的开头还是什么噶腰子的剧情？</span><span style="letter-spacing: 0.034em;">一般人不会天真到随便上陌生人的车吧？</span></p><p><span style="letter-spacing: 0.034em;">问了 AI 说欧洲曾经有一种骗术是，陌生人带你到车旁边，说有走私的货物便宜点卖给你，当然都是 A 货。</span></p><p>想看看大家怎么说……</p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=1a479347&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486081%26idx%3D1%26sn%3Dd5900c8ffd1a36e29172c1a4c91393cf">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 28 Jun 2026 03:26:00 +0800</pubDate>
    </item>
    <item>
      <title>技术文章被🦞作者转发了</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486076&amp;idx=1&amp;sn=398c9549139b25b967ce4bf40c9d2ae7</link>
      <description>之前发了篇笔记&lt;a href=&#34;https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;amp;mid=2247486070&amp;amp;idx=1&amp;amp;sn=a96b08ddc104e11df1bc47288f61dbf6&amp;amp;scene=142#wechat_redirect&#34; class=&#34;normal_text_link mp_article_text_link&#34; target=&#34;_blank&#34; data-itemshowtype=&#34;&#34;&gt;介绍 iOS 27 链接器机制的一些更新&lt;/a&gt;，周末顺手写了英文版发外网了。早上看到🦞作者 Peter Steinberger 一个转发，吓一跳。虽然不知道是他本人还是 ai [旺柴]&#xA;&#xA;Peter 在爆红很久以前就经常能刷到他的动态，毕竟以前也是资深 iOS 开发，不是 CRUD 的那种。&#xA;&#xA;做营销号嘛，反正只要关注他，天天截几个图搬回来翻来覆去的嚼，就能养个矩阵。咱可是公众号首发中文，然后才出口的。这个流量我是不能放过了。 一定要大书特书，狠狠蹭 [奸笑][奸笑]</description>
      <content:encoded><![CDATA[<p><span>0xcc</span> <span></span> <span style="display: inline-block;">瑞士</span></p>






  
  
  <p>rtDesc</p>
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=ec9281cf&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpmOYu9C8G7GAjv3Xz1icNLUjZ2oOfeRjSNRowdbP75zDyzXMKFKhA8xR3RQdyHGsJI8kIFHdk3FXVRRrk7U4FT3UWDvWJ7HP0mY%2F0%3Fwx_fmt%3Djpeg"/></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=9772cd52&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486076%26idx%3D1%26sn%3D398c9549139b25b967ce4bf40c9d2ae7">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Wed, 17 Jun 2026 06:48:49 +0800</pubDate>
    </item>
    <item>
      <title>IDA 9.4 beta 和 iOS 27 的 dyld_shared_cache 的一些变化</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486070&amp;idx=1&amp;sn=a96b08ddc104e11df1bc47288f61dbf6</link>
      <description>IDA Pro 9.4 beta 测试初体验；iOS 27 给链接器又上了什么黑魔法？</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-06-12 09:41</span> <span style="display: inline-block;">瑞士</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=34215a20&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpnJBTIY6YWDlJoTzpicxhgFliaOYRKeAqKqQo4cPO9qwGjNobnlRiamNvJXRicSgJ7JdkGbkxgicJicxOfxZdkahx84k8vuyRGjYdCOA%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>IDA Pro 9.4 beta 测试初体验；iOS 27 给链接器又上了什么黑魔法？</p>
  <p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.6311605723370429" data-s="300,640" data-type="png" data-w="1258" type="block" data-imgfileid="100002407" src="https://wechat2rss.xlab.app/img-proxy/?k=07dd8c09&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmCYm6NjXwvibz8wL8fIVAHTPAv4qVPLiapNgljfCXGM8RFCRx5icznzwBo6jfVLmOWA82BrBmlzYoauVdtlVe0mBxG4xlOXAkSQk%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">6 月 11 日 IDA Pro 9.4 放出了 beta 测试版。这一版相比上一版加入了<span textstyle="" style="font-weight: bold;">非常多</span><span textstyle="" style="font-weight: normal;">的功能，然而我就不丢给 AI 自动洗稿了，请参阅原文。</span></span></p><p><span leaf=""><a href="https://docs.hex-rays.com/release-notes/9_4beta" target="_blank">https://docs.hex-rays.com/release-notes/9_4beta</a></span></p><p><span leaf="">在这里提两个新功能的痛点。</span></p><p><span leaf="">一个是 PathFinder，顾名思义就是找调用链。可以给出 source 和 sink，然后帮你遍历路径，也就是之前需要外接一个图数据库才能做的。想象一下接上 llm，简直了。</span></p><p><span leaf="">在一个就是查找二进制序列。之前只能做逐字节匹配，例如：AA BB CC；现在可以用通配符了：AA B? C? DD。</span></p><hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"/><p><span leaf="">值得一提的是这一版的 dyld_shared_cache 工作流改善后非常之好用，从从交互到速度和各种 bug 修复都让人印象深刻。</span></p><p><span leaf=""><a href="https://docs.hex-rays.com/9.4/core/disassembler/concepts/dsc-workflow" target="_blank">https://docs.hex-rays.com/9.4/core/disassembler/concepts/dsc-workflow</a></span></p><p><span leaf="">我上个月写过一篇文章，由于现有的反编译器 loader 对 DSC 支持仅仅聊胜于无，我干脆写了个提取单个 dylib 的工具：<a class="normal_text_link" target="_blank" style="" href="https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485978&amp;idx=1&amp;sn=6f7b8114611ce0724611484066a6b3c0&amp;scene=21#wechat_redirect" textvalue="2026 年了，还在折腾 dyld_shared_cache" data-itemshowtype="0" linktype="text" data-linktype="2">2026 年了，还在折腾 dyld_shared_cache</a></span></p><p><span leaf="">才过去一个月这篇文章就过时了，现在的方案是：闭着眼用 9.4 就好。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="2.5794117647058825" data-s="300,640" data-type="png" data-w="680" type="block" data-imgfileid="100002416" src="https://wechat2rss.xlab.app/img-proxy/?k=abba270a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpnjnUTVibfIGiaJeFvlkImXWfn6YBWMBAArD4sZXNKVxKp5psayCN3fyTgucIfOlCCzO8JWODmSzDV2NeHsBqwXEWHtEVLGspdTQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">和之前每次载入 dylib 都要点开几层菜单，然后在对话框里选择路径不同，IDA Pro 把 DSC 支持提升到了一等公民，直接在工作区右边添加了一个新的侧边栏。</span></p><p><span leaf="">体验很顺滑，载入模块的体感快了很多。当然我没有严格对比掐过秒表，也可能是心理作用。毕竟现在数码评测要资质，还是别测了。</span></p><p><span leaf="">在二进制视图中的未知地址不再显示红色数字，而是会提示其所在的库，可以选择性载入内容。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.2788844621513944" data-s="300,640" data-type="png" data-w="1004" type="block" data-imgfileid="100002418" src="https://wechat2rss.xlab.app/img-proxy/?k=5fafd774&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqplSpk3O7rdO3KxToGy0LbXJLuus9OQlnHcRfuNAia8OQT3RTllr5LjMpvCLMBugPzo1dmicwrgLWUwRibOrj6icWOwqibb176icyuaLM%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5009259259259259" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002419" src="https://wechat2rss.xlab.app/img-proxy/?k=4a0606b7&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpm6BhMYMsv3pUTYYOlf8G1qIBSStRLIFk0uUClge4aNCP3YrLhPeeLLiaYtSsjzdoicn4ad0ic9iagliaCPic4KiaoROgcT7ib1U0M8v5E%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">一个显著修复的 bug 就是 </span><span leaf="">__objc_methlist</span><span leaf=""> 节的解析。9.3 下红字（错误的偏移量）：</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.5462962962962963" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002415" src="https://wechat2rss.xlab.app/img-proxy/?k=0e3c3565&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpmf77h9PqKXMibWQeiaUQeDqasXawQdCRc9ILfLgu3iadzzgzkOQjMlqAfV4YPJJ7yVHblYxkiaLYmU8u2OQd79Iw50abF6XWib1Qa8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">9.4 正确识别：</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.6824074074074075" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002414" src="https://wechat2rss.xlab.app/img-proxy/?k=9dc06023&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmtF56o2r9Y4dBRd9ib8UsCwIVA5puSprCJr6w2Ccqv8LXV5T7PXpz5rsbP65uTz2iajoJXYUPYQZHAg4bFZGYdIsHV2JKUMAyic8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">当然这个例子有点鸡蛋里挑骨头，大多数人可能都不会注意到。</span></p><p><span leaf="">这个节的信息对 class-dump 很有用，用以关联 Objective-C 方法名的 selector 和具体函数，以及方法类型签名。</span></p><p><span leaf="">但说回来直接在 dyld_shared_cache 上做 class-dump，静态的有 ipsw 工具内置支持，动态的话则只需要调用 </span><span leaf="">objc/runtime.h 里的 API 就可以，完全不需要管具体的结构。</span></p><p><span leaf="">目前试用下来个人给出绝对好评。哪怕是周一刚出炉的 iOS 27 beta 的 dyld_shared_cache 也做到了开箱即用。</span></p><p><span leaf="">下面是博主被打脸时间。</span></p><p><span leaf="">前面提到并链接了我之前解包单个链接库的思路，里面用到了一些作弊的技巧。</span></p><p><span leaf="">此前版本的 dyld 优化会讲一些跨文件的函数调用（__auth_stub）从模块中提取出来，统一合并成全局共享 stub island 和 global offset table（GOT）。这一过程处理完之后，原本 dylib 里的 __auth_stub 和 __auth_got 节实质上就已经没有用了，只是二进制优化这一步没有去掉。</span></p><p><span leaf="">类似的还有一些 Objective-C runtime 需要的数据，例如 selector 字符串池（__objc_methname 和 __objc_classname 等），会统一合并到 libobjc.A.dylib 的 __OBJC_RO 段。</span></p><p><span leaf="">原始库当中的副本实质上没有交叉引用，依旧保留到最终的 DSC 文件。我的工具利用这个特点省去了很多符号恢复和区段重建的工作。</span></p><p data-pm-slice="2 1 []"><span leaf="">但是！来看周一 WWDC 刚发的 KeyNote：</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5625" data-s="300,640" data-type="png" data-w="1024" type="block" data-imgfileid="100002417" src="https://wechat2rss.xlab.app/img-proxy/?k=992620fe&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmrLn4F85E5MMmsh5geVXqdMqPavgyYXmib732FCdYMOElNy8qJRQ0XtibX25KdIoY6APb5kLUDkG97icqTE5SXmQyFj1xQyPac3w%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">iOS 27 大刀阔斧地开始性能优化。</span></p><p><span leaf="">具体怎么做没说，但分析 DSC 就能看到一些端倪。</span></p><p><span leaf="">前文提到这些 section 在 iOS 26 还保留副本在 dylib，但是没有被实际用到。这次直接被优化掉了，可能是到了 35 岁了吧。</span></p><p><span leaf="">现在如果闲得慌还想实现单个文件提取，就得</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">从零重建好几个 section，而且这些 section 都是第一个 segment (__TEXT），这就导致</span><span leaf="">整个二进制文件需要重排。</span></p><p><span leaf="">于是我的工具炸了，一时半会修不好。笔者奉行实用主义，既然 IDA 已经足够好用，就不必炫技了——反正也是丢给 AI 写的。太不给面子了，公众号才发出来一个月呐。</span></p><hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"/><p><span leaf="">下面再节选几个点分析 iOS 27 二进制层面做的一些优化。</span></p><p><span leaf="">在 iOS 26 上，大部分调用 objc_msgSend 的代码会被 outline 处理，放进 __objc_stubs 当中，一共有 6 行指令实现（觉得我数错的请面壁并回去复习 ARM 伪指令）：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="ruby"><code><span leaf=""><span class="code-snippet__title">Foundation</span><span class="code-snippet__symbol">:__objc_stubs:</span>00000001815DD580</span></code><br/><code><span leaf="">_objc_msgSend<span class="code-snippet__variable">$HTTPBody</span>                  ; <span class="code-snippet__variable">CODE</span> <span class="code-snippet__variable">XREF</span>: <span class="code-snippet__title">URLRequest</span>.httpBody.getter+<span class="code-snippet__number">24</span>↑p</span></code><br/><code><span leaf=""><span class="code-snippet__variable">ADRP</span>            <span class="code-snippet__variable">X1</span>, <span class="code-snippet__comment">#selRef_HTTPBody</span><span class="code-snippet__comment"><span class="code-snippet__doctag">@PAGE</span></span></span></code><br/><code><span leaf=""><span class="code-snippet__variable">LDR</span>             <span class="code-snippet__variable">X1</span>, [<span class="code-snippet__variable">X1</span>,<span class="code-snippet__comment">#selRef_HTTPBody</span><span class="code-snippet__comment"><span class="code-snippet__doctag">@PAGEOFF</span></span><span class="code-snippet__comment">] ; &#34;HTTPBody&#34; ...</span></span></code><br/><code><span leaf=""><span class="code-snippet__variable">ADRL</span>            <span class="code-snippet__variable">X17</span>, _objc_msgSend_ptr</span></code><br/><code><span leaf=""><span class="code-snippet__variable">LDR</span>             <span class="code-snippet__variable">X16</span>, [<span class="code-snippet__variable">X17</span>] ; _objc_msgSend</span></code><br/><code><span leaf=""><span class="code-snippet__variable">BRAA</span>            <span class="code-snippet__variable">X16</span>, <span class="code-snippet__variable">X17</span> ; _objc_msgSend</span></code><br/></pre></p><p><span leaf="">到了 iOS 27 这个 __objc_stubs 不见了，和 stub island 一样被移出了框架，到了一个不属于任何一个 dylib 的区域，而且缩减成了 3 行指令：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="ruby"><code><span leaf=""><span class="code-snippet__variable">ADRL</span>            <span class="code-snippet__variable">X1</span>, selRef_HTTPBody</span></code><br/><code><span leaf="">B               objc_msgSend ; <span class="code-snippet__regexp">/usr/lib/objc/libobjc</span>MsgSend.dylib</span></code><br/></pre></p><p><span leaf="">这时候有些读者就要问了，branch 指令的跳转范围是有限制的，这一整个 cache 肯定超了。怎么做到所有的 objc_msgSend 调用都直接用标签而不用 GOT？</span></p><p><span leaf="">解析这个 DSC 的文件列表会发现 iOS 专门为 Objective-C 消息转发生成了一堆同样的 dylib：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="swift"><code><span leaf=""><span class="code-snippet__regexp">/usr/</span>lib<span class="code-snippet__regexp">/objc/</span>libobjcMsgSend.dylib</span></code><br/><code><span leaf=""><span class="code-snippet__regexp">/usr/</span>lib<span class="code-snippet__regexp">/objc/</span>libobjcMsgSend1.dylib</span></code><br/><code><span leaf=""><span class="code-snippet__regexp">/usr/</span>lib<span class="code-snippet__regexp">/objc/</span>libobjcMsgSend2.dylib</span></code><br/><code><span leaf=""><span class="code-snippet__operator">...</span></span></code><br/><code><span leaf=""><span class="code-snippet__regexp">/usr/</span>lib<span class="code-snippet__regexp">/objc/</span>libobjcMsgSend33.dylib</span></code><br/></pre></p><p><span leaf="">多机智……每隔一段距离就插入一份代码副本，你就说要不要担心跳转长度吧。</span></p><p><span leaf="">而对于跨 dylib 的函数调用，在 iOS 26 上 stub island 是这样的：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="nginx"><code><span leaf=""><span class="code-snippet__attribute">ADRL</span>            X17, _dlsym_ptr ; <span class="code-snippet__attribute">GOT</span> 里的函数指针</span></code><br/><code><span leaf="">LDR             X16, [X17]</span></code><br/><code><span leaf="">BRAA            X16, X17</span></code><br/></pre></p><p><span leaf="">到了 iOS 27 仍然可以看到这样的代码，但是多出了另外两种类型。</span></p><div><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">一种少了一次内存 load，直接跳转过去：</span></p></div><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="nginx"><code><span leaf=""><span class="code-snippet__attribute">ADRL</span>            X16, _open</span></code><br/><code><span leaf="">BR              X16</span></code><br/></pre></p><p><span leaf="">另一种让人第一眼非常困惑：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="apache"><code><span leaf=""><span class="code-snippet__attribute">dyld_shared_cache_arm64e</span>.<span class="code-snippet__number">02</span>:__stubs:<span class="code-snippet__number">0000000188138000</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">_objc_retainBlock_0</span>                     ; CODE XREF: _objc_retainBlock↑j</span></code><br/><code><span leaf=""><span class="code-snippet__attribute">ADR</span>             X16, loc_18803CC2C</span></code><br/><code><span leaf=""><span class="code-snippet__attribute">MOV</span>             X17, #<span class="code-snippet__number">0</span>x9B7</span></code><br/><code><span leaf=""><span class="code-snippet__attribute">ADD</span>             X16, X16, X17,LSL#<span class="code-snippet__number">21</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">BR</span>              X16</span></code><br/></pre></p><p><span leaf="">其实就是用一个加法移位计算出 x16 的值，也就是目标函数的地址，然后跳转过去。</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="bash"><code><span leaf="">  X16 = 0x18803CC2C + (0x9B7 &lt;&lt; <span class="code-snippet__string">21)</span></span></code><br/><code><span leaf="">      = 0x18803CC2C + 0x136E00000</span></code><br/><code><span leaf="">      = 0x2BEE3CC2C ; libsystem_block.dylib!__Block_copy</span></code><br/></pre></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">第一个 ADR 用的是 PC 相对地址，这是合法的位置无关代码。</span></p><p><span leaf="">但乍一看这个写法指令数也没少啊？</span></p><p><span leaf="">之前的代码需要从 GOT 里载入一个目标函数的指针。这个指针在程序启动（或者页面第一次被访问）的时候进行重定位，arm64e 下还要处理 PAC 加签。</span></p><p><span leaf="">现在少了 GOT，首先省去了启动时的指针 rebase 操作，第二执行时也不需要 load 内存，连 cache 都不用考虑。而且 PAC 指令的跳转还要校验指针合法性，相比无条件的 BR 也有额外开销。</span></p><p><span leaf="">我去，这也行。</span></p><hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"/><p><span leaf="">虽然对 IDA 一阵猛夸，还是看到了一处可以优化的点。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.14722222222222223" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002420" src="https://wechat2rss.xlab.app/img-proxy/?k=b57adadd&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpkN62nntw9ic9MpCbGmnNfeFEicvYEEib69niaY0FbUxcPyH0QPcpPtQxZs8ZSc1mGoDNfbk2sUcwNK76RicOlr1v7PAvsoXomksuDk%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">这堆代码有点莫名其妙。因为 IDA 暂时不认识新版 __objc_stub 的跳转逻辑，BL 的标签没有一个有效的名字：</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.19907407407407407" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002421" src="https://wechat2rss.xlab.app/img-proxy/?k=fc844b06&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmmdF3nKRKsRRVVXHTB1bNZclmG6PHu9WLygOquZokupO4AfakKMlVDrPHPegrAuicQ6xQvR7crpzcCHswV00Ia8vjeFyFcbbk4%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">但这个问题可以手动修复。如下例子：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="apache"><code><span leaf=""><span class="code-snippet__attribute">Foundation</span>:__text:<span class="code-snippet__number">0000000180</span>C8657C</span></code><br/><code><span leaf=""><span class="code-snippet__attribute">__NSBundle_load_</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">MOV</span>             X2, #<span class="code-snippet__number">0</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">B</span>               unk_1880035F0</span></code><br/></pre></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="objectivec"><code><span leaf=""><span class="code-snippet__type">BOOL</span> __cdecl -[<span class="code-snippet__built_in">NSBundle</span> load](<span class="code-snippet__built_in">NSBundle</span> *<span class="code-snippet__keyword">self</span>, SEL a2)</span></code><br/><code><span leaf="">{</span></code><br/><code><span leaf="">  <span class="code-snippet__type">BOOL</span> result; <span class="code-snippet__comment">// w0</span></span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">  unk_1880035F0();</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">return</span> result;</span></code><br/><code><span leaf="">}</span></code><br/></pre></p><p><span leaf="">双击 </span><span leaf="">unk_1880035F0 跳转到目标地址，按一下 c 标记成代码：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="apache"><code><span leaf=""><span class="code-snippet__attribute">dyld_shared_cache_arm64e</span>.<span class="code-snippet__number">01</span>:GAP:<span class="code-snippet__number">00000001880035</span>F0</span></code><br/><code><span leaf=""><span class="code-snippet__attribute">loc_1880035F0</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">ADRL</span>            X1, sel_loadAndReturnError_ ; <span class="code-snippet__string">&#34;loadAndReturnError:&#34;</span></span></code><br/><code><span leaf=""><span class="code-snippet__attribute">B</span>               ⇗ /usr/lib/objc/libobjcMsgSend.dylib:_objc_msgSend</span></code><br/></pre></p><p><span leaf="">这时候真正的 selector 就出来了。在 ADRL 上按 n 重命名地址，根据具体的 selector，如上的例子为 </span><span leaf="">_objc_msgSend$loadAndReturnError:</span></p><p><span leaf="">IDA Pro 允许函数命名包含冒号，提交之后会显示成下划线。</span></p><p><span leaf="">如果 IDA 没有自动识别出参数个数，最好按 y 手动定义一下。再返回调用方，F5 就好多了：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="objectivec"><code><span leaf=""><span class="code-snippet__type">BOOL</span> __cdecl -[<span class="code-snippet__built_in">NSBundle</span> load](<span class="code-snippet__built_in">NSBundle</span> *<span class="code-snippet__keyword">self</span>, SEL a2)</span></code><br/><code><span leaf="">{</span></code><br/><code><span leaf="">  <span class="code-snippet__type">BOOL</span> result; <span class="code-snippet__comment">// w0</span></span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">  objc_msgSend_loadAndReturnError_(a1: <span class="code-snippet__keyword">self</span>, (<span class="code-snippet__type">void</span> *)a2, a3: nullptr);</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">return</span> result;</span></code><br/><code><span leaf="">}</span></code><br/></pre></p><p><span leaf="">已经反馈给官方了 <img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1" data-w="20" style="display:inline-block;width:20px;vertical-align:middle;background-size:cover;" src="https://wechat2rss.xlab.app/img-proxy/?k=031e4a17&amp;u=https%3A%2F%2Fres.wx.qq.com%2Ft%2Fwx_fed%2Fwe-emoji%2Fres%2Fassets%2Fnewemoji%2FNoProb.png"/></span></p><p><span leaf="">觉得这篇笔记有意思的话给个打赏呗 <img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1" data-w="20" style="display:inline-block;width:20px;vertical-align:middle;background-size:cover;" src="https://wechat2rss.xlab.app/img-proxy/?k=8ddeb7c5&amp;u=https%3A%2F%2Fres.wx.qq.com%2Ft%2Fwx_fed%2Fwe-emoji%2Fres%2Fassets%2Fnewemoji%2FYellowdog.png"/></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=c5ba205b&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486070%26idx%3D1%26sn%3Da96b08ddc104e11df1bc47288f61dbf6">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 12 Jun 2026 09:41:00 +0800</pubDate>
    </item>
    <item>
      <title>iOS 26.4 如何限制系统进程使用 JavaScriptCore</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486053&amp;idx=1&amp;sn=94d02df5700c83173e6edd4fb665b40d</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-06-07 09:04</span> <span style="display: inline-block;">瑞士</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=d1a3a50d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpkFzxSiajnPZmSDoldiagIdFcD52YTx43877OxMicYicTWbkpYEZ96Im4K39YXETR5tVJuDCNdRpNxCrpbUzMnH8EaicCIGG2CWjL0k%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <div data-tool="markdown编辑器" data-website="https://markdown.com.cn/editor" style="font-size: 16px;color: black;padding: 25px 30px;line-height: 1.6;word-spacing: 0px;letter-spacing: 0px;word-break: break-word;word-wrap: break-word;text-align: justify;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#39;PingFang SC&#39;, Cambria, Cochin, Georgia, Times, &#39;Times New Roman&#39;, serif;margin-top: -10px;" data-pm-slice="0 0 []"><h2 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;"><span leaf="">背景</span></h2><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">JavaScriptCore 是 Apple 系统自带的 js 引擎。它不只服务于 Safari 和 WebKit，也可以被原生程序通过链接 JavaScriptCore.framework 直接调用执行 js。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">原本正常的系统框架，攻击者却可以把 JavaScriptCore 当成系统内置解释器，通过代码注入技术把后利用逻辑寄生在已有进程里。通过脚本访问原生接口，不需要下载可执行文件，也不会产生新的进程。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这种借助系统自带脚本解释器运行代码的思路并不是新鲜事。哪怕只看 iOS 平台的公开研究，Google Project Zero 在 2019 年演示 iMessage 零点击利用的时候就已经用过了。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">DarkSword 是比较近的现实案例。2026 年 3 月，iVerify、Google TAG 和 Lookout 联合披露了 DarkSword 工具包针对 iOS 用户大批量发起攻击的事件。它在完成沙箱逃逸和系统提权之后，并不启动独立 payload 进程，而是借用系统中已经存在的服务，在其中运行基于 JavaScriptCore 的代码来实现 C2 逻辑和提取系统敏感信息。甚至提权利用本身也是用 js 实现的。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">所谓的无文件代码执行大体步骤如下：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">使用 dlopen 动态链接 JavaScriptCore.framework</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">调用 JSContext 创建 js 执行环境</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">绑定系统 native API（bridge）和内存读写能力到上下文</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">运行 js</span></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">上面的步骤在浏览器、混合式应用或者需要脚本能力的系统组件里并不奇怪。但对某些关键系统进程（比如用户态核心的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">launchd</span></code><span leaf="">）来说，如果它们开始运行 js，那肯定是非预期行为。苹果的思路就是在预设的系统进程列表当中彻底禁用 JavaScriptCore。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">根据 WebKit 的历史记录来看，在 2025 年 8 月的提交 d5e7d2a3eeeeab55e93553b2fc91fc61327a6ffb 就引入了针对性的防御，应该是早于 DarkSword 活动的时间。而它恰好是 Apple 对这种滥用解释器的利用技术的防御，应该是早已设计好的加固能力的一部分，只是到 26.4 才正式发布。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">本文就来分析一下这个防御机制的具体实现。</span></p><h2 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;"><span leaf="">新的 Entitlement</span></h2><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">从 iOS 26.4 开始，launchd 以及若干高风险进程的 entitlement 就多了一个 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">com.apple.security.script-restrictions</span></code></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><em style="font-style: italic;color: black;"><span leaf="">注：entitlement 是苹果操作系统的机制。将一段 property list——键值对数据，与代码签名绑定后保存在可执行文件中，用来为操作系统标记特殊的权限</span></em></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.6824074074074075" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002400" src="https://wechat2rss.xlab.app/img-proxy/?k=b8181da1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpndzXJhDgtgKMlibiazuxoeV6dgQYIib3Qudv5wdKWoeETAnzfK5qxFiaDYbwuPnzkxxLY3fYqT2Afic18UgeDQL8PH1GRxtyCGlFib8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.9055555555555556" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002404" src="https://wechat2rss.xlab.app/img-proxy/?k=e7438652&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpnDDJpr5Pvn5gxtKMoVhNNvzrNqPDzWbPviahyFMd5hdbzriaDhiaw2SQYcvnLznvACxR1fkctQZOggnajB5c2fYVfMlsXKne5rYo%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0px;line-height: 26px;color: black;text-align: center;"><span leaf=""><span textstyle="" style="font-size: 14px;">这些进程多与缩略图生成和 BlastDoor 有关</span></span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">在苹果官方文档当中已经提到了如下 entitlement 可以启用包括 MTE 在内的多种加固措施，甚至对第三方开发者也开放了：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">com.apple.security.hardened-process</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">com.apple.security.hardened-process.enhanced-security-version-string</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">com.apple.security.hardened-process.checked-allocations</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">com.apple.security.hardened-process.platform-restrictions-string</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">com.apple.security.hardened-process.dyld-ro</span></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">它们可以单独展开写各自的文章，篇幅限制就不深入了。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这个 script-restrictions 并没有出现在文档中。尝试在 Xcode iOS 工程中添加，构建之后会被悄悄移除；如果手工调用 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">codesign</span></code><span leaf=""> 命令签名 app 加上，安装过程会被真机拒绝。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><em style="font-style: italic;color: black;"><span leaf="">所以目前这个机制不仅文档没有写，也不对第三方 app 开发者开放。不开放就算了，这个加固对第三方应用确实没任何作用，反而不少开发者都喜欢业务逻辑用 js 写，一套代码跑多端。禁了不是给自己找不快。</span></em></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">来实测验证一下。虽然 iOS 不让测试 app 用这个 entitlement，但是 macOS 26.5 没问题。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">test_jsc.c</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">include</span></span><span class="code-snippet__meta"><span class="code-snippet__string">&lt;stdio.h&gt;</span></span></span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">include</span></span><span class="code-snippet__meta"><span class="code-snippet__string">&lt;stdint.h&gt;</span></span></span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">include</span></span><span class="code-snippet__meta"><span class="code-snippet__string">&lt;dlfcn.h&gt;</span></span></span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__function"><span class="code-snippet__type">int</span></span><span class="code-snippet__function"><span class="code-snippet__title">main</span></span><span class="code-snippet__function"><span class="code-snippet__params">(</span></span><span class="code-snippet__function"><span class="code-snippet__params"><span class="code-snippet__type">void</span></span></span><span class="code-snippet__function"><span class="code-snippet__params">)</span></span>{</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">uint64_t</span> (*os_security_config_get)(<span class="code-snippet__type">void</span>) =</span></code><br/><code><span leaf="">        (<span class="code-snippet__built_in">uint64_t</span> (*)(<span class="code-snippet__type">void</span>))<span class="code-snippet__built_in">dlsym</span>(RTLD_DEFAULT, <span class="code-snippet__string">&#34;os_security_config_get&#34;</span>);</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">if</span> (!os_security_config_get) {</span></code><br/><code><span leaf="">        <span class="code-snippet__built_in">fprintf</span>(stderr, <span class="code-snippet__string">&#34;system too old\n&#34;</span>);</span></code><br/><code><span leaf="">        <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">1</span>;</span></code><br/><code><span leaf="">    }</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__type">uint64_t</span> cfg = <span class="code-snippet__built_in">os_security_config_get</span>();</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">&#34;os_security_config_get() = 0x%llx  | SCRIPT_RESTRICTIONS(0x40)=%s&#34;</span></span></code><br/><code><span leaf="">            <span class="code-snippet__string">&#34;  HARDENED_HEAP(0x1)=%s TPRO(0x2)=%s GUARD_OBJECTS(0x100)=%s\n&#34;</span>,</span></code><br/><code><span leaf="">            (<span class="code-snippet__type">unsigned</span> <span class="code-snippet__type">long</span> <span class="code-snippet__type">long</span>)cfg,</span></code><br/><code><span leaf="">            (cfg &amp; <span class="code-snippet__number">0x40</span>)  ? <span class="code-snippet__string">&#34;ON&#34;</span>  : <span class="code-snippet__string">&#34;off&#34;</span>,</span></code><br/><code><span leaf="">            (cfg &amp; <span class="code-snippet__number">0x1</span>)   ? <span class="code-snippet__string">&#34;on&#34;</span>  : <span class="code-snippet__string">&#34;off&#34;</span>,</span></code><br/><code><span leaf="">            (cfg &amp; <span class="code-snippet__number">0x2</span>)   ? <span class="code-snippet__string">&#34;on&#34;</span>  : <span class="code-snippet__string">&#34;off&#34;</span>,</span></code><br/><code><span leaf="">            (cfg &amp; <span class="code-snippet__number">0x100</span>) ? <span class="code-snippet__string">&#34;on&#34;</span>  : <span class="code-snippet__string">&#34;off&#34;</span>);</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span> *jsc = <span class="code-snippet__built_in">dlopen</span>(<span class="code-snippet__string">&#34;/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore&#34;</span>, RTLD_NOW);</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">if</span> (!jsc) { <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">&#34;dlopen(JavaScriptCore) FAILED: %s\n&#34;</span>, <span class="code-snippet__built_in">dlerror</span>()); <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">2</span>; }</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span>* (*JSGlobalContextCreate)(<span class="code-snippet__type">void</span>*)               = <span class="code-snippet__built_in">dlsym</span>(jsc, <span class="code-snippet__string">&#34;JSGlobalContextCreate&#34;</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span>* (*JSStringCreateWithUTF8CString)(<span class="code-snippet__type">const</span> <span class="code-snippet__type">char</span>*) = <span class="code-snippet__built_in">dlsym</span>(jsc, <span class="code-snippet__string">&#34;JSStringCreateWithUTF8CString&#34;</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span>* (*JSEvaluateScript)(<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">int</span>,<span class="code-snippet__type">void</span>**) = <span class="code-snippet__built_in">dlsym</span>(jsc, <span class="code-snippet__string">&#34;JSEvaluateScript&#34;</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">double</span> (*JSValueToNumber)(<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">void</span>*,<span class="code-snippet__type">void</span>**)       = <span class="code-snippet__built_in">dlsym</span>(jsc, <span class="code-snippet__string">&#34;JSValueToNumber&#34;</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">&#34;dlopen JSC=%p  JSGlobalContextCreate=%p\n&#34;</span>, jsc, (<span class="code-snippet__type">void</span>*)JSGlobalContextCreate);</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span> *ctx = <span class="code-snippet__built_in">JSGlobalContextCreate</span>(<span class="code-snippet__literal">NULL</span>);            <span class="code-snippet__comment">// &lt;- traps here under restrictions</span></span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">&#34;JSGlobalContextCreate -&gt; %p\n&#34;</span>, ctx);</span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span> *src = <span class="code-snippet__built_in">JSStringCreateWithUTF8CString</span>(<span class="code-snippet__string">&#34;40 + 2&#34;</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span> *exc = <span class="code-snippet__literal">NULL</span>;</span></code><br/><code><span leaf="">    <span class="code-snippet__type">void</span> *res = <span class="code-snippet__built_in">JSEvaluateScript</span>(ctx, src, <span class="code-snippet__literal">NULL</span>, <span class="code-snippet__literal">NULL</span>, <span class="code-snippet__number">0</span>, &amp;exc);</span></code><br/><code><span leaf="">    <span class="code-snippet__type">double</span> out = <span class="code-snippet__built_in">JSValueToNumber</span>(ctx, res, <span class="code-snippet__literal">NULL</span>);</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">&#34;40 + 2 = %g\n&#34;</span>, out);</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">0</span>;</span></code><br/><code><span leaf="">}</span></code><br/><code></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">ent.plist</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="xml"><code><span leaf=""><span class="code-snippet__meta">&lt;?xml version=</span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;1.0&#34;</span></span><span class="code-snippet__meta"> encoding=</span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;UTF-8&#34;</span></span><span class="code-snippet__meta">?&gt;</span></span></code><br/><code><span leaf=""><span class="code-snippet__meta">&lt;!DOCTYPE </span><span class="code-snippet__meta"><span class="code-snippet__keyword">plist</span></span><span class="code-snippet__meta"><span class="code-snippet__keyword">PUBLIC</span></span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;-//Apple//DTD PLIST 1.0//EN&#34;</span></span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;<a href="http://www.apple.com/DTDs/PropertyList-1.0.dtd" target="_blank">http://www.apple.com/DTDs/PropertyList-1.0.dtd</a>&#34;</span></span><span class="code-snippet__meta">&gt;</span></span></code><br/><code><span leaf=""><span class="code-snippet__tag">&lt;</span><span class="code-snippet__tag"><span class="code-snippet__name">plist</span></span><span class="code-snippet__tag"><span class="code-snippet__attr">version</span></span><span class="code-snippet__tag">=</span><span class="code-snippet__tag"><span class="code-snippet__string">&#34;1.0&#34;</span></span><span class="code-snippet__tag">&gt;</span></span></code><br/><code><span leaf=""><span class="code-snippet__tag">&lt;</span><span class="code-snippet__tag"><span class="code-snippet__name">dict</span></span><span class="code-snippet__tag">&gt;</span></span></code><br/><code><span leaf="">    <span class="code-snippet__tag">&lt;</span><span class="code-snippet__tag"><span class="code-snippet__name">key</span></span><span class="code-snippet__tag">&gt;</span>com.apple.security.script-restrictions<span class="code-snippet__tag">&lt;/</span><span class="code-snippet__tag"><span class="code-snippet__name">key</span></span><span class="code-snippet__tag">&gt;</span></span></code><br/><code><span leaf="">    <span class="code-snippet__tag">&lt;</span><span class="code-snippet__tag"><span class="code-snippet__name">true</span></span><span class="code-snippet__tag">/&gt;</span></span></code><br/><code><span leaf=""><span class="code-snippet__tag">&lt;/</span><span class="code-snippet__tag"><span class="code-snippet__name">dict</span></span><span class="code-snippet__tag">&gt;</span></span></code><br/><code><span leaf=""><span class="code-snippet__tag">&lt;/</span><span class="code-snippet__tag"><span class="code-snippet__name">plist</span></span><span class="code-snippet__tag">&gt;</span></span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">编译后加上自签名的 entitlement：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="css"><code><span leaf="">cc test_jsc<span class="code-snippet__selector-class">.c</span> -o test_jsc</span></code><br/><code><span leaf="">codesign -s - <span class="code-snippet__attr">--entitlements</span> ent<span class="code-snippet__selector-class">.plist</span> <span class="code-snippet__attr">--force</span> test_jsc</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">预期的行为是进程会抛异常，所以挂 lldb 跑：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="powershell"><code><span leaf="">➜  jsc_test lldb test_jsc</span></code><br/><code><span leaf="">(lldb) target create <span class="code-snippet__string">&#34;test_jsc&#34;</span></span></code><br/><code><span leaf="">Current executable <span class="code-snippet__built_in">set</span> to <span class="code-snippet__string">&#39;/Users/cc/Projects/phrack/jsc_test/test_jsc&#39;</span> (arm64).</span></code><br/><code><span leaf="">(lldb) <span class="code-snippet__built_in">r</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">Process</span> <span class="code-snippet__number">49313</span> launched: <span class="code-snippet__string">&#39;/Users/cc/Projects/phrack/jsc_test/test_jsc&#39;</span> (arm64)</span></code><br/><code><span leaf="">os_security_config_get() = <span class="code-snippet__number">0</span>x40  | SCRIPT_RESTRICTIONS(<span class="code-snippet__number">0</span>x40)=ON  HARDENED_HEAP(<span class="code-snippet__number">0</span>x1)=off TPRO(<span class="code-snippet__number">0</span>x2)=off GUARD_OBJECTS(<span class="code-snippet__number">0</span>x100)=off</span></code><br/><code><span leaf="">dlopen JSC=<span class="code-snippet__number">0</span>x365fa85a0  JSGlobalContextCreate=<span class="code-snippet__number">0</span>x1a786a9bc</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">Process</span> <span class="code-snippet__number">49313</span> stopped</span></code><br/><code><span leaf="">* thread <span class="code-snippet__comment">#1, queue = &#39;com.apple.main-thread&#39;, stop reason = EXC_BREAKPOINT (code=1, subcode=0x1a7ac6854)</span></span></code><br/><code><span leaf="">    frame <span class="code-snippet__comment">#0: 0x00000001a7ac6854 JavaScriptCore`WTF::makePagesFreezable(void*, unsigned long) + 304</span></span></code><br/><code><span leaf="">JavaScriptCore`WTF::makePagesFreezable:</span></code><br/><code><span leaf="">-&gt;  <span class="code-snippet__number">0</span>x1a7ac6854 &lt;+<span class="code-snippet__number">304</span>&gt;: brk    <span class="code-snippet__comment">#0xc471</span></span></code><br/><code><span leaf="">    <span class="code-snippet__number">0</span>x1a7ac6858 &lt;+<span class="code-snippet__number">308</span>&gt;: brk    <span class="code-snippet__comment">#0x1</span></span></code><br/><code><span leaf="">    <span class="code-snippet__number">0</span>x1a7ac685c &lt;+<span class="code-snippet__number">312</span>&gt;: adrp   x1, <span class="code-snippet__number">5970</span></span></code><br/><code><span leaf="">    <span class="code-snippet__number">0</span>x1a7ac6860 &lt;+<span class="code-snippet__number">316</span>&gt;: add    x1, x1, <span class="code-snippet__comment">#0xb44 ; &#34;/AppleInternal/Library/BuildRoots/4~CN9QugCEa5fya5kkZXSbadtTe9oVa3sO3gsEwzc/Library/Caches/com.apple.xbs/TemporaryDirectory.sbZNe3/Sources/WTF/Source/WTF/wtf/PageBlock.cpp&#34;</span></span></code><br/><code><span leaf="">Target <span class="code-snippet__number">0</span>: (test_jsc) stopped.</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">程序没有打印 42，而是触发崩溃。去掉 entitlement 之后则一切正常。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">到这里这个演示就结束了。也就是如果进程签名里有这个非公开的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">com.apple.security.script-restrictions</span></code><span leaf="">，JavaScriptCore 库可以被动态链接，但无法创建可用的执行上下文。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">如果读者想知道是如何实现的，可以继续看下去。</span></p><h2 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;"><span leaf="">实现</span></h2><h3 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span leaf="">状态查询 API</span></h3><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">上面的测试代码出现了一个 iOS 26 新加入的 API </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os_security_config_get</span></code><span leaf="">。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">实际上一共有三个 API：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os_security_config_t os_security_config_get();</span></code><span leaf="">：获取当前进程信息</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">int os_security_config_get_for_proc(pid_t pid, os_security_config_t *config);</span></code><span leaf="">：获取 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">pid</span></code><span leaf=""> 对应进程，可能需要 root 权限</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">int os_security_config_get_for_task(task_t task, os_security_config_t *config);</span></code><span leaf="">：获取 task 对应进程，需要先 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">task_for_pid</span></code><span leaf="">，权限要求更高</span></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">它们都属于苹果官网文档一个很不起眼的模块 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os</span></code><span leaf="">，一共就没几个 API。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这个 API 返回一个 os_security_config_t，也就是一个 64 位的无符号整数：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="php"><code><span leaf=""><span class="code-snippet__comment">/*!</span></span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@enum</span> os_security_config_t</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@discussion</span></span></code><br/><code><span leaf=""> * Supported security configurations that a process/task can have.</span></code><br/><code><span leaf=""> * This is a bitmask type, allowing multiple configurations to be active.</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@constant</span> OS_SECURITY_CONFIG_NONE</span></code><br/><code><span leaf=""> * No security config flags set.</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@constant</span> OS_SECURITY_CONFIG_HARDENED_HEAP</span></code><br/><code><span leaf=""> * Indicates that the Hardened Heap configuration is enabled for the process/task.</span></code><br/><code><span leaf=""> * This implies security-critical settings for the system memory allocator.</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@constant</span> OS_SECURITY_CONFIG_TPRO</span></code><br/><code><span leaf=""> * Indicates that Trusted Path Read-Only (TPRO) is enabled for the process/task.</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@constant</span> OS_SECURITY_CONFIG_SCRIPT_RESTRICTIONS</span></code><br/><code><span leaf=""> * Indicates Script Restrictions are enabled for the process/task.</span></code><br/><code><span leaf=""> *</span></code><br/><code><span leaf=""> * <span class="code-snippet__doctag">@constant</span> OS_SECURITY_CONFIG_GUARD_OBJECTS</span></code><br/><code><span leaf=""> * Indicates that the Guard Objects configuration is enabled for the process/task.</span></code><br/><code><span leaf=""> */</span></code><br/><code><span leaf=""><span class="code-snippet__title">__API_AVAILABLE</span>(<span class="code-snippet__title">macos</span>(<span class="code-snippet__number">26.0</span>), <span class="code-snippet__title">ios</span>(<span class="code-snippet__number">26.0</span>), <span class="code-snippet__title">tvos</span>(<span class="code-snippet__number">26.0</span>), <span class="code-snippet__title">watchos</span>(<span class="code-snippet__number">26.0</span>), <span class="code-snippet__title">visionos</span>(<span class="code-snippet__number">26.0</span>), <span class="code-snippet__title">driverkit</span>(<span class="code-snippet__number">25.0</span>))</span></code><br/><code><span leaf=""><span class="code-snippet__title">OS_OPTIONS</span>(os_security_config, uint64_t,</span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_NONE = <span class="code-snippet__number">0x0</span>,</span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_HARDENED_HEAP <span class="code-snippet__title">OS_SWIFT_NAME</span>(hardenedHeap) = <span class="code-snippet__number">0x1</span>,</span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_TPRO <span class="code-snippet__title">OS_SWIFT_NAME</span>(trustedPathReadOnly) = <span class="code-snippet__number">0x2</span>,</span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_MTE <span class="code-snippet__title">OS_SWIFT_NAME</span>(memoryTaggingExtension) = <span class="code-snippet__number">0x4</span>,</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_SCRIPT_RESTRICTIONS <span class="code-snippet__title">OS_SWIFT_NAME</span>(scriptRestrictions) = <span class="code-snippet__number">0x40</span>,</span></code><br/><code><span leaf="">  OS_SECURITY_CONFIG_GUARD_OBJECTS <span class="code-snippet__title">OS_SWIFT_NAME</span>(guardObjects) = <span class="code-snippet__number">0x100</span>,</span></code><br/><code><span leaf="">);</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">在 SDK 里的注释写得挺清楚。眼尖的读者应该发现这几个 bit 正好对应了前文提到的各种 entitlement，甚至还有 MTE 的配置。这也是我为什么没法展开的原因，真写起来可太长了。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这组枚举对应了 XNU 内核的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">task_security_config</span></code><span leaf="">（对应版本 xnu-12377）：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__keyword">struct</span> <span class="code-snippet__title">task_security_config</span> {</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">union</span> {</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">struct</span> {</span></code><br/><code><span leaf=""><span class="code-snippet__type">uint16_t</span> hardened_heap: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf="">			    tpro: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">if</span></span><span class="code-snippet__meta"> HAS_MTE || HAS_MTE_EMULATION_SHIMS</span></span></code><br/><code><span leaf="">			    sec: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">else</span></span><span class="code-snippet__meta"><span class="code-snippet__comment">/* HAS_MTE || HAS_MTE_EMULATION_SHIMS */</span></span></span></code><br/><code><span leaf="">			reserved: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">endif</span></span></span></code><br/><code><span leaf="">			platform_restrictions_version: <span class="code-snippet__number">3</span>,</span></code><br/><code><span leaf="">			    script_restrictions: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf="">			    ipc_containment_vessel: <span class="code-snippet__number">1</span>,</span></code><br/><code><span leaf="">			    guard_objects: <span class="code-snippet__number">1</span>;</span></code><br/><code><span leaf=""><span class="code-snippet__type">uint8_t</span> hardened_process_version;</span></code><br/><code><span leaf="">		};</span></code><br/><code><span leaf=""><span class="code-snippet__type">uint32_t</span> value;</span></code><br/><code><span leaf="">	};</span></code><br/><code><span leaf="">};</span></code><br/><code></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">在 XNU 开源代码里并没有找到这结构初始化的部分，只能去 kernelcache 里反编译。伪代码太长就不贴了，直接交叉引用字符串 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">com.apple.security.hardened-process.dyld-ro</span></code><span leaf=""> 就能定位到。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这个函数除了以上提到的加固 entitlement，还检测如下几个键，并针对性地调整防御等级：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">第三方浏览器引擎相关（感谢欧盟）：com.apple.developer.web-browser-engine.{host,rendering,networking,webcontent}</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">driverkit：com.apple.developer.driverkit</span></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">标志位传递到用户态有三种途径：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">当前进程：启动时由 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">applev[]</span></code><span leaf=""> 传递，一次性初始化，缓存在全局变量</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">获取 pid：通过 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">proc_pidinfo</span></code><span leaf=""> 调用</span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf="">获取 task：通过 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">task_info</span></code><span leaf=""> 调用</span></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">反编译 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">libsystem_platform.dylib!os_security_config_get</span></code><span leaf=""> 仅有一行代码：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="javascript"><code><span leaf="">uint64_t <span class="code-snippet__title">os_security_config_get</span>()</span></code><br/><code><span leaf="">{</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">return</span> __restrictions_config &amp; <span class="code-snippet__number">0x40</span> | __security_config &amp; <span class="code-snippet__number">0x107</span>;</span></code><br/><code><span leaf="">}</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这两个全局变量（注：其实有一个不可写）由 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__os_security_config_init</span></code><span leaf=""> 负责初始化。</span></p><h3 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span leaf="">内核参数传递</span></h3><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">XNU 内核在启动进程时，除了常用的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">argv[]</span></code><span leaf=""> 和 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">envp[]</span></code><span leaf=""> 之外还会通过栈传递一个 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">apple[]</span></code><span leaf=""> 字符串数组。如果当前进程有安全相关的配置，就会以 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">security_config=0x???</span></code><span leaf=""> 的格式传递给用户态：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="objectivec"><code><span leaf="">{</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">define</span></span><span class="code-snippet__meta"> SECURITY_CONFIG_KEY </span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;security_config=&#34;</span></span></span></code><br/><code><span leaf=""><span class="code-snippet__type">char</span> security_config_str[strlen(SECURITY_CONFIG_KEY) + HEX_STR_LEN + <span class="code-snippet__number">1</span>];</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">	snprintf(security_config_str, <span class="code-snippet__keyword">sizeof</span>(security_config_str),</span></code><br/><code><span leaf="">	    SECURITY_CONFIG_KEY <span class="code-snippet__string">&#34;0x%x&#34;</span>, task_get_security_config(task));</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">	error = exec_add_user_string(imgp, <span class="code-snippet__built_in">CAST_USER_ADDR_T</span>(security_config_str), <span class="code-snippet__built_in">UIO_SYSSPACE</span>, <span class="code-snippet__literal">FALSE</span>);</span></code><br/><code><span leaf="">	imgp-&gt;ip_applec++;</span></code><br/><code><span leaf="">}</span></code><br/><code></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">if</span></span><span class="code-snippet__meta"> HAS_MTE || HAS_MTE_EMULATION_SHIMS</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">if</span> (task_has_sec(task)) {</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> <span class="code-snippet__type">char</span> *sec_transition_shims = <span class="code-snippet__string">&#34;has_sec_transition=1&#34;</span>;</span></code><br/><code><span leaf="">		error = exec_add_user_string(imgp, <span class="code-snippet__built_in">CAST_USER_ADDR_T</span>(sec_transition_shims), <span class="code-snippet__built_in">UIO_SYSSPACE</span>, <span class="code-snippet__literal">FALSE</span>);</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">if</span> (error) {</span></code><br/><code><span leaf="">			printf(<span class="code-snippet__string">&#34;Failed to add security translation shims notification\n&#34;</span>);</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">goto</span> bad;</span></code><br/><code><span leaf="">		}</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">		imgp-&gt;ip_applec++;</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__comment">/* Push down MTE-specific configuration options that allocators may be interested into. */</span></span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">define</span></span><span class="code-snippet__meta"> SEC_TRANSITION_POLICY_KEY </span><span class="code-snippet__meta"><span class="code-snippet__string">&#34;sec_transition_policy=&#34;</span></span></span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__type">char</span> sec_transition_policy[strlen(SEC_TRANSITION_POLICY_KEY) + HEX_STR_LEN + <span class="code-snippet__number">1</span>];</span></code><br/><code><span leaf="">		snprintf(sec_transition_policy, <span class="code-snippet__keyword">sizeof</span>(sec_transition_policy),</span></code><br/><code><span leaf="">		    SEC_TRANSITION_POLICY_KEY <span class="code-snippet__string">&#34;0x%x&#34;</span>, task_get_sec_policy(task));</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">		error = exec_add_user_string(imgp, <span class="code-snippet__built_in">CAST_USER_ADDR_T</span>(sec_transition_policy), <span class="code-snippet__built_in">UIO_SYSSPACE</span>, <span class="code-snippet__literal">FALSE</span>);</span></code><br/><code><span leaf="">		imgp-&gt;ip_applec++;</span></code><br/><code><span leaf="">	}</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">endif</span></span><span class="code-snippet__meta"><span class="code-snippet__comment">/* HAS_MTE || HAS_MTE_EMULATION_SHIMS */</span></span></span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">针对 MTE 还专门有一个 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">has_sec_transition=1</span></code><span leaf=""> 的配置。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">dyld 在启动进程时负责初始化栈和启动参数（argc、argv、envp 和 apple 等），并传递给主程序的入口点，以及在每次载入 dylib 框架的时候调用其 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">_mod_init_func</span></code><span leaf=""> 注册的初始化函数。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">apple[]</span></code><span leaf=""> 字符串数组最终传递顺序：</span></p><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">dyld</span></code></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">libSystem.B.dylib!libSystem_initializer</span></code></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">libsystem_platform.dylib!__libplatform_init</span></code></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">libsystem_platform.dylib!__os_security_config_init</span></code></p></li></ul><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">也就是每个进程全局初始化一次。</span></p><h3 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span leaf="">进程状态初始化</span></h3><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">有趣的点在 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__os_security_config_init</span></code><span leaf=""> 函数内部的实现。其使用 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">simple_getenv</span></code><span leaf=""> 提取先前提到来自内核的字符串参数，然后解析十六进制字符串作为初始的配置值，也就是我们之前提到最终会存入的 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os_security_config_t</span></code><span leaf="">。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">这里有一个有意思的分支：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__keyword">if</span> (v7 &amp; OS_SECURITY_CONFIG_GUARD_OBJECTS)</span></code><br/><code><span leaf="">      __security_config |= OS_SECURITY_CONFIG_GUARD_OBJECTS;</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">if</span> (v7 &amp; OS_SECURITY_CONFIG_SCRIPT_RESTRICTIONS )</span></code><br/><code><span leaf="">{</span></code><br/><code><span leaf="">      address = (<span class="code-snippet__type">mach_vm_address_t</span>)&amp;os_script_config_storage;</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">if</span> ( <span class="code-snippet__built_in">mach_vm_map</span>(mach_task_self_, &amp;address,</span></code><br/><code><span leaf="">                       <span class="code-snippet__number">0x4000</span>, <span class="code-snippet__comment">// </span></span></code><br/><code><span leaf="">                       <span class="code-snippet__number">0</span>,                                 <span class="code-snippet__comment">// mask</span></span></code><br/><code><span leaf="">                       VM_FLAGS_OVERWRITE | VM_FLAGS_PERMANENT,</span></code><br/><code><span leaf="">                       MEMORY_OBJECT_NULL, <span class="code-snippet__number">0</span>, FALSE,      <span class="code-snippet__comment">// object / offset / copy</span></span></code><br/><code><span leaf="">                       VM_PROT_NONE,                      <span class="code-snippet__comment">// cur_protection</span></span></code><br/><code><span leaf="">                       VM_PROT_NONE,                      <span class="code-snippet__comment">// max_protection</span></span></code><br/><code><span leaf="">                       VM_INHERIT_COPY) )                 <span class="code-snippet__comment">// inheritance (== VM_INHERIT_DEFAULT)</span></span></code><br/><code><span leaf="">          __os_security_config_init_cold_2();</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">      address = (<span class="code-snippet__type">mach_vm_address_t</span>)&amp;__restrictions_config;</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">if</span> ( <span class="code-snippet__built_in">mach_vm_map</span>(mach_task_self_, &amp;address,</span></code><br/><code><span leaf="">                       <span class="code-snippet__number">0x4000</span>, <span class="code-snippet__number">0</span>,</span></code><br/><code><span leaf="">                       VM_FLAGS_OVERWRITE | VM_FLAGS_PERMANENT,</span></code><br/><code><span leaf="">                       MEMORY_OBJECT_NULL, <span class="code-snippet__number">0</span>, FALSE,</span></code><br/><code><span leaf="">                       VM_PROT_READ | VM_PROT_WRITE,      <span class="code-snippet__comment">// cur_protection</span></span></code><br/><code><span leaf="">                       VM_PROT_READ | VM_PROT_WRITE,      <span class="code-snippet__comment">// max_protection</span></span></code><br/><code><span leaf="">                       VM_INHERIT_COPY) )</span></code><br/><code><span leaf="">          __os_security_config_init_cold_3();</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">      __restrictions_config = OS_SECURITY_CONFIG_SCRIPT_RESTRICTIONS;</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">      result = <span class="code-snippet__built_in">mach_vm_protect</span>(mach_task_self_, address,</span></code><br/><code><span leaf="">                               <span class="code-snippet__number">0x4000</span>,</span></code><br/><code><span leaf="">                               <span class="code-snippet__comment">/*set_maximum=*/</span> TRUE,</span></code><br/><code><span leaf="">                               VM_PROT_READ);</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">if</span> ( (<span class="code-snippet__type">kern_return_t</span>)result )</span></code><br/><code><span leaf="">          __os_security_config_init_cold_4();</span></code><br/><code><span leaf="">  }</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">代码没有简单地把值存到全局变量，而是使用位运算拆成了两个部分：</span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__security_config</span></code><span leaf=""> 和 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__restrictions_config</span></code><span leaf="">。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">目前 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__restrictions_config</span></code><span leaf=""> 仅仅用来保存 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">OS_SECURITY_CONFIG_SCRIPT_RESTRICTIONS</span></code><span leaf=""> 状态，而一旦检测到这个状态启用，libsystem_platform 会锁定其所在的内存页面的访问权限为只读。不仅如此，还有另一个名为 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os_script_config_storage</span></code><span leaf=""> 的符号，直接连读权限都取消了。什么鬼？</span></p><h3 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span leaf="">WebKit 的处理</span></h3><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">我们刚才绕了一大圈从内核到链接器到系统库，主要为了演示如何禁用 JavaScriptCore。所以这个符号当然是 WebKit 在用。直接上源码：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__function"><span class="code-snippet__type">static</span></span><span class="code-snippet__function"><span class="code-snippet__type">bool</span></span><span class="code-snippet__function"><span class="code-snippet__title">scriptingIsForbidden</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span>{</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">return</span> <span class="code-snippet__built_in">processHasEntitlement</span>(<span class="code-snippet__string">&#34;com.apple.security.script-restrictions&#34;</span>_s);</span></code><br/><code><span leaf="">}</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"><span class="code-snippet__title">initialize</span></span><span class="code-snippet__function"><span class="code-snippet__params">()</span></span>{</span></code><br/><code><span leaf="">    ...</span></code><br/><code><span leaf="">    WTF::<span class="code-snippet__built_in">makePagesFreezable</span>(&amp;os_script_config_storage, OpcodeConfigSizeToProtect);</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">if</span> (g_jscConfig.vmEntryDisallowed || <span class="code-snippet__built_in">scriptingIsForbidden</span>()) [[unlikely]] {</span></code><br/><code><span leaf="">        g_jscConfig.vmEntryDisallowed = <span class="code-snippet__literal">true</span>;</span></code><br/><code><span leaf="">        WTF::<span class="code-snippet__built_in">permanentlyFreezePages</span>(&amp;os_script_config_storage, OpcodeConfigSizeToProtect,</span></code><br/><code><span leaf="">                                    WTF::FreezePagePermission::None);</span></code><br/><code><span leaf="">        <span class="code-snippet__keyword">return</span>;</span></code><br/><code><span leaf="">    }</span></code><br/><code><span leaf="">    WTF::<span class="code-snippet__built_in">compilerFence</span>();</span></code><br/><code><span leaf="">    ...</span></code><br/><code><span leaf="">}</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">乍一看 WebKit 也是检测标准的 entitlement 来拒绝初始化，但实际上压根走不到那个分支。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">早在上一行 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">WTF::makePagesFreezable</span></code><span leaf=""> 调用，如果当前进程禁止 JavaScriptCore，libsystem_platform.dylib 就会把 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">os_script_config_storage</span></code><span leaf=""> 所在内存标记为不可访问。</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__comment">// Works together with permanentlyFreezePages().</span></span></code><br/><code><span leaf=""><span class="code-snippet__function"><span class="code-snippet__type">void</span></span><span class="code-snippet__function"><span class="code-snippet__title">makePagesFreezable</span></span><span class="code-snippet__function"><span class="code-snippet__params">(</span></span><span class="code-snippet__function"><span class="code-snippet__params"><span class="code-snippet__type">void</span></span></span><span class="code-snippet__function"><span class="code-snippet__params">* base, </span></span><span class="code-snippet__function"><span class="code-snippet__params"><span class="code-snippet__type">size_t</span></span></span><span class="code-snippet__function"><span class="code-snippet__params"> size)</span></span></span></code><br/><code><span leaf="">{</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">RELEASE_ASSERT</span>(<span class="code-snippet__built_in">roundUpToMultipleOf</span>(<span class="code-snippet__built_in">pageSize</span>(), size) == size);</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">if</span></span><span class="code-snippet__meta"> PLATFORM(COCOA)</span></span></code><br/><code><span leaf="">    <span class="code-snippet__type">mach_vm_address_t</span> addr = std::<span class="code-snippet__built_in">bit_cast</span>&lt;<span class="code-snippet__type">uintptr_t</span>&gt;(base);</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">auto</span> flags = VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE | VM_FLAGS_PERMANENT;</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">auto</span> attemptVMMapping = [&amp;] {</span></code><br/><code><span leaf="">        <span class="code-snippet__keyword">auto</span> result = <span class="code-snippet__built_in">mach_vm_map</span>(<span class="code-snippet__built_in">mach_task_self</span>(), &amp;addr, size, <span class="code-snippet__built_in">pageSize</span>() - <span class="code-snippet__number">1</span>, flags, MEMORY_OBJECT_NULL, <span class="code-snippet__number">0</span>, <span class="code-snippet__literal">false</span>, VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_DEFAULT);</span></code><br/><code><span leaf="">        <span class="code-snippet__keyword">return</span> result;</span></code><br/><code><span leaf="">    };</span></code><br/><code><span leaf=""><br/></span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">auto</span> result = <span class="code-snippet__built_in">attemptVMMapping</span>();</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">if</span></span><span class="code-snippet__meta"> PLATFORM(IOS_FAMILY_SIMULATOR)</span></span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">if</span> (result != KERN_SUCCESS) {</span></code><br/><code><span leaf="">        flags &amp;= ~VM_FLAGS_PERMANENT; <span class="code-snippet__comment">// See rdar://75747788.</span></span></code><br/><code><span leaf="">        result = <span class="code-snippet__built_in">attemptVMMapping</span>();</span></code><br/><code><span leaf="">    }</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">endif</span></span></span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">RELEASE_ASSERT</span>(result == KERN_SUCCESS);</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">else</span></span></span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">UNUSED_PARAM</span>(base);</span></code><br/><code><span leaf="">    <span class="code-snippet__built_in">UNUSED_PARAM</span>(size);</span></code><br/><code><span leaf=""><span class="code-snippet__meta">#</span><span class="code-snippet__meta"><span class="code-snippet__keyword">endif</span></span></span></code><br/><code><span leaf="">}</span></code><br/></pre></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">因此 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">makePagesFreezable</span></code><span leaf=""> 直接就抛异常（</span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">RELEASE_ASSERT</span></code><span leaf="">）了。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">以上的内存权限也是为了防止漏洞利用在拥有读写原语之后修改 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">__restrictions_config</span></code><span leaf="">。照这样看来 Apple 认为剩余的几个 flag 并不需要只读保护。可能是因为读取时机的区别，其余的 bit 主要影响内存分配器（对应开源代码的 libmalloc）的行为，而它们早在进程初始化阶段就处理完了。</span></p><h2 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 22px;"><span leaf="">小结</span></h2><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">一个一句话能说清的需求：禁止某些系统进程使用 JavaScriptCore，牵扯到了一堆组件来实现。</span></p><p data-tool="markdown.com.cn编辑器" style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;"><span leaf="">内核将 entitlement 的设定转换成 </span><code style="word-spacing: 0px;letter-spacing: 0px;text-align: justify;line-height: 26px;font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="" style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">task_security_config</span></code><span leaf="">，再通过 </span><code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;color: #1e6bb8;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">apple[]</span></code><span leaf=""> 数组传递给用户态初始化逻辑，而用户态的状态消费者则有</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;nice&#34;,&#34;data-tool&#34;:&#34;markdown编辑器&#34;,&#34;data-website&#34;:&#34;https://markdown.com.cn/editor&#34;,&#34;style&#34;:&#34;font-size: 16px; color: black; padding: 25px 30px; line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: justify; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#39;PingFang SC&#39;, Cambria, Cochin, Georgia, Times, &#39;Times New Roman&#39;, serif; margin-top: -10px;&#34;,&#34;data-pm-slice&#34;:&#34;0 0 []&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{&#34;data-tool&#34;:&#34;markdown.com.cn编辑器&#34;,&#34;style&#34;:&#34;font-size: 16px; padding-top: 8px; padding-bottom: 8px; margin: 0; line-height: 26px; color: black;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">被动的内存访问失败和</span><span leaf="">显式检查 </span><span leaf="" style="word-spacing: 0px;letter-spacing: 0px;text-align: justify;line-height: 26px;font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;word-break: break-all;">processHasEntitlement</span><span leaf="">两层把关，让 JavaScriptCore 初始化失败。</span></p><h3 data-tool="markdown.com.cn编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span leaf="">参考资料</span></h3><ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://developer.apple.com/documentation/Xcode/enabling-enhanced-security-for-your-app" target="_blank">https://developer.apple.com/documentation/Xcode/enabling-enhanced-security-for-your-app</a></span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://developer.apple.com/documentation/javascriptcore/jscontext" target="_blank">https://developer.apple.com/documentation/javascriptcore/jscontext</a></span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://developer.apple.com/documentation/os/os_security_config_get" target="_blank">https://developer.apple.com/documentation/os/os_security_config_get</a></span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://github.com/apple-oss-distributions/xnu" target="_blank">https://github.com/apple-oss-distributions/xnu</a></span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://github.com/apple-oss-distributions/dyld" target="_blank">https://github.com/apple-oss-distributions/dyld</a></span></p></li><li><p style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;color: rgb(1,1,1);font-weight: 500;"><span leaf=""><a href="https://github.com/apple-oss-distributions/libsystem" target="_blank">https://github.com/apple-oss-distributions/libsystem</a></span></p></li></ul></div><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=ae3e5587&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486053%26idx%3D1%26sn%3D94d02df5700c83173e6edd4fb665b40d">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 07 Jun 2026 09:04:00 +0800</pubDate>
    </item>
    <item>
      <title>原来我五年前就整过 AI 泔水了</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486039&amp;idx=1&amp;sn=d9dc57365852f3fd4ee22bb621bf3ea2</link>
      <description>清理大而丑 app 的存储空间，偶然发现一张来自 2021 年九月的截图。当时著名程序员 Fabrice Bellard 在他的主页上线了 TextSynth——一个可以调用文本模型的网页工具。我就用 GPTJ-6B 围绕安全主题续写（瞎编）了一段文字。&#xA;&#xA;可以看到刚开始还编得像那么回事，第二段就开始不太对劲了。好在初代的文本模型没有遍地的 emoji。&#xA;&#xA;注意此 GPT 并不是 ChatGPT，而是本意 Generative Pre-trained Transformer。GPT-J-6B 是由开源研究团队 EleutherAI 在 2021 年推出的一款开源大语言模型。&#xA;&#xA;短短数年，恍如隔世。&#xA;&#xA;虽然 AI 幻觉依然无法消灭，在模型能力强化和各种工程化实践之后，都能找到很复杂的漏洞了。反过来看，在 2026 年的当下，如果还有谁不加验证复制粘贴 AI 生成的幻觉报告来浪费时间，那是真的很难评了。</description>
      <content:encoded><![CDATA[<p><span>非尝咸鱼贩</span> <span>2026-05-29 07:46</span> <span style="display: inline-block;">瑞士</span></p>






  
  
  <p>清理大而丑 app 的存储空间，偶然发现一张来自 2021 年九月的截图。当时著名程序员 Fabrice Bellard 在他的主页上线了 TextSynth——一个可以调用文本模型的网页工具。我就用 GPTJ-6B 围绕安全主题续写（瞎编）了一段文字。</p><p>可以看到刚开始还编得像那么回事，第二段就开始不太对劲了。好在初代的文本模型没有遍地的 emoji。</p><p>注意此 GPT 并不是 ChatGPT，而是本意 Generative Pre-trained Transformer。GPT-J-6B 是由开源研究团队 EleutherAI 在 2021 年推出的一款开源大语言模型。</p><p>短短数年，恍如隔世。</p><p>虽然 AI 幻觉依然无法消灭，在模型能力强化和各种工程化实践之后，都能找到很复杂的漏洞了。反过来看，在 2026 年的当下，如果还有谁不加验证复制粘贴 AI 生成的幻觉报告来浪费时间，那是真的很难评了。</p>
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=6815b128&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9Ehqpkw0iay2qSoNH7Ticl4AhUSLnNAlw9WN2sEpfr7FoIlF4pWxZknRlB3EIMZ2NFibsciaYRiapKEuAvj4LRLDQNvaKNp4w2icpdR3O5hw%2F0%3Fwx_fmt%3Djpeg"/></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=87b2c403&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486039%26idx%3D1%26sn%3Dd9dc57365852f3fd4ee22bb621bf3ea2">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 29 May 2026 07:46:00 +0800</pubDate>
    </item>
    <item>
      <title>国外某破解比赛结果揭晓</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247486016&amp;idx=1&amp;sn=7ce6c141dd8711d78c6b72fa91290e90</link>
      <description>2026 柏林 p2o 三天赛程结束，结果刚刚在 OffensiveCon 闭幕会上揭晓。DEVCORE 拿下 Master of Pwn，STARLabs SG 紧随其后。&#xA;&#xA;今年比赛戏份很足。由于 AI 加成，报名火爆程度超出主办方预料，有不少队伍没报上名。有人干脆就先交给厂商了。赛前 FireFox 紧急发布补丁干掉了一个队伍的项目。Palo Alto Networks 有一个难度相当高的 Safari RCE，赛前在 M4 硬件上调试，临期才告知最终环境是 M5。不巧遇上法定假日商店都不开门，没有买到和比赛环境匹配的设备，最终只差了一个 bit 适配问题遗憾没有演示成功。&#xA;&#xA;不少项目感觉都很有意思。个人最期待🍊神用纯逻辑漏洞链打下 Edge 浏览器的项目，坐等公开细节[666]</description>
      <content:encoded><![CDATA[<p><span>非尝咸鱼贩</span> <span>2026-05-17 02:50</span> <span style="display: inline-block;">德国</span></p>






  
  
  <p>2026 柏林 p2o 三天赛程结束，结果刚刚在 OffensiveCon 闭幕会上揭晓。DEVCORE 拿下 Master of Pwn，STARLabs SG 紧随其后。</p><p>今年比赛戏份很足。由于 AI 加成，报名火爆程度超出主办方预料，有不少队伍没报上名。有人干脆就先交给厂商了。赛前 FireFox 紧急发布补丁干掉了一个队伍的项目。Palo Alto Networks 有一个难度相当高的 Safari RCE，赛前在 M4 硬件上调试，临期才告知最终环境是 M5。不巧遇上法定假日商店都不开门，没有买到和比赛环境匹配的设备，最终只差了一个 bit 适配问题遗憾没有演示成功。</p><p>不少项目感觉都很有意思。个人最期待🍊神用纯逻辑漏洞链打下 Edge 浏览器的项目，坐等公开细节[666]</p>
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=c1861702&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqplKZ6T5prO0v0s5I648zRjU7ZLkm8dXMq5hpYaCtI8bBpt4hY5eUSI174Lw4dS9JUR3xfwTSJ76kF6OicnRjK31ZvyibnP14aBF4%2F0%3Fwx_fmt%3Djpeg"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=8802dd49&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpnOSLPIgI8d2RCxqbQL7tSFpFRxQ81NtxXF2Y9un77Vs1ZFKIDzEAnW9YOupZiaAnOuSNmWlicBfW9jqDo3zMvIMicBpaZibQibpW5k%2F0%3Fwx_fmt%3Djpeg"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=0be83cf1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpleUzMjWLfibWcPDGL1vJV7ht9z4BF6mmiaUmsE9INf9f1O0tPZVRiaicC6uwgqjfa10Y57LjFmkov0RSvmn1GPia0yBmvbXCA7wMzw%2F0%3Fwx_fmt%3Djpeg"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=c08d2128&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpnS7mrUe1zEr3icPNAQRQrtUQK3df8UuTqiaVbvLpvd3MdAAv6TPz4BSibM2lV46qRMiakc8bicP3nTyibxRFOAEvg7myCBWzJQ1ZqBk%2F0%3Fwx_fmt%3Djpeg"/></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=2ed2c19b&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247486016%26idx%3D1%26sn%3D7ce6c141dd8711d78c6b72fa91290e90">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 17 May 2026 02:50:00 +0800</pubDate>
    </item>
    <item>
      <title>2026 年了，还在折腾 dyld_shared_cache</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485978&amp;idx=1&amp;sn=6f7b8114611ce0724611484066a6b3c0</link>
      <description>赶时髦：用 Rust 重写；叫 AI 用 Rust 重写。</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-05-01 08:10</span> <span style="display: inline-block;">芬兰</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=ab970098&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpkiaeOIJ0TiciaCqkQibvzTCKlSx6Eicicjb0aR5mLia6lMumzYjv9kWu4Kgm7K7UhicZvyUom2ib99X46RZEA3FI2CyAasficos3DbXicfa4%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>赶时髦：用 Rust 重写；叫 AI 用 Rust 重写。</p>
  <p><span leaf="">今晚两个消息，Google Chrome VRP 大幅降低 bounty 价格，Claude 向企业用户开放 Claude Security 工具的 beta 测试。</span></p><p><span leaf="">装作没看见，依然写老掉牙的题材。虽然实在没劲，倒也是一直有人问。</span></p><p><span leaf="">iOS 的绝大多数用户态框架都在文件系统上找不到，而是预链接了几千个 dylib 作为一个巨大的共享缓存（dyld_shared_cache）。macOS 从 BigSur 开始也引入了这个机制。想反编译点代码还挺麻烦。</span></p><p><span leaf="">都已经 2026 年了，各大反编译工具如 IDA Pro / Binary Ninja /  Ghidra / Hooper / radare2 都内置了 dyld_shared_cache 的支持。</span></p><p><span leaf="">说是支持，体验起来还是难受。</span></p><p><span leaf="">毕竟文件体积摆在那里，你只想看一个库，还得载入很多不想干的文件。漫长等待、爆内存、xref 不能用……各种问题。</span></p><p><span leaf="">拆分成单个文件？系统自带了 </span><span leaf="">dsc_extractor.bundle，但是拆出来的文件也不能用，反编译一看全是红色的地址。</span></p><p><span leaf="">dyld_shared_cache 里的每个文件都被 dyld 预处理过了。很多原本属于单个 Mach-O 的信息，被挪到了 cache 的全局区域；很多指针已经按共享缓存地址空间修正过；跨库的符号引用不再使用 bind，而是直接变成 dsc 里的重定向地址。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5076660988074957" data-s="300,640" data-type="png" data-w="2935" type="block" data-imgfileid="100002321" src="https://wechat2rss.xlab.app/img-proxy/?k=d3fb33d9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9Ehqpn8YpibKclDqhY2lwAXyT6yPBDCv5LHWcib3kdduxPSPVBA08KibNA29e1kJ2ibZj1KEFSXvghv3PUOw5PEH1Gm2Q4tPZYGYjQdThI%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p data-pm-slice="2 2 []"><span leaf="">所以反编译器看到的是一个损坏的文件：</span><span leaf="">指针指向文件外，符号表缺失，__LINKEDIT 不完整，GOT 和 stub 对不上，ObjC 元数据里到处是共享缓存地址。</span></p><p data-pm-slice="2 2 []"><span leaf="">等等，上面的这个对比图是怎么来的？当然是写了个工具搞定了。</span></p><p><span leaf="">我几年前就用 C++ 手写过一个版本，需要串联 dsc_extractor.bundle 的输出结果和原始 dsc 文件一起处理。大体能用，但限制也很明显：只支持 iOS 18 以后的 arm64e 缓存，而且实际用起来经常遇到样本处理不完整的问题，只能哪里坏了补哪里。</span></p><p><span leaf="">现在当然要随波逐流：用 Rust 重写；叫 AI 用 Rust 重写。</span></p><p><span leaf="">这算是我用 vibe coding 做过的相对复杂的一个工作。当然，AI 不会一句话直接变出一个能用的方案，前提是我之前已经对 dyld 内部的不少机制比较熟悉，一开始能设计一个方案，并且解决不少性能和设计上的问题。</span></p><p><span leaf="">我不打算开源，所以这里简单介绍一下思路，哪位读者实在是需要，可以考虑自己复现。</span></p><p><span leaf="">这个工具的本质是恢复跨模块的链接信息：符号绑定和重定向。对应到现在的 dyld，主要就是恢复 chained fixups 结构信息，同时处理很多边角问题如二进制重排、Objective-C 运行时信息恢复，以及 ARM64 指令里那些已经被 dyld 重定位过的地址引用。</span></p><p><span leaf="">第一步当然是复刻 dsc_extractor.bundle 的行为。最简单的办法，是直接动态链接 Xcode 里自带的实现。</span></p><p><span leaf="">而 dyld 本身是开源的，都 2026 年了，当然也可以让 AI 参考 dyld 的实现，把相关逻辑移植到 Rust。然后提供几个不同版本的 iOS dyld_shared_cache 样本和 macOS 样本，让它在真实文件上自行修复、迭代。</span></p><p><span leaf="">macOS 系统和 LLVM 工具链本身就提供了很多检查 Mach-O 的工具，比如 nm、otool、dyld_info、objdump。这些工具可以作为 harness 的一部分，用来检查导出的 Mach-O 是否结构正常；同时明确要求 segment 地址、顺序、大小等关键布局尽量和原始输出保持一致，作为回归指标。</span></p><p><span leaf="">于是现在有了一个跨平台的 dsc_extractor，甚至可以部署在 NAS 上。还有一个好处是原版的并不让用户控制有选择地解压个别路径，现在可以只提取一两个库，即使是全量解压也比原版快很多。</span></p><p data-pm-slice="2 2 []"><span leaf="">接下来这个文件到底坏在哪里？</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="1.3" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002325" src="https://wechat2rss.xlab.app/img-proxy/?k=a53a1e86&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmwKMcgCTg9c3huibxJJXvA4ISU5BGuF77FX6vIH3PsevWQqjiaNiawOQKwBOa0s3n4pJPvpoX2ddQRr6USQDbDUUkxYaic8DKvJg8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p data-pm-slice="2 2 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;">主要有这么些症状：</span></p><ol class="list-paddingleft-1"><li><p data-pm-slice="2 2 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;">分支跳转指令指向共享的 stub island 或者直接跳转到另一个库的 __TEXT 段</span></p></li><li><p><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;">数据区里的指针已经被 dyld 预先重定位过，指向文件外。比如 GOT、Objective-C class refs、selector refs、常量区里的函数指针，本来应该通过 bind 绑定外部符号，或使用 rebase 指向同一文件内部地址</span></p></li><li><p><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;">Objective-C 元数据指向 __OBJC_RO 和 </span><span leaf="">__OBJC_RW 段，不在文件内</span></p></li><li><p><span leaf="">GOT 被清零，间接绑定的 stub 地址对不上</span></p></li><li><p><span leaf="">arm64e 架构的文件还能看到指针被编码，</span><span leaf="">混有 PAC 相关信息、diversity、key、next 等字段。对 dyld 来说这些是 chained fixups 的一部分；对单独拆出来的文件来说，就会变成一堆不像地址也不像符号的数值</span></p></li></ol><p><span leaf="">dyld_shared_cache 里有 slide info，描述哪些页面、哪些位置存在需要重定位的指针。系统加载 cache 时，dyld 会沿着这些信息把指针修到正确的共享地址空间里。</span></p><p><span leaf="">关键就是逆向这个行为，找出当前 dylib 里有哪些指针需要恢复到 chained fixups 里。</span></p><p><span leaf="">目前的 dsc 依然大发慈悲保留了 exports trie 结构，虽然链接器本身已经不再使用。我们可以通过这个解析某个 dylib 所有导出的符号和地址</span><span leaf="">，再反过来用地址去匹配符号。</span></p><p><span leaf="">slide info 结构迭代了五个版本。读者可以自行古法查找源代码，或者让 AI 代劳找出来。遍历 slide info 信息获取指针的所在地址和目标地址，如果目标地址在当前 dylib 范围内，生成一个 rebase；反之则反查符号索引，生成一个 bind。</span></p><p><span leaf="">当然实际情况会脏很多。地址可能带 Swift 或 arm64e 的额外 bit；目标可能落在符号中间，需要记录 addend；有些地址指向的不是函数，而是 ObjC 的 class、selector、protocol 或常量数据；还要递归处理 re-export 的情况。</span></p><p><span leaf="">在程序中会遇到大量“获取某个地址上 rebase 之后的数据”的操作。而 dsc 的 slide info 是以内存页为单位，用链表保存重定位信息。</span></p><p><span leaf="">dyld 在这里做了一个很有意思的设计：链表本身就保存在相应的地址上。重定位指针的时候，原来的指针值会被编码成一种特殊格式，其中一部分 bit 表示目标地址，另一部分 bit 表示到下一个 fixup 的距离。</span></p><p><span leaf="">页面里没有额外放一张“重定位表”。每个需要 fixup 的指针 slot 自己就是链表节点。dyld 处理某个页面时，只需要从 page start 指定的位置开始，读取这个 slot 上的 encoded pointer，解码出当前指针应该变成什么值，同时得到下一个节点距离当前位置多远。然后跳到下一个 slot，继续重复这个过程，直到 next == 0。</span></p><p><span leaf="">但对我们这种离线恢复工具来说，它有一个副作用：如果想知道某个随机地址是不是 fixup，不能只看一眼 metadata 就结束。你得找到它所在页面的 fixup 链，从 page start 一路走过去，才能知道这个地址在不在链上，以及它被 dyld rebase 之后应该是什么值。</span></p><p><span leaf="">实际运行会产生大量随机访问，重复解析多次产生严重的性能问题。</span></p><p><span leaf="">解决方法很简单，把文件以 copy on write 方式映射到内存，直接照着 dyld 的行为原地重定向即可。再简单加一层按需访问缓存，用 bitmap 标记状态，如果没有 rebase 过就走一遍。</span></p><p><span leaf="">所有地方都走同一个读取接口，只要页面被访问过，里面的指针就已经是“dyld 处理过”的状态。对于 Objective-C 元数据遍历、GOT 分析、ARM64 地址追踪这类会大量随机读指针的逻辑，性能会稳定很多。如果需要</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">读取原始文件内容，再 mmap 一个只读副本就好了。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5166666666666667" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002327" src="https://wechat2rss.xlab.app/img-proxy/?k=40d8ce98&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpkumNJpPJQAEAWdyjia4MS1aj75P1lXg38oVNjMw2q0JKhicmrztU5NNe8tjW2cspuiaib43ribXxZcQPpSGmuErtrV573yYvXWpxHk%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;"><span leaf=""><span textstyle="" style="font-size: 14px;">class 列表的修复</span></span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.85" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002328" src="https://wechat2rss.xlab.app/img-proxy/?k=7e0ad43b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9Ehqpm2C4420JGTEGQcxekl7scbBDmcD0ezgTfFwE5eOjcNHgbKDdw6LwVmL7aflJ5CKYMLtBTINcjQVNw0lmCBKmgCDzJcwvn5QVA%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;"><span leaf=""><span textstyle="" style="font-size: 14px;">CFString 的修复</span></span></p><p><span leaf="">最后一步是最麻烦的，如何修复指令当中对地址的无效引用。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.31666666666666665" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002329" src="https://wechat2rss.xlab.app/img-proxy/?k=78b21b2d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqplnhiczPDPnucAZUOHB3PIGMBAb5NOZOKfkLuAaCicH7VrALtFxvJt51RpD7DibfILN5y2rtJRDIiatm1XlUljEhn48flnbgeBTtc8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">需要处理如下情况：</span></p><ol style="list-style-type: decimal;" class="list-paddingleft-1"><li><p><span leaf="">B/BL 目标地址是 stub island，需要替换成当前 dylib 的 __auth_stub 当中的动态绑定符号</span></p></li><li><p><span leaf="">ADRP 的处理，一般会遇到 ADRP 和 ADD（如字符串、selector 的引用）或者 ADRP 和 LDR 的组合</span></p></li></ol><p><span leaf="">所以工具会做一层很轻量的指令扫描，不追求完整反编译，只识别几种模式。</span></p><p><span leaf="">第一种最明显的分支跳转，如果是</span><span leaf="">共享的 stub island，</span><span leaf="">就在当前 dylib 里找一个合适的 stub/GOT 位置，把这条分支改成跳到本文件内的 stub。</span></p><p><span leaf="">第二种是 ADRP + ADD，最常见就是 selector 和 class 的引用。替换成本地的 </span><span leaf="">__objc_methname 或者外部绑定地址。</span></p><p><span leaf="">第三种是 ADRP + LDR，一般是 G</span><span leaf="">OT、指针、ObjC 引用等。</span></p><p><span leaf="">以上两种 ADRP 都可以做一个快速路径处理，在识别到 ADRP 的时候，不需要解析后续的 ADD 或者 LDR，已经能获取到内存页的基地址，就能快速判断是不是外部的引用。ADRP 在 arm64 程序当中出现频次非常高，如果不加优化会导致运行极其缓慢。</span></p><p><span leaf="">这里还藏着一些坑。dyld 合并之后的 cache 有时候会出现同一个内存页包含两个 dylib 的结束和起始地址的情况……而这还不是最大的问题。</span></p><p><span leaf="">默认 ADRP 紧跟 </span><span leaf="">ADD 或 LDR 当然最容易处理，但真实代码当中</span><span leaf="">编译器经常会把它们隔开几条指令，中间穿插一些寄存器移动，甚至条件分支指令。</span></p><p><span leaf="">所以这里实现了一个简单的状态追踪，并不是真正的数据流分析。遇到类似如下指令</span></p><p><span leaf="">ADRP Xn, page</span></p><p><span leaf="">就记录一个状态，接下来线性扫描分支跳转指令简单记录控制流，如果遇到接下来匹配的操作就计算最终地址。</span><span leaf="">只要发现 Xn 被其他指令覆盖，就清掉这个寄存器的状态。再结合 </span><span leaf="">LC_FUNCTION_STARTS 限制函数边界，实际测试扫描的窗口不会很夸张。</span></p><p><span leaf="">在具体交给 agent 实现的时候，一开始我给的文档提到了主要思路和踩过的坑。但是生成的版本非常不满意，主要原因还是缺少回归测试的标准。</span></p><p><span leaf="">直到我偶然提到了一次 IDA，agent 给我加了一个判定的方法。生成新的 dylib 之后调用 idat 生成 .asm 文件，grep 有没有类似的无效地址引用：</span></p><p><span leaf="">0x1FAC66B18@PAGEOFF</span></p><p><span leaf="">再检查其他 Objective-C 的区段是不是正确地还原成了符号，而不是地址。代码里面每次遇到不合理的条件就直接输出日志作为反馈。这样测试覆盖率突然就上去了，挂机一晚自主解决了不少 bug。反正我手工验收，还没发现有问题的样本。</span></p><p><span leaf="">先这样吧，反正也不开源 <img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1" data-w="20" style="display:inline-block;width:20px;vertical-align:middle;background-size:cover;" src="https://wechat2rss.xlab.app/img-proxy/?k=8ddeb7c5&amp;u=https%3A%2F%2Fres.wx.qq.com%2Ft%2Fwx_fed%2Fwe-emoji%2Fres%2Fassets%2Fnewemoji%2FYellowdog.png"/></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=17b5a00a&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485978%26idx%3D1%26sn%3D6f7b8114611ce0724611484066a6b3c0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 01 May 2026 08:10:00 +0800</pubDate>
    </item>
    <item>
      <title>反编译白宫 app 会被定点……吗？</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485893&amp;idx=1&amp;sn=d11b1e647837ddcbf4a42bcdd50f8c4f</link>
      <description>好奇心杀死猫</description>
      <content:encoded><![CDATA[<p>原创 <span>营销号</span> <span>2026-03-30 08:57</span> <span style="display: inline-block;">瑞士</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=af4b6031&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpncibiaVvAonp5zibOiamUnnsGiboWPzfQJBwWicFw5zY0bhtzp5zs167rqggk4VZAgvnoE9GTj8N6auo9XFM6ZPxRe8jYR2YicYJr3Uc%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>好奇心杀死猫</p>
  <p><span leaf="">2026 年 3 月 27 日，“The White House”官方移动应用程序上线了。上线不久就有两位手痒的研究员发布了分析报告，分别针对 Android 和 iOS：</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002229" data-ratio="0.7138888888888889" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=fae46c2b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqplBjswVA32AoAic10Z7kiaVBzl0C69JJuD1Yic6UYF9ibTau9DkUW3BYc7N2mhTDSsoZu5sQqOceRXjbNygKX11y9KiaODBVLkaQZn0%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002230" data-ratio="0.5518518518518518" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=b193f2b2&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9Ehqpk55OWll7x50icW9LyRTYic97DoVaib9UGuxLJDribj4O5cXdowhKbSCUsNBlOhB2cK22nk6MWKctDzfCR5A6ibChO3VMa6HefX5TXU%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">外网链接咱就不贴了，很容易搜索到。由于这个 app 本质上是 expo（基于 React Native）框架开发，所以两篇文章大同小异。</span></p><div><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">在这里要提一嘴。React Native 有个坏处是，原本 iOS 下的 ipa 包都有fairplay 数字版权管理（DRM）保护，要反编译二进制代码，首先要做的事就是找个越狱设备进行“砸壳”。</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">然而 fairplay 只保护 Mach-O 可执行文件，React Native 的 hermes 字节码（jsbundle）是没有加密的。直接用 ipatool 工具从 iTunes 下载 ipa 回来直接 unzip 就好了。甚至是框架（.framework）里的本地代码，</span><span leaf="">LC_ENCRYPTION_INFO_64 的 </span><span leaf="">cryptoff 会跳过文件头的相当一部分数据，即使不解密也能用 nm 工具打印出一堆符号来猜。相当于砸壳可有可无了。</span></p><p><span leaf="">所以 iOS 那篇分析的作者直接甩锅，没有用破解工具哦：</span></p></div><blockquote class="js_blockquote_wrap"><div class="js_blockquote_digest"><p><span leaf="">We downloaded the app, unzipped it, and took a look at what’s inside. No hacking, no traffic interception, no DRM bypassing. Just standard macOS tools (strings, nm, plutil) pointed at a free app anyone can download from the App Store.</span></p></div><p class="blockquote_info js_blockquote_source" data-json="%7B%22type%22%3A%22out%22%2C%22article%22%3A%7B%7D%2C%22from%22%3A%22Security%20Analysis%20of%20the%20Official%20White%20House%20iOS%20App%22%7D"><span class="blockquote_other">Security Analysis of the Official White House iOS App</span></p></blockquote><p><span leaf="">研究人员</span><span leaf="">反编译发现，应用每隔数分钟采集一次 GPS 定位，数据同步至第三方服务器；在 WebView 注入 js 代码绕过网站付费墙（paywall）和隐私提示，违反欧盟 GDPR 法规；部分代码依赖的仓库是个人开发者，存在被篡改风险。</span></p><p><span leaf="">下面进入正题。</span></p><p><span leaf="">之前有发文章宣传过我写了个图形界面工具来方便 iOS 和 Android 两大主流平台的 app 分析。其中包括 React Native 运行时分析：</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002242" data-ratio="0.9267480577136515" data-s="300,640" type="block" data-type="png" data-w="1802" src="https://wechat2rss.xlab.app/img-proxy/?k=95180e01&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9Ehqpk8Qu39vLWI8crylvWlkfpLOt8Ricib0trJQdKcZKyc7BZibIeT5P2MPSxUR1la2WOGCVbTpUX51CFhxkW6atusTF00p15o5nw9V8%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">手欠的我当然是试了一把。理论上 React Native 的界面逻辑，通过注入 js 做原型链的钩子就能实现很多修改，暂时还没精力深入开发这块。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002240" data-ratio="0.7453703703703703" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=f625ffe5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmHcvKR7nibxHxj3coia6sUZ4qG4YVacCjWMKxEcibP8HSCwibYsMTPxYcZWtyPib4Ug4SsgBBeEFZCZAblpWzJmEr5uwAPIiaOfbdXM%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">但别人的分析都集中在 React Native 反编译上。我这时候意识到我的程序里面集成的 hermes 反编译还不够用，而正好前两天 push 了一下 radare2 开发者，给 r2hermes 工具加上了缺失的交叉引用功能。</span></p><p><span leaf="">在这里补充一下上下文。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">radare2 最近上了 hermes 字节码反编译的插件。</span><span leaf="">radare2 虽然反编译效果算不上怎么样，但胜在免费开源集成方便。即使是 GPL，反正我不改代码不静态链接就好了。</span></p><p><span leaf="">于是今天搞了一下午，做了一个网页版的 radare2。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.7459970887918487" data-s="300,640" data-type="png" data-w="2748" type="block" data-imgfileid="100002236" src="https://wechat2rss.xlab.app/img-proxy/?k=573e6398&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpn2MLI0nhDOPrGiahhfZJE9NXx9iaoYiaMk8Y71ObQ4wibJXo30FSlkQuaCiblEQQy9dI6owlCp8QicCOMUDkicjcsL1OHPARcqnqm6eo%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002237" data-ratio="0.7459970887918487" data-s="300,640" type="block" data-type="png" data-w="2748" src="https://wechat2rss.xlab.app/img-proxy/?k=a85a22ce&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpn07M4Uo0QqkwFwJ2n7CK6rkibTg6xTB0xcqjoVs5UtNnsyV1XXxpL4FI74nhWUwHIF5gCBAjO19OcEpkTfuTUgIlY0bQic47ZbE%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002235" data-ratio="0.7388483373884833" data-s="300,640" type="block" data-type="png" data-w="2466" src="https://wechat2rss.xlab.app/img-proxy/?k=fad4fb1e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmvKfLlAn9VHasYvejOPUa3lnXWiaSThQiajDO2GQIWb8FH5CG7TbeOwA9SSSPU0r0xBsG0fc5h1zCA0fXoaTOxsmtZSkkyZaF3g%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">配置 llm 之后简直就是开挂，反编译出来的东西跟源码似的。</span></p><p><span leaf="">基本找到了几位研究员提到的相关代码，在字符串里还多处硬编码了……不予置评。咱们是技术博主，不是观点输出博主。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002243" data-ratio="0.700925925925926" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=1d9ff4b2&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpkPdvNJeHreQwgB8YPwjS6C3A73ia0ias4BjiaGNFxl8Nvg2uwgxu96ibrkA3AT61Xq6nNCeAicswaFVh3GRmBHukxhU82vkraC4Pz4%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002244" data-ratio="0.700925925925926" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=127696bf&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmJrIiaiasGm1thJ57PAjYLWicSXTXr3IR2CHwHqjWg6Ng58cYf9V5ibiaibB43CnmtKPxAyibjkMQWsF19RMLpKHuuqZPdNqzjicqLhFg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">工具已经发布了 v1.1.0 到 npm，node 一键安装：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="css"><code><span leaf="">npm <span class="code-snippet__selector-tag">i</span> -<span class="code-snippet__selector-tag">g</span> igf</span></code></pre></p><p><span leaf="">也可以去 GitHub 页面直接下载 exe，基于 bun 打包的单文件。由于没（经费去）代码签名，下载安装的方式需要自行去除来自 Internet 标记，否则将无法运行。同样由于没有代码签名，没法验证文件是不是官方（我）构建的，所以还请风险自负。</span></p><p><span leaf="">问题来了，反编译白宫的 app 会被定点……吗？</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=8b86ce4e&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485893%26idx%3D1%26sn%3Dd11b1e647837ddcbf4a42bcdd50f8c4f">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Mon, 30 Mar 2026 08:57:00 +0800</pubDate>
    </item>
    <item>
      <title>更一下 VSCode Frida 插件</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485846&amp;idx=1&amp;sn=2ba63ea4705b30f5580dbec459f76b7f</link>
      <description>VSCode 插件市场直接搜索 frida 工作台安装。增强版 Java 和 ObjC 类型提示，可以补全类和方法。由于高度依赖注入进程的环境，需要配置 .vscode/frida.json，详见文档说明。此功能冷启动可能有几秒延迟；一键获取 AndroidManifest.xml 和 Info.plist；批量生成钩子模版代码；内存字符串搜索和一键转储；一键生成 Objective-C classdump 头文件。本插件和 frida 官方没有任何关系，倒是大胡子叔叔亲自转发了。</description>
      <content:encoded><![CDATA[<p><span>非尝咸鱼贩</span> <span>2026-03-18 07:51</span> <span style="display: inline-block;">西班牙</span></p>






  
  
  <p>VSCode 插件市场直接搜索 frida 工作台安装。增强版 Java 和 ObjC 类型提示，可以补全类和方法。由于高度依赖注入进程的环境，需要配置 .vscode/frida.json，详见文档说明。此功能冷启动可能有几秒延迟；一键获取 AndroidManifest.xml 和 Info.plist；批量生成钩子模版代码；内存字符串搜索和一键转储；一键生成 Objective-C classdump 头文件。本插件和 frida 官方没有任何关系，倒是大胡子叔叔亲自转发了。</p>
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=f201424d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpnKQAqbZsYGYUssaeKuBUDWjJjYPfK5fOQTn6GLZVEiackcdwSvMB7Edx4W2PibQ6iaJ4zicEjzyv8YgA7OmTyJfR4GzvwVcGcYibhc%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=b4efe5fa&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpkz3o376SCyX2cPnTqhNUawZWqicHOSDNnibic9YBIAg5AMhFTsEdrHjSmZXzSohoNP4g0jMHRboHXfHKlt3cecIZiaSiaj0m57tssA%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=8f650312&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpnkpu3rHogr9U5gsbTsYyC0IXJH5POYV03w7kWLkX5PtwhgAD7lXbBEXTP22Lw9fJibCMTaRc6T81X3nww8iaSRwBaxg4RvgIIgA%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=632b7de1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqpmoy70UUJrcLlOF5xyU7ul5VxovN2DnENHNHEjdNApNBzmTAQUVFuqqxR3lkZuZNBgleaKJiawzSGxkYD3mhu1PQ5Ko7ljkF6fk%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e9743a43&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqplezx16TDNoicJLsNj23S67VRogFRHrdTxFoI4NmYdAj1w5qHyLuFx0w4OLraGNt2YumuNjZsZtibuBpx6EFibiaiawgafD9AcO0488%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=a3fb2ff4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpniaCsp8gYDYn8RJxs9Us0ed1YbcVU3BFF9IcI5qiaGWpv1YzgM3MicY52480wSUb6CgyibogITGXZdcqtFdqqjNnQaFyvUU42up3A%2F0%3Fwx_fmt%3Dpng"/></p><p><img src="https://wechat2rss.xlab.app/img-proxy/?k=be823fa4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpkGpqXp9zwiaqeqm8ZACNzxIIHhs8a3v4CtzBKHdfygaYf9IjtZ0kfdalYk26NRsG2rcWibk5QEOCkPwVzRMIfxj0oFIX2lLwhaA%2F0%3Fwx_fmt%3Dpng"/></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=d47442b2&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485846%26idx%3D1%26sn%3D2ba63ea4705b30f5580dbec459f76b7f">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Wed, 18 Mar 2026 07:51:00 +0800</pubDate>
    </item>
    <item>
      <title>重访斯洛伐克：打卡名人机位和后朋克专辑封面</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485830&amp;idx=1&amp;sn=15fc406e15a254a81f974244bcd26415</link>
      <description>中欧抽象打卡之行</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-03-08 09:31</span> <span style="display: inline-block;">斯洛伐克</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=578fcbc9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpnqDbINM2IXRrXBnusCX1IBalUfu6ib8UE7IjvQfcwkLUjh0iacqYjQc8uaJnwWZaJYekbbo2swhosR4wkQ4ibqj0T4htWGLuEzmc%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>中欧抽象打卡之行</p>
  <p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;" data-pm-slice="0 0 []"><span leaf=""><span textstyle="" style="font-style: italic;">内容预警：本文为没有营养的旅游流水账，糅合一些电影和音乐的梗报菜名。不感兴趣现在可以划掉了。</span></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">斯洛伐克对亚洲游客来说并不是热门目的地，为什么我又来了？旅游主打的就是私人体验。照着某书攻略固然稳妥，倒是少了“开盲盒”的乐趣。所以最近迷上一些看上去不太靠谱，其实也没太大风险的坑爹目的地。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">比如上次去各种博主口中<a class="normal_text_link" target="_blank" style="" href="https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485579&amp;idx=1&amp;sn=f2804eb2900acb3ba45beb460771aff4&amp;scene=21#wechat_redirect" textvalue="“欧洲最穷”的摩尔多瓦" data-itemshowtype="0" linktype="text" data-linktype="2">“欧洲最穷”的摩尔多瓦</a>，物超所值。这个号应该是安全博主里为数不多去过德涅斯特河左岸的？后来发现凯奇《战争之王》现实中的原型人物曾在此叱咤风云，整个地区就是干军火生意的——这勉强解释了为什么那里的街头有着极高出镜率的特斯拉。去这种地方旅游，玩的就是心跳。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">相比之下，斯洛伐克只是冷门。平心而论，这里的自然风光相当能打，只是在邻国的衬托下显得有些低调。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-croporisrc="https://mmbiz.qpic.cn/sz_mmbiz_jpg/NBEba9EhqpnIMgK1GIr25Ph3XZXz5epqcQ3ibfzR5uDrvGCD0gqamZamWWYJp2sp0UOWbMaXG9FhqC2BNhLvw00UC7y1v3z6Tzse6sc8Nk2U/0?wx_fmt=jpeg&amp;from=appmsg" data-cropselx2="578" data-cropsely2="434" data-imgfileid="100002177" data-ratio="1.3328125" data-s="300,640" data-w="1280" data-type="jpeg" src="https://wechat2rss.xlab.app/img-proxy/?k=6b6cf5ed&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpnIMgK1GIr25Ph3XZXz5epqcQ3ibfzR5uDrvGCD0gqamZamWWYJp2sp0UOWbMaXG9FhqC2BNhLvw00UC7y1v3z6Tzse6sc8Nk2U%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a class="normal_text_link" target="_blank" style="box-sizing: border-box;color: rgb(30, 107, 184);text-decoration: none;background-color: initial;outline: none;cursor: pointer;transition: color 0.3s;touch-action: manipulation;overflow-wrap: break-word;font-weight: bold;border-bottom: 1px solid rgb(30, 107, 184);" href="https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485040&amp;idx=1&amp;sn=e1864c5373ec9001c4df74891dc7e35c&amp;scene=21#wechat_redirect" textvalue="" linktype="text" data-linktype="2">2023 年第一次到 Bratislava（布拉迪斯拉发）</a> 我就已经开启地域黑模式，疯狂引用电影《Hostel（中文译名：**客栈）》的烂梗。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">当时我对这里一无所知，阅片量贫乏到只剩下重口味。这部其实在捷克取景的片子，20 年前凭一己之力差点掀翻了斯洛伐克的旅游业，气得人家国会议员直接破防，隔空喊话让导演亲自来看看。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002140" data-ratio="0.6092592592592593" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=91d99eee&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9EhqpmqU80thJDJRa9IC9yyRwjMx9ncR9iaO7TrIoTzcoeSGLUreNwK8eEF8hYDMQkTibibjaGYfzzEjluvOyfzyngSUIFiaD9lu8pxSNk%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">捷克斯洛伐克曾经也是一家人，果然前任的恨才是最深的。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">比如 Hostel 不是唯一一部美国拍摄、捷克取景，对斯洛伐克展开地域黑的电影。小时候只看过《美国派》，并不知道还有 《EuroTrip（欧洲派）》。还好来欧洲以前没看过，不然里面对欧洲各国的嘲讽还未必能看得懂。去年 2025 年教皇方济各离世，全球直播梵蒂冈换届的那阵，除了《Conclave（秘密会议）》接到流量之外，Eurotrip 里恶搞美国高中生意外“当选”教皇的桥段也在社交网络上再次被翻出来。而这部电影点名黑的另一个地方，又是斯洛伐克首都布拉迪斯拉发……</span></p><p style="" data-remoteid="" data-asynid="" src="" data-src="" align="" alt="" border="" class="rich_pages wxw-img" data-ratio="" data-s="300,640" data-type="png" data-w="" aria-label="" aria-braillelabel="" aria-description="" height="" hspace="" ismap="" opacity="" sizes="" title="" type="block" usemap="" vspace="" width="" data-width="" data-height="" data-croporisrc="" data-cropx1="" data-cropx2="" data-cropy1="" data-cropy2="" data-cropselx1="" data-cropselx2="" data-cropsely1="" data-cropsely2="" data-backw="" data-backh="" data-copyright="" data-oversubscription-url="" data-before-oversubscription-url="" data-galleryid="" data-gallerysupplier="" data-cardimg="" data-fileid="" data-imgfileid="100002143" data-positionback="" data-imgqrcoded="" data-imgid="" data-upload="1" data-fromlib="" data-aiimageid="" data-aiimagesource="" data-cacheurl="" data-aistatus="1" data-retry="" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5625" data-s="300,640" data-type="png" data-w="1920" type="block" data-imgfileid="100002147" src="https://wechat2rss.xlab.app/img-proxy/?k=e680400c&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmR3ZfG0ZYHaributmfzHbbCrm13jXurap5bppQTCl2kgicUttNCek9AP8PjvMia6y7JIGcTePMkbW2KVVLTq8Fj82ySo2Unm1UBE%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5625" data-s="300,640" data-type="png" data-w="1920" type="block" data-imgfileid="100002146" src="https://wechat2rss.xlab.app/img-proxy/?k=2144e52b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9Ehqpk6Du9y49x7SxgIakg78tticdg9FfKOicMNN1VJGSHiaHruhZFyQf40qjQxd6y36CNEnUPRxfydV1kp7c1Z63hS1trs2dlYzxNthY%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">其中一段剧情是主角几个在高速公路上搭便车想去柏林，遇到不会说英文的怪蜀黍司机。双方鸡同鸭讲一番后上了车。老司机带带我，主角满心欢喜以为快到柏林了，结果车门一开——欢迎来到布拉迪斯拉发。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5625" data-s="300,640" data-type="png" data-w="1920" type="block" data-imgfileid="100002153" src="https://wechat2rss.xlab.app/img-proxy/?k=4a80f9fc&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmlTCbuXCBicS33bb4vLF2JqcFjXeGDJziadkMGiaS1PXZtYsY34K8Ir3RpecUW7RfqfeRk644GeQIZa52JLmv2F4GJS9pZfhPxfE%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">多的我就不做电影切片了，毕竟我也不是做视频号的。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这个桥段让我联想起当年在巴尔干坐穷鬼巴士 FlixBus 的阴影：凌晨四点被东欧司机扔到路边加油站。吓个半死却也有惊无险，也算攒了点谈资了。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">除了老电影，最近又发现一些新梗可以整活，也是我这次来的主要目的。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">某书暂时没有看到有博主推荐的名人同款机位——不过是臭名昭著的名。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">随着爱泼斯坦案的文件进一步解密，虽然老美努力打码，但冰山一角已经足够让舆论哗然。美国的大人物们稳如泰山，欧洲倒是有几个政客引咎辞职了。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">说明欧洲人还是要点脸的。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">解密文件里有一张爱泼斯坦 2018 年在斯洛伐克的合影。照片背景正是布拉迪斯拉发老城区最著名的打卡点——“守望者（Čumil）”雕塑。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这个机位我熟。隔壁就是汉堡王，2024 年 DEFCON 闭幕那天，我和几个网友在那儿一边啃汉堡一边看直播，当时网上还在疯传 IDA Pro 9 Beta 的泄漏版。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">作为一名一生要出片的老中，旧地重游自然要打卡阴阳怪气一番。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.4166666666666667" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002158" src="https://wechat2rss.xlab.app/img-proxy/?k=caa498b0&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9Ehqpl0iaibuNEgvZibM7luKajJgEfzkuvicKXko3E3MZUyvIFJOAX2EQVhe5MbtiaEdOiaicobiadkkgp83saUo8icdUk1WA6fSyUT8XGkicqpg%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">然而在抽象这条赛道上，我并不是孤身一人。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">当时我正纠结找哪个路人帮忙摆拍，路遇一队美国游客。我刚一开口并给对方看样板，大家瞬间对上暗号——合着他们也是来 Cosplay 这个名场面的。他们不仅热心地帮我掌镜，还大方地加入群演。虽然动作不够还原，还多了一个人。不过打上黑框，有那味儿了没？</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">第二天一早，我动身前往北部的斯特尔布斯凯普莱索（Štrbské Pleso）。这里是塔特拉山脉著名的滑雪胜地，但我此行醉翁之意不在酒。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这张专辑封面是白俄罗斯乐队 Molchat Doma（寂静空屋）于 2018 年发行的第二张录音室专辑 Этажи，直译为“楼层”或“地板”。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1" data-s="300,640" data-type="jpeg" data-w="1000" type="block" data-imgfileid="100002151" src="https://wechat2rss.xlab.app/img-proxy/?k=c2032ed4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqplG9uQP5QU4L3uOriaG4aa6icObotKKQRDaiaUFCJ3lOTymLrVNpFQhB8XJFwsvL5q0cmJKGEh9d5Wwicg4sVdKsjKibUdc5Iwkrzks%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">即使你没听过这名字，这支乐队也绝不算小众。他们多次来华巡演，最近一次就在 2025 年底，网易云评论过万，搞不好你就在某个短视频的背景音乐里听过那段阴冷郁结的合成器旋律。</span></p><p nodeleaf=""><mp-common-clmusic class="res_iframe clmusic_iframe js_uneditable custom_select_card" data-pluginname="insertaudio" type="1" music_name="Судно (Борис Рыжий)" albumurl="http://wx.y.gtimg.cn/music/photo_new/T002R500x500M000002Vzpx82um7sF_1.jpg" singer="Molchat Doma" count="0" is_vip="1" duration="141000" music_source="1" listenid="78221539931577312"></mp-common-clmusic></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">当然接下来不会写乐评这么高级的东西。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">有没有想过这个造型夸张的建筑，现实当中居然是真实存在的？</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.75" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002155" src="https://wechat2rss.xlab.app/img-proxy/?k=96b920b6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpmGaAzTKebkDVvVt3BpCCFaBrXg2ibqDibZ0YZADEsAaT6yQIAWVgkAjbUN4WGWHmEVKLMg5Vum8AgYUvvCqVvCEXiaOictiafUWMlY%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.3324074074074075" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002170" src="https://wechat2rss.xlab.app/img-proxy/?k=8270ecfd&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9Ehqpk3PAFuZKWY4NtxG1Iol8ib9lnuE1S99gScsnC4xE7Rvl4dxNbnicDnXLF0QFtXvvkspUgSRIsgPJSwzyKnpa2QeG14hfeSVrJB8%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这就是全景度假酒店（Hotel Panorama Resort）。它坐落在高塔特拉山国家公园内，以标志性的倒椎体设计闻名。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">从首都开车过来要 3 个多小时，其实从邻国波兰的克拉科夫出发反而更近。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">高塔特拉山（High Tatras）的名气虽不如阿尔卑斯，却是斯洛伐克与波兰的天然国界。酒店步行不远就是什特尔布斯凯湖，典型的冰川湖，清澈如镜。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">冬天的湖面彻底封冻，许多人直接穿行而过。但我对前阵子贝加尔湖的冰面事故心有余悸，走了一段之后还是老老实实回到环湖道上绕行。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.3324074074074075" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002156" src="https://wechat2rss.xlab.app/img-proxy/?k=f5471369&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqpmjGIEvb3US1yZEHH6rnT45dwicR4uHt63Obpf6KNGljX32o95TzMu1egsYrvs5dvfYNM8MRb7CP6zLiaMZhdK3ab9aohj5icOKqY%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.75" data-s="300,640" data-type="jpeg" data-w="5712" type="block" data-imgfileid="100002168" src="https://wechat2rss.xlab.app/img-proxy/?k=9294f0c9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9Ehqpl0VC4OABB061OYly9LJtQib2fuFDLejjeyd51ich0qt4N86kGLawDQibvHcWr9vB844I4oTtlSfwnamFAiarBBHTc1wp6DOiaL6Zq8%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.3341592920353982" data-s="300,640" data-type="jpeg" data-w="2825" type="block" data-imgfileid="100002166" src="https://wechat2rss.xlab.app/img-proxy/?k=17ea9302&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpmmrtBuNjcicpWbqjqib0icjz4PwQzfQpCKFFeafPtWcx40B6pwoTOV92SY9r5t2mHkibphKCWQK0w8OPkXwhIMStdicphicibNrFWdIY%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.3324074074074075" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002169" src="https://wechat2rss.xlab.app/img-proxy/?k=07d83051&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9Ehqpn81P0VGVls2kLrz0k3BvoBPD8dOQeMyh5cS7xuySsPAgcQm3wbfhkAjDqdb0NalVpDCS5Yb6FqIBRJMeeK7GO6VI6YuZuHwQc%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">既然来到了高塔特拉山，如果不来尝试一下 </span><span leaf="">Tatratea</span><span leaf="">（塔特拉茶），这趟旅行就不算完整。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002157" src="https://wechat2rss.xlab.app/img-proxy/?k=a088d47f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqpkJX918BobbC4t1l8HEYOKcX5YzL90RmpqoS0eniaNO8mQPD33UI7a45UnMRL1bzElq9GpBzguXFibujgQ6Opmr4cYV6v0GaHm3Q%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">虽然名字叫“茶”，但千万别被它名字骗了。这玩意儿的本质是利口酒，更接近于长岛冰茶，度数不低。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">少了长岛冰茶都市丽人属性，</span><span leaf="">Tatratea</span><span leaf=""> 是斯洛伐克糙汉用来对抗物理严寒的功能饮</span><span leaf="" style="box-sizing: border-box;font-size: 16px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">料，最早源于塔特拉山民的一种民间偏方。为了抵御高海拔的严寒，他们会将草药、黑茶、酒精和蜂蜜混合在一起，煮成热腾腾的强效饮品。</span></p><div><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">说到吃，午饭我们去了路上这家 </span><span leaf="">Fatrabeef。广告嫌疑？我要是能出息到接欧洲的广告那也不错呀。牛排我个人挺喜欢，意外倒是发现原来斯洛伐克人也吃牛肚，朋友还担心我嫌弃这是黑暗料理。找机会让你们见识一下火锅……</span></p></div><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.3324074074074075" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100002181" src="https://wechat2rss.xlab.app/img-proxy/?k=eb338de4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9Ehqpla2GJiaoGVzPaJEyiabAgm0NibQdUu23YX27oR6Bk3BRuqDLAutMmWwicvYjulDppG8RmOnxXzv6Rm2uExHMvcyTbPH2ZKicEBicupY%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="" style="box-sizing: border-box;font-size: 16px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">有点微醺了，本期的</span><span leaf="">流水账到此为止。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.562962962962963" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002172" src="https://wechat2rss.xlab.app/img-proxy/?k=525e3edd&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FNBEba9EhqpmZN8Y7tIRnpedErjibTlxbFGHr7KF5MWc1EppT4hjdWltgm8SibrBbXxF01Rl9w77nQyQxDb67DebMjScNBZ4WOaep6qq2uTyibo%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=3dd293b4&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485830%26idx%3D1%26sn%3D15fc406e15a254a81f974244bcd26415">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 08 Mar 2026 09:31:00 +0800</pubDate>
    </item>
    <item>
      <title>用 frida 向 React Native 动态注入 js 代码</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485767&amp;idx=1&amp;sn=27cdca6f29fa40ee772b5499208066ac</link>
      <description>又来乱给别人开 js 控制台</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-02-26 09:42</span> <span style="display: inline-block;">上海</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=6e939805&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FNBEba9EhqplqaK6ByoeNtIzvmZHCLFlO3OHcX9rPQTLzyQicVgic4J23Mpo5kjQ6NZsAjr2177Ju2OzFOicROsM6DnIVib79wliahvmZY6L2CcBk%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>又来乱给别人开 js 控制台</p>
  <h1 style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 24px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;" data-pm-slice="0 0 []"><span style="box-sizing: border-box;"><span leaf="">动机和背景</span></span></h1><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">我好像有个偏小众的恶趣味，就是给别人生产环境的应用开 js 控制台。虽然几年前发的那个某小程序的思路早就不能用了。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">最近看到国外开发者 Pilfer 一直在社交网络上宣传他的新产品 Bytecode Studio，这是一款专门用于反编译和分析 React Native 字节码的工具。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://bytecodestudio.com" target="_blank">https://bytecodestudio.com</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">他在两年前写过一篇博客 Reverse Engineering and Instrumenting React Native Apps：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://pilfer.github.io/mobile-reverse-engineering/react-native/reverse-engineering-and-instrumenting-react-native-apps/" target="_blank">https://pilfer.github.io/mobile-reverse-engineering/react-native/reverse-engineering-and-instrumenting-react-native-apps/</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这篇文章介绍了在 Android 平台的 legacy 架构下动态向当前运行的 React Native 应用注入 JavaScript 代码的过程。通过 js 层的 hook，他可以实现拦截网络请求、JSON 序列化，以及无意中 dump 一些 UI 层级结构等功能。文章里的相关代码开源了：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://github.com/Pilfer/heresy" target="_blank">https://github.com/Pilfer/heresy</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">他的 GitHub 主页还有一个基于 Rust 的 hermes 字节码反编译工具。有了这些技术积累，并不奇怪他会做 Bytecode Studio。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">而数天前 React Native 发布了 0.74 版本，默认启用 Bridgeless 架构。请注意之前引用的文章只讲了 legacy 架构。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://reactnative.dev/blog/2024/04/22/release-0.74" target="_blank">https://reactnative.dev/blog/2024/04/22/release-0.74</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">而还是这几天，radare2 发布了一款插件 r2hermes，专门用于分析 hermes 字节码。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://github.com/radareorg/r2hermes" target="_blank">https://github.com/radareorg/r2hermes</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">虽然笔者不做客户端，这一系列内容勾起了我的兴趣，也就有了今天这篇文章。</span></p><h2 style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span style="box-sizing: border-box;"><span leaf="">Legacy 和 Bridgeless 是什么鬼</span></span></h2><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">React Native 有两套架构。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">Legacy 架构下，JavaScript 运行在独立线程，通过 Bridge 与 Native 通信。Native 侧核心类在 iOS 是 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">RCTCxxBridge</span></code><span leaf="">，Android 是 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">CatalystInstanceImpl</span></code><span leaf="">。所有跨语言调用都要序列化成 JSON 经过 Bridge 传递。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">0.74 版本默认启用的 Bridgeless 架构移除了这座&#34;桥&#34;，JavaScript 直接调用 Native 方法，性能更好。iOS 侧核心类变为 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">RCTInstance</span></code><span leaf="">，Android 侧变为 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">ReactInstance</span></code><span leaf="">。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">向其中注入 JS 代码可以拦截网络请求、修改界面、调试业务逻辑等，静态反编译和动态修改运行时是软件逆向常见的手法。下面结合具体代码来说明实现思路。</span></p><h2 style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span style="box-sizing: border-box;"><span leaf="">脚本实现</span></span></h2><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">我们一共要支持 4 种情况：Android 和 iOS 的 Legacy 和 Bridgeless 架构。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">frida 里可以简单实用 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">ObjC.classes</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">Java.classes</span></code><span leaf=""> 来检查类是否存在。</span></p><table style="box-sizing: border-box;border-collapse: collapse;display: table;text-align: left;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><thead><tr style="box-sizing: border-box;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-image: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"><th style="box-sizing: border-box;text-align: left;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;font-weight: bold;background-color: rgb(240, 240, 240);"><p><span leaf="">平台</span></p></th><th style="box-sizing: border-box;text-align: left;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;font-weight: bold;background-color: rgb(240, 240, 240);"><p><span leaf="">Legacy 架构</span></p></th><th style="box-sizing: border-box;text-align: left;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;font-weight: bold;background-color: rgb(240, 240, 240);"><p><span leaf="">Bridgeless 架构</span></p></th></tr></thead><tbody><tr style="box-sizing: border-box;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-image: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><p><span leaf="">iOS</span></p></td><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><code style="box-sizing: border-box;font-size: 1em;font-family: source-code-pro, Menlo, Monaco, Consolas, &#34;Courier New&#34;, monospace;"><span leaf="">RCTCxxBridge</span></code></td><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><code style="box-sizing: border-box;font-size: 1em;font-family: source-code-pro, Menlo, Monaco, Consolas, &#34;Courier New&#34;, monospace;"><span leaf="">RCTInstance</span></code></td></tr><tr style="box-sizing: border-box;border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-image: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><p><span leaf="">Android</span></p></td><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><code style="box-sizing: border-box;font-size: 1em;font-family: source-code-pro, Menlo, Monaco, Consolas, &#34;Courier New&#34;, monospace;"><span leaf="">CatalystInstanceImpl</span></code></td><td style="box-sizing: border-box;font-size: 16px;border: 1px solid rgb(204, 204, 204);padding: 5px 10px;text-align: left;"><code style="box-sizing: border-box;font-size: 1em;font-family: source-code-pro, Menlo, Monaco, Consolas, &#34;Courier New&#34;, monospace;"><span leaf="">com.facebook.react.runtime.ReactInstance</span></code></td></tr></tbody></table><h3 style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span style="box-sizing: border-box;"><span leaf="">拦截 JS Bundle 加载</span></span></h3><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">React Native 的 JS 代码以 Bundle 的形式加载。如果应用版本很旧，可能用的是压缩混淆后的 js，分析很简单。不过目前多数情况都是 hemes 字节码，分析门槛比前者显著提高。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">我们可以拦截以下方法拿到 js 或者字节码。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">iOS legacy 架构：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">-[RCTCxxBridge executeSourceCode:withSourceURL:sync:]</span></code><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">-[RCTCxxBridge executeApplicationScript:url:async:]</span></code></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">iOS bridgeless 架构：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">-[RCTInstance _loadJSBundle:]</span></code></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">Android legacy 架构：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">CatalystInstanceImpl</span></code><span leaf=""> 的 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">loadScriptFromAssets</span></code><span leaf=""> 以及 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">loadScriptFromFile</span></code></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">Android bridgeless 架构：</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">com.facebook.react.runtime.ReactInstance</span></code><span leaf=""> 的 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">loadJSBundleFromFile</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">loadJSBundleFromAssets</span></code></p><h3 style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span style="box-sizing: border-box;"><span leaf="">主动注入 JS 代码</span></span></h3><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">React Native 核心的逻辑使用 C++ 实现，用 frida 直接交互虽然不是不可能，但是构造参数非常麻烦，还得处理内存管理和偏移量适配等问题。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">从 Java 层或者 Objective-C 层并没有提供可以传入字符串的接口，只能把 js 写入临时的 bundle 然后载入。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">在文章开头提到的 Pilfer 的博客里，作者为了拿到当前运行的 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">CatalystInstanceImpl</span></code><span leaf=""> 实例，用了比较 hack 的方法，创建定时器等待 loadScriptFromAssets 被调用，然后在 hook 里把实例保存下来。</span></p><div><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="javascript"><code><span leaf=""><span class="code-snippet__comment">// This is the app identifier you&#39;re trying to hook</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> package_name = <span class="code-snippet__string">&#39;com.foo.bar&#39;</span>;</span></code><br/><code><span leaf=""><span class="code-snippet__comment">// Write the hermes-hook.js payload to file</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> f = <span class="code-snippet__keyword">new</span> <span class="code-snippet__title">File</span>(<span class="code-snippet__string">`/data/data/</span><span class="code-snippet__string"><span class="code-snippet__subst">${package_name}</span></span><span class="code-snippet__string">/files/hermes-hook.js`</span>, <span class="code-snippet__string">&#39;w&#39;</span>);</span></code><br/><code><span leaf="">f.<span class="code-snippet__title">write</span>(<span class="code-snippet__string">`console.log(Object.keys(this)); console.log(&#39;hello from React Native!&#39;);`</span>);</span></code><br/><code><span leaf="">f.<span class="code-snippet__title">close</span>();</span></code><br/><code><span leaf=""><span class="code-snippet__title">Java</span>.<span class="code-snippet__title">perform</span>(<span class="code-snippet__keyword">function</span> () {</span></code><br/><code><span leaf="">  <span class="code-snippet__comment">// Lazily wait for the class to be available to us  </span></span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">var</span> looper = <span class="code-snippet__built_in">setInterval</span>(<span class="code-snippet__keyword">function</span> () {</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">try</span> {</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">const</span> <span class="code-snippet__title">CatalystInstanceImpl</span> = <span class="code-snippet__title">Java</span>.<span class="code-snippet__title">use</span>(<span class="code-snippet__string">&#34;com.facebook.react.bridge.CatalystInstanceImpl&#34;</span>);</span></code><br/><code><span leaf="">      <span class="code-snippet__title">CatalystInstanceImpl</span>.<span class="code-snippet__property">loadScriptFromAssets</span>.<span class="code-snippet__property">implementation</span> = <span class="code-snippet__keyword">function</span> (<span class="code-snippet__params">assetManager, assetURL, z</span>) {</span></code><br/><code><span leaf="">        <span class="code-snippet__comment">// Load the original index.android.bundle</span></span></code><br/><code><span leaf="">        <span class="code-snippet__variable">this</span>.<span class="code-snippet__title">loadScriptFromAssets</span>(assetManager, assetURL, z);</span></code><br/><code><span leaf="">        <span class="code-snippet__comment">// Load custom JS into the global hermes context</span></span></code><br/><code><span leaf="">        <span class="code-snippet__variable">this</span>.<span class="code-snippet__title">loadScriptFromFile</span>(<span class="code-snippet__string">`/data/data/</span><span class="code-snippet__string"><span class="code-snippet__subst">${package_name}</span></span><span class="code-snippet__string">/files/hermes-hook.js`</span>, <span class="code-snippet__string">`/data/data/</span><span class="code-snippet__string"><span class="code-snippet__subst">${package_name}</span></span><span class="code-snippet__string">/files/hermes-hook.js`</span>, z);</span></code><br/><code><span leaf="">      };</span></code><br/><code><span leaf="">      <span class="code-snippet__built_in">clearInterval</span>(looper);</span></code><br/><code><span leaf="">    } <span class="code-snippet__keyword">catch</span> (error) {</span></code><br/><code><span leaf="">      <span class="code-snippet__variable">console</span>.<span class="code-snippet__title">log</span>(<span class="code-snippet__string">&#39;failed&#39;</span>);</span></code><br/><code><span leaf="">    }</span></code><br/><code><span leaf="">  }, <span class="code-snippet__number">10</span>);</span></code><br/><code><span leaf="">});</span></code><br/></pre></p></div><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">其实 frida 本身的 Java.choose 和 ObjC.choose 就可以直接在内存里检索到实例。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">以 iOS 的 legacy 架构为例：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cpp"><code><span leaf=""><span class="code-snippet__type">const</span> nsData = ObjC.classes.NSData.<span class="code-snippet__built_in">dataWithContentsOfFile_</span>(path);</span></code><br/><code><span leaf=""><span class="code-snippet__type">const</span> nsURL = ObjC.classes.NSURL.<span class="code-snippet__built_in">fileURLWithPath_</span>(path);</span></code><br/><code><span leaf="">instance[<span class="code-snippet__string">&#34;- enqueueApplicationScript:url:onComplete:&#34;</span>](nsData, nsURL, <span class="code-snippet__literal">NULL</span>);</span></code><br/></pre></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">新架构注入 js bundle 用的是 </span><span leaf="">RCTInstance 的 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, \&#34;PingFang SC\&#34;, Cambria, Cochin, Georgia, Times, \&#34;Times New Roman\&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;node&#34;,{&#34;tagName&#34;:&#34;code&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;box-sizing: border-box;font-size: 14px;font-family: \&#34;Operator Mono\&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">_loadJSBundle:</span></code><span leaf=""> 方法。但是没想到吧，还有惊喜。这个方法在三年前的提交改过名字，之前是没有下划线的</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf=""><a href="https://github.com/facebook/react-native/commit/0dcf81b4f19484a4e43" target="_blank">https://github.com/facebook/react-native/commit/0dcf81b4f19484a4e43</a></span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">不过这个适配好做，直接 </span><span leaf="" style="line-height: 26px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;">respondsToSelector:</span><span leaf=""> 判断一下就行。</span></p><p style="box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="" data-pm-slice="1 1 [&#34;heading&#34;,{&#34;tagName&#34;:&#34;h3&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;box-sizing: border-box;margin-top: 30px;margin-bottom: 15px;color: rgb(0, 0, 0);font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, \&#34;PingFang SC\&#34;, Cambria, Cochin, Georgia, Times, \&#34;Times New Roman\&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;,&#34;level&#34;:3},&#34;node&#34;,{&#34;tagName&#34;:&#34;span&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;box-sizing: border-box;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]" style="box-sizing: border-box;">获取返回值</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">在这里遇到了另一个问题，上层封装的加载 js 接口并不等待脚本执行完成，也没有提供获取执行结果的接口。虽然我们在 js 脚本里使用 </span><code style="box-sizing: border-box;font-size: 14px;font-family: &#34;Operator Mono&#34;, Consolas, Monaco, Menlo, monospace;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0px 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;"><span leaf="">console.log</span></code><span leaf=""> 可以在 iOS 的系统日志或者 Android 的 logcat 里看到输出，对手工测试的场景绰绰有余，但如果想开发自动化工具，到处 grep 就不太优雅。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">很容易想到一个很糟糕的思路：js 里内置了 XMLHttpRequest，直接把执行的结果回传到一个本地监听的 http 服务器上。也不是不可以。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">那么既然我们想到了 React Native 内置函数这一点，又有二进制级别的函数插桩，不妨直接用 alert 当作 callback 回传。这并不是笔者原创，多年以前就有人用这个思路实现 WebView 的 js 和 native 互传数据了。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">先把待执行代码包装一下：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="php"><code><span leaf=""><span class="code-snippet__keyword">const</span> <span class="code-snippet__variable">wrapped </span>= `</span></code><br/><code><span leaf=""><span class="code-snippet__keyword">try</span> {</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">var</span> r = (<span class="code-snippet__function"><span class="code-snippet__keyword">function</span></span><span class="code-snippet__function">() </span>{ <span class="code-snippet__keyword">return</span> ${script} })();</span></code><br/><code><span leaf="">  <span class="code-snippet__title">alert</span>(<span class="code-snippet__string">&#39;frida-callback:${id}:&#39;</span> + JSON.<span class="code-snippet__title">stringify</span>(r));</span></code><br/><code><span leaf="">} <span class="code-snippet__keyword">catch</span>(e) {</span></code><br/><code><span leaf="">  <span class="code-snippet__title">alert</span>(<span class="code-snippet__string">&#39;frida-callback:${id}:&#39;</span> + JSON.<span class="code-snippet__title">stringify</span>({<span class="code-snippet__attr"> error</span>: e.message }));</span></code><br/><code><span leaf="">}</span></code><br/><code><span leaf="">`;</span></code><br/></pre></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">接着这个字符串 frida-callback:...</span><span leaf=""> 会被封装成字典格式传到 native 层。以 iOS 为例，就是一个 NSMutableDictionary，其中的 key 是 &#34;message&#34;。但这里有一个小坑。从 6 年前的一个提交到截止本文发布的版本，这个 native 方法接受的参数是一个 C++ 的对象，解引用第一个指针才是 NSMutableDictionary：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="php"><code><span leaf=""><span class="code-snippet__title">RCT_EXPORT_METHOD</span>(alertWithArgs : (JS::<span class="code-snippet__variable">NativeAlertManager</span>::<span class="code-snippet__variable">Args</span> &amp;)args callback : (RCTResponseSenderBlock)callback)</span></code></pre></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">而 2019 年的这个 a5ad0bf12468fc831c2a 提交当中，函数原型曾经是直接传的：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cs"><code><span leaf="">RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)<span class="code-snippet__keyword">args</span></span></code><br/><code><span leaf="">                  callback:(RCTResponseSenderBlock)callback)</span></code><br/></pre></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这就导致同样的代码会崩，还得特殊处理一下。不过都 7 年了，如果不是特别执着兼容性，直接按照新的函数原型来构造参数就好了。</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="javascript"><code><span leaf="">  <span class="code-snippet__keyword">const</span> { <span class="code-snippet__title">RCTAlertManager</span> } = <span class="code-snippet__title">ObjC</span>.<span class="code-snippet__property">classes</span>;</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">const</span> method = <span class="code-snippet__title">RCTAlertManager</span>[<span class="code-snippet__string">&#34;- alertWithArgs:callback:&#34;</span>];</span></code><br/><code><span leaf="">  <span class="code-snippet__keyword">const</span> original = method.<span class="code-snippet__property">implementation</span>;</span></code><br/><code><span leaf="">  method.<span class="code-snippet__property">implementation</span> = <span class="code-snippet__title">ObjC</span>.<span class="code-snippet__title">implement</span>(</span></code><br/><code><span leaf="">    method,</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">function</span> (</span></code><br/><code><span leaf="">      handle: NativePointer,</span></code><br/><code><span leaf="">      selector: NativePointer,</span></code><br/><code><span leaf="">      args: NativePointer,</span></code><br/><code><span leaf="">      callback: NativePointer,</span></code><br/><code><span leaf="">    ) {</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">const</span> message = <span class="code-snippet__keyword">new</span> <span class="code-snippet__title">ObjC</span>.<span class="code-snippet__title">Object</span>(args.<span class="code-snippet__title">readPointer</span>()) <span class="code-snippet__comment">// &lt;- 注意 readPointer</span></span></code><br/><code><span leaf="">        .<span class="code-snippet__title">objectForKey_</span>(<span class="code-snippet__string">&#34;message&#34;</span>)</span></code><br/><code><span leaf="">        .<span class="code-snippet__title">toString</span>();</span></code><br/><code><span leaf="">      <span class="code-snippet__variable">console</span>.<span class="code-snippet__title">debug</span>(<span class="code-snippet__string">`React Native alert(</span><span class="code-snippet__string"><span class="code-snippet__subst">${message}</span></span><span class="code-snippet__string">)`</span>);</span></code><br/><code><span leaf="">      <span class="code-snippet__keyword">return</span> <span class="code-snippet__title">original</span>(handle, selector, args, callback);</span></code><br/><code><span leaf="">    },</span></code><br/><code><span leaf="">  );</span></code><br/><code><span leaf="">  <span class="code-snippet__variable">console</span>.<span class="code-snippet__title">log</span>(<span class="code-snippet__string">&#39;replaced RCTAlertManager[&#34;- alertWithArgs:callback:&#34;]&#39;</span>);</span></code><br/></pre></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">这个 Module 看上去不受 bridgeless 架构的影响，都可以用同样的方式 hook。</span></p><p style="box-sizing: border-box;margin: 0px;font-size: 16px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &#34;PingFang SC&#34;, Cambria, Cochin, Georgia, Times, &#34;Times New Roman&#34;, serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><span leaf="">最后看看效果，搞了个类似 F12 的东西：</span></p><p style="text-align: center;"><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002113" data-ratio="0.6620370370370371" data-s="300,640" data-type="png" data-w="1080" type="block" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=772efa0d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FNBEba9Ehqplpvkco8P30MRNwrcBt6RXCian9df4eSDBzmxOZz38hRlb07CjMpyicIfQNIgYGnP6G9n8Q1ky5WWMHrVN1xXl19TM5V0rx55Txw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=60e900b8&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485767%26idx%3D1%26sn%3D27cdca6f29fa40ee772b5499208066ac">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 26 Feb 2026 09:42:00 +0800</pubDate>
    </item>
    <item>
      <title>恶趣味之用 Wireshark 显示 Hook 日志</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485760&amp;idx=1&amp;sn=fc052e2f15e37015bb6eb7936572d4f2</link>
      <description>Wireshark 抓包用得多了，有没有试过拿来打日志？依靠内置的 lua 脚本（dissector）可以实现自定义的解码和展示，理论上什么结构化数据都可以往里面塞。&#xA;&#xA;各位榜上大哥刷🍎赏金必然要分析的一类组件就是 XPC 通信。这是之前想到的一个脑洞，用 hook 抓 iOS/mac 的进程间通信然后转存到 Wireshark 里，还能保存成 pcap。&#xA;&#xA;直接输出 XPC 消息的服务名，消息内容和调用堆栈。如果是 NSXPC 还可以直接打参数出来。&#xA;&#xA;写得很烂有 bug 一直没办法用，于是雪藏了很久。刚才突发奇想塞给 llm，很快把 bug 修掉了…&#xA;&#xA;代码在 github/ChiChou/XpcScope/releases/tag/v1.0.0</description>
      <content:encoded><![CDATA[<p><span>0xcc</span> <span></span> <span style="display: inline-block;">意大利</span></p>






  
  
  <p>Wireshark 抓包用得多了，有没有试过拿来打日志？依靠内置的 lua 脚本（dissector）可以实现自定义的解码和展示，理论上什么结构化数据都可以往里面塞。</p><p>各位榜上大哥刷🍎赏金必然要分析的一类组件就是 XPC 通信。这是之前想到的一个脑洞，用 hook 抓 iOS/mac 的进程间通信然后转存到 Wireshark 里，还能保存成 pcap。</p><p>直接输出 XPC 消息的服务名，消息内容和调用堆栈。如果是 NSXPC 还可以直接打参数出来。</p><p>写得很烂有 bug 一直没办法用，于是雪藏了很久。刚才突发奇想塞给 llm，很快把 bug 修掉了…</p><p>代码在 github/ChiChou/XpcScope/releases/tag/v1.0.0</p>
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=115955ef&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FNBEba9EhqplGhvmBdcVXyBrw6EiauPxeTcJWVAic2ZOCMeyHtHEWicNG712ZGkNYoU69m5Q08ceojJwjCXtWk7cAhu7nRibl1E4rlEIm5ox8nyw%2F0%3Fwx_fmt%3Djpeg"/></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=4a48a80e&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485760%26idx%3D1%26sn%3Dfc052e2f15e37015bb6eb7936572d4f2">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 13 Feb 2026 09:30:51 +0800</pubDate>
    </item>
    <item>
      <title>Bun 打包独立可执行文件的一些坑</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485753&amp;idx=1&amp;sn=058a35532bd8d0b7f024be939a1504db</link>
      <description>js 应用打包成可执行文件</description>
      <content:encoded><![CDATA[<p>原创 <span>0xcc</span> <span>2026-01-29 23:57</span> <span style="display: inline-block;">上海</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=130a8934&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDGse2zicAiaGXFkXW7nDee5wzlaNyFKDbHUlm34k8NCp8Pjllib6FhwdJg%2F0%3Fwx_fmt%3Djpeg"/></p>
  <p>js 应用打包成可执行文件</p>
  <p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5555555555555556" data-s="300,640" data-type="png" data-w="900" type="block" data-imgfileid="100002095" src="https://wechat2rss.xlab.app/img-proxy/?k=a51c8537&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDGzWjYA5yE263yNicwcDvF0WDAgicPUVV5LrZs7Cl8ib8tnJnXtNoIjPog%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">Bun 去年年底被 </span><span leaf="">Anthropic 收购的新闻刷屏了一阵，在此之前我已经在个人项目玩了好久了。</span></p><p><span leaf="">简单来说 Bun 是 js 运行时里的新秀，和 Node.js 在开发语言和引擎上都走了不同的路线。Bun 使用 Zig 开发，脚本引擎用的 Safari 的 JavaScriptCore。</span></p><div><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">其实我并不在乎 Bun 大力宣传的运行速度的提升。对我来说比较吸引人的地方在于 Bun 在努力兼容 node.js 核心库的同时也内置了一些非常实用的功能，不需要额外安装 npm 包。比如前阵子加入了 Bun.Archive API 可以直接读写 tar 格式，在未来还将引入 zip 的支持。今天还新鲜出炉了内置的 markdown 解析和渲染。</span></p><p><span leaf=""><img alt="import { markdown } from &#34;bun&#34;;

const html = markdown.html(&#34;# Hello **world**&#34;);
// &lt;h1&gt;Hello &lt;strong&gt;world&lt;/strong&gt;&lt;/h1&gt;

// ANSI terminal output
const ansi = markdown.render(&#34;# Hello\n\n**bold**&#34;, {
  heading: (children) =&gt;" class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002104" data-ratio="0.5824074074074074" data-w="1080" data-type="jpeg" src="https://wechat2rss.xlab.app/img-proxy/?k=a825be0b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDKPARCVHAXYoo4EJcldfVv1ANKHt3lVoIFhj93MsqwokN0KjVWBzX5w%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></span></p><p style="text-align: center;"><span leaf=""><span textstyle="" style="font-size: 14px;">来自 bun CEO Jarred Sumner</span></span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">除了作为 js/ts 运行时之外，Bun 还能做前端打包，测试框架，替代 npm 包管理。Bun 对 node.js 核心库的兼容当然不是 100%，在我的玩具里暂时还没有遇到问题，这就够用了。</span></p></div><p><span leaf="">去年 Agent 开发话题颇为火热，TypeScript 是不少人首选的开发语言。各种终端界面工具的流行甚至有了一点文艺复兴的味道。最新版的 Node.js 支持通过 Type Stripping 开箱即用运行 ts 项目</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">（无需特定 flag，但不支持部分特定语法），Bun 也类似。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">现在运行 ts 项目已经可以基本摆脱转译器。</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">下面开始正题。</span></p><p><span leaf="">两年前的外国贴吧上的一封帖子《我是 GitHub 新手，不吐不快》走红了。楼主飙脏话怒喷开源作者提供的安装构建步骤繁琐，对新手不友好。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002093" data-ratio="0.6403326403326404" data-s="300,640" type="block" data-type="png" data-w="962" src="https://wechat2rss.xlab.app/img-proxy/?k=ed16a557&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDsriaIoouyqAahzpgC9RHuogHuXr8U383IlZedGtLUFWTuZyMGqe9ntQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><div data-pm-slice="2 2 []"><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">有的人嘲笑楼主太菜，GitHub 本来的用途就是开放源代码，不是软件下载站；也有人觉得不无道理，开源软件应该面向最终用户提供友好的部署方式。</span></p></div><p data-pm-slice="2 2 []"><span leaf="">而回到 TypeScript / Javascript 构建出来的命令行工具。包管理一条命令就能一键安装，然而在桌面操作系统环境上，打包成独立可执行文件直接让用户下载也不失为一种分发的途径。</span></p><p data-pm-slice="2 2 []"><span leaf=""><span textstyle="" style="font-style: italic;">当然提供可执行文件下载并不见得比包管理一条命令安装友好多少。首先主流桌面系统的安全机制（Windows 的 SmartScreen 和 macOS 的 GateKeeper）会阻止不带签名的可执行文件直接运行。想要丝滑体验还得去搞一个签名。</span></span></p><div data-pm-slice="2 2 []"><p data-pm-slice="2 2 []"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;data-pm-slice&#34;:&#34;2 2 []&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">Bun 另一个功能，也是写这篇笔记的目的，就是可以把 ts / js 项目打包成一个单独的可执行文件（Single-executable application，简称 SEA），无需安装运行时，而是直接复制到目标机器上部署。目前 claude code 就是这样做的。</span></p><p data-pm-slice="2 2 []"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;data-pm-slice&#34;:&#34;2 2 []&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;data-pm-slice&#34;:&#34;2 2 []&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">这种打包分发对 python 程序员已经轻车熟路了，有 pyinstaller 和 pyexe 等若干方案。Electron 和 tauri 也是打包成单应用，但并不是面向命令行终端程序。</span></p></div><p data-pm-slice="2 2 []"><span leaf="">在我之前折腾这个环境的时候 Node.js 的 SEA 的构建步骤还不太友好。前两天 Node.js </span><span leaf="">25.5.0 发布，总算把构建命令简化了。对比起来，目前 Node.js 的 asset API 反而更合我需求一点。</span></p><p data-pm-slice="2 2 []"><span leaf="">首先还是 hello world 示例。</span></p><p data-pm-slice="2 2 []"><span leaf="">首先 cli.ts</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="javascript"><code><span leaf=""><span class="code-snippet__variable">console</span>.<span class="code-snippet__title">log</span>(<span class="code-snippet__string">&#34;Hello world!&#34;</span>);</span></code></pre></p><p><span leaf="">然后使用 bun 打包成可执行文件：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="css"><code><span leaf="">bun build ./cli<span class="code-snippet__selector-class">.ts</span> <span class="code-snippet__attr">--compile</span> <span class="code-snippet__attr">--outfile</span> mycli</span></code></pre></p><p><span leaf="">接下来直接运行这个 </span><span leaf="">./mycli 就可以。默认只会生成当前环境的可执行文件。如果需要交叉构建，例如在 Linux 下生成可供 Windows 运行的 exe，则需要加上 --target 参数。可选的平台如下：</span></p><table style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: inherit;"><thead><tr style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><th style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">—target</span></p></th><th style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">系统</span></p></th><th style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">CPU</span></p></th><th style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Libc</span></p></th></tr></thead><tbody><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-linux-x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Linux</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">glibc</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-linux-arm64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Linux</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">arm64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">glibc</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-windows-x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Windows</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">-</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-darwin-x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">macOS</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">-</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-darwin-arm64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">macOS</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">arm64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">-</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-linux-x64-musl</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Linux</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">x64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">musl</span></p></td></tr><tr style="box-sizing: border-box;border-width: 0px 0px 1px;border-style: solid;border-color: rgba(45, 40, 42, 0.5);"><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">bun-linux-arm64-musl</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">Linux</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">arm64</span></p></td><td style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: rgb(230, 226, 227);"><p><span leaf="">musl</span></p></td></tr></tbody></table><p><span leaf="">更多选项请参考官方文档，下面讲讲之前遇到的一些坑。</span></p><p><span leaf="">本公众号的老读者肯定一下就猜到我想用这个打包 frida，没错。</span></p><p><span leaf="">在 js 里导入了 frida 库之后，编译打包运行，得到类似如下错误：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="bash"><code><span leaf="">2614 |         <span class="code-snippet__built_in">dir</span> = process.cwd();</span></code><br/><code><span leaf="">2615 |       }</span></code><br/><code><span leaf="">2616 |       <span class="code-snippet__keyword">if</span> (exists(join2(<span class="code-snippet__built_in">dir</span>, <span class="code-snippet__string">&#34;package.json&#34;</span>)) || exists(join2(<span class="code-snippet__built_in">dir</span>, <span class="code-snippet__string">&#34;node_modules&#34;</span>))) {</span></code><br/><code><span leaf="">2617 |         <span class="code-snippet__built_in">return</span> <span class="code-snippet__built_in">dir</span>;</span></code><br/><code><span leaf="">2618 |       }</span></code><br/><code><span leaf="">2619 |         throw new Error(<span class="code-snippet__string">&#39;Could not find module root given file: &#34;&#39;</span> + file + <span class="code-snippet__string">&#39;&#34;. Do you have a `package.json` file? &#39;</span>);</span></code><br/><code><span leaf="">                     ^</span></code><br/><code><span leaf="">error: Could not find module root given file: <span class="code-snippet__string">&#34;/</span><span class="code-snippet__string"><span class="code-snippet__variable">$bunfs</span></span><span class="code-snippet__string">/root/igf-darwin-arm64&#34;</span>. Do you have a `package.json` file?</span></code><br/><code><span leaf="">      at getRoot (/<span class="code-snippet__variable">$bunfs</span>/root/igf-darwin-arm64:2619:15)</span></code><br/><code><span leaf="">      at bindings (/<span class="code-snippet__variable">$bunfs</span>/root/igf-darwin-arm64:2549:41)</span></code><br/></pre></p><p><span leaf="">光看这个错误是比较让人困惑，但大体可以猜到和二进制 npm 包有关。出错的上下文在 bindings 库尝试逐层目录查找 package.json 来定位根目录，然后拼接出需要 process.dlopen 的路径来载入二进制 npm 库。这里有一个对应的 issue：</span></p><p><span leaf=""><a href="https://github.com/oven-sh/bun/issues/10964" target="_blank">https://github.com/oven-sh/bun/issues/10964</a></span></p><p><span leaf="">我一开始以为二进制库不会随着 bun 的构建过程打包，询问 ai 也没有搞出来解决方案。直到有天我关注到这个 issue 下出现了几条神回复，精准地指出了问题的关键。</span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.8379629629629629" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002102" src="https://wechat2rss.xlab.app/img-proxy/?k=4e0feb37&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDeAQvf6YLSQJjnPqcHTTXBtibMaEJhxVSja1gCtfgdQDJYqLnIT4Hxbg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">由于 bun 打包之后会把文件系统路径转换成虚拟的 $bunfs 路径，bindings 按照目录搜索会失败。而 bun 有一个与 Node.js 不同的地方，就是除了 process.dlopen(.so) 之外，还可以直接用 require(.so)。</span></p><p><span leaf="">只要给 node_modules 下的库（在这里是 frida）打补丁，去掉 bindings 改成 require 就可以了。当然这样一来用 node 就会报错，但我们的目的是生成可执行文件，无所谓。</span></p><p><span leaf="">Bun 还内置了一个功能就是 patch，可以在 bun install 之后自动根据 package.json 里配置的 </span><span leaf="">patchedDependencies，直接修改第三方 npm 包。</span></p><p><span leaf="">如下是能让 frida@17.5.1 正常打包运行的补丁：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="javascript"><code><span leaf="">diff --git a/build/src/frida.<span class="code-snippet__property">js</span> b/build/src/frida.<span class="code-snippet__property">js</span></span></code><br/><code><span leaf="">index 0b047472199e9151691c52f03ffd36a85952234c..<span class="code-snippet__property">ee9395ae0a8307d8e5a9a31f8663d5d612683b0e</span> <span class="code-snippet__number">100644</span></span></code><br/><code><span leaf="">--- a/build/src/frida.<span class="code-snippet__property">js</span></span></code><br/><code><span leaf="">+++ b/build/src/frida.<span class="code-snippet__property">js</span></span></code><br/><code><span leaf="">@@ -<span class="code-snippet__number">1</span>,<span class="code-snippet__number">15</span> +<span class="code-snippet__number">1</span>,<span class="code-snippet__number">8</span> @@</span></code><br/><code><span leaf="">-<span class="code-snippet__keyword">import</span> bindings <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;bindings&#34;</span>;</span></code><br/><code><span leaf="">+<span class="code-snippet__keyword">const</span> binding = <span class="code-snippet__built_in">require</span>(<span class="code-snippet__string">&#39;../../build/frida_binding.node&#39;</span>);</span></code><br/><code><span leaf=""> <span class="code-snippet__keyword">import</span> util <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;util&#34;</span>;</span></code><br/><code><span leaf=""> <span class="code-snippet__keyword">import</span> { <span class="code-snippet__title">Minimatch</span> } <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;minimatch&#34;</span>;</span></code><br/><code><span leaf=""> <span class="code-snippet__keyword">import</span> { <span class="code-snippet__title">Duplex</span> } <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;stream&#34;</span>;</span></code><br/><code><span leaf=""> <span class="code-snippet__keyword">const</span> { inspect } = util;</span></code><br/><code><span leaf="">-<span class="code-snippet__keyword">const</span> binding = <span class="code-snippet__title">bindings</span>({</span></code><br/><code><span leaf="">-    <span class="code-snippet__attr">bindings</span>: <span class="code-snippet__string">&#34;frida_binding&#34;</span>,</span></code><br/><code><span leaf="">-    <span class="code-snippet__attr">try</span>: [</span></code><br/><code><span leaf="">-        [<span class="code-snippet__string">&#34;module_root&#34;</span>, <span class="code-snippet__string">&#34;build&#34;</span>, <span class="code-snippet__string">&#34;bindings&#34;</span>],</span></code><br/><code><span leaf="">-        [process.<span class="code-snippet__title">cwd</span>(), <span class="code-snippet__string">&#34;bindings&#34;</span>],</span></code><br/><code><span leaf="">-    ]</span></code><br/><code><span leaf="">-});</span></code><br/><code><span leaf=""> <span class="code-snippet__keyword">var</span> <span class="code-snippet__title">MessageTypeImpl</span>;</span></code><br/><code><span leaf=""> (<span class="code-snippet__keyword">function</span> (<span class="code-snippet__params">MessageTypeImpl</span>) {</span></code><br/><code><span leaf="">     <span class="code-snippet__title">MessageTypeImpl</span>[<span class="code-snippet__string">&#34;Send&#34;</span>] = <span class="code-snippet__string">&#34;send&#34;</span>;</span></code><br/></pre></p><p><span leaf="">下一步就是怎么蹭 GitHub 的持续集成自动构建多个平台的可执行文件。</span></p><p><span leaf="">bun compile 命令在没有制定 target 的情况下只会生成当前平台的文件。但加上 target 参数还没完，同样因为 frida 是一个二进制包，在安装的时候会调用 prebuild（也是一个 npm 包）来下载安装对应平台的 so。</span></p><p><span leaf="">因此在 GitHub Action 的构建脚本当中也需要针对性的，对每一个 target 参数都执行一次 prebuild 命令。</span></p><p><span leaf="">如果看到这有点摸不着头脑，实例代码我放 GitHub 了。</span></p><p><span leaf=""><a href="https://github.com/ChiChou/frida-node-portable/" target="_blank">https://github.com/ChiChou/frida-node-portable/</a></span></p><p style="text-align: center;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.0097087378640777" data-s="300,640" data-type="png" data-w="1030" type="block" data-imgfileid="100002103" src="https://wechat2rss.xlab.app/img-proxy/?k=804c7c92&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOJgZzmysBwlMdYIuDAfEiabDREOqkTzWtWLzF0k8ibcKKMb57j1ibCKQw2Q6IRVEGt4slR9rabmcv3WQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">反正现在大家都觉得多占点内存和存储多大点事，80M 还好吧（斜眼）</span></p><p><span leaf="">最后一个困扰我的坑就是如何打包一整个文件夹。</span></p><p><span leaf="">嵌入图片等非代码等资源文件，官方的示例是这样的：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="cs"><code><span leaf="">import icon <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;./icon.png&#34;</span> <span class="code-snippet__keyword">with</span> { type: <span class="code-snippet__string">&#34;file&#34;</span> };</span></code><br/><code><span leaf="">import { <span class="code-snippet__keyword">file</span> } <span class="code-snippet__keyword">from</span> <span class="code-snippet__string">&#34;bun&#34;</span>;</span></code><br/><code><span leaf=""><span class="code-snippet__comment">// Get file contents as different types</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> bytes = <span class="code-snippet__keyword">await</span> <span class="code-snippet__keyword">file</span>(icon).arrayBuffer(); <span class="code-snippet__comment">// ArrayBuffer</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> text = <span class="code-snippet__keyword">await</span> <span class="code-snippet__keyword">file</span>(icon).text(); <span class="code-snippet__comment">// string (for text files)</span></span></code><br/><code><span leaf=""><span class="code-snippet__keyword">const</span> blob = <span class="code-snippet__keyword">file</span>(icon); <span class="code-snippet__comment">// Blob</span></span></code><br/></pre></p><p><span leaf="">因为我要打包一个 webui 进去，而前端用的构建工具并不是 bun。</span></p><p><span leaf="">这就导致我需要编写一个脚本遍历整个文件夹，针对每一个文件生成一个 import 语句。</span></p><p><span leaf="">官网确实给了一个打包目录的示例：</span></p><p><span leaf=""><a href="https://bun.com/docs/bundler/executables" target="_blank">https://bun.com/docs/bundler/executables</a><a class="wx_topic_link" topic-id="mkzmas70-ex1mia" style="color: #576B95 !important;" data-topic="1">#embed</a>-directories</span></p><p><span leaf="">但同样地，在引用具体文件的时候只能专门用一条 import 语句指定相对路径。而 import 函数还不能用动态的字符串，因为打包的过程需要确定 import 的路径，否则会导致缺失对应的资源文件。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">更无语的是别忘了 bun 本身就是一个 js 打包器。按照官网给的示例把 .js 路径传进去，bun 不会原样打包，而是会尝试将这个 js 作为一个入口点进行代码分析，对于前端工具已经生成好的生产代码自然报错满天飞。</span></p><p><span leaf="">所以如果我要打包一整个 assets 文件夹然后调用 serveStatic……不行。</span></p><p><span leaf="">折衷的方案就是用构建脚本把前端目录打成 tar 压缩包，这样只需要 import 一个确定的文件名，然后在主程序初始化过程动态解压出来。Node 的 SEA 似乎也没有简单处理这种场景的办法，而那边甚至没有内置的 tar 解压支持。</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="https://github.com/ChiChou/frida-node-portable/">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=efec8381&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485753%26idx%3D1%26sn%3D058a35532bd8d0b7f024be939a1504db">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 29 Jan 2026 23:57:00 +0800</pubDate>
    </item>
    <item>
      <title>海边的苹果安全会议：OBTS v8</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485691&amp;idx=1&amp;sn=5cfacb1a166c4fcef6b336fa7ad65a57</link>
      <description>安卓人的苹果会议手记</description>
      <content:encoded><![CDATA[<p>
原创 <span>0xcc</span> <span>2025-10-19 06:28</span> <span style="display: inline-block;">法国</span>
</p>




<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=7aa30ca5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevUKYsXZ5FdxXicr55Ekb4aWribW44uaK8EWd3O5kFUoibanX8PlTBic5M0g%2F0%3Fwx_fmt%3Djpeg"/></p>

<p>安卓人的苹果会议手记</p>

<p><span leaf="">会棍博主恢复营业。</span><span style="letter-spacing: 0.034em;"><span leaf="">前几年的 </span></span><span style="letter-spacing: 0.034em;"><span leaf="">Objective by the Sea 由于各种各样的奇葩理由都未能成行，今年第八届总算安排</span></span><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;">上了。</span></p><p><span leaf="">先简单介绍一下 OBTS 的背景，虽然以前可能写过了。Patrick Wardle 是 OS X 恶意软件对抗领域的专家，维护了多个 macOS 下的安全工具[1]，撰写的 Objective-See（谐音 Objective-C）博客。他的博客和书籍可以说是学习 macOS 安全的必读材料之一。</span></p><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.75" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=54740e3e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZeveseuhqZdeWU9yHvFcoia1Bj7ZrtNPe5oFyJmoRvpgJBkITy4rRcsZdw%2F640%3Fwx_fmt%3Djpeg"/></p></div><p><span style="letter-spacing: 0.034em;font-size: 12px;"><span leaf="">总算网友见面。反正会议回放也能看到我，露脸无所谓了。</span></span></p><p data-pm-slice="2 2 []"><span leaf="">从 2018 年起 Objective-See 开始举办一系列 Objective by the Sea <span textstyle="" style="font-weight: normal;">[2]</span> 安全会议，正如其名字所示，每年的地点都在海边。不成文的规矩是一年在夏威夷，也就是 Patrick 的老家，下一年在欧洲选一个海滩，循环交替。</span></p><p data-pm-slice="2 2 []"><span leaf="">OBTS v8 选的会议地点在欧洲知名的电音海岛，西班牙的 Ibiza 岛。在旺季不仅有许多游客前来蹦迪，也是不少大牌球星度假的目的地。</span></p><p><span leaf="">不过 OBTS 选在十月中，天气说实话已经不太适合去海滩玩了，而且派对活动也步入尾声。住宿和机票相比旺季更好订，想趁机去体验蹦迪的可能要失望了。</span></p><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.6650406504065041" data-type="jpeg" data-w="615" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=44da08b2&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevKNV7thqF9fbs3rYMRVLcia7AwmPVxctC0icqy6cyOlRCJFpg5azVKg9Q%2F640%3Fwx_fmt%3Djpeg"/></p></div><p data-pm-slice="2 2 []"><span style="font-size: 12px;"><span leaf="">配图：都市传说之 Ibiza Final Boss</span></span></p><p><span leaf="">顺便提一个烂梗。今年夏天有一个游客因为打扮比较奇葩，波波头墨镜配上极富个性的胡须，被多个人偷拍发到网上，并配以 Ibiza Final Boss 的称号，瞬间出道成网红。</span></p><p><span style="font-size: 17px;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;node&#34;,{&#34;tagName&#34;:&#34;span&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;font-size: 17px;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">两周前 Ibiza 遭到洪水袭击，来之前我还有点担心。到这一看大部分风暴的痕迹都被清理掉了，偶尔残留一些水坑和损坏的设施。</span><span style="font-size: 17px;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;node&#34;,{&#34;tagName&#34;:&#34;span&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;font-size: 17px;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">会场准确地点并不在 Ibiza 老城，而是 Santa Eulària des Riu。整个区域看上去比较高端和清净。</span></span></span></p><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="1.3333333333333333" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=3fa85363&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevZZMGyheO7iaQtgopTQx33sreRjlRiabQjmFpdMBbSqRygE0KnSs4jIlw%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.75" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=b6047a4a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevyLWNoCkmXsKoLIwpm7e0Rmk7ib6vWSppaibCPuqWibV5ibESRaKibGkK8Lg%2F640%3Fwx_fmt%3Djpeg"/></p></div><p><span leaf="" style="letter-spacing: 0.034em;">本届 OBTS 从 10 月 12 日到 17 日结束，其中三天的培训课和三天议题会场。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]" style="letter-spacing: 0.034em;">安全本来就是小众行业，细分到 iOS/macOS 人就更少了。我感觉议题</span><span leaf="" style="letter-spacing: 0.034em;">能整出来三天的日程有点不可思议。</span></p><div><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.75" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=d40bca5e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevWQYqVgHBCjc6s0p2VDSm5uyzNW1hCSmrdlib4UxFdxFPet0Z6X1QcBw%2F640%3Fwx_fmt%3Djpeg"/></p></div></div><p><span leaf="">目前公开的讲稿不多，整理一下已经发布的内容，和一些相关的链接。</span></p><p><span leaf=""><span textstyle="" style="font-weight: bold;">Make XNU &lt;del&gt;GREAT&lt;/del&gt; Little Again (Jonathan Levin)</span></span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><a href="https://technologeeks.com/files/MXlA.pdf" target="_blank">https://technologeeks.com/files/MXlA.pdf</a></span></p><p><span leaf=""><span textstyle="" style="font-weight: normal;">来自 *OS Internals 的作者对 XNU 近期各种软硬件结合实现的安全机制的分析。</span></span></p><p><span leaf="">巧合的是，和会议无关，前几天 </span><span leaf="">Moritz Steffin 公开一篇类似的文章，基于他的硕士论文。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">内容预警，实打实 167 页 pdf</span><span leaf="">：</span></p><p><span leaf="">Modern iOS Security Features – A Deep Dive into SPTM, TXM, and Exclaves</span></p><p><span leaf=""><a href="https://arxiv.org/abs/2510.09272" target="_blank">https://arxiv.org/abs/2510.09272</a></span></p><p><span leaf=""><span textstyle="" style="font-weight: bold;">Trust me, I’m an Apple Watch — On Protocol Reversing, Mimicry, and Data Exfiltration (Nils Rollshausen)</span></span></p><p><span leaf="">本次会议我个人最喜欢的议题是关于 Apple Watch 配对协议栈的逆向分析和一些有趣的攻击场景。</span></p><p><span leaf="">Nils Rollshausen 来自</span><span leaf="">达姆施塔特工业大学的 seemoo labs。这个实验室之前就针对诸多移动生态和无线协议做过深入的逆向分析和漏洞研究，发表过不少让人印象深刻的文章。</span></p><p><span leaf="">虽然这个议题讲稿没放出来，但相关的源代码等资料其实作者早就公开了。</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">作者实现了一个安卓系统上可以和 Apple Watch 配对和通信的应用，这算是安卓人还是苹果人？</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><a href="https://github.com/seemoo-lab/watchwitch" target="_blank">https://github.com/seemoo-lab/watchwitch</a></span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,null]">研究中提到的各种协议分析和各种格式的编解码工具：</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><a href="https://github.com/seemoo-lab/watchwitch-tools" target="_blank">https://github.com/seemoo-lab/watchwitch-tools</a></span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">此外作者写了一个网页同来解码苹果协议中用到的各种二进制封装格式（例如 bplist 和 protobuf 等）：</span></p><p><span leaf=""><a href="https://rec0de.net/open/bytewitch/" target="_blank">https://rec0de.net/open/bytewitch/</a></span></p><p><span leaf=""><span textstyle="" style="font-weight: bold;">Crash One - A StarBucks Story (CVE-2025-24277) (Csaba Fitzl &amp; Gergely Kalman)</span></span></p><p><span leaf=""><a href="https://theevilbit.github.io/talks_workshops/2025/OBTS-25-Fitzl-Kalman-CrashOne.pdf" target="_blank">https://theevilbit.github.io/talks_workshops/2025/OBTS-25-Fitzl-Kalman-CrashOne.pdf</a></span></p><p><span leaf="">macOS 沙箱逃逸和本地 root 权限提升等漏洞案例分析。涉及到一些文件系统，XPC 服务和 BSD 的知识。</span></p><p><span leaf=""><span textstyle="" style="font-weight: bold;">Breaking the Sound Barrier: Exploiting CoreAudio via Mach Message Fuzzing (Dillon Franke)</span></span></p><p><span leaf=""><a href="https://www.dillonfrankesecurity.com/Objective-By-the-Sea-2025_Breaking-the-Sound-Barrier.pdf" target="_blank">https://www.dillonfrankesecurity.com/Objective-By-the-Sea-2025_Breaking-the-Sound-Barrier.pdf</a></span></p><p><span leaf="">这篇之前就已经在 GP0 的博客上发布过：</span></p><p><span leaf=""><a href="https://googleprojectzero.blogspot.com/2025/05/breaking-sound-barrier-part-i-fuzzing.html" target="_blank">https://googleprojectzero.blogspot.com/2025/05/breaking-sound-barrier-part-i-fuzzing.html</a></span></p><p><span leaf="">相关源代码：</span></p><p><span leaf=""><a href="https://github.com/googleprojectzero/p0tools/tree/master/CoreAudioFuzz" target="_blank">https://github.com/googleprojectzero/p0tools/tree/master/CoreAudioFuzz</a></span></p><p><span leaf="">两个漏洞案例：</span></p><p><span leaf=""><a href="https://project-zero.issues.chromium.org/issues/406271181" target="_blank">https://project-zero.issues.chromium.org/issues/406271181</a></span></p><p><span leaf=""><a href="https://project-zero.issues.chromium.org/issues/372511888" target="_blank">https://project-zero.issues.chromium.org/issues/372511888</a></span></p><p><span leaf="">所有的议题都提供油管了同步直播，虽然已经结束，还是可以访问 @objectiveseefoundation 的主页查看回放。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.6555555555555556" data-s="300,640" data-type="png" data-w="1080" style="height: auto !important;" type="block" data-imgfileid="100002016" src="https://wechat2rss.xlab.app/img-proxy/?k=724183f4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevEIloPohrrBrVANLOyzscrlT5m3COXTia0pDvOVcEr78BTOxVCzzicEPg%2F640%3Fwx_fmt%3Dpng"/></p><p data-pm-slice="2 2 []"><span leaf=""><span textstyle="" style="font-size: 14px;">在这里为了稍微节省读者一些时间，点名 MacPaw 的议题。虽然我没听，但会后不止一个人反馈议题质量堪忧，可能作者都不知道自己在说些什么。既然点名道姓说坏话了，那就坏人做到底。</span></span><span leaf=""><span textstyle="" style="font-size: 14px;">会议赞助商又不是本公众号赞助商，CleanMyMac 的母公司就是 MacPaw。关于这个软件可以去网上找一下两极分化的风评 :)</span></span></p><p><span leaf="">会议第二晚安排了 ctf。而我作为养生老年人当然直接跳过去吃饭。</span></p><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="1.3333333333333333" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=6739c1ea&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevjOeWkOsibGDt0ic1ibfcOYE0vM9Iw6FibGAmoaBPm22PLGYSTk2Mw5h10A%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="1.3333333333333333" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=c0cdc8a9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevbQ6gvvXRrEuxmISfBQWpB73EuzhsfNutKzNRnwWCVcjAeTZGOd60mg%2F640%3Fwx_fmt%3Djpeg"/></p></div><p>会议有签售环节，要买<span style="letter-spacing: 0.034em;">书的人太多，我愣是一本没搞到。还好之前有买过一本 Patrick 的《mac 恶意软件分析艺术（卷 1）》，直接找他签了。</span></p><p><span leaf="">参会少不了尬聊。</span></p><p><span leaf="">有用户问我还会不会维护 grapefruit，甚至他们还在用。我知道这个项目基本就是死了。npm 生态各种框架迭代得实在太快了，隔一阵就要重写，不然各种构建错误。如果不剥削代码助手谁扛得住。再说还有某国的黑客最近虎视眈眈多次往 npm 下毒。</span></p><p><span leaf="">我 GitHub 上所有的工具都是写着玩，也不打算变现，没什么动力去更。假如去做什么订阅粉丝群之类的，就有种服务客户的感觉，好像被架着加班一样，何苦。都是开源的东西，你们倒是来帮写啊。</span></p><p><span leaf="">会棍博主沉寂好一阵了，再次出来营业还是挺开心。</span><span style="letter-spacing: 0.034em;">最后以 Ibiza 老城码头的夜景结束。</span></p><div><p style="display: inline-block;"><img data-ratio="1.33359375" data-w="1280" data-type="jpg" src="https://wechat2rss.xlab.app/img-proxy/?k=b867507e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevtSkXL81lNwTqicBP0PcJHH2ibV0FuoBJeHyoCI44vlib7yBXKQ7NoY8yw%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.75" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=5a383061&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJoCazHiaKvo3UExLYaxwZevokI7cibqoyw3p8tuS04663XhHRdIoSt9hCvXwpNsr3d3NKolfJK1RDw%2F640%3Fwx_fmt%3Djpeg"/></p></div><p><span leaf="">参考资料：</span></p><ol style="list-style-type: decimal;" class="list-paddingleft-1"><li><p><span leaf="">Objective-See: Tools <a href="https://objective-see.org/tools.html" target="_blank">https://objective-see.org/tools.html</a></span></p></li><li><p><span leaf="">OBTS </span><span leaf=""><a href="https://objectivebythesea.org/" target="_blank">https://objectivebythesea.org/</a></span></p></li></ol><p style="display: none;"><mp-style-type data-value="10000"></mp-style-type></p>


<p><a href="2247485691">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=d7705596&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485691%26idx%3D1%26sn%3D5cfacb1a166c4fcef6b336fa7ad65a57">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 19 Oct 2025 06:28:00 +0800</pubDate>
    </item>
    <item>
      <title>frida 17.4 发布，修复了 Xcode 模拟器下的 bug（原理分析）</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485655&amp;idx=1&amp;sn=81c5f129193aef517329956372f52d97</link>
      <description>frida 近期修复的 Xcode 模拟器 bug 和背后细节分析</description>
      <content:encoded><![CDATA[<p>
原创 <span>0xcc</span> <span>2025-10-16 02:26</span> <span style="display: inline-block;">西班牙</span>
</p>




<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=efbbfcb5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOItywJ50dUMP04kPfmRbTUK0PXLRicXWCTwBStNe36kUULCf2R94ep3tZ4tpYQMrUiafASKIYkzLliaA%2F0%3Fwx_fmt%3Djpeg"/></p>

<p>frida 近期修复的 Xcode 模拟器 bug 和背后细节分析</p>

<p style="text-align: center;" nodeleaf=""><img data-imgfileid="100001988" class="rich_pages wxw-img" data-ratio="0.7861111111111111" data-s="300,640" data-type="png" data-w="1080" style="height: auto !important;" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=00b42287&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOItywJ50dUMP04kPfmRbTUKSy3A331xbrEK06HJJCGXOuUg8qVON7O5X9Jrdl23hRlI9SBIj6EaJA%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">frida 17.4 修复了一个存在很长时间的问题，就是对 iOS 模拟器附加进程的支持。而这个版本顺手增强了 iOS 模拟器的处理，本文结尾将简单介绍。</span></p><p><span leaf="">这个补丁是笔者提的。虽然最后合并的实现已经大相径庭，还是专程发文得瑟一下。</span></p><p><span leaf="">问题主要就是这个 GitHub issue 所描述的：</span></p><p><span leaf=""><a href="https://github.com/frida/frida/issues/2763" target="_blank">https://github.com/frida/frida/issues/2763</a></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100001995" class="rich_pages wxw-img" data-ratio="0.850925925925926" data-s="300,640" data-type="png" data-w="1080" style="height: auto !important;" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=065b0707&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOItywJ50dUMP04kPfmRbTUKpiaDull5ibW9mWClYf4eqJicJOxFoFbH3ZyEZ83LVjqqvYgHZNjOn7asg%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">首先简单介绍一下 Xcode 自带的 iOS 模拟器有什么特点。</span></p><p><span leaf="">iOS 模拟器不是真正意义的虚拟机，其实读者在 macOS 上运行 ps 查看进程列表，同时也会列出模拟器的进程。不仅如此，宿主机直接 lldb 都可以附加上去（系统进程可能需要禁用 SIP）。</span></p><p><span leaf="">所以使用 frida 框架有两种方法：</span></p><ol style="list-style-type: decimal;" class="list-paddingleft-1"><li><p><span leaf="">反正能在模拟器运行的应用都不是加密的（至少也是砸壳过），所以直接打补丁加上 </span><span leaf="">frida-gadget</span></p></li><li><p><span leaf="">直接在宿主 macOS 上 frida 附加对应的进程名 / pid</span></p></li></ol><p><span leaf="">出现问题的就是第二种方式。</span></p><p><span leaf="">由于附加进程，iOS 模拟器和 macOS 进程并没有本质区别，关键在于模拟器内的进程使用了独立的 RuntimeRoot，例如笔者机器上的 iOS 26 模拟器：</span></p><p><span leaf="">/Library/Developer/CoreSimulator/Volumes/iOS_23A343/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 26.0.simruntime/Contents/Resources/RuntimeRoot/</span></p><p><span leaf="">顺便提一句。虽然模拟器和真实 iOS 的实现由于条件编译可能存在差异，但截至目前版本 RuntimeRoot 下的所有 dylib 都是独立存在，没有合并成一个巨大的 dyld_shared_cache，阅读分析起来会轻松很多。iOS 开发老司机要逆向分析 iOS 私有框架都知道这个目录。</span></p><p><span leaf="">在 iOS 模拟器进程中可以检测到一些特定的环境变量，例如：</span></p><ul style="list-style-type: disc;" class="list-paddingleft-1"><li><p><span leaf="">IPHONE_SIMULATOR_ROOT</span></p></li><li><p><span leaf="">SIMULATOR_ROOT</span></p></li><li><p><span leaf="">DYLD_FALLBACK_LIBRARY_PATH</span></p></li><li><p><span leaf="">DYLD_ROOT_PATH</span></p></li></ul><p><span leaf="">甚至 dyld 也有一个额外的特殊版本 dyld_sim。</span></p><div><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">试想在模拟器里的链接器必然要处理 sysroot，无论是代码的 dlopen 还是符号导入表，默认都是 /。而 frida 进程注入也需要考虑路径转换问题，否则就会出现前文的找不到模块的 bug。</span></p></div><p><span leaf="">我先后给这个 bug 提交过两次补丁，成因还不一样。</span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100001996" class="rich_pages wxw-img" data-ratio="0.4772117962466488" data-s="300,640" data-type="png" data-w="746" style="height: auto !important;" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=4301de55&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOItywJ50dUMP04kPfmRbTUKsrrvjlY1rWibvV95R5zRYA8GHMFwd01dr4kIlSf5JvTHW69zDHicLlLA%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">frida 处理进程模块信息时会在内部维护一个列表结构，并动态跟踪模块的变化，也要自行处理 sysroot。</span></p><p data-pm-slice="2 2 []"><span leaf="">在之前版本实现中，可能是考虑跨进程读取环境变量比较啰嗦，就使用了一个启发式检测的思路。首先遍历进程模块，如果存在 </span><span leaf="">/usr/lib/dyld_sim 结尾的模块，就取路径前缀作为模拟器根目录。</span></p><p><span leaf="">在 iPhone 15 模拟器之前，dyld_sim 加载的顺序是固定的，默认就是第一个。frida 只用了一个循环，一边遍历一边获取路径前缀，没出现问题。之后 dyld_sim 的顺序被打乱，就识别出了错误的 sysroot。</span></p><p><span leaf="">我在 0x41con 期间和另外两个核心开发者碰面，当场掏出电脑咨询了一下怎么快速跑起来单元测试。接着就用 print 大法开始调，还真让我修好了。</span></p><p><span leaf="">但这个 bug 今年又出现了。虽然看上去错误信息一样，原因有所不同。</span></p><p><span leaf="">frida 此时还是依赖 dyld_sim 的绝对路径来检测模拟器的前缀。在 iOS 26 模拟器上，无论是 </span><span leaf="">_dyld_image_count 还是编程获取 </span><span leaf="">TASK_DYLD_ALL_IMAGE_INFO，都会把 dyld_sim 排除在外。而这个模块实际上还在，只是遍历不到了。</span></p><p><span leaf="">我交的补丁只能去遍历进程所有 mmap 的文件来查找 dyld_sim，弊端也很明显，准确性和性能都降低了。虽然合并了我的补丁，其实已经改的大相径庭。既然每次都报找不到 libSystem.B.dylib，那干脆用这个模块的路径来找前缀。</span></p><p><span leaf="">到这里我受启发动了点歪脑筋。App 的作者能不能利用这些启发式检测对抗 frida 的代码注入？</span></p><p><span leaf="">我做了一个快速的 poc。在 macOS 上把文件 </span><span leaf="">/usr/lib/system/libsystem_kernel.dylib 复制到 </span><span leaf="">/tmp/usr/lib/libSystem.B.dylib，接着编译一个什么也不干的空程序运行：</span></p><div><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="objectivec"><code><span leaf=""><span class="code-snippet__meta">#import </span><span class="code-snippet__meta"><span class="code-snippet__string">&lt;Foundation/Foundation.h&gt;</span></span></span></code><br/><code><span leaf=""><span class="code-snippet__type">int</span> main(<span class="code-snippet__type">int</span> argc, <span class="code-snippet__keyword">const</span> <span class="code-snippet__type">char</span> * argv[]) {</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">@autoreleasepool</span> {</span></code><br/><code><span leaf="">        <span class="code-snippet__built_in">NSLog</span>(<span class="code-snippet__string">@&#34;frida %d&#34;</span>, getpid());</span></code><br/><code><span leaf="">        <span class="code-snippet__built_in">CFRunLoopRun</span>();</span></code><br/><code><span leaf="">    }</span></code><br/><code><span leaf="">    <span class="code-snippet__keyword">return</span> EXIT_SUCCESS;</span></code><br/><code><span leaf="">}</span></code><br/></pre></p></div><p><span leaf="">运行的时候加上环境变量，让它优先载入一个同名的 dylib：</span></p><p class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"></ul><pre class="code-snippet__js" data-lang="ini"><code><span leaf=""><span class="code-snippet__attr">DYLD_INSERT_LIBRARIES</span>=/tmp/usr/lib/libSystem.B.dylib</span></code></pre></p><p><span leaf=""><span textstyle="" style="color: rgb(217, 33, 66);">注意在这里必须使用链接器添加 </span></span><span leaf=""><span textstyle="" style="color: rgb(217, 33, 66);">LC_LOAD_DYLIB，或者 DYLD 环境变量，否则会影响模块载入顺序，先加载系统正常的 libSystem.B.dylib。</span></span></p><p><span leaf="">这样一来 frida 的模块检测就会被扰乱：</span></p><p><span leaf="">Failed to attach: unable to bind, “_DefaultRuneLocale” not found in “/private/tmp/usr/lib/libSystem.B.dylib”</span></p><p><span leaf="">笑死。</span></p><p><span leaf="">frida 除了修复 bug 之外还增强了对模拟器的支持。</span><span leaf="">frida-ls-devices 从 17.4 开始会单独将模拟器列为设备，也支持启动 App 了：</span></p><p><span leaf="">frida -D 6AB414C0-98BC-4E41-9112-14EA89F2FFD7 -f com.bundle.app</span></p><p><span leaf="">之前只能先运行再附加。</span></p><div><p style="display: inline-block;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.7498535442296427" data-w="1707" data-type="jpg" src="https://wechat2rss.xlab.app/img-proxy/?k=6038e2b9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOItywJ50dUMP04kPfmRbTUK7ywvRyUFGAF0R2faONRN8Jsu8AbDYPNJkrIiajKsibBNiaCKhtdwHtuicQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p><span style="letter-spacing: 0.034em;"><span leaf="">笔者有一个 VSCode 插件暂时没适配上新版。现在在参加 OBTS，只能先缓缓了。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="2247485655">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=2a3fee0f&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485655%26idx%3D1%26sn%3D81c5f129193aef517329956372f52d97">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 16 Oct 2025 02:26:00 +0800</pubDate>
    </item>
    <item>
      <title>苹果官方的漏洞赏金涨价了，最高两百万刀</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485634&amp;idx=1&amp;sn=a52db3903c3ee01c3754f66cb4dce23c</link>
      <description>巴黎的 Hexacon 第一天邀请到了苹果的安全架构 VP Ivan Krstić 做 keynote 演讲。宣布演讲嘉宾的时候大家就已经猜到了肯定是和 iPhone 17 的 MIE （内存安全性防护 ）特性有关，对漏洞研究员来说号称目前是消费级市场最难搞定的手机型号。&#xA;&#xA;而 Hexacon 本身是偏向攻击技术的安全会议，这个议题和背后的赞助商 logo 同框真是相映成趣。&#xA;&#xA;价目调整后，满足要求的“零点击”漏洞最高给高达两百万美元的奖励。而如果漏洞影响 beta 测试版并能绕过锁定模式（Lockdown Mode，面向极少数对安全有高要求用户，通过禁用部分系统功能减少远程攻击面的安全机制），叠加奖励最高能给到五百万美金。&#xA;&#xA;针对 WebKit 带沙箱逃逸的完整利用链条，最高奖金 30 万（译者注：和今年的 Pwn2Own 价格一样，在整活）。无线近源攻击最高 100 万刀。&#xA;&#xA;新规则还会引入类似 ctf 的 Target Flags 模式，方便漏洞提交者演示漏洞危害程度和作为赏金的评判标准。具体怎么实现还没提。&#xA;&#xA;此外赏金计划还扩展到 iCloud 未授权访问和 macOS 特有的 GateKeep 机制绕过等。面向记者等容易受到入侵威胁等人群，苹果还开启了另一个计划，向高风险用户免费提供一千台支持 MIE 的 iPhone 17 设备（赤裸裸的广告）。&#xA;&#xA;SEAR 官方博客已经针对新的规则做了一部分介绍，但更多的规则和新的赏金计划将在 11 月实行和披露。&#xA;&#xA;https://security.apple.com/blog/apple-security-bounty-evolved/&#xA;&#xA;这下苹果人生了。</description>
      <content:encoded><![CDATA[<p>
<span></span> <span>2025-10-11 02:04</span> <span style="display: inline-block;">上海</span>
</p>

 
<div id="js_image_content" class="image_content "><h1 class="rich_media_title ">苹果官方的漏洞赏金涨价了，最高两百万刀</h1> <p id="js_image_desc" class="share_notice js_underline_content "></p>   <!---->    <!---->   <!----> <!----> <!----> <!----> <!----> <!----> <!----> <!----> <div class="rich_media_tool "><div class="rich_media_info weui-flex policy_tips js_ad_policy_tips tips_global_primary claim_source_block "><div class="media_tool_meta tips_global_primary meta_primary ">素材来源官方媒体/网络新闻</div> <!----></div></div>   </div>
<p>巴黎的 Hexacon 第一天邀请到了苹果的安全架构 VP Ivan Krstić 做 keynote 演讲。宣布演讲嘉宾的时候大家就已经猜到了肯定是和 iPhone 17 的 MIE （内存安全性防护 ）特性有关，对漏洞研究员来说号称目前是消费级市场最难搞定的手机型号。</p>
<p>而 Hexacon 本身是偏向攻击技术的安全会议，这个议题和背后的赞助商 logo 同框真是相映成趣。</p>
<p>价目调整后，满足要求的“零点击”漏洞最高给高达两百万美元的奖励。而如果漏洞影响 beta 测试版并能绕过锁定模式（Lockdown Mode，面向极少数对安全有高要求用户，通过禁用部分系统功能减少远程攻击面的安全机制），叠加奖励最高能给到五百万美金。</p>
<p>针对 WebKit 带沙箱逃逸的完整利用链条，最高奖金 30 万（译者注：和今年的 Pwn2Own 价格一样，在整活）。无线近源攻击最高 100 万刀。</p>
<p>新规则还会引入类似 ctf 的 Target Flags 模式，方便漏洞提交者演示漏洞危害程度和作为赏金的评判标准。具体怎么实现还没提。</p>
<p>此外赏金计划还扩展到 iCloud 未授权访问和 macOS 特有的 GateKeep 机制绕过等。面向记者等容易受到入侵威胁等人群，苹果还开启了另一个计划，向高风险用户免费提供一千台支持 MIE 的 iPhone 17 设备（赤裸裸的广告）。</p>
<p>SEAR 官方博客已经针对新的规则做了一部分介绍，但更多的规则和新的赏金计划将在 11 月实行和披露。</p>
<p>https://security.apple.com/blog/apple-security-bounty-evolved/</p>
<p>这下苹果人生了。</p>

<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e3a526ef&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOIw7fFib2KRibiapfW2P0wnxOS5IFaehYww2jusnras49Zibx0zib7jDLul6sOVjst4Lg6nAq7FicHFiaTnA%2F0%3Fwx_fmt%3Djpeg"/></p>
<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=3b06b31b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOIw7fFib2KRibiapfW2P0wnxOSwHaFYJ0x67og2tb4KHPjJO0ZHiaxsKW0xyugzyGIn9uk1Uia5dqUSGtQ%2F0%3Fwx_fmt%3Dpng"/></p>




<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=c264b2db&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485634%26idx%3D1%26sn%3Da52db3903c3ee01c3754f66cb4dce23c">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 11 Oct 2025 02:04:00 +0800</pubDate>
    </item>
    <item>
      <title>来路不明的“漏洞分析”，实则防不胜防的 AI 垃圾</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485619&amp;idx=1&amp;sn=2d2b1a0724c2aa29991629189d1976a5</link>
      <description>Threat retard</description>
      <content:encoded><![CDATA[<p>
原创 <span>0xcc</span> <span>2025-10-10 07:21</span> <span style="display: inline-block;">上海</span>
</p>




<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=88ee017b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteBvvwGNib4UTxZGLIg6lFUho2810H2bt4yD19IDYHqBCHbEGof3VicGsw%2F0%3Fwx_fmt%3Djpeg"/></p>

<p>Threat retard</p>

<p><span leaf="">今天扒一个来路不明的 GitHub 账号。</span></p><p><span leaf="">github[.]com/JGoyd</span></p><p><span leaf="">linkedin[.]com/in/josephg007/</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001942" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.8425925925925926" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=696b5c19&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteUV1ZHOuXfgBRTjA3rIqsibT2VwCLYttp0MSZxicBC1HcJez1BwghDbhw%2F640%3Fwx_fmt%3Dpng"/></p><div><div data-pm-slice="3 3 []"><p><span leaf="">这个 GitHub 的主页如此整齐划一的报告格式，不难想象那些报告是用什么东西拉出来的。简单来说作者在公告里找了几个（不一定相关联的）标记有野外利用的 CVE 编号，丢给 AI 一通炮制。</span></p><p><span leaf="">这些漏洞分析编的有鼻子有眼的，这里不要求读者有足够多的平台相关知识能一眼识别。就丢一张截图：</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001949" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.36147757255936674" data-w="758" src="https://wechat2rss.xlab.app/img-proxy/?k=3719d7b5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteGrPvoWxkc2sHqcf3w0Gs4gvBPp3UFicIAEG8H5lMiaOURexspVwPJZiaQ%2F640%3Fwx_fmt%3Dpng"/></p></div><p data-pm-slice="2 2 [&#34;para&#34;,null]"><span leaf=""><span textstyle="" style="color: #d92142;font-weight: bold;">IoC 贴了个 </span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="color: #d92142;font-weight: bold;">172.16.x 的 IP，简直是拿大伙的智商按地上摩擦。</span><span textstyle="" style="font-weight: normal;">没看出来哪里不对劲的请回去补习基本计算机知识。</span></span></p><p data-pm-slice="2 2 [&#34;para&#34;,null]"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">没有说 AI 不好的意思。只是这位仁兄会用 AI 总结瞎编，完了还要到处投稿，是觉得别人没账号还是没有钱充 token？</span></p><p data-pm-slice="2 2 [&#34;para&#34;,null]"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">平时 C**N 之类的低质内容农场站我都要花点时间从搜索引擎里屏蔽掉。碰到这种 AI 瞎编的内容完蛋了，还得多花点时间甄别，等模型再迭代几代估计就彻底看不出来了。到时也别上网了，指不定转一圈下来没一个活人。</span></p><p data-pm-slice="2 2 [&#34;para&#34;,null]"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">之前看一些不明所以的微信营销号在转发就算了。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">这几天看到有些正儿八经的安全研究员也被糊弄，实在绷不住。</span></p></div><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001939" data-ratio="0.9601851851851851" data-s="300,640" data-type="jpeg" data-w="1080" type="block" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=8cd00d42&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteJFI2Ul1wMuibagRskcrj0K4UibyRmKLW1w2D8BJicCUxbS6V3evCv2tQg%2F640%3Fwx_fmt%3Djpeg"/></p><div><p><span leaf="">最早看到这人是前阵子他投稿了一个所谓的 A16 硬件级调试后门上了 Hacker News，写的有板有眼的，仔细一读是 llm 加上他自己莫名其妙的截图一通胡说八道。HN 评论区已经识别出来了。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001944" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.3074074074074074" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=b508b95a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteXNaoGGkZ33eAAxx2Gc2NqF3m5JibeNdqokX6b5NhDdbt58q041NdRoQ%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">这人之后也没闲着，还积极往 Full Disclosure 投递。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-backh="307" data-backw="578" data-imgfileid="100001943" data-ratio="0.5314814814814814" data-s="300,640" data-type="png" data-w="1080" style="width: 100%;height: auto !important;" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=9f1534be&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZtee32k84uLub8P7pDyvTNHKzQ1sjRibmSVEYXYY5HQvDthk5HtaqBtq5w%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">终于看的人多了，开始出现在各种时间线上。</span></p><p><span leaf="">我顺着搜索引擎找到这里，</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;&#34;},&#34;para&#34;,null]">最神奇的是他在 LinkedIn 上贴了<span textstyle="" style="font-weight: bold;">两个 CNVD 证书，上官网查验居然是真的</span>。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001945" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="1.012037037037037" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=f7d4b739&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZteicmib1hBFMjYB2wqkQZA6xfAficWdVbBZ6ZibM21cV4wLcFpBg44cuorRA%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">看到这个 CNVD 证书之前我还以为哥们是想红，出来浑水摸鱼。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001946" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.9771241830065359" data-w="612" src="https://wechat2rss.xlab.app/img-proxy/?k=7a8da178&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZtecMWj8d9poBzElHth4aIZSVlXEgZm4a47ToEVOU1IUpuOYltlgNqicDQ%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">领英地理位置标的亚特兰大（此处应有背景音乐 </span><span leaf="">Georgia On My Mind），为什么跑来中文的漏洞库申请证书？</span></p><p><span leaf="">不会是韩国北面人吧？</span></p><p><span leaf="">谁有 ai 检测一下头像是不是生成出来的……</span></p><p><span leaf="">对不起我太敏感了，毕竟以前遇到太多次。</span></p></div><hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);"/><div><p><span leaf="">说到安全圈用 AI 浑水摸鱼，昨天正好看到另一篇文章开撕。</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">《这篇 DEFCON 关于 eBPF 的演讲是（大模型的）幻觉吗？》</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001950" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.4527777777777778" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=982c7099&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZtemqI3E0zibicxsicWNxDY13vU03Hrv2qoe0XKqSiaKUKeU6eIax3gHjJYicA%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">www[.]thestack[.]technology/defcon-ebpf-bug-talk-was-hallucinated-what-now/</span></p><p><span leaf="">文章开门见山就点名今年 DEFCON33 主会场的一个演讲者。哥们一口气中了两篇：</span></p><p><span leaf="">De-Virtualizing the Dragon Automated Unpacking and Deobfuscation of Nested VM-Based Protectors using Symbolic Execution and Taint Tracking （关于用 llm 破解 VMP）</span></p><p><span leaf="">Jailbreaking the Hivemind Finding and Exploiting Kernel Vulnerabilities in the eBPF Subsystem（eBPF 的漏洞挖掘和利用）</span></p><p><span leaf="">中两篇不是史诗级成就，史诗级成就在于每一篇都被人点名道姓出来开撕对线。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100001948" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.5203703703703704" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=5a8e95e9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZtecnQMtnN1zoMkhp0iaCX4TmOcsjibGDianH1xT8BibvVyxV2iadvK3OicNbJg%2F640%3Fwx_fmt%3Dpng"/></p><p><span leaf="">同样做反编译的 rev.ng 对议题质量颇为不忿，还是意大利老乡，当场上去线下真实。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100001947" data-s="300,640" data-type="png" type="block" style="height: auto !important;" data-ratio="0.7777777777777778" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=7366a983&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOKTM4a0ntia8C9eBzibibZJZte4gUsUwLGB6MKFFZGLL0oVK5o5N6INyFHFqcmkVbpUtZqLibianmYtVuA%2F640%3Fwx_fmt%3Dpng"/></p><div><p><span leaf="">我一看被喷的哥们在推上还 fo 了我，难绷。本文在此仅作转述，并不表达对哪一方的支持。</span></p></div><p><span leaf="">文章还提到了另一件无关的例子。curl 作者审核漏洞报告项目，在 llm 普及之后屡屡收到用 ai 生成的不存在的漏洞，实则浑水摸鱼骗致谢骗赏金的，导致项目管理方不堪其扰。</span></p><p><span leaf="">笔者想起前段时间审核一些议题。其中有一位超人投稿人，声称用 llm 挖到了各种漏洞，从浏览器 js 引擎到内核 GPU 驱动再到即时通讯应用的零点击代码执行，而他公开可查询的致谢记录只有寥寥数个浏览器地址栏欺骗。</span></p><p><span leaf="">没有说浏览器地址栏欺骗漏洞不够危害的意思，也没有质疑 llm 在研究里可应用的潜力。相反笔者写代码提示用得很香。起疑心是因为这人跨度有点大，国籍正好又是那种常有吹牛不打草稿的……</span></p><p><span leaf="">为了负责任起见，我们发了跟进邮件直接问有没有证明。对方直接说把 Signal telegram 什么全打了，然后把 0day 卖了，所以不能提供细节。</span></p><p><span leaf="">那我们还能说什么，刘德华还有两个月才出来，提前祝您发财吧。</span></p><p><span leaf="">任何技术都有被滥用的可能。大模型正在努力引领生产力的革新，同时也给招摇撞骗的人提供了便利，哪怕胸无点墨也可以造出虚实难辨的内容。浪费别人的时间不说，所谓的“</span><span leaf="">互联网死亡论（互联网大部分内容</span><span leaf="">不再由真实用户创造，而是</span><span leaf="">机器人产生）”离现实也越来越近。</span></p><p><span leaf="">只能说转发东西的时候还是擦亮眼睛吧。</span></p></div><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="2247485619">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=83cf076d&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485619%26idx%3D1%26sn%3D2d2b1a0724c2aa29991629189d1976a5">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 10 Oct 2025 07:21:00 +0800</pubDate>
    </item>
    <item>
      <title>去了一趟摩尔多瓦</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485579&amp;idx=1&amp;sn=f2804eb2900acb3ba45beb460771aff4</link>
      <description>蚂蚁呀嘿 蚂蚁呀呼</description>
      <content:encoded><![CDATA[<p>
原创 <span>0xcc</span> <span>2025-09-22 07:23</span> <span style="display: inline-block;">摩尔多瓦</span>
</p>

<p>蚂蚁呀嘿 蚂蚁呀呼</p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=a2fc2628&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVTWr5iccvmiaiaNhXlWRTsTSnMmknSjOrfTD1ic2enQkpStKk2XChkBkMrQ%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p><span leaf="">事情是这样的。</span><span leaf="" style="letter-spacing: 0.034em;">前阵子看到去马尔代夫🇲🇻的机票很便宜，马上锁座支付一气呵成激情下单。<span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]" style="letter-spacing: 0.034em;">完事一看发现大意了。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]" style="letter-spacing: 0.034em;">外语不好，人家是摩尔多瓦🇲🇩。</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]" style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.998792270531401" data-s="300,640" data-type="jpeg" data-w="828" style="width: 354px;height: auto !important;" data-croporisrc="https://mmbiz.qpic.cn/sz_mmbiz_jpg/6N4b2yN3FOKLkU6zqdyajFT8qGXMmczOhFBvHcB0LDUdKOWJd4GubicI9luib7aLvA9Prj5IibouyoXzdib1sXnOew/0?wx_fmt=jpeg&amp;from=appmsg" data-cropselx2="578" data-cropsely2="573" data-imgfileid="100001919" src="https://wechat2rss.xlab.app/img-proxy/?k=7a5d8623&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOKLkU6zqdyajFT8qGXMmczOhFBvHcB0LDUdKOWJd4GubicI9luib7aLvA9Prj5IibouyoXzdib1sXnOew%2F640%3Fwx_fmt%3Djpeg"/></p><p><span style="letter-spacing: 0.578px;">段子而已不要当真。</span></p><p><span style="letter-spacing: 0.034em;">大概许多读者都没听过这个地方……这是欧洲 GDP 第二垫底的国家（你猜倒数第一是谁？），据说一年游客加起来没有巴黎半天多。</span></p></div><p><span leaf="">早几年做背包客单人去摩尔多瓦倒是没什么问题。但现在欧洲 GDP 倒数第一就在隔壁打仗，有一些风险。当然那边我是万万不敢去的。</span></p><div><p><span leaf="">这下好了，自称会棍博主，今年到现在一个会也没去。被小偷暗算之后破罐破摔，画风突变成了咸鱼亡命天涯。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001918" data-ratio="0.6925925925925925" data-s="300,640" data-type="jpeg" data-w="1080" style="height: auto !important;" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=83afd6f1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJWDmdCeMtiabeDFTQHLIX2FCzv6bZFBvNkebN0OYSFF8Db86uhiayia2Uvkj5htQMNEMKyNHggibxEOg%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">玩笑归玩笑，<span style="letter-spacing: 0.034em;">其实我拉上了三个斯拉夫朋友一起才敢出发。四个人的小团，有两个拿过 Pwnie，占比高达 50%。</span></p><p style="text-align: start;"><span leaf="">这次旅行纯粹就是略带猎奇的态度看看一个成本不高，又相对冷门的目的地。反正没有期待值，搞不好有惊喜呢。</span></p><p style="text-align: start;"><span style="font-weight: bold;letter-spacing: 0.034em;">行程包含一些有争议的地区，先说在前面，文中出现的地区我们只逛，不代表任何立场，请勿过度解读。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=808e6105&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVdpINw3MwuWYGZXKOXULiakaUQ6IuUrjAGRLacXUs8tVOFB9uMSZfpFw%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;"></p><span style="font-size: 17px;">这次降落的目的地就是摩尔多瓦的首都 <span style="caret-color: rgb(0, 29, 53);color: rgb(0, 29, 53);font-family: &#34;Google Sans&#34;, &#34;Helvetica Neue&#34;, sans-serif;font-style: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;word-spacing: 0px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration: none;float: none;display: inline !important;">Chișinău（基希讷乌）。</span></span></div><p style="text-align: start;"><span data-change-font="1" style="font-size: 17px;color: rgb(51, 51, 51);font-style: normal;text-decoration: none;font-weight: normal;"></span><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="0.75" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=3578949f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVbLeDIWbXjya2IoBBC5m6Oq8qu1zYha4vSRDlmtuaAGe3OxweNgKxPg%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">从机场打车到市区，价格大约在 200MDL 左右，约合 10 欧元。习惯了西欧的物价，感到不可思议。即使司机喊价一口要 300，我直接就答应了。</p><div><p style="display: inline-block;"><img data-ratio="0.75" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=a2da0ed9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVFCEiaC1hibZBiabQZFt0S3ljrlviaib1Sgqmr6X6XhNkJDiaj1HgVMpe5JrQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">在东欧国家，甚至柏林墙以东，居民楼的建筑风格经常给我一种既熟悉又陌生的奇怪感觉。</p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=cd0d90d6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVBR9EDROWQmxS53eGGofz2jzibibzB01chzRSICRDeXibLOp2CwqgNEHXQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p><span style="text-align: start;letter-spacing: 0.034em;">市中心有一些苏联时期遗留的大型建筑，看上去以前曾经是酒店。</span></p><div><p style="display: inline-block;"><img data-ratio="1.3342592592592593" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=1ede3dc4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOJIuFIrCfA0TpapC9JsA5CVFuVpRqyKyr51G6OVvubljRPhB2Fgc6Yq7woOENiaXVNq8uYLry1ibGEw%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.034em;">这个有 MOLDOVA 字样的彩色建筑是 Hotelul Național。我在油管上找到了一个今年初（2025）上传的探险视频，内部基本就是荒废的状态。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;">自从有了小🍠之后感觉已经没有什么冷门目的地了。不管北欧还是巴尔干，走到哪都能扎堆遇到老中。这次在摩尔多瓦总算体验到一条街都碰不到一个亚洲人的感觉了，时不时会有人盯着我看。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3342592592592593" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=fb32db00&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NCXYLhP6vtsem5Bq4sRiazwzqXJvDmIvQxicUzesJ22fWqt83p9Lnxh0w%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;">楼上 LED 轮番滚动美股七姐妹、大饼、主流货币汇率、油气等的交易行情。今天一片绿光，行情还不错。算是东欧时代广场？</span><br/><span style="letter-spacing: 0.034em;"></span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><p><span style="letter-spacing: 0.034em;text-align: start;">摩尔多瓦的顶级域名是 .md，网址给人一种文件名的错觉。看到波兰域名会感觉都是 perl 脚本，塞尔维亚的网站好像都是 rust 源文件，而摩尔多瓦早就为 llm 做好准备，用上了 markdown。</span></p><p style="text-align: start;"><span leaf="">说到摩尔多瓦不得不提 </span><span leaf="">O-Zone 组合的神曲 </span><span leaf="">Dragostea Din Tei。</span></p><p nodeleaf=""><mp-common-clmusic class="res_iframe clmusic_iframe js_uneditable custom_select_card mp_common_widget" data-pluginname="insertaudio" type="1" music_name="Dragostea Din Tei (Dj Aligator Vs CS-Jay Radio Edit)" albumurl="http://wx.y.gtimg.cn/music/photo_new/T002R500x500M000000QTEj63KLsbo_3.jpg" singer="O-Zone" count="0" is_vip="1" duration="215000" music_source="1" listenid="78225003407947552"></mp-common-clmusic></p><p style="text-align: start;"><span leaf="">这首歌当年在欧洲太火，根据 Wikipedia 的说法“</span><span leaf="">被全球逾一百名歌手翻唱成二十种不同语言，逾三十个版本”。2021 年这首歌在中文互联网上因为 ai 换脸的短视频又翻红过一阵。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;">而汉化版你大概率也听过，彩铃的年代曾经也响彻过大街小巷。时代的眼泪。</span></p><p nodeleaf=""><mp-common-clmusic class="res_iframe clmusic_iframe js_uneditable custom_select_card mp_common_widget" data-pluginname="insertaudio" type="1" music_name="不怕不怕" albumurl="http://wx.y.gtimg.cn/music/photo_new/T002R500x500M000000lUUGA47XZoq_3.jpg" singer="美美jocie" count="0" is_vip="1" duration="215000" music_source="1" listenid="78238783126727489"></mp-common-clmusic></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;">我之前发过一篇关于</span><a class="normal_text_link" target="_blank" href="https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485335&amp;idx=1&amp;sn=b924e5c00dfe33e14e92bab2788d5577&amp;scene=21#wechat_redirect" textvalue="布加勒斯特的流水账游记" data-itemshowtype="0" linktype="text" data-linktype="2" style="letter-spacing: 0.034em;">布加勒斯特的流水账游记</a><span style="letter-spacing: 0.034em;">，当时误认为 O-Zone 是罗马尼亚的乐队。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">罗马尼亚🇷🇴和摩尔多瓦🇲🇩不仅国旗相似，语言仅是</span><span style="letter-spacing: 0.578px;">方言的差别，这两国历史上的分分合合说来话长。O-Zone </span><span style="letter-spacing: 0.034em;">乐队成员都是摩尔多瓦人，但乐队主要在罗马尼亚发展，这首神曲就是在布加勒斯特制作。所以给自己洗地一下，这个误会情有可原。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.33359375" data-w="1280" data-type="jpg" src="https://wechat2rss.xlab.app/img-proxy/?k=adb82444&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NH4wHQtWkTmOQQAknib33KzrlAzyl0Bm4CKJibUjPygzRxKglKNFlCwUw%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;">这个万怡（目测）已经是基希讷乌最好的酒店了，你敢信。</p></div><div><p style="display: inline-block;"><img data-ratio="1.33359375" data-w="1280" data-type="jpg" src="https://wechat2rss.xlab.app/img-proxy/?k=1f0287d1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NbGkkZJkSd1z1GTgddjjhTCMJGm0nhvHEZxL3yOM3e9oicLQo1oibFYyQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">第一天打卡了市区中心的一些公园，很安静很闲适，倒也乏善可陈。午饭在 MallDOVA 购物中心解决，这个名字玩了一手谐音梗。格鲁吉亚菜，居然还不错。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">晚上我们原本打算找一个 K 歌</span><span style="letter-spacing: 0.578px;">酒吧，在门口被嫌弃有人</span><span style="letter-spacing: 0.578px;">穿短裤不让进。后来偶遇另一波本地人，会一点英文，刚给家里的小孩办完十八岁成人礼。他们解释了下，基希讷乌确实是这样，KTV 算是</span><span style="letter-spacing: 0.578px;">高档场所，有着装要求。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">这是平民得不能再平民的活动了吧…在欧洲十几个国家的酒吧唱过 K 都没听过这规矩。只能调侃一下米兰巴黎算个毛时尚之都，摩尔多瓦才是潮人街。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">接下来有一些不知道适不适合发布的内容。没错，</span><span style="letter-spacing: 0.578px;">我们颤颤巍巍地去德涅斯特河沿岸地区（中文一般简称德左）打卡了……</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">有一点搞笑，上一篇推文的时候我在波兰，大毛的无人机入侵空域，搞得波兰很紧张，我也赶紧跑路。没隔多久为了猎奇，自行前往有大毛驻军（字面意思）实控地区。</span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=15f3d0aa&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NORlEef09fAHChrgBDyfkg43VicrMTRTnvS3MwdXN5N5KY4UmnB33Yrg%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">这是一个存在争议的地区，目前国际上公认属于摩尔多瓦领土。博主无心讨论他国内政，更不想在评论区看到对线，所以这个背景科普就随便找了一篇别的公众号的文章：</p><p style="text-align: start;"><a class="normal_text_link" localeditorid="4a5n2jw208nvh3l73sw" href="https://mp.weixin.qq.com/s?__biz=MzIzNzMzMTAwMA==&amp;mid=2247505090&amp;idx=1&amp;sn=4d0ad4a3923febea248f574b4ff51321&amp;scene=21#wechat_redirect" textvalue="德左两次申请加入俄罗斯，为何被俄罗斯拒绝？" target="_blank" data-linktype="2">德左两次申请加入俄罗斯，为何被俄罗斯拒绝？</a></p><p style="text-align: start;">近些年有一些油管甚至 B 站 Up 主为了满足观众的好奇心，前往打卡拍摄。不过目前 B 站亲自去过的 Up 主一只手数得过来。我这为了搞抽象，冒险去看看。</p><p style="text-align: start;">我们有个朋友文化衫背后印着明显的 HACKER 字样，头晚上强烈要求他不要穿。后来<span style="letter-spacing: 0.034em;">换了件 CrowdStrike，应该没人知道。</span></p><p style="text-align: start;">从基希讷乌到 Tiraspol 驱车需要一小时多一点。检查站会查护照，比想象中容易很多，一会就放行了。</p><div><p style="display: inline-block;"><img data-ratio="0.75" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=dda222c7&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NqdocRt92w62ic8K6ZfsibGMQIe4J7y6vsyzHTOkEqtR4she2eaTeXFhQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">有不少博主和视频都说这个地区像凝固的时间胶囊，到处是列宁像，保留着很多苏联时期的风貌，街上有很多老爷车云云。</p><p style="text-align: start;">我本来脑子里想象的是周杰伦逛哈瓦那那种画风。<span style="letter-spacing: 0.034em;">进了 Tiraspol 市区一看，巴士比我年纪还大不假，但是私家车可不敢苟同。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=a2b3ff7c&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NWDTcfpvDHiaN3ibHao2EOuIdjJVI8xBia36KfRh3Ztpyr5pRcy1lrIe0A%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.578px;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=ad1f90d6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NGT0g3SFHafuic3ulrNqwakpxib91iaibOFmkNInqJR1jkffciagicictOaVcw%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.578px;"></span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">欧洲的新能源车推广比较激进的在北欧，特别是挪威，奥斯陆甚至有不少中国产 EV 的门店。西欧私家车本来就有保养量，没必要换掉，即使新车也偏爱插电式混动。所以之前看到特斯拉有一些但不多。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">谁想来了 Chișinău 街上一堆特斯拉，到了 Tiraspol 密度更多，就基本上只要是有路必有特斯拉。我们一行人大大的问号，一路上一个充电桩都没见着，这么多特斯拉去哪充的？当然中国产电车也零星遇到了，相比之下完全没有存在感。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.578px;">我们是周日去，一些纪念品店休息，大部分银行也不开门。总算找了个地方能换欧元，突然感觉变有钱了。可惜当地特色塑料硬币我们没搞到。</span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=4e354d64&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NLiauribL3hAeeSPp3e51yuibkS3RhlJBibXIgUe1XlLOUJspHB8Mvr9FTQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.034em;">当地的纪念品还有冰箱贴和明信片，但是上面文案都是半开玩笑地说“承不承认我们的国际地位？”，不太敢带怕回申根区有麻烦就作罢了。</span></p><p style="text-align: start;"><span style="letter-spacing: 0.034em;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=cdefa36f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NS1KNAwyibZczp5tSxG1zngxvUe65SzicbMpA6ibCqjHydMhrdn8N5PjJQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;"><span style="letter-spacing: 0.578px;"></span></p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=93d505a6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NPECRnxX7HPJSJzMRyXgCajVv3vjG9eT0Y31J8r0fPEXVhjpJL3qeaQ%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">午饭在 Tiraspol 的 Back in the U.S.S.R. 餐馆，我没翻译是因为这个名字引用了披头士的一首歌，就叫这名字。就点了一个类似 Goulash 的汤，印象不是很深。有意思的是餐馆隔壁居然有个赌场，叫做 Macau……</p><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=08c09749&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NuMBmQQ90Cwu37Z58SJzEDuoia2PXrwUHOI8LOWtEckb5nCIb1u5ISjA%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><div><p style="display: inline-block;"><img data-ratio="0.75" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=174f04ba&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NGibxx7HnK3hiaTFBW807sL7icVj7NX6qfmZiaVPrfjYEYw1FXu6U013k8w%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=bba6e7ad&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6Nkznp4zEko7ica5puq9Zk9JEAZDJQoZ0KjkzoSogzNYEjPzpPjEdN0nw%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><div><p style="display: inline-block;"><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=625abdc3&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NvckRpQs0jZ2I4LRnW88iar0NhmibPYVHwrU3E9k5GXg6lPtv0kN3wPaQ%2F640%3Fwx_fmt%3Djpeg"/></p><img data-ratio="1.3333333333333333" data-type="jpg" data-w="1080" style="letter-spacing: 0.034em;height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=06832948&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6Nib7yoPQffxgsutYax1bPmxwHn0Van6Pf9AMTaaXesaG1E6UGoAgOaCw%2F640%3Fwx_fmt%3Djpeg"/><span style="letter-spacing: 0.034em;"></span><span style="letter-spacing: 0.034em;"></span></div></div><p style="text-align: start;">说到旅行体验真的没啥地方可逛。基本就是广场和公园，或者顺带去中心市场看看本地人的生活状态。连德左都有卖 labubu，妥妥的消费主义。</p><p style="text-align: start;">出检查站会再查一次证件，护照不留任何记录，只打印一张纸，相当于到此一游的凭证。</p><div><p style="display: inline-block;"><img data-ratio="0.562037037037037" data-type="jpeg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=37108943&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NhGTamAy7O2Wq2uXAdnZNuGcIMWDkR5DpnO6Clz3M7J0Fly9Xo9nPSA%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="text-align: start;">回来的路上顺道去了个酒庄，避免广告嫌疑就不提名字。根据 wiki 说法，摩尔多瓦葡萄酒产量在欧洲国家能排到 11 位。和其他地区的酒庄类似，这也有参观酒窖和品酒的项目。我们时间有限直接去吃饭了。</p><div><p style="display: inline-block;"><img data-ratio="0.5638888888888889" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=af1f2c16&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NXgcSUTUMPNvoaa7RztHHxpWiaIic6R27WS6B9VicUO6XY1ibRuzGP68Fibg%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;font-size: 12px;">（图片来源：consilium.europa.eu）</p></div><p>欧洲理事会于 2023 年 6 月在这办过一次领导人聚会。本来我以为在东欧会因为食物不合口味饿肚子，没想到还吃了顿好的。</p><p>咸鱼也是出息了，都和马克龙泽连斯基吃上同款了。</p><div><div><p style="display: inline-block;"><img data-ratio="0.75" data-type="jpg" data-w="1080" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=214b3761&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOLZQgzcO7SuGjylq9Otuj6NA5Qics30H8fuIFjapcnjemQE81f6Hq4GmbwPwh9V64nSKeZA4ZBbaUg%2F640%3Fwx_fmt%3Djpeg"/></p></div></div><p>这次抽象旅行确实远超期待值，实在没想到我一向挑剔的胃口还能在东欧大快朵颐。</p><p>不过确实这个国家游客少有其客观原因，沧海遗珠也好实在无聊也罢。目前如果不是进阶背包客，或者真就是来刷护照印章，欧洲旅行还是优先考虑别的国家深度体验。</p><p style="display: none;"><mp-style-type data-value="10000"></mp-style-type></p>



<p><a href="2247485579">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=1f66bd0d&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485579%26idx%3D1%26sn%3Df2804eb2900acb3ba45beb460771aff4">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Mon, 22 Sep 2025 07:23:00 +0800</pubDate>
    </item>
    <item>
      <title>iPhone 17 和 Air 将搭载并开启 MTE</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485562&amp;idx=1&amp;sn=db1dbccd955c3a1cabc78997375917d0</link>
      <description>iOS 漏洞研究倒闭了</description>
      <content:encoded><![CDATA[<p>
<span>营销号</span> <span>2025-09-10 04:14</span> <span style="display: inline-block;">波兰</span>
</p>

<p>iOS 漏洞研究倒闭了</p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=a14b07dd&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOIeXKfPHQ11kOiaKT2HZ1cicKEbUJhy6t6fSc48TbqZm8SNy38gQexnpj0FaMiby5u8Psp6kxbblJM4g%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p><span leaf="">又一年苹果新品发布会。给 17 Pro 系列摄像头一下堆料上了 200mm，可惜血月都结束了。都怪太阳系，就不能给等到下个月再月全食吗？</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,null]">发布会后，苹果的 SEAR 团队立马发布了一篇博客，介绍发布会没有展开介绍的 A19 芯片一个特性 </span><span leaf="">Memory Integrity Enforcement（强制内存完整性）。这是苹果基于 ARM Memory Tagging Extension 增强开发的针对内存安全漏洞的保护。</span></p><div><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;p&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><a href="https://security.apple.com/blog/memory-integrity-enforcement/" target="_blank">https://security.apple.com/blog/memory-integrity-enforcement/</a></span></p></div><p><span leaf="">2023 年搭载了 ARM Memory Tagging Extension 的 Google Pixel 8 上市，到现在近两年了，越狱圈一直都在观望看苹果什么时候上。这不终于等来了。</span></p><p><span leaf="">博客中提到这个防护针对两种常见的内存安全问题做阻断，一个是缓冲区溢出（buffer overflow），另一个是释放后重用（UAF）。</span></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001913" data-ratio="0.24537037037037038" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=ad6efaff&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOIeXKfPHQ11kOiaKT2HZ1cicKBOwibrAqWGHb4kmIWxZrd5VgbHPjXzUgLgpTfTiaKiaxgGXSiaK61gyBqg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001912" data-ratio="0.7611111111111111" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=65365f57&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOIeXKfPHQ11kOiaKT2HZ1cicK9TxlXz0Oxia1pCcKkaxzEhQgCexA7PNhbP7otp6sB6LPT068WQnrcrA%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf="">前阵子 iOS </span><span leaf="">18.6.2 紧急修复了一个图像处理相关的越界写漏洞看上去可以被阻断。不过这有个前提，就是对应的进程需要在编译阶段启用相关的功能，详见：</span></p><p><span leaf=""><a href="https://developer.apple.com/documentation/xcode/enabling-enhanced-security-for-your-app" target="_blank">https://developer.apple.com/documentation/xcode/enabling-enhanced-security-for-your-app</a><a class="wx_topic_link" topic-id="mfcz3tow-a6akvb" style="color: #576B95 !important;" data-topic="1">#Adopt</a>-memory-integrity-enforcement</span></p><p><span leaf="">这个 0day 利用攻击的是第三方应用 WhatsApp。首先第三方厂商不会这么激进地适配新硬件，另一方面 MIE 可能会识别出程序本身的 bug 导致更频繁的异常崩溃现象。短期内第三方应用上保护可能不太现实。</span></p><p><span leaf="">iOS 漏洞研究倒闭啦！</span></p><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">等等。Android MTE 发布之后有一些厉害的研究员仍然找到了一些绕过案例。</span></p><ul style="list-style-type: disc;" class="list-paddingleft-1"><li style="font-size:14px;"><p><span leaf="">Gaining kernel code execution on an MTE-enabled Pixel 8</span></p><p><span leaf=""><a href="https://github.blog/security/vulnerability-research/gaining-kernel-code-execution-on-an-mte-enabled-pixel-8/" target="_blank">https://github.blog/security/vulnerability-research/gaining-kernel-code-execution-on-an-mte-enabled-pixel-8/</a></span></p></li><li style="font-size:14px;"><p><span leaf=""><span textstyle="" style="font-size: 14px;">Bypassing MTE with CVE-2025-0072</span></span></p><p><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:&#34;mp-quote&#34;, &#34;PingFang SC&#34;, system-ui, -apple-system, BlinkMacSystemFont, &#34;Helvetica Neue&#34;, &#34;Hiragino Sans GB&#34;, &#34;Microsoft YaHei UI&#34;, &#34;Microsoft YaHei&#34;, Arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;"><span textstyle="" style="font-size: 14px;"><a href="https://github.blog/security/vulnerability-research/bypassing-mte-with-cve-2025-0072/" target="_blank">https://github.blog/security/vulnerability-research/bypassing-mte-with-cve-2025-0072/</a></span></span></p></li><li style="font-size:14px;"><p><span leaf=""><span textstyle="" style="font-size: 14px;">TIKTAG: Breaking ARM’s Memory Tagging Extension with Speculative Execution</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 14px;"><a href="https://taesoo.kim/pubs/2025/kim:tiktag-sp.pdf" target="_blank">https://taesoo.kim/pubs/2025/kim:tiktag-sp.pdf</a></span></span></p></li><li style="font-size:14px;"><p><span leaf="">破解 Pixel 8：利用未公开的 DSP 漏洞绕过 MTE 防护</span></p><p><span leaf=""><a href="https://hitcon.org/2025/zh-TW/agenda/b7635c13-282e-4673-8297-43ed3550b3d3/" target="_blank">https://hitcon.org/2025/zh-TW/agenda/b7635c13-282e-4673-8297-43ed3550b3d3/</a></span></p></li></ul><p><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">让我们看看接下来如何。</span></p><p><span leaf=""><span textstyle="" style="font-weight: bold;">参考资料</span></span></p><ol style="list-style-type: decimal;" class="list-paddingleft-1"><li style="font-size:12px;"><p><span leaf=""><span textstyle="" style="font-size: 12px;">Enhanced Memory Tagging Extension (EMTE)</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 12px;"><a href="https://developer.arm.com/documentation/109697/0100/Feature-descriptions/The-Armv8-9-architecture-extension?lang=en" target="_blank">https://developer.arm.com/documentation/109697/0100/Feature-descriptions/The-Armv8-9-architecture-extension?lang=en</a></span><a class="wx_topic_link" topic-id="mfcyshtt-jraomf" style="color: #576B95 !important;" data-topic="1"><span textstyle="" style="font-size: 12px;">#md454</span></a><span textstyle="" style="font-size: 12px;">-the-armv89-architecture-extension__FEAT_MTE4</span></span></p></li><li style="font-size:12px;"><p><span leaf=""><span textstyle="" style="font-size: 12px;">First handset with MTE on the market</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 12px;"><a href="https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html" target="_blank">https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html</a></span></span></p></li><li style="font-size:12px;"><p><span leaf=""><span textstyle="" style="font-size: 12px;">Memory Integrity Enforcement: A complete vision for memory safety in Apple devices</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 12px;"><a href="https://security.apple.com/blog/memory-integrity-enforcement/" target="_blank">https://security.apple.com/blog/memory-integrity-enforcement/</a></span></span></p></li></ol><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://security.apple.com/blog/memory-integrity-enforcement/">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=242eb6d1&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485562%26idx%3D1%26sn%3Ddb1dbccd955c3a1cabc78997375917d0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Wed, 10 Sep 2025 04:14:00 +0800</pubDate>
    </item>
    <item>
      <title>达芬奇密码：在调色软件运行代码</title>
      <link>https://mp.weixin.qq.com/s?__biz=Mzk0NDE3MTkzNQ==&amp;mid=2247485531&amp;idx=1&amp;sn=fea342d1b407650413a9a22bbee853fb</link>
      <description>这是功能！feature！</description>
      <content:encoded><![CDATA[<p>
原创 <span>0xcc</span> <span>2025-03-27 10:47</span> <span style="display: inline-block;">上海</span>
</p>

<p>这是功能！feature！</p>
<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=abed1b9e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOKfohy1kAG6V6DVNoZgMUrCoSicnm4Nnn2aZ2sibXPWTiaxwW2KGqSDEjR7C8m9sPSmzwftMNUFobM6A%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<section><span leaf=""><span textstyle="" style="font-weight: normal;">重要的事放开头。</span><span textstyle="" style="color: rgb(217, 33, 66);font-weight: bold;">先说明本文提到的信息都是功能！feature！</span></span></section><section><br/></section><section><span leaf="">有段时间没更新了，当然是不务正业去摸鱼啦。</span><span style="letter-spacing: 0.034em;">在沉迷学习视频调色，不然感觉对不起自己的 id（codecolorist）。都怪影视飓风。</span></section><section><span style="letter-spacing: 0.034em;"><br/></span></section><section><section>标题玩了个小聪明，英文里代码和密码都是一个词。</section><span style="letter-spacing: 0.034em;"></span></section><section><span leaf=""><br/></span></section><section><span leaf="">我估计会看到本公众号的人群和视频创作者基本不存在交集，所以先简单科普一下 DaVinci Resolve（达芬奇）。</span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">如果经常看过影视飓风应该会略有耳闻。这个软件支持视频非编剪辑、调色甚至加特效。最流行的场景还是作为影视工作流调色的这一步。在官网的宣传稿上可以看到，近年各种大家耳熟能详的奥斯卡获奖影片相当一部分都用了达芬奇做后期调色。<span textstyle="" style="text-decoration: line-through;">那么找到 bug 是不是就可以拿下好莱坞了？</span></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">恶补了一堆教程视频，嫌弃我几年前买的相机视频只有 8bit，没有 60 帧，又整了一台机身。折腾一圈下来发现拍视频比拍照麻烦多了，没两把刷子做出来效果惨不忍睹。先不说手机也可以拍 ProRes log，原相机都自带亮瞎眼的 HDR。没技术真就</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="text-decoration: none;">不如手机加剪映滤镜，打水漂了。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">达芬奇提供免费版和付费解锁高级功能的 Studio 版，相比硬件投入，授权连零头都够不到。免费版极其良心，已经能覆盖普通 vlog 绝大多数需求，但我又菜又爱玩，想试试相机输出杜比视界什么效果，就搞了个正版。免费版和 Studio 还有一个区别就是从 Store 直接下载和从 dmg 安装。免费版有沙箱，而 Studio 版则不带 app sandbox。</span></span></section><section><span leaf=""><br/></span></section><section style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.5944444444444444" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100001870" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=f67373f0&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOLCJ7ojGnOeqYKzekpfhBKRbHBUbCV1icpC6dMo1RaibVoARHImicPlc2FeibNGbIOn46iaDqHxhtsEukg%2F640%3Fwx_fmt%3Dpng"/></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">我有个习惯，时不时看一下哪个应用乱开端口。用上了正版第二天就发现不对劲，多了一个 fuscript 进程，还监听 tcp 0.0.0.0:1144。进程名看上去感觉在用英文骂人，</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="text-decoration: none;">不会被搞了吧？</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">定位到文件一看是达芬奇的组件。这个程序免费版也有，但付费版才会默认跟随主应用一起运行。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">挂上调试器给 socket api 下断点：</span></span></section><section><span leaf=""><br/></span></section><section><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="nginx"><code><span leaf=""><span class="code-snippet__attribute">Target</span> <span class="code-snippet__number">0</span>: (fuscript) stopped.</span></code><code><span leaf="">(lldb) bt</span></code><code><span leaf="">* thread <span class="code-snippet__comment">#1, queue = &#39;com.apple.main-thread&#39;, stop reason = breakpoint 1.15</span></span></code><code><span leaf="">  * frame <span class="code-snippet__comment">#0: 0x00000001909a37fc libsystem_kernel.dylib`__accept</span></span></code><code><span leaf="">    frame <span class="code-snippet__comment">#1: 0x0000000102e09b00 fusionscript.so`Fusion::Platform::AcceptSocket(Fusion::Platform::_Socket*) + 28</span></span></code><code><span leaf="">    frame <span class="code-snippet__comment">#2: 0x0000000102e312dc fusionscript.so`___lldb_unnamed_symbol4493 + 480</span></span></code><code><span leaf="">    frame <span class="code-snippet__comment">#3: 0x0000000102e31a34 fusionscript.so`ScriptServerMain + 112</span></span></code></pre></section></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">主要逻辑都在 fusionscript.so 里面。打开一看里面一堆 lua 相关的符号，而同时这个链接库又是一个可以加载的 python 二进制模块。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">那个可疑的端口用的二进制报文格式大概是（对不起，没仔细分析）先发送一个 dword 表示长度，然后紧跟一段二进制系列化的对象。对应编解码函数如下：</span></span></section><section><span leaf=""><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]">Fusion::ScriptVal::ToPkt</span></section><section><span leaf="">Fusion::ScriptVal::FromPkt</span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">到这里我浪费了几个小时研究发包的格式，这时候突然发现……这不就有现成的 api。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">DaVinci 支持 lua 脚本（宏）自动化。</span></span></section><section><span leaf=""><br/></span></section><section style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.8" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100001872" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=87a9d46d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOId269nbqvAcibpykchFKQbxVLS9rRTR2oothpveCqTh0WWQdYgibqfFX0duVBl4mKHoo2tqnFAQ2YA%2F640%3Fwx_fmt%3Dpng"/></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">可以从 Workspace / Console 菜单打开 REPL，然后执行 lua 代码操作工程。</span></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;"><br/></span></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">在系统设置里还有一处 External Scripting 的选项：</span></span></section><section><span leaf=""><br/></span></section><section style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-ratio="0.5462962962962963" data-s="300,640" data-type="jpeg" data-w="1080" type="block" data-imgfileid="100001871" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=fbb36e0b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2F6N4b2yN3FOId269nbqvAcibpykchFKQbxQCatn1xuiaNJy4ic8QbdyXlibiabs9fEXkPb5wvmWvpny4hNAdJjXHqMTQ%2F640%3Fwx_fmt%3Djpeg"/></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">存在三个模式：</span></span></section><section><span leaf=""><br/></span></section><ul style="list-style-type: disc;" class="list-paddingleft-1"><li><section><span leaf=""><span textstyle="" style="text-decoration: none;">禁用（None）</span></span></section></li><li><section><span leaf=""><span textstyle="" style="text-decoration: none;">本地（Local）</span></span></section></li><li><section><span leaf=""><span textstyle="" style="text-decoration: none;">远程（Network）</span></span></section></li></ul><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">系统默认是 Local，限制从 localhost 访问脚本端口。如果改成 Network，就可以从局域网甚至公网访问过来。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">具体是什么呢？</span></span></section><section><span leaf=""><br/></span></section><section><span leaf="">达芬奇安装后会在系统提供可导入的 python 模块，用来编写脚本和工程交互。如下是 macOS 的路径，其他系统存在差异。</span></section><section><span leaf=""><br/></span></section><section><span leaf="">&#34;/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting/Modules/&#34;</span></section><section><span leaf=""><br/></span></section><section><span leaf="">例如让 UI 切换标签页到渲染输出：</span></section><section><span leaf=""><br/></span></section><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li></ul><pre class="code-snippet__js" data-lang="nginx"><code><span leaf=""><span class="code-snippet__attribute">resolve</span> = bmd.scriptapp(<span class="code-snippet__string">&#39;Resolve&#39;</span>)</span></code><code><span leaf="">resolve.OpenPage(<span class="code-snippet__string">&#39;deliver&#39;</span>)</span></code></pre></section><section><span leaf=""><br/></span></section><section><span leaf="">有一个 BBS 叫 WeSuckLess 专门交流脚本的编写：</span></section><section><span leaf="">www.steakunderwater.com/wesuckless/index.php</span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span leaf="">不少人开始给各种软件适配 </span><span leaf="">Model Context Protocol，来实现让 AI 自动化各种任务的效果，从 Ghidra 到 IDA Pro，达芬奇也不例外。随便搜了一下，两周内有不止一个 GitHub 项目尝试用 python 集成 MCP 到达芬奇。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">重点来了。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">这个 python binding 底层和 DaVinci 主程序通信就是通过我们前文提到的这几个程序和端口。如果在系统设置里把权限改成网络访问，从局域网另一台电脑上无需安装完整版程序，也可以直接通过 python 模块控制达芬奇的实例。一个典型的远程过程调用机制。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">但是没有验证？</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">对，没有身份验证……一旦开启，谁都可以通过 tcp 连上来（除非有防火墙）。在程序二进制代码里看到一个 __Login 方法，但目前是空的，没实现。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">Office 的宏几十年前就被拿来做恶了。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">首先 DaVinci Resolve 的 fusion（视频特效）支持 lua 表达式，因此发送一个嵌有 lua 代码的工程是可行的。就是理论上只有到渲染一步才会运行。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">其次这个远程过程调用确实可以传 lua 代码：</span></span></section><section><span leaf=""><br/></span></section><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="bash"><code><span leaf="">fusion = bmd.scriptapp(<span class="code-snippet__string">&#34;Fusion&#34;</span>, <span class="code-snippet__string">&#34;test.local&#34;</span>)</span></code><code><span leaf=""><span class="code-snippet__comment"># test.local 为内网的目标系统地址</span></span></code><code><span leaf=""><span class="code-snippet__built_in">print</span>(<span class="code-snippet__built_in">dir</span>(fusion))</span></code><code><span leaf="">fusion.Execute(<span class="code-snippet__string">&#39;lua code here&#39;</span>)</span></code></pre></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">到了 lua 这一步压根就不用什么沙箱逃逸，直接带了 os.execute 模块……以下是弹计算器的流量。</span></span></section><section><span leaf=""><br/></span></section><section style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001873" data-ratio="0.9425925925925925" data-s="300,640" data-type="png" data-w="1080" type="block" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=b69d41ba&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOId269nbqvAcibpykchFKQbxxAslN54sXPzmYficVl5zQAibNpIJtpdBNVeiar1JXdz50NPWZ9BDxSfJQ%2F640%3Fwx_fmt%3Dpng"/></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: line-through;">这不演示小视频就有了，拿去吓唬一下 B 站各种百大。</span></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="text-decoration: none;">甚至还带了 ffi，可以调用任意 native 代码。喜欢 41414141 的读者有福了。</span></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section style="text-align: center;" nodeleaf=""><img class="rich_pages wxw-img" data-imgfileid="100001874" data-ratio="0.32685185185185184" data-s="300,640" data-type="png" data-w="1080" type="block" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=48fac0d2&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2F6N4b2yN3FOId269nbqvAcibpykchFKQbxqh9MBpTpUMvr5mIicM5Cze85XLkCRVeC3CibBuL326QHgaKNrR9haRzw%2F640%3Fwx_fmt%3Dpng"/></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="font-weight: bold;text-decoration: none;">这是功能！</span></span><span style="letter-spacing: 0.034em;">就是这么设计的，反正默认也不开启。</span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="text-decoration: none;">实测发现默认的配置虽然是 Local，不影响这几个端口监听 0.0.0.0 的请求，非本机发探针还是会应答系统版本。只是到真正执行 __Connect 调用的时候会判断 </span></span><span leaf=""><span textstyle="" style="text-decoration: none;">gethostbyaddr，拒绝非 127.1 的连接。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="text-decoration: none;">我赶紧把脚本先设置成 None，外加防火墙过滤端口。</span></span></section><section><span leaf=""><br/></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="text-decoration: none;">依然对这个实现依然存在疑问。比如 DNS 劫持的情况下会不会导致 host 检测绕过，解析二进制数据的反序列化函数是否安全，还有这整个 RPC 机制会不会有别的逻辑问题？</span></span></section><section><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><br/></span></section><section><span leaf="">我找了一下达芬奇的历史 CVE。2021 年有两个 Cisco Talos 实验室 fuzz 的文件格式相关的 CVE-2021-40417 和 CVE-2021-40418；还有一个比较近的 </span><span leaf="">CVE-2025-1413 略蛋疼，一个本地文件权限问题给了吓人的 8.4 CVSS。有兴趣研究还是盯一下这个网络的向量吧。</span></section><section><span leaf=""><br/></span></section><section><span leaf=""><span textstyle="" style="font-size: 12px;">题图来自 unsplash，作者 </span></span><span leaf=""><span textstyle="" style="font-size: 12px;">Andrey Novik</span></span></section><p style="display: none;"><mp-style-type data-value="10000"></mp-style-type></p>



<p><a href="2247485531">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=a3a39a20&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzk0NDE3MTkzNQ%3D%3D%26mid%3D2247485531%26idx%3D1%26sn%3Dfea342d1b407650413a9a22bbee853fb%26subscene%3D0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 27 Mar 2025 10:47:00 +0800</pubDate>
    </item>
  </channel>
</rss>