<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>天空软件工作室的博客 — 全部文章</title><description>AI 编程开发经验 · 逆向经验与算法（仅公开文章全文）</description><link>https://tkrjw.cn/</link><language>zh-cn</language><item><title>Astro 混合渲染怎么做？SSG 与 SSR 按页面级切换的完整实践</title><link>https://tkrjw.cn/posts/dev/astro-hybrid-rendering/</link><guid isPermaLink="true">https://tkrjw.cn/posts/dev/astro-hybrid-rendering/</guid><description>Astro 5 混合渲染实操指南：output: &apos;server&apos; + 适配器，用一行 prerender 决定页面走静态生成还是服务端渲染，附付费墙场景的完整落地方案。</description><pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Astro 的混合渲染只需要两个动作：全局设 &lt;code&gt;output: &apos;server&apos;&lt;/code&gt;，再在静态页面顶部加一行 &lt;code&gt;export const prerender = true&lt;/code&gt;。这样构建期就把首页、列表页打成静态 HTML，只有真正需要读 Cookie 的付费文章页走 Node 服务端按请求渲染，性能与权限门控两全。&lt;/p&gt;
&lt;h2 id=&quot;为什么内容站需要混合渲染&quot;&gt;为什么内容站需要混合渲染？&lt;/h2&gt;
&lt;p&gt;纯静态最快，但付费墙必须在服务端读会话并截断正文；纯 SSR 灵活，却把首页、归档这类&amp;quot;内容永不变&amp;quot;的页面也变成了每请求计算。混合渲染的本质是：&lt;strong&gt;按页面分配渲染时机&lt;/strong&gt;——内容在构建期已确定的页面在构建期渲染，内容依赖请求上下文的页面在请求期渲染。&lt;/p&gt;
&lt;h2 id=&quot;怎么配置-astro-5-的混合渲染&quot;&gt;怎么配置 Astro 5 的混合渲染？&lt;/h2&gt;
&lt;p&gt;先装 Node 适配器，然后在 &lt;code&gt;astro.config.mjs&lt;/code&gt; 里声明 server 输出：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// astro.config.mjs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;defineConfig&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;astro/config&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt; node&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;@astrojs/node&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#C678DD&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; defineConfig&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;  output&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;server&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;,                 &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 默认 SSR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;  adapter&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; node&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;({ &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;mode&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;standalone&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;静态页面在文件顶部声明预渲染：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-astro&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// src/pages/index.astro&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; prerender&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;      &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 这一行让该页在构建期生成静态 HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;prerender&lt;/code&gt; 是&lt;strong&gt;页面级&lt;/strong&gt;开关，不影响其他路由。需要按请求读 Cookie 的页面保持默认（SSR）即可。&lt;/p&gt;
&lt;h2 id=&quot;付费文章页为什么要-ssr&quot;&gt;付费文章页为什么要 SSR？&lt;/h2&gt;
&lt;p&gt;判断&amp;quot;当前用户能不能看全文&amp;quot;只能发生在服务端：读会话 Cookie → 查会员身份/单篇授权 → 决定输出全文还是截断版。这个流程发生在每一条请求上，因此文章详情页整体走 SSR 是最简单可靠的做法。&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// src/pages/posts/[...slug].astro（示意）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; prerender&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;     &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// SSR：每请求判定权限&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt;slug&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; Astro&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; entry&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; getEntry&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;posts&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;slug&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; decision&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; resolvePostAccess&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;Astro&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E5C07B&quot;&gt;locals&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;entry&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// decision.full ? 输出全文 : 输出服务端截断后的墙前内容&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;两个必须守住的底线：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;截断在服务端完成&lt;/strong&gt;——绝不能把全文发给浏览器再用 CSS/JS 藏起来，查看源码即泄露；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;墙前内容进初始 HTML&lt;/strong&gt;——标题、目录、摘要、FAQ 必须是服务端渲染的静态标签，AI 爬虫多数不执行 JS。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;上线前怎么验证效果&quot;&gt;上线前怎么验证效果？&lt;/h2&gt;
&lt;p&gt;三步：&lt;code&gt;npm run build&lt;/code&gt; 检查构建日志中各页面的渲染方式；用 &lt;code&gt;curl&lt;/code&gt; 匿名请求一篇付费文章，确认返回的 HTML 里没有付费段正文；跑一次 Lighthouse 确认静态页性能达标。更完整的权限判定实现可参考本站源码 &lt;code&gt;src/lib/access.js&lt;/code&gt;，页面级切换的思路也适用于 &lt;a href=&quot;/posts/dev/node-stream-backpressure&quot;&gt;Node.js 流式处理&lt;/a&gt; 等服务端场景。&lt;/p&gt;
&lt;h2 id=&quot;常见坑&quot;&gt;常见坑&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;中间件在构建期也会执行&lt;/strong&gt;：混合输出下，prerender 页面在 build 时会跑一遍中间件，因此中间件里不要做&amp;quot;必须有请求上下文&amp;quot;的强假设（读 Cookie 返回空是正常的）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适配器与托管平台绑定&lt;/strong&gt;：&lt;code&gt;@astrojs/node&lt;/code&gt; 用于自有服务器/Nginx 反代，上 Vercel/Netlify 则换对应适配器。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sitemap 要自己补 SSR 页面&lt;/strong&gt;：&lt;code&gt;@astrojs/sitemap&lt;/code&gt; 只收录预渲染页，付费文章页需要手工加入站点地图。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>astro</category><category>ssr</category><category>ssg</category><category>性能</category></item><item><title>逆向工程的方法论是什么？从入口定位到算法还原的通用路径</title><link>https://tkrjw.cn/posts/reverse/reverse-methodology/</link><guid isPermaLink="true">https://tkrjw.cn/posts/reverse/reverse-methodology/</guid><description>把逆向分析沉淀为可复用的五步方法论：明确目标、找入口、跟数据流、还原文法、验证闭环。适用于协议分析、客户端分析与算法识别，附工具链建议。</description><pubDate>Sat, 05 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;逆向分析的通用方法论只有五步：&lt;strong&gt;明确目标 → 定位入口 → 追踪数据流 → 还原逻辑 → 闭环验证&lt;/strong&gt;。所有具体技巧都挂在这条链上。这篇文章把这五步展开，让你在拿到任何陌生目标时有一张确定性的地图。&lt;/p&gt;
&lt;h2 id=&quot;为什么逆向需要方法论而不是技巧&quot;&gt;为什么逆向需要方法论而不是技巧？&lt;/h2&gt;
&lt;p&gt;技巧（某个 Hook 点位、某条 IDA 快捷键）会随目标与工具版本过期，但&amp;quot;从现象反推实现&amp;quot;的路径是稳定的。方法论的另一个作用是&lt;strong&gt;控制范围&lt;/strong&gt;：明确这次分析只回答什么问题，防止在百万行的反编译代码里漫无目的地漂移。&lt;/p&gt;
&lt;h2 id=&quot;第一步明确目标与边界&quot;&gt;第一步：明确目标与边界&lt;/h2&gt;
&lt;p&gt;动手前写下三行字：要还原什么（例：请求头里 X-Sign 的生成算法）、验收标准是什么（例：本地能对任意输入复现出一致的签名）、合法边界在哪（例：自建靶场/授权项目）。这一步看似形式主义，实际决定了后面每一步的取舍。&lt;/p&gt;
&lt;h2 id=&quot;第二步怎么找入口&quot;&gt;第二步：怎么找入口？&lt;/h2&gt;
&lt;p&gt;按性价比从高到低试这些锚点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;字符串与字段名&lt;/strong&gt;：参数名、URL 片段、错误文案在反编译产物里全局搜索，命中率最高；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络层回溯&lt;/strong&gt;：Hook 收发函数（如 &lt;code&gt;XMLHttpRequest&lt;/code&gt;、&lt;code&gt;OkHttp&lt;/code&gt; 拦截点），对请求体下断点，沿调用栈向上找；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;算法指纹&lt;/strong&gt;：魔数（0x67452301 等）、S-box、固定表名——直接暴露标准算法的存在。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 示例：用 Frida 快速确认某函数是否是目标入口&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;Interceptor&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;attach&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;getBaseAddress&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;libtarget.so&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt;0x1A2B3C&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;), {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  onEnter&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;arg0:&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;readUtf8String&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;());  &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 观察输入&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  onLeave&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;ret :&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;readUtf8String&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;());      &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 观察输出&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;第三步追踪数据流&quot;&gt;第三步：追踪数据流&lt;/h2&gt;
&lt;p&gt;拿到入口后，问三个问题：&lt;strong&gt;输入从哪来、经过哪些变换、输出去了哪&lt;/strong&gt;。把中间变量按顺序 dump 出来，对相邻两次调用做差分——值变了但逻辑没变的字段是盐/时间戳，值不变的往往是密钥或设备指纹。&lt;/p&gt;
&lt;h2 id=&quot;第四步还原逻辑&quot;&gt;第四步：还原逻辑&lt;/h2&gt;
&lt;p&gt;先判断是标准算法还是自研变体：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;特征: MD5 常量 0x67452301 / AES S-box / SHA-256 K 表 → 标准算法，直接套库验证&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;异常: 常量被替换、轮数改变、多一轮异或 → 魔改，逐段 diff 定位改动点&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用 python 快速验证假设，输入输出对不上就回到第三步补 dump。常见的 &lt;a href=&quot;/posts/reverse/hash-encoding-identify&quot;&gt;哈希与编码特征对照&lt;/a&gt; 可以把识别时间从小时级压到分钟级。&lt;/p&gt;
&lt;h2 id=&quot;第五步闭环验证&quot;&gt;第五步：闭环验证&lt;/h2&gt;
&lt;p&gt;把还原的算法封装成独立函数，用&lt;strong&gt;目标在真实运行中产生的多组输入输出对&lt;/strong&gt;做回归验证：10 组全对才算还原成功。只对一组样例&amp;quot;碰巧一致&amp;quot;是最常见的假阳性。&lt;/p&gt;
&lt;h2 id=&quot;工具链建议&quot;&gt;工具链建议&lt;/h2&gt;
&lt;p&gt;静态：IDA / Ghidra / jadx（Android）/ 浏览器 DevTools（JS）。动态：Frida 通用性最好，入门见 &lt;a href=&quot;/posts/reverse/frida-hook-layers&quot;&gt;Frida Hook 的三个层次&lt;/a&gt;。所有分析在授权范围内进行——本文与后续实战篇只覆盖方法论与自建靶场演示，不涉及任何具体商业产品的绕过。&lt;/p&gt;
</content:encoded><category>逆向</category><category>方法论</category><category>协议分析</category></item><item><title>Node.js 流为什么能省内存？背压机制详解与实战代码</title><link>https://tkrjw.cn/posts/dev/node-stream-backpressure/</link><guid isPermaLink="true">https://tkrjw.cn/posts/dev/node-stream-backpressure/</guid><description>用 Node.js 流（Stream）处理大文件能保持常数级内存占用，核心在于背压机制：readable.pipe/writable.cork 之后的 drain 信号让生产者等待消费者，本文附可运行示例与常见误区。</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Node.js 流省内存的关键不是&amp;quot;分块读&amp;quot;本身，而是&lt;strong&gt;背压（backpressure）&lt;/strong&gt;：当下游消费不过来时，&lt;code&gt;write()&lt;/code&gt; 返回 &lt;code&gt;false&lt;/code&gt;，上游暂停生产，直到 &lt;code&gt;drain&lt;/code&gt; 事件通知缓冲已排空再继续。这让内存占用与文件大小无关，始终保持在常数级。&lt;/p&gt;
&lt;h2 id=&quot;用-buffer-一次性读文件会发生什么&quot;&gt;用 Buffer 一次性读文件会发生什么？&lt;/h2&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 反例：整个文件进内存&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;readFileSync&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:fs&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; buf&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; readFileSync&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;access-10gb.log&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 10GB 日志 → OOM 或换页抖动&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;处理 10GB 文件时，这段代码至少需要 10GB 堆内存，V8 默认堆上限内直接崩溃。而同样的任务用流只需几十 MB：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 正例：常数级内存&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;createReadStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;createWriteStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:fs&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;pipeline&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:stream/promises&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;createGzip&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:zlib&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; pipeline&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  createReadStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;access-10gb.log&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;),   &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 按块读&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  createGzip&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(),                          &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 边读边压&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  createWriteStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;access-10gb.log.gz&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;背压到底是怎么工作的&quot;&gt;背压到底是怎么工作的？&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;writable.write(chunk)&lt;/code&gt; 把数据放进内部缓冲区（上限由 &lt;code&gt;highWaterMark&lt;/code&gt; 控制，默认 64KB）。当缓冲超过上限，&lt;code&gt;write()&lt;/code&gt; 返回 &lt;code&gt;false&lt;/code&gt;——这不是报错，而是&lt;strong&gt;协议信号&lt;/strong&gt;：请暂停写入。缓冲被消费完之后触发 &lt;code&gt;drain&lt;/code&gt; 事件，上游恢复写入。手写这个协议长这样：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 手动背压协作（理解原理用，生产推荐 pipeline）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; readable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; createReadStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;in.log&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; writable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; createWriteStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;out.log&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;readable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;chunk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;writable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;chunk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    readable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;pause&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;();                  &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 缓冲已满，暂停生产&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    writable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;once&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;drain&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; readable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;resume&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;()); &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// 排空后恢复&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;readable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;end&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; writable&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pipe()&lt;/code&gt; 和 &lt;code&gt;pipeline()&lt;/code&gt; 做的就是这件事的健壮版本——包括错误传播与资源清理，因此生产代码永远优先 &lt;code&gt;pipeline&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&quot;实战逐行处理-10gb-日志并统计&quot;&gt;实战：逐行处理 10GB 日志并统计&lt;/h2&gt;
&lt;p&gt;结合 &lt;code&gt;readline&lt;/code&gt;（基于流的行解析）与批量写库，是日志分析最常用的模式：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;createReadStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:fs&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;createInterface&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:readline&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;pipeline&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;node:stream/promises&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; stats&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; Map&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(); &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// url -&gt; count&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; pipeline&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  createReadStream&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;access-10gb.log&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, { &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E06C75&quot;&gt;encoding&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &apos;utf8&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;  async&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; function*&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; line&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt; source&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; line&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;      stats&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;stats&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// stats 里就是全量统计结果，峰值内存 &amp;#x3C; 100MB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;async generator 也是流：它天然遵守背压协议，上游快了会自动暂停迭代。&lt;/p&gt;
&lt;h2 id=&quot;三个常见误区&quot;&gt;三个常见误区&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;忽略 &lt;code&gt;write()&lt;/code&gt; 的返回值又不用 pipe&lt;/strong&gt;——缓冲无限增长，流等于白用；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在 &lt;code&gt;pipe&lt;/code&gt; 链里忘了错误处理&lt;/strong&gt;——某一段崩了，其他段不会自动销毁，用 &lt;code&gt;pipeline&lt;/code&gt; 一并解决；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对流做 &lt;code&gt;JSON.parse&lt;/code&gt; 整体操作&lt;/strong&gt;——流的价值在&amp;quot;逐块、无需全量&amp;quot;的场景，需要全量数据时应改用聚合策略。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把这套思路放到 Web 服务里同样成立：本站的付费文章页就是用服务端截断输出控制响应体大小的，底层思想与 &lt;a href=&quot;/posts/dev/astro-hybrid-rendering&quot;&gt;Astro 混合渲染实践&lt;/a&gt; 一脉相承——按需生产，不做无用功。&lt;/p&gt;
</content:encoded><category>nodejs</category><category>stream</category><category>性能</category><category>后端</category></item><item><title>Frida 入门：Hook 函数的三个层次与调试技巧</title><link>https://tkrjw.cn/posts/reverse/frida-hook-layers/</link><guid isPermaLink="true">https://tkrjw.cn/posts/reverse/frida-hook-layers/</guid><description>Frida Hook 从易到难的三个层次：Java 层 Hook、Native 函数 Hook、运行中代码的内存级操作，附完整可运行脚本与环境搭建步骤。</description><pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Frida 的 Hook 能力分三个层次：&lt;strong&gt;Java 层方法拦截 → Native 函数拦截 → 内存级读写&lt;/strong&gt;。从上往下难度递增、能力递增。本文按层次给出可运行的最小脚本与排错思路，帮你把&amp;quot;注入成功&amp;quot;到&amp;quot;拿到数据&amp;quot;的距离缩到最短。&lt;/p&gt;
&lt;h2 id=&quot;环境怎么搭&quot;&gt;环境怎么搭？&lt;/h2&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;# PC 端（以 Python 环境为例）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;pip&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; frida-tools&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;frida&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;# Android 设备端：下载对应架构的 frida-server 推送并运行&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; push&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; frida-server-android-arm64&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; /data/local/tmp/fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;adb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &quot;chmod +x /data/local/tmp/fs &amp;#x26;&amp;#x26; /data/local/tmp/fs &amp;#x26;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;# 验证连接&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;frida-ps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; -U&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试目标建议使用 OWASP UnCrackable 或自写的 demo app——&lt;strong&gt;不要拿线上商业产品练手&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;层次一java-层-hook&quot;&gt;层次一：Java 层 Hook&lt;/h2&gt;
&lt;p&gt;目标在 jadx 里能看到的方法，用 &lt;code&gt;Java.perform&lt;/code&gt; 拦截：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// hook_java.js — 拦截某类的静态方法并打印参数与返回值&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;Java&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;perform&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; Cls&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; Java&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;com.demo.app.CryptoUtil&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;  Cls&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E5C07B&quot;&gt;sign&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;overload&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;java.lang.String&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;implementation&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E45649;--shiki-dark:#E5C07B&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;sign&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;[sign] in :&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;[sign] out:&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt; ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;frida&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; -U&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; -l&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; hook_java.js&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; -f&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; com.demo.app&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;   # spawn 模式，覆盖 attach 抓不到早期调用的场景&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见坑：方法重载时必须用 &lt;code&gt;overload()&lt;/code&gt; 指定签名；类名被混淆就用脚本枚举当前内存里的类。&lt;/p&gt;
&lt;h2 id=&quot;层次二native-层-hook&quot;&gt;层次二：Native 层 Hook&lt;/h2&gt;
&lt;p&gt;目标在 so 库里，先用偏移量定位，再 &lt;code&gt;Interceptor.attach&lt;/code&gt;：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;// hook_native.js — 拦截 so 中的未导出函数（偏移 0x1A2B3C）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#E5C07B&quot;&gt; base&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt; Module&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;getBaseAddress&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;libnative.so&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;Interceptor&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;attach&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt;0x1A2B3C&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;), {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  onEnter&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;    // 按函数约定读参数：指针按字节读，整型按位读&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;[n] arg0 ptr:&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E06C75&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;readCString&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;  onLeave&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic&quot;&gt;ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;    console&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&apos;[n] ret:&apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#E5C07B&quot;&gt;ret&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt;toInt32&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;定位偏移的方法：IDA 打开 so → 找到目标函数 → 记录函数起始地址减去模块基址。导出函数可以直接 &lt;code&gt;Module.getExportByName(null, &apos;symbol&apos;)&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&quot;层次三内存级操作&quot;&gt;层次三：内存级操作&lt;/h2&gt;
&lt;p&gt;前两层都不奏效时（函数被内联、逻辑写在宏里），退到内存层：&lt;code&gt;Memory.scan&lt;/code&gt; 搜特征字节、&lt;code&gt;Memory.readByteArray&lt;/code&gt; 直接读数据区、&lt;code&gt;Memory.protect&lt;/code&gt; 改页属性。这是&amp;quot;最后手段&amp;quot;，脚本可移植性差，每次版本更新都要重新定位。&lt;/p&gt;
&lt;h2 id=&quot;调试心法&quot;&gt;调试心法&lt;/h2&gt;
&lt;p&gt;三个技巧贯穿三层次：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;差分观察&lt;/strong&gt;：同一操作重复两次，对比 dump 结果，找&amp;quot;变的&amp;quot;和&amp;quot;不变的&amp;quot;字段；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;从调用栈反推&lt;/strong&gt;：&lt;code&gt;console.log(Java.use(&apos;android.util.Log&apos;).getStackTraceString(Java.use(&apos;java.lang.Exception&apos;).$new()))&lt;/code&gt; 打印 Java 调用栈，定位是谁在调目标函数；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最小化注入&lt;/strong&gt;：一次只 Hook 一个函数，确认生效再加下一个——批量 Hook 出错时几乎无法定位。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Frida 在完整分析流程中的位置，见 &lt;a href=&quot;/posts/reverse/reverse-methodology&quot;&gt;逆向方法论五步&lt;/a&gt;；拿到关键数据后如何还原算法，将在会员篇 &lt;a href=&quot;/posts/reverse/sign-algorithm-analysis&quot;&gt;签名算法分析实战&lt;/a&gt; 中以自建靶场为例完整演示。&lt;/p&gt;
</content:encoded><category>frida</category><category>hook</category><category>逆向</category><category>android</category></item><item><title>Prompt 工程有哪些被验证有效的模式？附可复用模板</title><link>https://tkrjw.cn/posts/dev/prompt-patterns/</link><guid isPermaLink="true">https://tkrjw.cn/posts/dev/prompt-patterns/</guid><description>沉淀 8 个在生产环境被反复验证的 Prompt 工程模式：角色与边界、少示例、结构化输出、思维链、自检回路等，每个模式给出适用场景与反例。</description><pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Prompt 工程被验证有效的模式并不多：角色与边界、结构化输出、少示例、思维链、自检回路、上下文分区、失败降级、版本化评测。这 8 个模式覆盖了生产环境 90% 的场景，本文逐一给出模板与反例。&lt;/p&gt;
&lt;h2 id=&quot;为什么大多数-prompt-失败&quot;&gt;为什么大多数 Prompt 失败？&lt;/h2&gt;
&lt;p&gt;失败 Prompt 有个共同点：&lt;strong&gt;把模型当搜索引擎用&lt;/strong&gt;——一句话需求丢进去，指望它理解你没有说出口的约束。有效 Prompt 的本质是工程约定：输入是什么、输出长什么样、边界在哪、错了怎么办。下面按模式展开。&lt;/p&gt;
&lt;h2 id=&quot;模式一角色与边界role--boundary&quot;&gt;模式一：角色与边界（Role + Boundary）&lt;/h2&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;你是一名资深代码评审员。职责：只评审给出代码的正确性与安全问题。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;边界：不讨论代码风格，不重写整个文件；发现的问题按 [严重度][位置][原因][建议] 四段输出。&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;如果代码无法评审（信息不足），直接回复&quot;需要补充上下文&quot;并列出缺失项。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;要点：&lt;strong&gt;边界句和职责句同样重要&lt;/strong&gt;。没有边界，模型会用&amp;quot;热心&amp;quot;填补空白——重写你的代码、解释基础概念，输出不可控。&lt;/p&gt;
&lt;h2 id=&quot;模式二结构化输出schema-first&quot;&gt;模式二：结构化输出（Schema First）&lt;/h2&gt;
&lt;p&gt;用示例把格式&amp;quot;钉死&amp;quot;，而不是用形容词描述格式：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;输出必须严格是 JSON 数组，不要任何额外文字：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[{&quot;issue&quot;: &quot;问题描述&quot;, &quot;severity&quot;: &quot;high|medium|low&quot;, &quot;line&quot;: 12}]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;示例：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[{&quot;issue&quot;: &quot;未校验空指针&quot;, &quot;severity&quot;: &quot;high&quot;, &quot;line&quot;: 42}]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;反例：&amp;quot;请结构化地输出你的分析结果&amp;quot;——&amp;quot;结构化&amp;quot;是人类的想象，模型需要的是具体 schema。&lt;/p&gt;
&lt;h2 id=&quot;模式三少示例few-shot&quot;&gt;模式三：少示例（Few-shot）&lt;/h2&gt;
&lt;p&gt;2–5 个精选示例的效果稳定优于零示例，也优于 20 个冗余示例。选示例的标准：&lt;strong&gt;覆盖边界情况&lt;/strong&gt;，尤其要包含一个&amp;quot;应拒绝/判空&amp;quot;的示例，否则模型对模糊输入会强行编造答案。&lt;/p&gt;
&lt;h2 id=&quot;模式四思维链按任务类型启用&quot;&gt;模式四：思维链（按任务类型启用）&lt;/h2&gt;
&lt;p&gt;推理类任务（数学、多条件判断、根因分析）在要求&amp;quot;先列出推理步骤，再给最终答案&amp;quot;后有可测量提升；简单分类与抽取任务不要加，纯属浪费 token 与延迟。经验法则：&lt;strong&gt;答案需要组合两个以上事实的任务，才值得思维链&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;模式五自检回路self-check&quot;&gt;模式五：自检回路（Self-check）&lt;/h2&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;完成草稿后，先按以下清单自检并修正，再输出最终答案：&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. 输出格式是否符合 schema&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. 每个事实性断言是否有材料支撑&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3. 是否存在未处理的空值/异常分支&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实测能拦截大部分格式错误与编造断言，代价是一轮额外推理。对质量敏感、对延迟不敏感的管线值得开启。&lt;/p&gt;
&lt;h2 id=&quot;模式六上下文分区&quot;&gt;模式六：上下文分区&lt;/h2&gt;
&lt;p&gt;长上下文 prompt 按固定顺序组织：&lt;code&gt;角色与规则 → 材料（带编号） → 任务指令 → 输出格式&lt;/code&gt;。检索增强场景下，把最强证据放在材料的&lt;strong&gt;开头与结尾&lt;/strong&gt;（模型对中间内容注意力弱），这一条在 &lt;a href=&quot;/posts/dev/rag-from-scratch&quot;&gt;RAG 系统搭建实践&lt;/a&gt; 里有详细展开。&lt;/p&gt;
&lt;h2 id=&quot;模式七失败降级&quot;&gt;模式七：失败降级&lt;/h2&gt;
&lt;p&gt;预定义三档输出：正常答案 / &amp;quot;资料未覆盖&amp;quot; / &amp;quot;需要人工&amp;quot;。让模型&lt;strong&gt;有台阶下&lt;/strong&gt;，是压住幻觉最便宜的手段——大量幻觉来自模型不敢说&amp;quot;不知道&amp;quot;。&lt;/p&gt;
&lt;h2 id=&quot;模式八版本化与评测&quot;&gt;模式八：版本化与评测&lt;/h2&gt;
&lt;p&gt;Prompt 进 Git、变更写说明、每次修改跑同一套评测集（哪怕只有 30 条）。没有回归评测的 Prompt 迭代等于裸奔。把这些模式组合进工程管线的方法，可参考逆向分析里的&lt;a href=&quot;/posts/reverse/reverse-methodology&quot;&gt;提示词驱动辅助分析&lt;/a&gt;思路——方法论是通用的。&lt;/p&gt;
</content:encoded><category>prompt</category><category>llm</category><category>ai工程</category></item><item><title>如何快速识别一个哈希或编码算法？特征长度对照表</title><link>https://tkrjw.cn/posts/reverse/hash-encoding-identify/</link><guid isPermaLink="true">https://tkrjw.cn/posts/reverse/hash-encoding-identify/</guid><description>通过长度、字符集与已知特征串快速识别 MD5/SHA 家族、Base64/Base58/Hex、AES/RC4 等常见算法，附速查表与验证代码，逆向分析的第一块拼图。</description><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;逆向分析中，识别&amp;quot;这段数据是什么算法的产物&amp;quot;是第一块拼图。方法就三招：&lt;strong&gt;看长度、看字符集、用已知输入验证&lt;/strong&gt;。本文给一张速查表加一段验证代码，把识别时间压到分钟级。&lt;/p&gt;
&lt;h2 id=&quot;第一步看长度与字符集&quot;&gt;第一步：看长度与字符集&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;输出特征&lt;/th&gt;
&lt;th&gt;候选算法&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;32 hex&lt;/td&gt;
&lt;td&gt;MD5&lt;/td&gt;
&lt;td&gt;空串结果 &lt;code&gt;d41d8cd9...8427e&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40 hex&lt;/td&gt;
&lt;td&gt;SHA-1&lt;/td&gt;
&lt;td&gt;空串 &lt;code&gt;da39a3ee5e6b4b0d3255bfef95601890afd80709&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64 hex&lt;/td&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;空串 &lt;code&gt;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128 hex&lt;/td&gt;
&lt;td&gt;SHA-512&lt;/td&gt;
&lt;td&gt;空串 &lt;code&gt;cf83e135...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A-Za-z0-9+/=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Base64&lt;/td&gt;
&lt;td&gt;末尾 &lt;code&gt;=&lt;/code&gt; 是填充标志&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A-Za-z0-9&lt;/code&gt;（无 &lt;code&gt;+/=&lt;/code&gt;，无 &lt;code&gt;0OlI&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;Base58&lt;/td&gt;
&lt;td&gt;比特币地址常用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;纯数字&lt;/td&gt;
&lt;td&gt;纯数字编码/自研&lt;/td&gt;
&lt;td&gt;常见于业务混淆 ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;高熵二进制&lt;/td&gt;
&lt;td&gt;加密/压缩&lt;/td&gt;
&lt;td&gt;需结合代码特征判断&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;第二步用已知输入验证&quot;&gt;第二步：用已知输入验证&lt;/h2&gt;
&lt;p&gt;记住四个&amp;quot;指纹值&amp;quot;，验证标准哈希只需一行：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; hashlib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;known &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;    &quot;md5&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;:    &lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&quot;d41d8cd98f00b204e9800998ecf8427e&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;    &quot;sha1&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;:   &lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&quot;da39a3ee5e6b4b0d3255bfef95601890afd80709&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;    &quot;sha256&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&quot;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;--shiki-light:#4078F2;--shiki-dark:#61AFEF&quot;&gt; identify&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-dark:#D19A66;--shiki-dark-font-style:italic&quot;&gt;digest&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;) -&gt; &lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#56B6C2&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;--shiki-light:#986801;--shiki-dark:#D19A66&quot;&gt; None&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;    d &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; digest.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#61AFEF&quot;&gt;lower&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; name, empty &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; known.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#61AFEF&quot;&gt;items&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; hashlib.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#61AFEF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(name, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#61AFEF&quot;&gt;hexdigest&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#56B6C2&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; empty &lt;/span&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; len&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(d) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#56B6C2&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--shiki-light:#0184BC;--shiki-dark:#56B6C2&quot;&gt; len&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt;(empty):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#383A42;--shiki-dark:#ABB2BF&quot;&gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A626A4;--shiki-dark:#C678DD&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#50A14F;--shiki-dark:#98C379&quot;&gt; &quot;unknown（可能加盐/魔改/截断）&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对不上指纹值不一定是&amp;quot;不是这个算法&amp;quot;——&lt;strong&gt;加盐或魔改&lt;/strong&gt;会让空串指纹失效，这时转入第三步。&lt;/p&gt;
&lt;h2 id=&quot;第三步进代码找结构特征&quot;&gt;第三步：进代码找结构特征&lt;/h2&gt;
&lt;p&gt;数据层面区分不了加密算法，要进代码看常量：&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light one-dark-pro&quot; style=&quot;--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;AES   : S-box 以 0x63, 0x7c, 0x77, 0x7b... 开头；轮常量 0x01, 0x02, 0x04...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;DES   : 初始置换表 IP[58, 50, 42, ...]；16 轮迭代&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RC4   : 256 长度状态盒 + KSA/PRGA 双循环，无魔数常量&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RSA   : 大数运算 + e 常见取值 0x10001 (65537)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CRC32 : 查表法 0xEDB88320（反射）或 0x04C11DB7（正向）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IDA/Ghidra 里全局搜索这些字节序列，命中即有答案。Standard Hash 的魔数（MD5 的 &lt;code&gt;0x67452301&lt;/code&gt;、SHA-1 的 &lt;code&gt;0x5A827999&lt;/code&gt;）也适用于定位哈希函数位置。&lt;/p&gt;
&lt;h2 id=&quot;常见陷阱&quot;&gt;常见陷阱&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;长度对上就下结论&lt;/strong&gt;——32 hex 也可能是两次 MD5 套接或加盐 MD5，必须动态验证；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;忽略编码嵌套&lt;/strong&gt;——&lt;code&gt;Base64(Hex(MD5(x)))&lt;/code&gt; 三层嵌套很常见，逐层解到指纹值为止；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;把压缩当加密&lt;/strong&gt;——zlib/gzip 头分别是 &lt;code&gt;78 9C&lt;/code&gt; 和 &lt;code&gt;1F 8B&lt;/code&gt;，先解压再分析。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;识别只是起点，数据流追踪与算法还原的完整路径见&lt;a href=&quot;/posts/reverse/reverse-methodology&quot;&gt;逆向方法论&lt;/a&gt;；Frida 动态验证手段见 &lt;a href=&quot;/posts/reverse/frida-hook-layers&quot;&gt;Frida Hook 三个层次&lt;/a&gt;。&lt;/p&gt;
</content:encoded><category>逆向</category><category>算法</category><category>哈希</category><category>编码</category></item></channel></rss>