Code Iterates, Minds Innovate https://ret0.dev/zh/ Recent content on Code Iterates, Minds Innovate Hugo zh-cn Mon, 16 Mar 2026 00:00:00 +0000 macOS AMFI Bypass:ObjC Runtime Swizzle 实战 https://ret0.dev/zh/posts/macos-amfi-bypass-objc-runtime-swizzle/ Mon, 16 Mar 2026 00:00:00 +0000 https://ret0.dev/zh/posts/macos-amfi-bypass-objc-runtime-swizzle/ 在 Apple Silicon 上对 amfid 注入的完整分析,以及为什么 call-through ObjC swizzle 在常见注入手段失效时仍可行。 CVE-2026-20660:CFNetwork NSGZipDecoder 路径穿越导致任意文件写入 https://ret0.dev/zh/posts/cve-2026-20660/ Tue, 10 Mar 2026 00:00:00 +0000 https://ret0.dev/zh/posts/cve-2026-20660/ CVE-2026-20660 的 1-day 分析——Apple CFNetwork 中 NSGZipDecoder 的路径穿越漏洞,可通过恶意 gzip FNAME 头实现任意文件写入。 在 macOS 上为 IDA Pro 配置 Python 虚拟环境的简明指南 https://ret0.dev/zh/posts/using-venv-with-ida/ Thu, 02 Oct 2025 00:00:00 +0000 https://ret0.dev/zh/posts/using-venv-with-ida/ <p>对于逆向工程师来说,保持一个干净、有序的脚本环境至关重要。为 IDA Pro 项目使用 Python 虚拟环境 (<code>venv</code>) 是管理依赖、避免冲突的最佳方式。</p> <p>网上很多指南已经过时,推荐的方法已经不再适用。这篇文章提供一个现代、直接的方案——使用 IDA Pro 官方内置的 <code>IDAPythonrc</code> 启动脚本,在 macOS 上将 Python venv 连接到 IDA。</p> <h2 id="目标自动加载-venv">目标:自动加载 Venv</h2> <p>我们的目标很简单:</p> <ol> <li>创建一个隔离的虚拟环境 (<code>venv</code>)。</li> <li>使用 <code>pip</code> 在 venv 中安装任何 Python 包。</li> <li>让 IDA Pro 每次启动时自动找到并使用这些包,无需手动操作。</li> </ol> <h2 id="现代方案idapythonrc-脚本">现代方案:<code>IDAPythonrc</code> 脚本</h2> <p>过时的 <code>activate_this.py</code> 方法已经不可用——现代虚拟环境中不再包含这个脚本。正确的方法是直接告诉 IDA 的 Python 解释器你的包在哪里,通过修改 <code>sys.path</code> 实现。我们可以在 IDA 的用户目录中放置一个启动脚本来自动完成这个工作。</p> <p><strong>第 1 步:创建虚拟环境</strong></p> <p>首先,创建一个 venv 来存放你的工具。一个方便的位置是 IDA 的用户目录。</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#6272a4"># 进入 IDA 用户目录</span> </span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">cd</span> ~/.idapro </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#6272a4"># 创建名为 venv 的虚拟环境</span> </span></span><span style="display:flex;"><span>python3 -m venv venv </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#6272a4"># 激活它来安装包</span> </span></span><span style="display:flex;"><span><span style="color:#8be9fd;font-style:italic">source</span> venv/bin/activate </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#6272a4"># 安装你需要的包(例如 keystone-engine)</span> </span></span><span style="display:flex;"><span>pip install keystone-engine </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#6272a4"># 完成后退出</span> </span></span><span style="display:flex;"><span>deactivate </span></span></code></pre></div><p><strong>第 2 步:创建 <code>IDAPythonrc</code> 启动脚本</strong></p> 如何用 Frida 动态获取 ObjC Block 的参数类型 https://ret0.dev/zh/posts/how-to-use-frida-hook-oc-block/ Sun, 11 May 2025 00:00:00 +0000 https://ret0.dev/zh/posts/how-to-use-frida-hook-oc-block/ <p>你是否想过窥探 iPhone 或 iPad 上的应用,观察它到底在处理什么数据?今天介绍一种简单而强大的方法——使用 Frida 动态获取 iOS 应用中 Block 的参数类型。</p> <h2 id="什么是-block">什么是 Block?</h2> <p>在 iOS 编程中,Block 是一小段可以被传递、稍后执行的自包含代码。可以把它想象成你把电话号码(Block)给朋友,朋友在有重要事情时给你回电话。</p> <p>有时你想精确观察这些 Block 接收了什么输入、产出了什么结果。Frida 可以在不修改应用原始代码的情况下帮你做到这一点。</p> <h2 id="block-的内存结构">Block 的内存结构</h2> <p>理解 Block 的内部结构有助于你准确地获取它的签名和参数信息。以下是 Block 的内存布局:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#ff79c6">struct</span> Block_literal_1 { </span></span><span style="display:flex;"><span> <span style="color:#8be9fd">void</span> <span style="color:#ff79c6">*</span>isa; <span style="color:#6272a4">// 指向 &amp;_NSConcreteStackBlock 或 &amp;_NSConcreteGlobalBlock </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">int</span> flags; <span style="color:#6272a4">// 标志位,指示 block 类型和属性 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">int</span> reserved; <span style="color:#6272a4">// 保留字段 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">void</span> (<span style="color:#ff79c6">*</span>invoke)(<span style="color:#ff79c6">struct</span> Block_literal_1 <span style="color:#ff79c6">*</span>, ...); <span style="color:#6272a4">// 指向 block 实现的函数指针 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#ff79c6">struct</span> Block_descriptor_1 { </span></span><span style="display:flex;"><span> <span style="color:#8be9fd">unsigned</span> <span style="color:#8be9fd">long</span> reserved; <span style="color:#6272a4">// 保留,通常为 NULL </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">unsigned</span> <span style="color:#8be9fd">long</span> size; <span style="color:#6272a4">// Block_literal_1 结构体的大小 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#6272a4">// 可选的辅助函数 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">void</span> (<span style="color:#ff79c6">*</span>copy_helper)(<span style="color:#8be9fd">void</span> <span style="color:#ff79c6">*</span>dst, <span style="color:#8be9fd">void</span> <span style="color:#ff79c6">*</span>src); <span style="color:#6272a4">// flag (1&lt;&lt;25) 置位时存在 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#8be9fd">void</span> (<span style="color:#ff79c6">*</span>dispose_helper)(<span style="color:#8be9fd">void</span> <span style="color:#ff79c6">*</span>src); <span style="color:#6272a4">// flag (1&lt;&lt;25) 置位时存在 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#6272a4">// 包含签名的 block 必须有此字段 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> <span style="color:#ff79c6">const</span> <span style="color:#8be9fd">char</span> <span style="color:#ff79c6">*</span>signature; <span style="color:#6272a4">// flag (1&lt;&lt;30) 置位时存在 </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span> } <span style="color:#ff79c6">*</span>descriptor; </span></span><span style="display:flex;"><span> <span style="color:#6272a4">// 捕获的变量(如果有) </span></span></span><span style="display:flex;"><span><span style="color:#6272a4"></span>}; </span></span></code></pre></div><p>Block 内部的 signature 提供了返回类型和参数类型等关键信息,是动态分析的基础。</p> 如何在 Mac 上搭建 PWN 调试环境 https://ret0.dev/zh/posts/how-to-build-pwn-env-on-mac/ Tue, 15 Apr 2025 00:00:00 +0000 https://ret0.dev/zh/posts/how-to-build-pwn-env-on-mac/ <ol> <li>下载并安装 UTM,可以用命令:</li> </ol> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>brew install --cask utm </span></span></code></pre></div><ol start="2"> <li>从 <a href="https://releases.ubuntu.com/22.04/">https://releases.ubuntu.com/22.04/</a> 下载镜像并安装。</li> </ol> <p>然后在 Ubuntu 虚拟机中安装 gdbserver:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>sudo apt install gdbserver </span></span></code></pre></div><p>如果需要调试 32 位可执行文件,还需要执行:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>sudo dpkg --add-architecture i386 </span></span><span style="display:flex;"><span>sudo apt update </span></span><span style="display:flex;"><span>sudo apt install libc6:i386 libncurses5:i386 libstdc++6:i386 </span></span></code></pre></div><p>环境搭建完成后,在 Ubuntu 虚拟机中运行:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>gdbserver :1234 ./test </span></span></code></pre></div><p>在 Mac 上使用以下命令连接:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>gdb ./test \ </span></span><span style="display:flex;"><span> -ex &#34;target extended-remote 192.168.64.13:1234&#34; </span></span></code></pre></div><p>记得替换 IP 地址和端口。</p> <p>在 Mac 上执行:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>gdb ./pwn101-1644307211706.pwn101 \ </span></span><span style="display:flex;"><span> -ex &#34;target extended-remote gdbserver.local:1234&#34; \ </span></span><span style="display:flex;"><span> -ex &#34;set remote exec-file /home/gdb/pwn101-1644307211706.pwn101&#34; \ </span></span><span style="display:flex;"><span> -ex &#34;break main&#34; </span></span></code></pre></div><p>注意:<code>target extended-remote 192.168.64.13:1234</code> 必须是第一条命令,否则不会生效。 你也可以用 pwndbg 来运行调试器。</p> 关于 https://ret0.dev/zh/about/ Mon, 01 Jan 0001 00:00:00 +0000 https://ret0.dev/zh/about/ 关于这个博客与作者