<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN">
  <generator uri="http://jekyllrb.com" version="3.10.0">Jekyll</generator>
  
  
  <link href="https://umi.cat/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://umi.cat/" rel="alternate" type="text/html" hreflang="zh-CN" />
  <updated>2026-04-15T04:19:09+00:00</updated>
  <id>https://umi.cat/</id>

  
    <title type="html">奇思妙想</title>
  

  
    <subtitle>umi 的个人博客，记录关于加密货币、安全研究、iOS 越狱等方面的技术探索与思考。</subtitle>
  

  
    <author>
        <name>umi</name>
      
      
    </author>
  

  
  
    <entry>
      
      <title type="html">Now You See Me: 抽象钱包是如何隐藏真实链上操作的</title>
      
      
      <link href="https://umi.cat/2025/10/18/now-you-see-me/" rel="alternate" type="text/html" title="Now You See Me: 抽象钱包是如何隐藏真实链上操作的" />
      
      <published>2025-10-18T00:00:00+00:00</published>
      <updated>2025-10-18T00:00:00+00:00</updated>
      <id>https://umi.cat/2025/10/18/now-you-see-me</id>
      <content type="html" xml:base="https://umi.cat/2025/10/18/now-you-see-me/">&lt;p&gt;首先声明，这里有些标题党，并不是完全隐藏，而是加大了溯源难度。在文章后半段，我会给出可操作的溯源方法。
你有没有遇到过这样的情况：在一些扫链工具里，没看到巨鲸大额砸盘，但自己买的土狗代币价格却已经直线下跌。从链上看，也没发现哪个地址进行了大额卖出。
本文用一个例子解释AA 钱包会让授权/发起者/资金流彼此分离，从而让部分传统扫链规则失效，并给出可操作的溯源方法。&lt;/p&gt;

&lt;h1 id=&quot;背景介绍&quot;&gt;背景介绍&lt;/h1&gt;
&lt;p&gt;先来简单复习一下以太坊的地址种类：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;EOA地址&lt;/strong&gt;：外部账户地址，由私钥控制。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;智能合约地址&lt;/strong&gt;：由合约代码控制，这类地址没有私钥，只有合约代码。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;从日常链上交互的视角来看，我们可以大致地把链上买币/卖币分为以下几个步骤：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;授权&lt;/strong&gt;：授权智能合约使用你的代币。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;交易&lt;/strong&gt;：智能合约扣减你的代币，执行卖出。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;转账&lt;/strong&gt;：把卖出得到的代币转到收款人地址。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这里，通常1可以提前做，3则是一个可选项。这里可能会出现很多变体，比如：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Binance / OKX DEX 以及其他路由，可能会先把买的币转到一个中间地址，然后在一个交易内把你买到的代币转给你。&lt;/li&gt;
  &lt;li&gt;卖出的代币转到指定收款人。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一笔典型的交易如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.v2ex.co/BB2UacWY.jpeg&quot; alt=&quot;EOA 交易&quot; /&gt;
在这里，地址 0x5c6C6BD98573030206E9dfb70F6266FE5892Dbd0 与 Dex Router 交互，是交易的&lt;strong&gt;发起人&lt;/strong&gt;、&lt;strong&gt;gas 支付人&lt;/strong&gt;、&lt;strong&gt;收款人&lt;/strong&gt;。
Dex Router 扣掉 BNB 后，把买的 TST 转给0x5c6C6BD98573030206E9dfb70F6266FE5892Dbd0.&lt;/p&gt;

&lt;p&gt;上述基础的链上交互流程，大家应该都比较熟悉，接下来，我们来看一个可能的情况：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;你持有 1000 USDC，想买 TST。&lt;/li&gt;
  &lt;li&gt;你通过混币的方式（跨链/交易所提取等）把 1000 USDC 转账给一个中间地址。&lt;/li&gt;
  &lt;li&gt;中间地址等待你的指令，当你执行买入，卖出或转账时，中间地址会执行相应的操作。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;与上面提到的基础链上交互流程相比，这里直接参与的地址，即：&lt;strong&gt;交易发起人&lt;/strong&gt;、&lt;strong&gt;交易 gas 支付人&lt;/strong&gt;、&lt;strong&gt;收款人&lt;/strong&gt;，都&lt;strong&gt;不是&lt;/strong&gt;代币实际持有者的EOA地址。&lt;/p&gt;

&lt;p&gt;此外，收到的代币，在控制人发起转账之前，代币还是放在中间地址的。&lt;/p&gt;

&lt;p&gt;这正是 EIP-4337（账户抽象，AA）的工作方式。AA 钱包本质上是一个可充当钱包的智能账户，它允许“签名者、交易发起者、gas 支付者与资金持有者”分离。AA 最初的目标是提升可用性（如无原生 gas 也能交易），并非“隐藏交易”，但也确实增加了解析难度。&lt;/p&gt;

&lt;p&gt;一开始是为了即使不在链上持有gas token时也能执行交易，但因为链上解析的复杂性，目前很多链上信息工具，均没有解析这一环节。&lt;/p&gt;

&lt;p&gt;这就导致，虽然你在链上没有看到大额卖出，但是价格却已经直线下跌，本质上是因为你盯的是 EOA 的授权与资金流，但真正的卖出发生在一个智能账户里，让传统的扫链规则失效。
一笔典型的 AA 钱包交易在这里：
&lt;img src=&quot;https://i.v2ex.co/blera8O2.jpeg&quot; alt=&quot;AA 钱包交易&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;为什么会看不到大额卖出&quot;&gt;为什么会看不到大额卖出？&lt;/h1&gt;

&lt;p&gt;回到开头的问题：为什么价格在跌，却在链上看不到“大额卖出”？&lt;/p&gt;

&lt;p&gt;传统流程：&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;EOA地址 0x5c6C6B... ──[1) 调用 Swap 交易]──&amp;gt; DEX Router ──────────&amp;gt; AMM Pool (BNB/TST)
        ^                                                 │                         │
        |                                                 │                         │
        └────────────────[2) 买到的币转回去给EOA地址 ]───────┴─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;AA流程：&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;主私钥持有者 ──[签名 UserOperation (离线)]──&amp;gt; Bundler ──&amp;gt; EntryPoint.handleOps ──[校验签名/费率 + Paymaster 检查]──&amp;gt; Smart Account (AA)
(私钥/主身份)                                                 │                                                    │
                                                              │                                                    ├─&amp;gt; (1) Permit/授权
                                                              │                                                    ├─&amp;gt; (2) Swap：调用 DEX Router
                                                              │                                                    └─&amp;gt; (3) Transfer：转给收款人 0xB8aa6c...
                                                              │
                                                          Paymaster ─────&amp;gt; Gas 支付：扣押金/代币结算

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;传统扫链工具的监控逻辑&quot;&gt;传统扫链工具的监控逻辑&lt;/h2&gt;

&lt;p&gt;传统扫链规则隐含了一个前提：授权者=发起者=gas 支付者=资金持有者=同一 EOA。于是“授权→交易→转账”都能在同一地址时间线上被看见。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;监控 EOA 地址的授权交易&lt;/strong&gt;：当一个地址发起 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve&lt;/code&gt; 交易时，标记为”准备交易”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;追踪资金流动&lt;/strong&gt;：监控代币从哪个地址转出、转到哪里&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;识别交易发起者&lt;/strong&gt;：通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; 字段识别是谁发起了交易&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;关联 gas 支付者&lt;/strong&gt;：通过谁支付 gas 来辅助判断真实的操作者&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这套逻辑对于普通的 EOA 地址交易非常有效，因为：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;授权者 = 交易发起者 = gas 支付者 = 代币持有者 = 同一个 EOA 地址&lt;/li&gt;
  &lt;li&gt;所有操作都会显示在该地址的 Transaction 列表中&lt;/li&gt;
  &lt;li&gt;资金流向清晰可见&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;更进一步地说，回到开头，买卖本质就是交易、转账两个步骤的组合，如果扫链工具能正确解析到这两个步骤，就能正确识别出真实的操作者。&lt;/p&gt;

&lt;h2 id=&quot;aa-钱包如何间接隐藏操作&quot;&gt;AA 钱包如何间接隐藏操作&lt;/h2&gt;

&lt;p&gt;AA 将“签名/发起/gas/资金归属”拆散：授权可通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permit&lt;/code&gt; 与交易合并，调用经 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntryPoint&lt;/code&gt; 内部执行，发起者可能是 Bundler，gas 由 Paymaster 结算，资金暂存在 AA 钱包中并直达另一个收款地址，传统的可见性与归因链条因此断裂。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;没有独立的授权交易&lt;/strong&gt;：通过 Permit 或批处理，授权和交易合并在一次执行中，扫链工具抓不到”准备卖出”的信号&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;交易不出现在 Transaction 列表&lt;/strong&gt;：AA 钱包的操作是通过 EntryPoint 合约的内部调用执行的，只会出现在 Internal Transactions 中，大多数人不会专门去查看这个标签页
&lt;img src=&quot;https://i.v2ex.co/rx2u6V2Z.jpeg&quot; alt=&quot;Internal Transactions&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;发起者≠控制者&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;链上看到的发起者可能是 Bundler 的地址&lt;/li&gt;
      &lt;li&gt;真正的控制者只是签了一个 UserOp，不会直接出现在链上&lt;/li&gt;
      &lt;li&gt;Gas 由 Paymaster 支付，与实际控制者无关&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;资金流特征被打散&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;代币放在智能合约地址（AA 钱包）中，而不是 EOA 地址，这里通常会被直接过滤掉&lt;/li&gt;
      &lt;li&gt;卖出操作在合约内部完成&lt;/li&gt;
      &lt;li&gt;收款可以直接到另一个地址，不经过原地址&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;一个具体的例子&quot;&gt;一个具体的例子&lt;/h2&gt;
&lt;p&gt;以这笔交易为例：
https://bscscan.com/tx/0xb12ce0488c5689a6c5ea2582a9bef4259723e57618893f1a32c9a0327c00a7a0
0x4Ed01522D6d4193f98F2be67460cB38078adCaaB 虽然是交易发起者，但他只负责支付gas fee。
在该交易中，链上“发起者”仅是 Bundler/gas 支付相关地址；真正的操作者通过 UserOperation 间接完成了授权与卖出，这些关键信息多出现在“Internal Transactions/Logs”，而非“Transactions”列表。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;监控不到任何的授权（没有独立的 approve 交易）&lt;/li&gt;
  &lt;li&gt;在 0xB8aa6c1042F7DA2eA6399fA53b0D58894c754F95 的 Transaction 列表里看不到任何记录&lt;/li&gt;
  &lt;li&gt;0xB8aa6c1042F7DA2eA6399fA53b0D58894c754F95 的操作在 Internal Transactions 中，容易被忽略&lt;/li&gt;
  &lt;li&gt;即使看到了链上可见的交易，执行方是 Paymaster，也很难直接关联到对应持有者，除非转账。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这就是为什么看到价格在跌，却找不到是谁在砸盘——因为传统的监控规则失效了。
市面上扫链工具的解析逻辑，很多都没解析到这一个环节。&lt;/p&gt;

&lt;h1 id=&quot;怎么查出是谁在砸盘&quot;&gt;怎么查出是谁在砸盘？&lt;/h1&gt;
&lt;p&gt;回到最初的问题，怎么查出是谁在砸盘？
一个最基本的想法是，直接从 Token 的 Transfer 事件出发，逐一排查转账。
然后从浏览器中直接看， bscscan 、debank 跟 oklink 等均能较好直接语义化解析到对应交易，前提是你能找到对应的交易 hash。
&lt;img src=&quot;https://i.v2ex.co/88cvj6D4.jpeg&quot; alt=&quot;oklink&quot; /&gt;&lt;/p&gt;

&lt;p&gt;但更好的办法是直接从支持的扫链工具入手：
能正确解析 AA 的工具（举例，非推荐，调研时间为 2025/10/18）：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;OKX DEX&lt;/li&gt;
  &lt;li&gt;Axiom&lt;/li&gt;
  &lt;li&gt;BullX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;以下工具暂时无法正确解析到 AA 相关交易：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;gmgn&lt;/li&gt;
  &lt;li&gt;AveAI&lt;/li&gt;
  &lt;li&gt;Photon&lt;/li&gt;
  &lt;li&gt;Binance Web3 DEX&lt;/li&gt;
&lt;/ul&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;AA 钱包本质&lt;/strong&gt;：用智能合约代替 EOA 进行链上操作&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;隐藏效果&lt;/strong&gt;：部分扫链工具依赖 EOA 交易记录，无法追踪 AA 内部操作&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：使用支持 AA 解析的工具，或直接追踪 Token Transfer 事件&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;需要强调的是，AA 钱包的设计初衷是改善用户体验（无需持有 gas token、批量操作等），
并非刻意隐藏交易。但客观上确实增加了链上监控的难度。&lt;/p&gt;

&lt;p&gt;撰文时发现，很遗憾的是， OKX Wallet 去年6月就把 AA 钱包创建功能给关了（也许是因为快人两步导致没人用🤷），虽然不知是什么原因，但比较可惜。
上述所有操作均可以通过 Coinbase Wallet 直接创建 Smart Account 直接复现。&lt;/p&gt;

&lt;h1 id=&quot;附录&quot;&gt;附录&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;AA 钱包发起的 Swap： 0xb12ce0488c5689a6c5ea2582a9bef4259723e57618893f1a32c9a0327c00a7a0&lt;/li&gt;
  &lt;li&gt;EOA 钱包发起的 Swap：0xf3660c31d65e21912edc3aa5b2aee18ddf6304ce87bd97f8c7d609c6a693af5f&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;附录2-eip-4844&quot;&gt;附录2: EIP-4844&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://i.v2ex.co/8SBJjVx2l.webp&quot; alt=&quot;EIP-4844&quot; /&gt;&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="CryptoCurrency" />
      
        <category term="Ethereum" />
      
        <category term="EVM" />
      
        <category term="Smart Contracts" />
      
        <category term="Solidity" />
      
        <category term="Blockchain" />
      
        <category term="Security" />
      
        <category term="EIP-4337" />
      
        <category term="Account Abstraction" />
      

      
        <summary type="html">首先声明，这里有些标题党，并不是完全隐藏，而是加大了溯源难度。在文章后半段，我会给出可操作的溯源方法。 你有没有遇到过这样的情况：在一些扫链工具里，没看到巨鲸大额砸盘，但自己买的土狗代币价格却已经直线下跌。从链上看，也没发现哪个地址进行了大额卖出。 本文用一个例子解释AA 钱包会让授权/发起者/资金流彼此分离，从而让部分传统扫链规则失效，并给出可操作的溯源方法。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">解析 EVM Custom Error</title>
      
      
      <link href="https://umi.cat/2025/10/14/decode-custom-error-ethereum/" rel="alternate" type="text/html" title="解析 EVM Custom Error" />
      
      <published>2025-10-14T00:00:00+00:00</published>
      <updated>2025-10-14T00:00:00+00:00</updated>
      <id>https://umi.cat/2025/10/14/decode-custom-error-ethereum</id>
      <content type="html" xml:base="https://umi.cat/2025/10/14/decode-custom-error-ethereum/">&lt;h1 id=&quot;背景&quot;&gt;背景&lt;/h1&gt;

&lt;p&gt;Solidity 0.8.4 引入的 Custom Error 机制相比传统的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require(condition, &quot;error message&quot;)&lt;/code&gt; 更节省 gas。
当你看到一串十六进制数据时，如何解码出真实的错误信息？
假设我们收到这样一段 revert data：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x6e8698f20000000000000000000000009c5d7cfc31374100b03c0aebe82d5c68df901111
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x6e8698f2&lt;/code&gt; 是 Error Selector，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0000000000000000000000009c5d7cfc31374100b03c0aebe82d5c68df901111&lt;/code&gt; 是 Error Data。&lt;/p&gt;

&lt;h1 id=&quot;custom-error&quot;&gt;Custom Error&lt;/h1&gt;
&lt;h2 id=&quot;error-selector-的生成&quot;&gt;Error Selector 的生成&lt;/h2&gt;
&lt;p&gt;Custom error 的 selector 是通过对错误签名进行 Keccak-256 哈希，然后取前 4 个字节生成的：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;web3&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Web3&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 错误签名格式：ErrorName(type1,type2,...)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;InsufficientFee(uint256,uint256)&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Web3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keccak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 结果: 0xa458261b
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;abi-编码规则&quot;&gt;ABI 编码规则&lt;/h2&gt;

&lt;p&gt;错误参数使用 ABI 编码：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;静态类型&lt;/strong&gt;（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt; 等）：直接编码为 32 字节&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;动态类型&lt;/strong&gt;（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, 数组等）：使用偏移量指针 + 长度 + 数据&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;selector-生成&quot;&gt;selector 生成&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load_abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;error_signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;input_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argument&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;inputs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_types&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;)&quot;&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print_error_selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error_signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Web3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keccak&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; -&amp;gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__file__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;abi.abi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi_entries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;print_error_selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;所以，这个错误，其实就是TokenNotTradable(0x9c5d7cfc31374100b03c0aebe82d5c68df901111)&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="CryptoCurrency" />
      
        <category term="Ethereum" />
      
        <category term="EVM" />
      
        <category term="Smart Contracts" />
      
        <category term="Solidity" />
      
        <category term="Blockchain" />
      
        <category term="Security" />
      

      
        <summary type="html">背景</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">USDC CCTP Bridge Investigation</title>
      
      
      <link href="https://umi.cat/2024/10/01/usdc-cctp-bridge-investigation/" rel="alternate" type="text/html" title="USDC CCTP Bridge Investigation" />
      
      <published>2024-10-01T00:00:00+00:00</published>
      <updated>2024-10-01T00:00:00+00:00</updated>
      <id>https://umi.cat/2024/10/01/usdc-cctp-bridge-investigation</id>
      <content type="html" xml:base="https://umi.cat/2024/10/01/usdc-cctp-bridge-investigation/">&lt;h1 id=&quot;背景&quot;&gt;背景&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://files.readme.io/316de4a-CCTP_architecture_domains2x.png&quot; alt=&quot;CCTP架构图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;跨链转账协议（Cross-Chain Transfer Protocol，简称CCTP）是Circle公司开发的一种无需许可的链上工具。
按照官方说法：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;CCTP 旨在通过原生燃烧和铸造机制，实现USDC在不同区块链网络间的安全转移。CCTP的设计目标是提高资本效率，并在跨链使用USDC时最小化信任要求。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CCTP 不需要KYC，不需要许可，也没有额外的资金损耗。&lt;/p&gt;

&lt;p&gt;CCTP的工作原理可以简化为三个步骤：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;在源链上燃烧USDC&lt;/li&gt;
  &lt;li&gt;从Circle获取签名证明&lt;/li&gt;
  &lt;li&gt;在目标链上铸造USDC&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;目前，CCTP支持8个区块链网络，包括Arbitrum、Avalanche、Base、Ethereum、Noble、OP Mainnet、Polygon PoS和Solana，形成了56条独特的跨链转账路径。&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;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum&lt;/td&gt;
      &lt;td&gt;Arbitrum Sepolia&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche&lt;/td&gt;
      &lt;td&gt;Avalanche Fuji&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base&lt;/td&gt;
      &lt;td&gt;Base Sepolia&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum&lt;/td&gt;
      &lt;td&gt;Ethereum Sepolia&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Noble&lt;/td&gt;
      &lt;td&gt;Noble Testnet&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OP Mainnet&lt;/td&gt;
      &lt;td&gt;OP Sepolia&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon PoS&lt;/td&gt;
      &lt;td&gt;Polygon PoS Amoy&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Solana&lt;/td&gt;
      &lt;td&gt;Solana Devnet&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sui (即将推出)&lt;/td&gt;
      &lt;td&gt;Sui Testnet&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;所需确认数&quot;&gt;所需确认数&lt;/h2&gt;

&lt;p&gt;官网提供了一组&lt;a href=&quot;https://developers.circle.com/stablecoins/docs/required-block-confirmations&quot;&gt;数据&lt;/a&gt;，用于描述不同链上转账所需的确认数和平均时间。&lt;/p&gt;
&lt;h3 id=&quot;mainnet&quot;&gt;Mainnet&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source Chain&lt;/th&gt;
      &lt;th&gt;Number of Blocks&lt;/th&gt;
      &lt;th&gt;Average Time&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum&lt;/td&gt;
      &lt;td&gt;~65*&lt;/td&gt;
      &lt;td&gt;~13 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OP Mainnet&lt;/td&gt;
      &lt;td&gt;~65 ETH blocks*&lt;/td&gt;
      &lt;td&gt;~13 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum&lt;/td&gt;
      &lt;td&gt;~65 ETH blocks*&lt;/td&gt;
      &lt;td&gt;~13 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Noble&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base&lt;/td&gt;
      &lt;td&gt;~65 ETH blocks*&lt;/td&gt;
      &lt;td&gt;~13 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon PoS&lt;/td&gt;
      &lt;td&gt;~200*&lt;/td&gt;
      &lt;td&gt;~8 minutes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Solana&lt;/td&gt;
      &lt;td&gt;32&lt;/td&gt;
      &lt;td&gt;~25 seconds&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;testnet&quot;&gt;Testnet&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source Chain&lt;/th&gt;
      &lt;th&gt;Number of Blocks&lt;/th&gt;
      &lt;th&gt;Average Time&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum Sepolia&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;~1 minute&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche Fuji&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OP Sepolia&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum Sepolia&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Noble Testnet&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base Sepolia&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon PoS Amoy&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Solana Devnet&lt;/td&gt;
      &lt;td&gt;32&lt;/td&gt;
      &lt;td&gt;~25 seconds&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;目标&quot;&gt;目标&lt;/h1&gt;
&lt;p&gt;由于业务需要，想了解从某条链上跨到另一条链时，实际到账的时间。由于上述步骤中的 Step 2 生成签名依赖 Circle 官方API，这个API我们无法感知具体情况，故需要通过其他方式来获取实际到账时间。
此外，我们还想了解跨链的实际成本如何。&lt;/p&gt;

&lt;p&gt;这里我写了一个&lt;a href=&quot;https://github.com/Umiiii/CCTP-Analytics&quot;&gt;脚本&lt;/a&gt;，用于获取跨链转账的实际到账时间。&lt;/p&gt;

&lt;p&gt;当前做了以下几个方向的调研：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SOL -&amp;gt; EVM&lt;/li&gt;
  &lt;li&gt;EVM -&amp;gt; SOL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;方案是先从源链中获取指定燃烧事件，然后从目标链中获取指定铸造事件，通过时间差来计算实际到账时间。&lt;/p&gt;

&lt;h2 id=&quot;sol---evm&quot;&gt;SOL -&amp;gt; EVM&lt;/h2&gt;

&lt;p&gt;SOL 中 CCTP Program ID 为 CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3， 其对应燃烧事件为 depositForBurn，事件结构如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type DepositForBurnArgs = {
    params: {
        amount: BN;
        destinationDomain: BN;
        mintRecipient: PublicKey;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里，我们采用debridge-finance的第三方工具解析链上数据。&lt;/p&gt;
&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SolanaParser&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@debridge-finance/solana-transaction-parser&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CCTP_PROGRAM_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rpcConnection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SOLANA_RPC_URL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;txParser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SolanaParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;idl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CCTPIdl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Idl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;programId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PublicKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CCTP_PROGRAM_ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}]);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;txParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parseTransaction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rpcConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;txSignature&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;depositForBurn&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DepositForBurnArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// do something&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;需要注意的是，TxFee并不包含在DepositForBurnArgs中，需要单独获取。&lt;/p&gt;

&lt;p&gt;主函数遍历：&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getAllTransactions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;txs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rpcConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getSignaturesForAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PublicKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CCTP_PROGRAM_ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//console.log(&quot;Length: &quot;, txs.length);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;txs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  
        &lt;span class=&quot;nx&quot;&gt;parseTx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`Error parsing transaction &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;// wait 1 second&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对于EVM，我们将mintReceipt 转换为对应的EVM地址即可&lt;/p&gt;
&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;publicKeyToEthereumAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;publicKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PublicKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;publicKey&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_bn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;evm---sol&quot;&gt;EVM -&amp;gt; SOL&lt;/h2&gt;

&lt;p&gt;对于 EVM，官方给出了另外一组合约对应的表格：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Chain&lt;/th&gt;
      &lt;th&gt;Domain&lt;/th&gt;
      &lt;th&gt;Address&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0xbd3fa81b58ba92a82136038b25adec7066af3155&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;0x6b25532e1060ce10cc3b0a99e5683b91bfde6982&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;OP Mainnet&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;0x2B4069517957735bE00ceE0fadAE88a26365528f&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;0x19330d10D9Cc8751218eaf51E8885D058642E08A&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;0x1682Ae6375C4E4A97e4B583BC394c861A46D8962&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon PoS&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;这里我们采取相同的手段即可，与 Solana 不同的是，EVM需要依靠 Filter Event的方式获取。&lt;/p&gt;
&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;transferFilterTopic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ethereumStandardAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;web3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toChecksumAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;web3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;padLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;targetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;padding&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;web3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;padLeft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ethereumStandardAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;fromBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fromBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;toBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;topics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transferFilterTopic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x0000000000000000000000000000000000000000000000000000000000000000&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里，我们还有另外一个需要注意的点，L2有些链的Gas Fee需要把 L1 跟 L2加起来，才是最终消耗的Gas Fee。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getL2Fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;chainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;txId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;eth_getTransactionReceipt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;txId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rpcInstanceCfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;chainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rpcInstanceCfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Invalid chain ID&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rpcInstanceCfg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rpcAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;axiosInstance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;axios&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;baseURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;jsonrpc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;axiosInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2GasUsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gasUsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2GasPrice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;effectiveGasPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2Fee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2GasUsed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2GasPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isNaN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;totalFee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l1Fee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;l2Fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;totalFee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;totalFee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//console.log(`L1 Fee: ${l1Fee}, L2 Fee: ${l2Fee}, Total Fee: ${totalFee}`);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;totalFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;通过上述方法，我们可以获取到跨链转账的实际到账时间。&lt;/p&gt;

&lt;p&gt;直接给结论。&lt;/p&gt;

&lt;p&gt;从 SOL 跨链到 EVM 各链的平均时间/成本如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;目标链&lt;/th&gt;
      &lt;th&gt;平均目标链mint成本(USD)&lt;/th&gt;
      &lt;th&gt;平均目标链Mint时间&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum&lt;/td&gt;
      &lt;td&gt;0.014992835&lt;/td&gt;
      &lt;td&gt;406.6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche&lt;/td&gt;
      &lt;td&gt;0.119040534&lt;/td&gt;
      &lt;td&gt;117.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base&lt;/td&gt;
      &lt;td&gt;0.003440751&lt;/td&gt;
      &lt;td&gt;131.4814815&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum&lt;/td&gt;
      &lt;td&gt;9.390838272&lt;/td&gt;
      &lt;td&gt;161.4347826&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Optimism&lt;/td&gt;
      &lt;td&gt;0.012127123&lt;/td&gt;
      &lt;td&gt;138.1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon&lt;/td&gt;
      &lt;td&gt;0.002715731&lt;/td&gt;
      &lt;td&gt;101.05&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;以上成本还需加上 Solana 销毁 Tx 的 Gas Fee， 约为0.00295 SOL = 0.45 USD&lt;/p&gt;

&lt;p&gt;从 EVM 跨链到 SOL 各链的平均时间/成本如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;目标链&lt;/th&gt;
      &lt;th&gt;平均目标链mint成本(transfer)&lt;/th&gt;
      &lt;th&gt;平均目标链Mint时间&lt;/th&gt;
      &lt;th&gt;官方标称时间&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Arbitrum&lt;/td&gt;
      &lt;td&gt;0.009897&lt;/td&gt;
      &lt;td&gt;2204.197279&lt;/td&gt;
      &lt;td&gt;~13 minutes = 780s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Avalanche&lt;/td&gt;
      &lt;td&gt;0.113491&lt;/td&gt;
      &lt;td&gt;66.9245283&lt;/td&gt;
      &lt;td&gt;~20 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Base&lt;/td&gt;
      &lt;td&gt;0.006112&lt;/td&gt;
      &lt;td&gt;1797.410072&lt;/td&gt;
      &lt;td&gt;~13 minutes = 780s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ethereum&lt;/td&gt;
      &lt;td&gt;3.431554&lt;/td&gt;
      &lt;td&gt;1745.436975&lt;/td&gt;
      &lt;td&gt;~13 minutes = 780s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Optimism&lt;/td&gt;
      &lt;td&gt;0.002721&lt;/td&gt;
      &lt;td&gt;5731.428571&lt;/td&gt;
      &lt;td&gt;~13 minutes = 780s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Polygon&lt;/td&gt;
      &lt;td&gt;0.007612&lt;/td&gt;
      &lt;td&gt;602.18273&lt;/td&gt;
      &lt;td&gt;~8 minutes = 480s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;以上成本还需加上Solana Mint Tx 的 Gas Fee， 约为0.0000675 SOL = $0.00995 USD。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="CryptoCurrency" />
      
        <category term="USDC" />
      
        <category term="CCTP" />
      
        <category term="Bridge" />
      
        <category term="Solana" />
      
        <category term="Ethereum" />
      
        <category term="Arbitrum" />
      
        <category term="Optimism" />
      
        <category term="Avalanche" />
      

      
        <summary type="html">背景</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Chia 折腾手记</title>
      
      
      <link href="https://umi.cat/2021/06/13/chia-mining-records/" rel="alternate" type="text/html" title="Chia 折腾手记" />
      
      <published>2021-06-13T02:49:59+00:00</published>
      <updated>2021-06-13T02:49:59+00:00</updated>
      <id>https://umi.cat/2021/06/13/chia-mining-records</id>
      <content type="html" xml:base="https://umi.cat/2021/06/13/chia-mining-records/">&lt;h1 id=&quot;前言&quot;&gt;前言&lt;/h1&gt;

&lt;p&gt;大约有一年时间没有写博客了，这段时间经历了很多事情，自己的生活也发生了很多以前没有想过的变化。一年间，主要的精力除了上班码代码之外，基本上都花在了投机市场当中。挣了不少钱，也亏了不少钱，但让我感到有些意思的，是这个 Chia 项目，想着如果不写一下的话，之后大约会忘记，于是就此执笔。&lt;/p&gt;

&lt;h1 id=&quot;什么是-chia-&quot;&gt;什么是 Chia ?&lt;/h1&gt;

&lt;p&gt;Chia 是一个新的区块链系统，是由 BitTorrent 之父 Bram Cohen 创立的。创立之初是觉得比特币太浪费电了（感觉这说法并不怎么靠谱），于是想搞个绿色数字货币，用硬盘来挖矿。 XCH 是 Chia 区块链系统中的代币，类比的话，大概相当于 XBT。对于 Chia 画下的大饼（智能合约、Chialisp等等）暂时按下不表，先说说他的挖矿，他的挖矿原理其实跟市面上的 FIL 挖矿不太一样，具体来说，分两步。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;第一步：计算 Plot 文件（俗称 P 盘），这个过程会使用一种特殊函数（Verifiable Delay Function），根据提供的 Farmer public key 与 Pool public key 预计算一批数字。在计算过程中，需要一块高速缓存盘用于存放临时计算数据，官方推荐 SSD 作为缓存盘。由于 SSD 具有 TBW (Terabytes Written，TB写入量) 的寿命，因此该过程实质上需要消耗大量 SSD。此外，对于 CPU 也有一定要求，CPU cache越大的话，速度也就越快。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;第二步：挖矿。与比特币挖矿类似，Chia 区块链的出块权利由应答 Challenge 成功的节点获得。但与比特币不一样的是，Challenge 的结果并不是由矿机计算出来的。取而代之的是，矿机会去扫描所有 Plot 文件，如果里面有能响应 Challenge 的 Plot 文件，则该 Plot 文件对应的 Public Key 获得该区块的打包权利与其对应的奖励。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chia 的初心是想让大家用闲置的硬盘去 P 盘，并使用这些 Plot 文件去维护 Chia 区块链的稳定性。想法是好的，但在Chia 主网开启的两个月过程中，实际上算力还是逐渐向寡头集结的。截止至2021年5月14日，HPool 的 Chia 矿池算力已经达到2279PB，已经达到了全网的50%。&lt;/p&gt;

&lt;h1 id=&quot;投机&quot;&gt;投机&lt;/h1&gt;

&lt;p&gt;Chia 的主网启动时间是 3 月 19 日， 我大约是 20 日知道的这个消息。 忘记是出于什么原因，总之就是想开始折腾，于是 21 号在研究了一番之后，往 OVHCloud 下了第一单测试机。&lt;/p&gt;

&lt;h2 id=&quot;一独立服务器挖矿&quot;&gt;一、独立服务器挖矿&lt;/h2&gt;

&lt;p&gt;最开始的想法很单纯，当时主网算力增速较缓，在一番计算过后我发现，如果 Chia 币能维持在 50 美元的话，大概一个月便能收回成本。由于转账功能在 5 月 4 日才开放，本质上是在赌这个币是否能成功，于是我自己并没有花很多钱投入。最后是租了大概三台 P 盘机器，两台 48 T 的存储机器，花了大概一个月时间填满。这期间 SOLO + 矿池断断续续挖了大约 72 个币，使用的解决方案是笨拙的 rsync + bash。原理很简单，写一个监控程序将 P 盘机器中已经 P 完的文件实时传输到存储机的硬盘中，这中间为了加速传输的速度，还购买了 OVHCloud 的 Private bandwidth (虽然最后也好像没有快多少)。&lt;/p&gt;

&lt;h2 id=&quot;二云挖矿的尝试&quot;&gt;二、云挖矿的尝试&lt;/h2&gt;

&lt;p&gt;由于瓶颈实际上是在 CPU 上，对于优化的方向，最开始我是想，如果能优化这个算法，提升多线程利用率就好了。在阅读完 chiapos 的源代码之后，感觉优化源代码这个方向的性价比实在太低，于是放弃，决定转向以量取胜，遂开始研究各大云厂商的产品。当时的想法是，Chia 挖矿原理无非是扫盘中的数据进行应答，并且扫盘不可能扫全部的文件内容，所以 OSS 是非常适合这项任务的，再加上云服务器的 CPU 比自己买实体矿机更是要划算许多。核心的思想也非常简单，使用 fuse 将 OSS mount 成系统的一个盘符即可。&lt;/p&gt;

&lt;h3 id=&quot;aws&quot;&gt;AWS&lt;/h3&gt;

&lt;p&gt;(题外话：在我调研完 AWS 大约一个月后， AWS官方曾短暂放出过一篇 Chia on AWS 的教程，但之后估计因为合规问题删除了，原链接为：https://aws.amazon.com/cn/campaigns/chia-solution/ ，仍然能通过 archive.org 查看)
第一站当然是先调研了 AWS 的 S3 与自家 EC2 的契合度，在经过测试后发现，虽然 AWS 不愧是云服务商的中流砥柱，但价格上相对来说也比较贵，于是放弃。&lt;/p&gt;

&lt;h3 id=&quot;gcp--gcs&quot;&gt;GCP + GCS&lt;/h3&gt;

&lt;p&gt;那么谷歌又如何呢？经过研究之后发现，谷歌有一个抢占式实例的服务，这个抢占式实例跟 AWS on demand 差不多，都可以让你用更低（谷歌基本上是半价，AWS则是2折起）运行一个实例，但谷歌的这个实例没有办法自己报价，而且只能运行24小时，但这对我来说并没有什么影响。在前面的benchmark中我计算过，用最低配机器（N2-2vCPU,8G,1Local SSD）跑一个100 G的文件大约是8小时，在谷歌云最便宜的区域us-central1跑折算下来每T只要6.6美元。&lt;/p&gt;

&lt;p&gt;存储方面，一开始，我曾经想使用 Google Drive，但后来发现 GD 并不支持随机读取，这就导致不可能使用 GD 进行 挖矿，因为如果你想读一个文件的中间部分，也需要把一个100G文件下载下来，这显然不现实。后来就直接选用了谷歌自家的 GCS ，GCS 的收费依据文件的存储时间分四个档次，存储越久的文件，价格越低，但与之相对的，读取文件的价格也越贵。刚开始我选择的是存储最久的 ARCHIVE，事实证明这并不是一个最佳选择，在经过成本核算后改成了 CODELINE。&lt;/p&gt;

&lt;p&gt;技术方案中，选择了最稳妥的 gcsfuse，大致运行流程也很简单：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;新建一个虚拟机，把自动脚本调试完成，确保这个虚拟机一开机就开始进行 P 盘并上传到 GCS 指定 bucket 中，在这个阶段，我使用的是 rclone。有一点需要注意的是，实例默认创建时是没有 gcs 的权限的，如果遇到权限问题，不妨再检查一下虚拟机对 API 的权限设置。&lt;/li&gt;
  &lt;li&gt;新建一个虚拟机模版，原型镜像就选上面那个虚拟机，然后把实例类型改为抢占式实例。&lt;/li&gt;
  &lt;li&gt;新建一个实例组，然后拉满起飞。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;由于实例组会帮我们自动维护实例的生命周期，所以如果一个文件完成上传，或者因为抢占式实例被关闭，也能自动重启打开，这就完成了 P 盘第一步。&lt;/p&gt;

&lt;p&gt;挖矿方面，也有一些坑需要注意的。&lt;/p&gt;

&lt;p&gt;第一个问题就是在bucket的文件超过 500 T 之后，可能经常会遇到超时的问题。&lt;/p&gt;

&lt;p&gt;首先，需要把gcsfuse的http2关闭，这是第一个坑，但因为比较少人复现，gcsfuse的issue中并没有人解决这个问题，后来经过debug发现就是http2的问题。&lt;/p&gt;

&lt;p&gt;在解决了 http2 后，扫盘也会间歇性的超时，这个问题无法避免，我一开始采用的方案是分 bucket 放文件，后来改了一下 gcsfuse，让每个被 mount 的 bucket 可以有不同的 offset，解决了问题。&lt;/p&gt;

&lt;p&gt;最后在折腾了半个月后，我的最终解决方案是 docker + hpool的挖矿程序，每个文件夹独立分配一个docker的容器，然而这个时候 xch 已经从 每 PB 10个 xch 跌落到 0.33 个 xch 了。&lt;/p&gt;

&lt;h1 id=&quot;假算力&quot;&gt;假算力&lt;/h1&gt;

&lt;p&gt;// TODO&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="Chia" />
      
        <category term="Blockchain" />
      
        <category term="CryptoCurrency" />
      

      
        <summary type="html">前言</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Secure key establishment and management</title>
      
      
      <link href="https://umi.cat/2020/04/29/secure-key-establishment-and-management/" rel="alternate" type="text/html" title="Secure key establishment and management" />
      
      <published>2020-04-29T07:30:59+00:00</published>
      <updated>2020-04-29T07:30:59+00:00</updated>
      <id>https://umi.cat/2020/04/29/secure-key-establishment-and-management</id>
      <content type="html" xml:base="https://umi.cat/2020/04/29/secure-key-establishment-and-management/">&lt;h1 id=&quot;agenda&quot;&gt;Agenda&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;Ad Hoc Network Key Establishment&lt;/li&gt;
  &lt;li&gt;Key Distribution in Large-scale Network&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;ad-hoc-network-key-establishment&quot;&gt;Ad Hoc Network Key Establishment&lt;/h1&gt;

&lt;h2 id=&quot;what-is-ad-hoc-network&quot;&gt;What is Ad hoc network?&lt;/h2&gt;

&lt;p&gt;In a ad hoc network, each device acts as a router.
Anyone can join and leave in the middle. The range, location of them can be totally different.
It is almost impossible to predict the structure of network. 
We need to run a routing protocol to discover the path through network. 
The resources in those node usually has few resources.&lt;/p&gt;

&lt;h2 id=&quot;ad-hoc-network-properties&quot;&gt;Ad hoc network properties&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Mobile&lt;/li&gt;
  &lt;li&gt;Wireless communication&lt;/li&gt;
  &lt;li&gt;No fixed infrastructure&lt;/li&gt;
  &lt;li&gt;Participants from different administrative domains&lt;/li&gt;
  &lt;li&gt;Medium to high computation, memory&lt;/li&gt;
  &lt;li&gt;Usually human user with each device&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;typical-key-establishment&quot;&gt;Typical Key Establishment&lt;/h2&gt;

&lt;h3 id=&quot;ssltls&quot;&gt;SSL/TLS&lt;/h3&gt;

&lt;p&gt;Assumption: Browser can authenticate server’s certificate with its local CA root certificates&lt;/p&gt;

&lt;h3 id=&quot;large-group-key-distribution&quot;&gt;Large-group key distribution&lt;/h3&gt;

&lt;p&gt;Assumption: Each client already has a secure connection to key distribution server&lt;/p&gt;

&lt;p&gt;The challenge in ad hoc networks: establish keys without any prior trust relationships&lt;/p&gt;

&lt;h2 id=&quot;problem-definition&quot;&gt;Problem definition&lt;/h2&gt;

&lt;h3 id=&quot;goals&quot;&gt;Goals&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Secure, authenticated communication between devices that share no prior context&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Demonstractive identification&lt;/em&gt;: ensure to human user which other device they are communicating with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if I have an Apple device and I walk to a room which contains an Epson projector. It is hard to tell whether the projector is the one that I want to connect. There may exists another Epson projector in other room which hijacks and relays the connection.&lt;/p&gt;

&lt;h3 id=&quot;conditions&quot;&gt;Conditions&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;No CAs or other trusted authorities&lt;/li&gt;
  &lt;li&gt;No PKI&lt;/li&gt;
  &lt;li&gt;No shared secrets&lt;/li&gt;
  &lt;li&gt;No shared communication history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem reduces to key establishment.&lt;/p&gt;

&lt;p&gt;Diffie &amp;amp; Hellman tells us how to share secret.&lt;/p&gt;

&lt;h3 id=&quot;diffie-hellman-key-agreement&quot;&gt;Diffie-Hellman Key Agreement&lt;/h3&gt;

&lt;p&gt;Public values: large prime $p$, generator $g$&lt;/p&gt;

&lt;p&gt;Alice has secret $a$, Bob has secret $b$&lt;/p&gt;

&lt;p&gt;A -&amp;gt; B: $g^a mod p$&lt;/p&gt;

&lt;p&gt;B -&amp;gt; A: $g^b mod p$&lt;/p&gt;

&lt;p&gt;Bob: ${(g^a mod p)}^b mod p = g^{ab} mod p$&lt;/p&gt;

&lt;p&gt;Alice: ${g^b mod p}^a mod p = g^{ab} mod p$&lt;/p&gt;

&lt;p&gt;$g^{ab} mod p$ is the final key.&lt;/p&gt;

&lt;p&gt;Eve cannot compute $g^{ab} mod p$, even she observe all messages.&lt;/p&gt;

&lt;p&gt;But we are not done. The problem is Man-in-the-middle attack.&lt;/p&gt;

&lt;h3 id=&quot;mitm-attack&quot;&gt;MitM Attack&lt;/h3&gt;

&lt;p&gt;Mallory can impersonate Alice to Bob, and impersonate Bob to Alice.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     g^a        g^m2
A --------&amp;gt; M --------&amp;gt; B
  &amp;lt;-------    &amp;lt;--------
   g^m1   m1,m2  g^b

   g^am1         g^bm2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;B can listen this message, since it is a boardcast message.&lt;/p&gt;

&lt;p&gt;By the time when M is sending the impersonated message, B may said he is already received this message.&lt;/p&gt;

&lt;p&gt;How does M prevent it?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ARP posioning. When M send ARP message, A think M is B and B think M is A.&lt;/li&gt;
  &lt;li&gt;Change wireless channel. KRACK attack (2018). The attacker forces A to use channel 1 and B to use channel 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;how-serious-is-mitm-attack&quot;&gt;How serious is MitM attack?&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Wireless communication is invisible
    &lt;ul&gt;
      &lt;li&gt;People can’t tell which devices are connected&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Neighbor can easily execute MitM attack
    &lt;ul&gt;
      &lt;li&gt;If neighbor has a faster computer, it can easily respond faster than the legitimate devices&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Easy to perform with high success rate.&lt;/p&gt;

&lt;h4 id=&quot;solution-to-mitm-attack&quot;&gt;Solution to MitM attack&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Authentication&lt;/li&gt;
  &lt;li&gt;Public DH values must be authenticated&lt;/li&gt;
  &lt;li&gt;Tradeoffs between security, usability, and transparency to the user
    &lt;ul&gt;
      &lt;li&gt;Transparency
        &lt;ul&gt;
          &lt;li&gt;Does the user realize she is involved in a key establishment protocol?&lt;/li&gt;
          &lt;li&gt;Does the user need to realize this?&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;key-agreement-in-p2p-wiresless-networks&quot;&gt;Key Agreement in P2P Wiresless Networks&lt;/h1&gt;

&lt;p&gt;Source: Key agreement in peer-to-peer wireless networks. Mario Cagalj, Srdjan Capkun, Jean-Pierre Hubaux.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use Diffie-Hellman to establish keys&lt;/li&gt;
  &lt;li&gt;Present three techniques to combat MitM
    &lt;ul&gt;
      &lt;li&gt;Visual comparison of short strings&lt;/li&gt;
      &lt;li&gt;Distance bounding&lt;/li&gt;
      &lt;li&gt;Integrity codes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;All 3 verify the integrity of DH public parameters $g^A$ and $g^B$&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;commitment-schemes&quot;&gt;Commitment schemes&lt;/h2&gt;

&lt;p&gt;Commitment semantics&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Binding&lt;/li&gt;
  &lt;li&gt;Hiding&lt;/li&gt;
&lt;/ul&gt;

\[(c, d) &amp;lt;- commit(m)\]

&lt;p&gt;m: message; c: commitment; d: opening value&lt;/p&gt;

&lt;p&gt;A want to commit the message, but doesn’t weant to reveal the message. So A send $c$ first to B, and send $d$ after. By sending $d$, A is revealing the message $m$, and also B knows A is commiting the message $m$ by $c$.&lt;/p&gt;

&lt;p&gt;Given $c$, infeasible to find the decommitment $d’$&lt;/p&gt;

&lt;p&gt;It is infeasible to find $d’$ s.t. $(c, d’)$ reveals $m’ \neq m$&lt;/p&gt;

&lt;p&gt;Example&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;$c=H(m&lt;/td&gt;
          &lt;td&gt; &lt;/td&gt;
          &lt;td&gt;r)$ where $r$ is a random number&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;$d = m,r$&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;simple-protocol-string-comparison&quot;&gt;Simple Protocol: String Comparison&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Public values: large prime $p$, generator $g$&lt;/li&gt;
  &lt;li&gt;Alice has secret $a$, Bob has secret $b$&lt;/li&gt;
  &lt;li&gt;A -&amp;gt; B: $g^a mod p$&lt;/li&gt;
  &lt;li&gt;B -&amp;gt; A: $g^b mod p$&lt;/li&gt;
  &lt;li&gt;Alice and Bob computer: $g^{ab} mod p$&lt;/li&gt;
  &lt;li&gt;Alice’s and Bob’s devices display last 20 bits of $H(g^{ab} mod p)$ and they manually compare them (5 hexadecimal digits), if they match, the both click “ok”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is it a secure protocol?&lt;/p&gt;

&lt;p&gt;No! Birthday paradox.&lt;/p&gt;

&lt;h4 id=&quot;shortcomings-of-simple-protocol&quot;&gt;Shortcomings of Simple Protocol&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;First, Alice and Bob may not really compare the strings, but simply click “ok”, how to avoid this?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Knowing $g^a$ and $g^b$, attack can computer $g^c$ and $g^d$ such that $H(g^{ac})&lt;em&gt;{n} = H(g^{bd})&lt;/em&gt;{n}$&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Complexity: Only $ O(2^{n/2}) $, around 1000.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="Network" />
      
        <category term="Security" />
      

      
        <summary type="html">Agenda Ad Hoc Network Key Establishment Key Distribution in Large-scale Network</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">iOS 越狱插件开发</title>
      
      
      <link href="https://umi.cat/2020/04/29/ios-jailbreak-development/" rel="alternate" type="text/html" title="iOS 越狱插件开发" />
      
      <published>2020-04-29T07:30:59+00:00</published>
      <updated>2020-04-29T07:30:59+00:00</updated>
      <id>https://umi.cat/2020/04/29/ios-jailbreak-development</id>
      <content type="html" xml:base="https://umi.cat/2020/04/29/ios-jailbreak-development/">&lt;p&gt;https://stackoverflow.com/questions/18776718/jailbreak-app-how-can-i-distribute-my-app-which-need-to-be-install-in-applicat&lt;/p&gt;

&lt;p&gt;https://stackoverflow.com/questions/9261945/ios-explore-other-application-folder-with-jailbreak&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="iOS" />
      
        <category term="Security" />
      
        <category term="Jailbreak" />
      

      
        <summary type="html">https://stackoverflow.com/questions/18776718/jailbreak-app-how-can-i-distribute-my-app-which-need-to-be-install-in-applicat</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">iOS Nintendo Switch Online app 闪退的解决方法</title>
      
      
      <link href="https://umi.cat/2020/03/29/nintendo-switch-online-ios-app-jailbreak-detection/" rel="alternate" type="text/html" title="iOS Nintendo Switch Online app 闪退的解决方法" />
      
      <published>2020-03-29T09:49:59+00:00</published>
      <updated>2020-03-29T09:49:59+00:00</updated>
      <id>https://umi.cat/2020/03/29/nintendo-switch-online-ios-app-jailbreak-detection</id>
      <content type="html" xml:base="https://umi.cat/2020/03/29/nintendo-switch-online-ios-app-jailbreak-detection/">&lt;p&gt;任天堂的 iOS 手机 app Nintendo Switch Online 具有与 switch 联动的功能，但鉴于任天堂一贯对黑客精神的严防，这个 app 在 iOS 上实行了非常严格的越狱检测，甚至连你重启恢复未越狱状态也不行，各种反越狱检测插件自然也不行。&lt;/p&gt;

&lt;p&gt;研究了一会，发现唯一的办法就是安装 SnapBack 插件，恢复被越狱修改的 rootfs 分区。
具体操作很简单，先安装 SnapBack 插件，然后点击右上角的 + 号创建一个 APFS 快照，然后回退到原始orig-fs中，此时 SnapBack 会进行一段进度条，进度条结束后会黑屏，退出 SnapBack 你会发现所有越狱 app 的名字都消失了，此时直接打开 app 即可。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="iPhone" />
      
        <category term="jailbreak" />
      
        <category term="nintendo" />
      

      
        <summary type="html">任天堂的 iOS 手机 app Nintendo Switch Online 具有与 switch 联动的功能，但鉴于任天堂一贯对黑客精神的严防，这个 app 在 iOS 上实行了非常严格的越狱检测，甚至连你重启恢复未越狱状态也不行，各种反越狱检测插件自然也不行。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">iOS 越狱史及技术简析 - iOS 2</title>
      
      
      <link href="https://umi.cat/2019/12/15/jailbreak-history-iOS2/" rel="alternate" type="text/html" title="iOS 越狱史及技术简析 - iOS 2" />
      
      <published>2019-12-15T20:15:59+00:00</published>
      <updated>2019-12-15T20:15:59+00:00</updated>
      <id>https://umi.cat/2019/12/15/jailbreak-history-iOS2</id>
      <content type="html" xml:base="https://umi.cat/2019/12/15/jailbreak-history-iOS2/">&lt;h1 id=&quot;回顾&quot;&gt;回顾&lt;/h1&gt;

&lt;p&gt;在上一篇文章中，我们已经提到了苹果对 iOS 1 的安全保护正在一步一步进化中。截止 iOS 1.1.5，从上至下层级排列，iOS 的安全措施如下&lt;/p&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;Secure Boot&lt;/td&gt;
      &lt;td&gt;iOS 1.0&lt;/td&gt;
      &lt;td&gt;启动链的每个环节都会负责验证下一阶段的签名&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;fsroot 只读&lt;/td&gt;
      &lt;td&gt;iOS 1.0&lt;/td&gt;
      &lt;td&gt;系统盘 /dev/disk0s1 默认是只读的&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;AFC Restriction&lt;/td&gt;
      &lt;td&gt;iOS 1.0&lt;/td&gt;
      &lt;td&gt;iPhone 通过 AFC 服务与电脑进行数据交换，这个服务默认只允许宿主机访问&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Media&lt;/code&gt;目录&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;固件加密&lt;/td&gt;
      &lt;td&gt;iOS 1.1&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IMG2&lt;/code&gt;格式的系统固件通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Key 0x837&lt;/code&gt;被加密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;mobile 用户&lt;/td&gt;
      &lt;td&gt;iOS 1.1.3&lt;/td&gt;
      &lt;td&gt;在此之前，所用应用程序均使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;权限运行&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;随后，2008 年 7 月 1 日， 苹果推出了 iOS 2 更新，同时推出了 iPhone 3G，更重要的是，App Store 开始内置在 iPhone 内，这意味着用户可以自己下载并安装应用程序了。相对应的，iOS 新增了以下安全机制:&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="iPhone" />
      
        <category term="jailbreak" />
      

      
        <summary type="html">回顾</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">iOS 越狱史及技术简析 - iPhone OS (iOS 1)</title>
      
      
      <link href="https://umi.cat/2019/12/13/jailbreak-history-iOS1/" rel="alternate" type="text/html" title="iOS 越狱史及技术简析 - iPhone OS (iOS 1)" />
      
      <published>2019-12-13T05:27:59+00:00</published>
      <updated>2019-12-13T05:27:59+00:00</updated>
      <id>https://umi.cat/2019/12/13/jailbreak-history-iOS1</id>
      <content type="html" xml:base="https://umi.cat/2019/12/13/jailbreak-history-iOS1/">&lt;p&gt;本文是对自己这么多年以来对 iPhone 越狱学习的一个总结。&lt;/p&gt;

&lt;p&gt;总是谈越狱越狱，结果自己连基本核心都没有搞太懂，于是就想从技术角度回顾一下越狱这么多年都做了些什么，也希望能帮到有相同兴趣的人。&lt;/p&gt;

&lt;h1 id=&quot;iphone-os-ios-10---2007-年-10-月&quot;&gt;iPhone OS (iOS 1.0) - 2007 年 10 月&lt;/h1&gt;
&lt;p&gt;当时，iOS 还被叫做 iPhone OS ，预装在 iPhone 第一代里面。没有 App Store，只有一些基础应用，当然，也没有办法安装新的应用。&lt;/p&gt;

&lt;p&gt;苹果一开始的想法是用户只需要使用 Safari 访问 HTML5 应用就够了，所以他们并没有提供 iPhone SDK。这个阶段越狱团队的工作一方面是逆向 iPhone 自带的应用程序，搞清楚 iPhone 原生应用程序是如何工作的，然后提供一套工具链用于开发自制的第三方应用&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;（事实证明，后来苹果发布的 SDK 就是这套东西），一方面是取得系统 root 权限，然后安装自制铃声和应用程序。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;一个远古&lt;a href=&quot;https://github.com/planetbeing/iphonecommunity/blob/44ab6523fe8acb5b176b15960078c69f2ed2a43b/Upgrade.app-113/sources/UpgradeApplication.m&quot;&gt;第三方自制程序&lt;/a&gt;是这样写的&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#import &amp;lt;CoreFoundation/CoreFoundation.h&amp;gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;
#import &amp;lt;UIKit/UITableColumn.h&amp;gt;
#import &amp;lt;UIKit/UISwitchControl.h&amp;gt;
#import &amp;lt;UIKit/UIAlertSheet.h&amp;gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;progressCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formatString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UpgradeApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myApp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UpgradeApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myApp&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doProgress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;progress&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;withTotal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withFormat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formatString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UpgradeApplication&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;applicationDidFinishLaunching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unused&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UIWindow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UIView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mainView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CGRect&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个时候的 iPhone 的安全机制如下:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;安全引导链（每个引导环节，都会由上一个引导环节检查签名，但bootrom此时不会检查LLB的签名&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;）&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fsboot&lt;/code&gt; 默认只读&lt;/li&gt;
  &lt;li&gt;AFC 默认只能访问并读写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Media&lt;/code&gt;（即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media&lt;/code&gt;)&lt;sup id=&quot;fnref:2:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;lockdownd 激活锁，防止第三方运营商 SIM 卡使用 iPhone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所有应用程序都放在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Application&lt;/code&gt;下，并默认以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;权限执行，没有代码签名，甚至刷机不会校验 SHSH（iPhone 一代），这意味着你可以随便降级，所以在这个阶段，越狱实际上是非常简单的。&lt;/p&gt;

&lt;h2 id=&quot;iboot-cp-command&quot;&gt;iBoot cp-command&lt;/h2&gt;

&lt;p&gt;iOS 版本: iOS 1.0 - iOS 1.0.2&lt;/p&gt;

&lt;p&gt;利用软件: iBrickr (Windows) / AppTapp Installer (Mac OS X)&lt;/p&gt;

&lt;p&gt;严格意义上来说，这并不算一个漏洞，而更像是一个 feature。起因是 Apple 并没有删除恢复模式中的很多命令，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;流程大致如下：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;让设备进入恢复模式，从固件中找出 Restore Ramdisk 和 kernelcache，然后上传到设备上。&lt;/li&gt;
  &lt;li&gt;创建两个文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/fstab&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/Services.plist&lt;/code&gt;，后者会创建一个新的服务&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;com.apple.afc2&lt;/code&gt;，允许通过AFC访问所有文件目录。&lt;/li&gt;
  &lt;li&gt;将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk0s1&lt;/code&gt; 挂载到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt1&lt;/code&gt;，用户数据&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk0s2&lt;/code&gt;挂载到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt2&lt;/code&gt;，然后把我们上一步创建的两个文件用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt;分别替换掉&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt1/etc/fstab&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mnt1/System/Library/Lockdown/Services.plist&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;iBrickr 还会安装 PXLDaemon 守护进程，这个守护进程可以与电脑端 iBrickr 通信，安装第三方软件包，替换铃声等等。而 AppTapp Install 则会安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Installer.app&lt;/code&gt;，其功能与前者大致相同。&lt;/li&gt;
  &lt;li&gt;重启完成越狱。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;修复：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;在 iOS 1.0.2 后更新 iBoot，删除了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt;以及其他一些命令。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;libtiff-exploit-cve-2006-3459&quot;&gt;libtiff-exploit (CVE-2006-3459)&lt;/h2&gt;

&lt;p&gt;iOS 版本: iOS 1.0 - iOS 1.1.1&lt;/p&gt;

&lt;p&gt;利用软件: AppSnapp / JailbreakMe  1.0&lt;/p&gt;

&lt;p&gt;核心原理是经典的 buffer overflow — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtiff&lt;/code&gt; 在处理 tiff 文件的时候会发生 buffer overflow，允许任意代码执行，只需要让用户访问一个含有tiff图片的网站就可以完成越狱。&lt;/p&gt;

&lt;p&gt;碰巧的是，当年 PSP 也饱受 tiff 漏洞的&lt;a href=&quot;https://www.youtube.com/watch?v=WRWJtI-HzpY&quot;&gt;摧残&lt;/a&gt;，这个漏洞应该是从 PSP 的破解中收到了启发。&lt;/p&gt;

&lt;p&gt;shellcode 做了一些微小的工作:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;将&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media&lt;/code&gt;重命名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/oldMedia&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;创建符号链接&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/ -&amp;gt; /&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;重新挂载&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk0s1&lt;/code&gt;为读写&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r0 = &quot;/var/root/Media&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r1 = &quot;/var/root/Oldmedia&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BYTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// r2,r3,r5,r6,r12&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// sp    -&amp;gt; offset 12&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ldmia_sp_r4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;// lr = load r4,r7,pc from sp&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;// pc = rename(r0, r1)&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r0 = &quot;/&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r1 = &quot;/var/root/Media&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BYTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// r2,r3,r5,r6,r12&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// sp -&amp;gt; offset 12&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ldmia_sp_r0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;// lr = load from r0..pc from sp&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;symlink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;// pc = symlink(r0, r1)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r0 = &quot;hfs&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// r1 = &quot;/&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x00050000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// r2 = MNT_RELOAD | MNT_UPDATE&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STACK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// r3 = **data&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;// pc = mount(r0, r1, r2, r3)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// data = &quot;/dev/disk0s1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;完整代码可以在&lt;a href=&quot;https://github.com/OpenJailbreak/JailbreakMe-1.0/blob/master/tiff_exploit.cpp&quot;&gt;这里&lt;/a&gt;看到。&lt;/p&gt;

&lt;p&gt;修复：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;更新 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtiff&lt;/code&gt; 库。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;mknod-vulnerability&quot;&gt;mknod-vulnerability&lt;/h2&gt;

&lt;p&gt;iOS 版本: iOS 1.1.2&lt;/p&gt;

&lt;p&gt;利用软件： OktoPrep + &lt;a href=&quot;https://github.com/planetbeing/touchfree&quot;&gt;touchFree&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;iOS 1.1.2 版本之后，Apple 修复了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtiff&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iBoot cp-command&lt;/code&gt; 的漏洞，然而，因为前文所提到的，iPhone 第一代可以随便刷机，所以新版的方法也很简单粗暴：先在 iOS 1.1.1 动手脚，然后升级到 iOS 1.1.2 继续搞事情。&lt;/p&gt;

&lt;p&gt;具体来说：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;在 iPhone 升级之前，OktoPrep 使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mknod /var/root/Media/disk c 14 1&lt;/code&gt;直接在用户盘符创建一个字符设备，这句命令的意思是，为主设备号是14，次设备号是1的设备创建一个在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/disk&lt;/code&gt;的字符设备，这等同于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/rdisk0s1&lt;/code&gt;。（可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls -lR /dev&lt;/code&gt;查看主次设备号）&lt;/li&gt;
  &lt;li&gt;升级系统到 iOS 1.1.2，由于升级系统只更改fsroot，而我们创建的文件在用户数据分区中，所以不受影响。&lt;/li&gt;
  &lt;li&gt;touchFree 检查 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/disk&lt;/code&gt; 是否存在，然后创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/touchFree&lt;/code&gt;文件夹，复制必要文件到此文件夹中。&lt;/li&gt;
  &lt;li&gt;将&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/disk&lt;/code&gt;dump为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rdisk0s1.dmg&lt;/code&gt;，挂载这个dmg文件，修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;往&lt;a href=&quot;https://github.com/planetbeing/touchfree/blob/f01e306513fd01c678d6e639ac53692daf6b4383/java/resources/required/com.apple.syslogd.new.plist&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;com.apple.syslogd.plist&lt;/code&gt;&lt;/a&gt;里面添加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DYLD_INSERT_LIBRARIES:/var/root/Media/touchFree/planetbeing.dylib&lt;/code&gt;环境变量键值对（熟悉逆向的朋友们可能已经猜到了，没错，syslogd在下一次执行的时候会首先被注入这个动态库。）&lt;/li&gt;
  &lt;li&gt;动态库会将touchFree文件夹里的东西复制到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin&lt;/code&gt;，创建 AFC2 服务，运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/root/Media/touchFree/run.sh&lt;/code&gt;脚本，然后把自己的注入环境变量删掉。&lt;/li&gt;
  &lt;li&gt;脚本会继续复制&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Installer.app&lt;/code&gt;和ssh服务，然后给Springboard和lockdown打补丁。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中，Springboard 补丁是因为当时 Springboard 显示的程序是写死在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowedDisplayIcons&lt;/code&gt;里的，所以需要给&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[SBIconModel addItemsToIconList: fromPath: withTags:]&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; [SBIconController relayoutIcons]&lt;/code&gt;里面打补丁，让&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Installer.app&lt;/code&gt;能显示在主屏幕，而lockdown的补丁主要是绕过iPhone激活锁。&lt;/p&gt;

&lt;p&gt;修复:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/rdisk0s1&lt;/code&gt;被加上了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodev&lt;/code&gt;，所以不能再用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mknod&lt;/code&gt;创建它的设备文件了。&lt;/p&gt;

&lt;h2 id=&quot;ramdisk-hack&quot;&gt;Ramdisk Hack&lt;/h2&gt;

&lt;p&gt;iOS 版本: iOS 1.1.3 - 1.1.5&lt;/p&gt;

&lt;p&gt;利用软件: &lt;a href=&quot;https://github.com/Zibri/ZiPhone/&quot;&gt;ZiPhone&lt;/a&gt; &amp;amp; iLiberty&lt;/p&gt;

&lt;p&gt;从 iOS 1.1 开始，iPhone 新增了以下安全机制:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;新增&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mobile&lt;/code&gt;用户，大部分进程都开始以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mobile&lt;/code&gt;权限运行。（iOS 1.1.3）&lt;/li&gt;
  &lt;li&gt;所有固件都被&lt;a href=&quot;https://www.theiphonewiki.com/wiki/AES_Keys#Key_0x837&quot;&gt;Key 0x837&lt;/a&gt;加密了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这意味着即使应用出现了 libtiff 的 userland 漏洞，也不再能一招吃遍天了。&lt;/p&gt;

&lt;p&gt;这次出现的漏洞还是在恢复模式中。之前 Apple 把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt; 之类的调试命令删掉了，但是，他们还留了一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boot-args&lt;/code&gt;环境变量。我们知道，恢复模式需要挂载一个 Ramdisk，这个 Ramdisk 在一般情况下是需要验证签名的。但如果 Ramdisk 的内存地址超过了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x09C00000&lt;/code&gt;，则无论什么情况下都会启动。&lt;/p&gt;

&lt;p&gt;这回我们轻车熟路了，以&lt;a href=&quot;https://github.com/Zibri/ZiPhone/blob/d7dca81b2707fe962f116b23bface18de88f4351/ziphone.cpp&quot;&gt;ZiPhone&lt;/a&gt;为例：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;AFC 复制必要文件到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/mobile/Media&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;重启进入恢复模式，设置引导环境变量&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setenv boot-args rd=md0 -s -x pmd0=0x09CC2000.0x0133D000&lt;/code&gt;（以单用户模式、安全模式启动）&lt;/li&gt;
  &lt;li&gt;发送&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bootx&lt;/code&gt;，让 iPhone 从 Ramdisk 启动&lt;/li&gt;
  &lt;li&gt;Ramdisk 首先挂载&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk0s1&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk0s2&lt;/code&gt;，然后复制一些必要的文件，同时修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt;，开机启动&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prof.sh&lt;/code&gt;
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/usr/bin/nvram jailbreak 2&amp;gt;/dev/null|/bin/cut &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; 2&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
/bin/echo &lt;span class=&quot;s2&quot;&gt;&quot;Starting jailbreak...&quot;&lt;/span&gt;
/bin/cp /bin/sh /mnt1/bin/sh
/bin/cp /bin/sync /mnt1/bin/sync
/bin/cp /bin/rm /mnt1/bin/rm
/bin/cp /zib/prof.sh /mnt1/private/etc/profile
/bin/cp /zib/fstab /mnt1/private/etc/fstab
…
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;重启，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prof.sh&lt;/code&gt;会完成之后的一系列操作，比如给Springboard打补丁什么的。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;修复:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boot-args&lt;/code&gt;从iOS 2.0开始，在生产环境中不生效。（这一点可以从 iBoot 泄露的源码中看出）&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// iBoot/apps/iBoot/main.c&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;env_blacklist_nvram&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whitelist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#if DEVELOPMENT_BUILD || DEBUG_BUILD
&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;boot-args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// factory needs to set boot-args&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;本文回顾了 iPhone OS 中大部分已经公开并使用的越狱工具与他们的利用方法，以及苹果的修补方法。&lt;/p&gt;

&lt;p&gt;虽然 iPhone OS 离我们已经有一轮年头了，但从上面的做的事情中，我们可以看出，实际上，越狱所做的东西还是没有变化太多。&lt;/p&gt;

&lt;p&gt;就以本文所有越狱工具为例，基本上就做这么几件事:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fstab&lt;/code&gt;，挂载系统盘为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rw&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;安装一个软件包管理器(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Installer.app&lt;/code&gt;)，然后安装第三方软件&lt;/li&gt;
  &lt;li&gt;给系统打补丁（解锁，换壁纸，铃声）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;为了做这些事情，我们需要:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;修改系统文件&lt;/li&gt;
  &lt;li&gt;破坏 iOS 引导链&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在之后长达 12 年中，围绕着这两件事情，苹果跟安全研究员们展开了斗智斗勇。&lt;/p&gt;

&lt;h1 id=&quot;参考资料&quot;&gt;参考资料&lt;/h1&gt;

&lt;p&gt;[1] https://www.peerlyst.com/posts/ios-jailbreaks-history-part-1-ivan-ponurovskiy?trk=profile_page_overview_panel_posts&lt;/p&gt;

&lt;p&gt;[2] https://www.theiphonewiki.com/&lt;/p&gt;

&lt;p&gt;[3] http://blog.iphone-dev.org/&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;iPhone Open Application Development, 2nd Edition by Jonathan Zdziarski &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;这里的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Media&lt;/code&gt;指的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/root/Media&lt;/code&gt;而并非我们熟知的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/mobile/Media&lt;/code&gt;，因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mobile&lt;/code&gt;用户在iOS 1.0-1.1.2中暂时还不存在，下同。 &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:2:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="iPhone" />
      
        <category term="jailbreak" />
      

      
        <summary type="html">本文是对自己这么多年以来对 iPhone 越狱学习的一个总结。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">无SHSH将iPhone5S降级到10.3.3</title>
      
      
      <link href="https://umi.cat/2019/12/01/downgrade-iPhone-5S-to-10.3.3/" rel="alternate" type="text/html" title="无SHSH将iPhone5S降级到10.3.3" />
      
      <published>2019-12-01T07:36:59+00:00</published>
      <updated>2019-12-01T07:36:59+00:00</updated>
      <id>https://umi.cat/2019/12/01/downgrade-iPhone-5S-to-10.3.3</id>
      <content type="html" xml:base="https://umi.cat/2019/12/01/downgrade-iPhone-5S-to-10.3.3/">&lt;p&gt;前几天琢磨着写一篇有关 iPhone 越狱的文章，奈何手里没有越狱机器，只有一台 iPhone 5S，但这台机器作为信息转发机早已被我升级到 iOS 13。无奈之下，只好亲自动手开始降级。&lt;/p&gt;

&lt;p&gt;我从红雪时代开始就再也没有接触过 iPhone 降级这种事情了，所以遇到了不少坑，在这里我会将这些坑一一记录下来。&lt;/p&gt;

&lt;h1 id=&quot;0x01-常见疑难解答&quot;&gt;0x01 常见疑难解答&lt;/h1&gt;

&lt;p&gt;Q: 为什么可以降级？不是说 iPhone 一旦苹果服务器关闭某个版本的验证之后就不能刷机了吗？&lt;/p&gt;

&lt;p&gt;A: 因为 checkm8 漏洞的出现，使得DFU模式可以传入自制 iBEC/iBSS，从而破坏整个引导链，最后进入刷机。&lt;/p&gt;

&lt;p&gt;Q: 为什么不降级到更早的版本？比如iOS 7.1.1？&lt;/p&gt;

&lt;p&gt;A: 苹果已经关闭那些版本的激活服务器，如果强行刷入，即使通过越狱删除系统文件进入界面，也会失去通信功能与iCloud相关功能。&lt;/p&gt;

&lt;p&gt;同时，这个刷入 iOS 10.3.3 利用的似乎是OTA包，而不是普通的刷机包，所以可以实现无引导启动。如果刷入别的固件，可能需要每次手动进入DFU模式引导才能启动。这是一个猜测，暂时还没有验证。&lt;/p&gt;

&lt;h1 id=&quot;0x02-步骤&quot;&gt;0x02 步骤&lt;/h1&gt;

&lt;p&gt;目前市面上已经有不少工具支持降级，其中我使用的是&lt;a href=&quot;StableA7&quot;&gt;https://devluke.gitlab.io/stablea7/&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;这个工具将安装依赖与刷机集成到一个文件中，只需通过一个命令即可以自动下载并安装所有依赖：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bash &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://gitlab.com/snippets/1907816/raw&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在实际操作过程中，需要下载所对应设备的10.3.3系统固件，比如我的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iPhone6,1&lt;/code&gt;，那么我要下载的固件就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iPhone_4.0_64bit_10.3.3_14G60_Restore.ipsw&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;要注意的一点是，这个工具只支持 mojave 和 catalina。&lt;/p&gt;

&lt;p&gt;之后根据实际操作进入DFU模式，然后它会要求你选择降级方式，有两种方法可以选择：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Normal/Auto&lt;/li&gt;
  &lt;li&gt;/rsu&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中方法2需要futurerestore加载额外的dylib，这个方法成功率非常高，但我不知道为什么futurerestore非得读取根目录，由于这个原因，我们需要关闭macOS的rootless功能，并且给予root权限。&lt;/p&gt;

&lt;p&gt;之后它会调用ipwndfu尝试进入pwned模式，这个步骤可能会循环很久，因为堆风水并不一定能保证一次成功。总而言之，进入之后，它就会开始发送iBEC/iBSS，如果成功载入上述引导，设备会显示绿色屏幕，然后一路回车直接刷机。（理想情况）&lt;/p&gt;

&lt;h1 id=&quot;0x03-遇到的问题&quot;&gt;0x03 遇到的问题&lt;/h1&gt;

&lt;h2 id=&quot;一阶段没有显示绿色屏幕ibec卡在80左右如下所示&quot;&gt;一阶段没有显示绿色屏幕/iBEC卡在80%左右（如下所示）&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;==&amp;gt; Sending test file to device...
[==================================================] 100.0%
==&amp;gt; Sending patched iBSS/iBEC to device...
[=============================================     ] 81.5%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;解决方法：换线！&lt;/p&gt;

&lt;p&gt;没错，就这么简单粗暴。 我是新款MacBook Pro，用了一根usb-c的线，折腾了好久，绝望之下死马当活马医，找来一根usb-a的转换器，换了一根usb-a的线，结果就成功了。&lt;/p&gt;

&lt;h2 id=&quot;dyld-library-not-loaded&quot;&gt;dyld: Library not loaded&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;umi@umi StableA7 % bin/futurerestore &lt;span class=&quot;nt&quot;&gt;--exit-recovery&lt;/span&gt;
dyld: Library not loaded: /usr/local/opt/usbmuxd/lib/libusbmuxd.4.dylib
  Referenced from: /Users/umi/Desktop/1033-OTA-Downgrader/new/StableA7/bin/futurerestore
  Reason: image not found
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;解决方法：下载&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusbmuxd.4.dylib&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这里，如果你安装了高版本libusbmuxd.6.dylib，千万不要自作聪明建立软链接，这样futurerestore可以成功执行，但一旦刷机，就会报错。&lt;/p&gt;

&lt;h2 id=&quot;卡在checking-filesystem-15&quot;&gt;卡在Checking filesystem (15)&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Personalizing IMG4 component iBoot...
Personalizing IMG4 component RestoreSEP...
Personalizing IMG4 component SEP...
Sending NORData now...
Done sending NORData
About to send RootTicket...
Sending RootTicket now...
Done sending RootTicket
Waiting &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;NAND &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;28&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Checking filesystems &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;15&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;解决方法：等&lt;/p&gt;

&lt;h2 id=&quot;激活icloud时提示kvs-synchronizewithcompletionhandler-failed&quot;&gt;激活iCloud时提示KVS synchronizeWithCompletionHandler failed&lt;/h2&gt;
&lt;p&gt;解决方法：按下 Home 键，选没有Apple ID，进入桌面后注销重新登录。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="iPhone" />
      
        <category term="jailbreak" />
      

      
        <summary type="html">前几天琢磨着写一篇有关 iPhone 越狱的文章，奈何手里没有越狱机器，只有一台 iPhone 5S，但这台机器作为信息转发机早已被我升级到 iOS 13。无奈之下，只好亲自动手开始降级。</summary>
      

      
      
    </entry>
  
  
  
  
  
    <entry>
      
      <title type="html">​Implement a strace equivalent using DynamoRio Framework</title>
      
      
      <link href="https://umi.cat/2019/10/14/implement-strace-equivalent-using-dynamorio/" rel="alternate" type="text/html" title="​Implement a strace equivalent using DynamoRio Framework" />
      
      <published>2019-10-14T19:41:12+00:00</published>
      <updated>2019-10-14T19:41:12+00:00</updated>
      <id>https://umi.cat/2019/10/14/implement-strace-equivalent-using-dynamorio</id>
      <content type="html" xml:base="https://umi.cat/2019/10/14/implement-strace-equivalent-using-dynamorio/">&lt;p&gt;cs5231的大作业，要求写一个 DynamoRio Client 实现strace的无参数版本，
其输出必须与strace一模一样，在实现过程中遇到了不少坑，在这里记录一下。&lt;/p&gt;

&lt;h1 id=&quot;简介&quot;&gt;简介&lt;/h1&gt;

&lt;h2 id=&quot;strace--ptrace&quot;&gt;strace &amp;amp;&amp;amp; ptrace&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace&lt;/code&gt; 是一个追踪程序系统调用的系统实用工具。&lt;/p&gt;

&lt;p&gt;以执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace date&lt;/code&gt;为例，其输出大致如下:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;execve(&quot;/bin/date&quot;, [&quot;date&quot;], 0x7ffe396958a0 /* 57 vars */) = 0
brk(NULL)                               = 0x5599fa9db000
access(&quot;/etc/ld.so.nohwcap&quot;, F_OK)      = -1 ENOENT (No such file or directory)
access(&quot;/etc/ld.so.preload&quot;, R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, &quot;/etc/ld.so.cache&quot;, O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=86799, ...}) = 0
mmap(NULL, 86799, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3e75b65000
close(3)                                = 0
access(&quot;/etc/ld.so.nohwcap&quot;, F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, &quot;/lib/x86_64-linux-gnu/libc.so.6&quot;, O_RDONLY|O_CLOEXEC) = 3
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace&lt;/code&gt;工具的核心是系统的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ptrace&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ptrace&lt;/code&gt;也是一个系统调用，只需调用它，即可观察一个程序的系统调用。&lt;/p&gt;

&lt;p&gt;详细的说，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strace&lt;/code&gt;首先fork()一个子进程，然后给子进程设置一个标志&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PTRACE_TRACEME&lt;/code&gt;后使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execve&lt;/code&gt;执行目标进程。&lt;/p&gt;

&lt;p&gt;之后父进程将会等待，子进程的每一个系统调用都会先返回该系统调用号和寄存器状态给父进程，父进程接着解析并打印相关信息。&lt;/p&gt;

&lt;h2 id=&quot;dynamorio&quot;&gt;DynamoRio&lt;/h2&gt;

&lt;p&gt;DynamoRio是一个动态二进制分析框架，它可以在程序执行的时候插入额外的分析代码，同时不影响程序正常运行效率。&lt;/p&gt;

&lt;p&gt;具体原理是：DynamoRio将程序的执行流由原来的结构转移到代码缓存中，在这个缓存里，代码可以被任意修改，之后再进行模拟执行。&lt;/p&gt;

&lt;h3 id=&quot;dynamorio-client&quot;&gt;DynamoRio Client&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://dynamorio.org/docs/client.png&quot; alt=&quot;DynamoRio Client&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Client 与 DynamoRio 的关系如上图所示。&lt;/p&gt;

&lt;p&gt;一个 Client 的运行方式为:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;drrun &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; libstrace.so &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;开工&quot;&gt;开工&lt;/h1&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;每个syscall中如果该参数是结构体，那么结构体的指针存在arg-&amp;gt;value64中，仅能在event_post_syscall才能拿到&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;了解了以上信息之后，就可以大概知道我们要干什么了。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;获取每个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syscall&lt;/code&gt;及其相关信息&lt;/li&gt;
  &lt;li&gt;解析相关信息&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;实现&quot;&gt;实现&lt;/h2&gt;
&lt;p&gt;DynamoRio 中有一个框架叫做 Dr.Memory，其中的 Dr.Syscall 就是我们所需要的。&lt;/p&gt;

&lt;p&gt;首先我们需要声明一个 Client 的 main 函数，注册回调函数。&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;DR_EXPORT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dr_client_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client_id_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;freopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/dev/null&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 关闭stdout&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drsys_options_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ops&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;drmgr_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dr_register_filter_syscall_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_filter_syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drmgr_register_pre_syscall_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_pre_syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drmgr_register_post_syscall_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_post_syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drsys_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRMF_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;DR_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dr_register_exit_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;参数处理&quot;&gt;参数处理&lt;/h3&gt;
&lt;p&gt;之后每次目标程序呼叫系统调用时，DynamoRio都会截取并返回给我们的回调函数处理。&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;event_pre_syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcontext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sysnum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;drsys_syscall_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;unknown&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drsys_cur_syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcontext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRMF_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;drsys_syscall_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OUTBUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;drsys_iterate_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcontext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsys_iter_arg_cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OUTBUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s(%s)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dr_fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STDERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%-39s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* execute normally */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;由于需要跟strace的输出保持一致，在这里使用了一个buf来保存最后输出。使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drsys_iterate_args&lt;/code&gt;遍历参数，对于每个参数都会调用我们的自定义函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drsys_iterate_arg_cb&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drsys_iter_arg_cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drsys_arg_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;对于每个参数，其类型存在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arg-&amp;gt;type&lt;/code&gt;中，实测不支持太多Linux类型，所以只能按syscall的大分类一个一个处理过去。&lt;/p&gt;

&lt;p&gt;第一个坑是struct。
以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fstat&lt;/code&gt;为例：，他的第二个参数是一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct stat&lt;/code&gt;。
如果按照一般类型处理的话，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arg-&amp;gt;value&lt;/code&gt;里面存的应该就是内容，
然而如果是struct的话，里面似乎是全是垃圾。&lt;/p&gt;

&lt;p&gt;那么来看看另外一个回调函数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drsys_iter_memarg_cb&lt;/code&gt;，又如何呢？&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drsys_iter_memarg_cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drsys_arg_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[%s]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;测试了一下，里面是NULL，陷入了僵局。&lt;/p&gt;

&lt;p&gt;没办法，看看&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drstrace&lt;/code&gt;它怎么实现的打印struct:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;drstrace_print_info_class_struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf_info_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsys_arg_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TYPE_OUTPUT_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drsym_type_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drsym_type_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drsym_error_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsym_get_type_by_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sympath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enum_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;n&quot;&gt;buf_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUFFER_SIZE_BYTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                               &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRSYM_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;NOTIFY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Value to symbol %s lookup failed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enum_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsym_expand_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sympath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UINT_MAX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                          &lt;span class=&quot;n&quot;&gt;buf_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUFFER_SIZE_BYTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                          &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRSYM_SUCCESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;NOTIFY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s structure expanding failed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enum_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type_has_unknown_components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;NOTIFY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s structure has unknown types&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enum_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;NULL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/* We return true since we already printed for this value */&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* We&apos;re expecting an address here. So we truncate int64 to void*. */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;print_structure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expand_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print_structure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf_info_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsym_type_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drsys_arg_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRSYM_TYPE_VOID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;void=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;safe_read_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DRSYM_TYPE_PTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;得，看样子struct的指针存在arg-&amp;gt;value64里面，不是我想象的垃圾。&lt;/p&gt;

&lt;p&gt;那打印arg-&amp;gt;value64地址所在的内存出来看看吧：&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fstat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ordinal1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x00007f5080f4b7d0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-----------------&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-------------------&lt;/span&gt;
&lt;span class=&quot;mo&quot;&gt;05&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;91&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;05&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;02&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;02&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;------------------&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-------------------&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x00007f50f09c4ad0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-----------------&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-------------------&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;d0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b7&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;05&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;58&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;02&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;08&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;07&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;01&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;08&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;f0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;mo&quot;&gt;05&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;02&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;00&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;------------------&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-------------------&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;观察到有个很像地址的东西，接着探究，结果发现似乎并不是……&lt;/p&gt;

&lt;p&gt;是不是有什么地方看漏了？&lt;/p&gt;

&lt;p&gt;回头再看drstrace的源码，突然发现，他在pre_syscall和post_syscall都遍历了一遍参数，而且判断了只有在postcall的时候才去打印结构体。&lt;/p&gt;

&lt;p&gt;照葫芦画瓢试试看：&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drsys_iter_arg_cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drsys_arg_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    
        &lt;span class=&quot;n&quot;&gt;dr_fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STDERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;st_size=%d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;结果正常了。&lt;/p&gt;

&lt;p&gt;这个故事告诉我们，要好好看文档。&lt;/p&gt;

&lt;p&gt;第二个坑是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这是自己程序运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cal&lt;/code&gt;时的输出&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   November 2019write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;   November 2019&quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
      
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mber 2019&quot;&lt;/span&gt;..., 7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
Su Mo Tu We Th Fwrite&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;Su Mo Tu We Th F&quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
r Sa  
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;r Sa  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;u We Th F&quot;&lt;/span&gt;..., 7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
                write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;                &quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
1  2  
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;1  2  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;         &quot;&lt;/span&gt;..., 7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
 3  4  5  6  7  write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot; 3  4  5  6  7  &quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
8  9  
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;8  9  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;5  6  7  &quot;&lt;/span&gt;..., 7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
10 11 12 13 14 1write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;10 11 12 13 14 1&quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
5 16  
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;5 16  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;2 13 14 1&quot;&lt;/span&gt;..., 7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
17 18 19 20 21 2write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;17 18 19 20 21 2&quot;&lt;/span&gt;..., 16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
2 23  
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;2 _&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;..., 11)                 = 11
24 25 26 27 28 2write(1, &quot;&lt;/span&gt;24 25 26 27 28 2&lt;span class=&quot;s2&quot;&gt;&quot;..., 16)     = 16
9 30  
write(1, &quot;&lt;/span&gt;9 30  &lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;6 27 28 2&lt;span class=&quot;s2&quot;&gt;&quot;..., 7)     = 7
                write(1, &quot;&lt;/span&gt;                &lt;span class=&quot;s2&quot;&gt;&quot;..., 16)     = 16
      
write(1, &quot;&lt;/span&gt;      &lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;         &lt;span class=&quot;s2&quot;&gt;&quot;..., 7)     = 7
exit_group(0)                           = ?
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而strace标准输出则是&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;   November 2019&quot;&lt;/span&gt;, 16   November 2019&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 7      
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;Su Mo Tu We Th F&quot;&lt;/span&gt;, 16Su Mo Tu We Th F&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;r Sa  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 7r Sa  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;                &quot;&lt;/span&gt;, 16                &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;1  2  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 71  2  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot; 3  4  5  6  7  &quot;&lt;/span&gt;, 16 3  4  5  6  7  &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;8  9  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 78  9  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;10 11 12 13 14 1&quot;&lt;/span&gt;, 1610 11 12 13 14 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;5 16  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 75 16  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;17 18 19 20 21 2&quot;&lt;/span&gt;, 1617 18 19 20 21 2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;2 &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\3&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;3[7m23&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\3&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;3[27m  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 162 23  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;24 25 26 27 28 2&quot;&lt;/span&gt;, 1624 25 26 27 28 2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;9 30  &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 79 30  
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;                &quot;&lt;/span&gt;, 16                &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 16
write&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1, &lt;span class=&quot;s2&quot;&gt;&quot;      &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, 7      
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 7
exit_group&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                           &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; ?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到，流的顺序完全不一样。&lt;/p&gt;

&lt;p&gt;这部分应该再看看strace的实现的，然而来不及了，先把作业交上去，以后再说吧。&lt;/p&gt;

&lt;h1 id=&quot;代码&quot;&gt;代码&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Umiiii/strace&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="strace" />
      
        <category term="Dynamorio" />
      

      
        <summary type="html">cs5231的大作业，要求写一个 DynamoRio Client 实现strace的无参数版本， 其输出必须与strace一模一样，在实现过程中遇到了不少坑，在这里记录一下。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">macOS 10.15 Catalina 中 使用 Apple Watch 进行 sudo 鉴权</title>
      
      
      <link href="https://umi.cat/2019/10/01/mac-10-15-with-apple-watch/" rel="alternate" type="text/html" title="macOS 10.15 Catalina 中 使用 Apple Watch 进行 sudo 鉴权" />
      
      <published>2019-10-01T14:41:50+00:00</published>
      <updated>2019-10-01T14:41:50+00:00</updated>
      <id>https://umi.cat/2019/10/01/mac-10-15-with-apple-watch</id>
      <content type="html" xml:base="https://umi.cat/2019/10/01/mac-10-15-with-apple-watch/">&lt;h1 id=&quot;简介&quot;&gt;简介&lt;/h1&gt;

&lt;p&gt;最近更新了 macOS 10.15，sidecar（官方中文叫随航）确实好用，不过我在闲逛官网的时候发现了另外一个功能，如题图所示。
实际测试了一下，效果确实好使。&lt;/p&gt;

&lt;p&gt;问题有二：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;可以让 sudo 也支持这个功能吗？&lt;/li&gt;
  &lt;li&gt;Apple Watch 时不时无法连接，需要重启才能连回，有办法检测 Apple Watch 的连接状态吗？&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- more --&gt;

&lt;h1 id=&quot;初探&quot;&gt;初探&lt;/h1&gt;

&lt;p&gt;翻看了一些资料，找到了之前使用 Touch ID 鉴权 sudo 的方法：
在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/pam.d/sudo&lt;/code&gt; 中加入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auth       sufficient     pam_tid.so&lt;/code&gt;。
那么这一招对 Apple Watch 是否管用？&lt;/p&gt;

&lt;p&gt;一开始，我的想法是，会不会有类似 pam_watch.so 的 pam 文件？&lt;/p&gt;

&lt;p&gt;macOS 的默认 pam 文件夹在 /usr/lib/pam，看了看，里面并没有新增什么东西。&lt;/p&gt;

&lt;p&gt;我们首先按照老方法直接加入，经过测试之后发现，当拉起 Touch ID 验证窗时，手表也会收到鉴权提示，证明此方法有效。&lt;/p&gt;

&lt;p&gt;那么就这么解决了吗？并没有。&lt;/p&gt;

&lt;p&gt;当电脑合盖连显示器之后，这个鉴权就失效了，回退到原本的密码输入中，想解决这个问题，还需要进一步探究原理。&lt;/p&gt;

&lt;h1 id=&quot;macos-的鉴权机制&quot;&gt;macOS 的鉴权机制&lt;/h1&gt;
&lt;p&gt;macOS 有两套鉴权机制，一套是 pam.d ，另一套则是 LocalAuthentication.framework。
&lt;img src=&quot;https://docs-assets.developer.apple.com/published/08a1846d5e/b32218fc-f538-412c-80d7-183c920d9429.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;查看源码后我们得知，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pam_tid&lt;/code&gt;是对后者的一个封装。
https://opensource.apple.com/source/pam_modules/pam_modules-173.50.1/modules/pam_tid/pam_tid.c.auto.html&lt;/p&gt;

&lt;p&gt;也就是 sudo -&amp;gt; pam_tid.so -&amp;gt; LocalAuthentication.framework -&amp;gt; 指纹或手表验证，这样一条调用链&lt;/p&gt;

&lt;p&gt;观察到这一段：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;cm&quot;&gt;/* evaluate policy */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LAEvaluatePolicy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// error is intended as failure means Touch ID is not usable which is in fact not an error but the state we need to handle&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CFErrorGetCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kLAErrorNotInteractive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;os_log_debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PAM_LOG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;policy evaluation failed: %ld&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CFErrorGetCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAM_AUTH_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cleanup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;该段代码执行 LAEvaluatePolicy 调起生物识别。
找一下 macOS 10.15 的 SDK 头文件:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Objective-C&quot;&gt;// LocalAuthentication.framework/Versions/A/Headers/LAPublicDefines.h
#define kLAPolicyDeviceOwnerAuthenticationWithBiometrics        1
#define kLAPolicyDeviceOwnerAuthentication                      2
#define kLAPolicyDeviceOwnerAuthenticationWithWatch             3
#define kLAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;果不其然，相比 10.14 新增了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Watch&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiometricsOrWatch&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;那是什么原因导致我们合盖就无法鉴权的呢？&lt;/p&gt;

&lt;h2 id=&quot;猜测一apple-watch-的鉴权和-touch-id-是同时进行的and当-touch-id-无法执行时即合上电脑apple-watch-也会返回无法执行&quot;&gt;猜测一：Apple Watch 的鉴权和 Touch ID 是同时进行的(and)，当 Touch ID 无法执行时（即合上电脑），Apple Watch 也会返回无法执行。&lt;/h2&gt;

&lt;p&gt;做个实验：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Objective-C&quot;&gt;BOOL can = [context canEvaluatePolicy:kLAPolicyDeviceOwnerAuthenticationWithWatch error:&amp;amp;error];
LABiometryType bioType = context.biometryType;
NSLog(@&quot;%hhd&quot;,can);
&lt;/code&gt;&lt;/pre&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;kLAPolicyDeviceOwnerAuthenticationWithWatch&lt;/td&gt;
      &lt;td&gt;开盖&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch&lt;/td&gt;
      &lt;td&gt;开盖&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;kLAPolicyDeviceOwnerAuthenticationWithWatch&lt;/td&gt;
      &lt;td&gt;合盖&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch&lt;/td&gt;
      &lt;td&gt;合盖&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;证明我们猜测是错误的，而且，用 IDA 打开新版的 pam_tid.so 发现，调用的参数竟然不是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiometricsOrWatch&lt;/code&gt; , 而仍是之前的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Biometric&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;__int8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LAEvaluatePolicy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v33&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v65&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CFErrorGetCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v65&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1004&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                            &lt;span class=&quot;o&quot;&gt;~~~&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这是怎么一回事？按照苹果的说法，只有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiometricsOrWatch&lt;/code&gt; 才能实现若指纹识别无法使用的情况下使用Watch。&lt;/p&gt;

&lt;h2 id=&quot;猜测二klapolicydeviceownerauthenticationwithbiometrics-的真实表现型为-biometricandwatch即猜测一但-apple-watch-无法检测的话不影响-touch-id&quot;&gt;猜测二：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometrics&lt;/code&gt; 的真实表现型为 “BiometricAndWatch”，即猜测一，但 Apple Watch 无法检测的话不影响 Touch ID。&lt;/h2&gt;

&lt;p&gt;打开 IDA，找到 pam_tid.so，跳转到地址 1FBB，此处语句为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov esi,1&lt;/code&gt;，也就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometrics&lt;/code&gt;的枚举值。&lt;/p&gt;

&lt;p&gt;选择 Edit - Patch Program - Patch Word，将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x1BE&lt;/code&gt; 改为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4BE&lt;/code&gt;（即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch&lt;/code&gt;的枚举值）
&lt;img src=&quot;patch.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后选择 Apply patches to input file,得到新的 pam_tid.so。&lt;/p&gt;

&lt;p&gt;由于pam文件经过签名，我们如果直接使用这个文件，会被 Kill 掉，使用以下语句进行签名：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo codesign -f -s pam_tid.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; 代表替换原签名，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt;代表使用 Ad-Hoc 签名。&lt;/p&gt;

&lt;p&gt;由于 macOS 的 rootless 机制，我们无法修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/pam&lt;/code&gt;。所以签名完成后，你需要找一个文件夹放置，然后重新将 /etc/pam.d/sudo 里面的so文件指向新的so文件。&lt;/p&gt;

&lt;p&gt;测试后发现，无论是 Touch ID， 还是 Apple Watch，均能完成鉴权，且在屏幕合盖后，Apple Watch 也能进行独立鉴权。
&lt;img src=&quot;success.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不过，有一个缺点，Apple Watch 总是断连，这个问题不知道如何解决。&lt;/p&gt;

&lt;h1 id=&quot;检测-apple-watch-与-macos-的连接状态&quot;&gt;检测 Apple Watch 与 macOS 的连接状态&lt;/h1&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;LAContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LAContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;NSLog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%hhd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canEvaluatePolicy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithWatch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;当 Apple Watch 与 macOS 连接正常时，该值返回 1。问题在于，第一次要求鉴权时，Apple Watch 总是不可用（即返回0），需要等待较久时间才能自动连回电脑。&lt;/p&gt;

&lt;p&gt;而 macOS 自带的使用 Apple Watch 解锁基本上每次都能成功，准确地说：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;运行上述代码，显示 0。&lt;/li&gt;
  &lt;li&gt;锁定 macOS。&lt;/li&gt;
  &lt;li&gt;唤醒 macOS，手表自动解锁。&lt;/li&gt;
  &lt;li&gt;再次运行上述代码，显示 1。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;暂时不知道如何实现的，留作以后探究吧。&lt;/p&gt;

&lt;h1 id=&quot;结论&quot;&gt;结论&lt;/h1&gt;

&lt;p&gt;由于未知的原因，系统自带的 pam_tid.so 仍然没有更新，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LAContext&lt;/code&gt; 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canEvaluatePolicy&lt;/code&gt; 方法将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kLAPolicyDeviceOwnerAuthenticationWithBiometrics&lt;/code&gt; 的默认表现型改为当 Touch ID 无法执行时（即合上电脑），Apple Watch 也会返回无法执行。&lt;/p&gt;

&lt;p&gt;以上结论基于实验与猜测，附上 &lt;a href=&quot;pam_tid_edit.so&quot;&gt;pam_tid.so&lt;/a&gt; 的修改版。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="macOS" />
      
        <category term="Apple Watch" />
      

      
        <summary type="html">简介</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">OKEX 藏宝图 第三关 WriteUp</title>
      
      
      <link href="https://umi.cat/2019/09/06/okex-ltc-stage-3/" rel="alternate" type="text/html" title="OKEX 藏宝图 第三关 WriteUp" />
      
      <published>2019-09-06T21:24:53+00:00</published>
      <updated>2019-09-06T21:24:53+00:00</updated>
      <id>https://umi.cat/2019/09/06/okex-ltc-stage-3</id>
      <content type="html" xml:base="https://umi.cat/2019/09/06/okex-ltc-stage-3/">&lt;p&gt;OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。&lt;/p&gt;

&lt;p&gt;此为第三关 writeup。&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;从第二关中我们获得了第二关的奖励地址 LTSYo5LL7oKopwt62Su2wUqUNcykacj4Fw 。&lt;/p&gt;

&lt;p&gt;区块链浏览器查一查，发现 LTSYo5LL7oKopwt62Su2wUqUNcykacj4Fw 为 vout0， 而 vout1 为 LXd4oah1kaCY1GKzoQVEGxCNrzNVRarcqV。&lt;/p&gt;

&lt;p&gt;LXd4oah1kaCY1GKzoQVEGxCNrzNVRarcqV 里面有 100 个 LTC，看来这就是我们的目标了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://umi.cat/pic/okex/stage3-1.png&quot; alt=&quot;explorer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;嗯？中间还有一笔交易。 刚刚的 vout1 被分成七份发送给了七个地址。&lt;/p&gt;

&lt;p&gt;有了上次的经验，我们先把金额转换成字符串看看。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;binascii&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06250329&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.03175719&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.07759199&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06697077&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.07234655&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06832236&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06709087&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unhexlify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出结果为&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;5f5f5930752776655f6630756e645f68406c665f5f
__Y0u&apos;ve_f0und_h@lf__
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;找到一半了，那剩下一半呢？&lt;/p&gt;

&lt;p&gt;这里我们有第二个知识点：&lt;/p&gt;

&lt;p&gt;根据 &lt;a href=&quot;https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki&quot;&gt;BIP-13&lt;/a&gt;，比特币地址是这样构成的:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;base58-encode: [one-byte version][20-byte hash][4-byte checksum]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;而莱特币作为比特币的分叉币，自然也继承了 BIP-13。 其中 version 字段，莱特币为 0x30。&lt;/p&gt;

&lt;p&gt;那我们来看看对应的比特币地址，如何呢？&lt;/p&gt;

&lt;p&gt;utils 文件取自 pycoin&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;utils&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b58decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LXd4oah1kaCY1GKzoQVEGxCNrzNVRarcqV&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyhash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chksum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyhash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chksum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash2addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyhash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(&apos;30&apos;, &apos;8800895af18dac1775984e46790118bb8a9c48e4&apos;, &apos;8e34a920&apos;)
1DQ7YNPBfuxUkTdqdGVvzw8cen1DJLKyXr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后去比特币对应的地址看看，果然又是7个vout，先将这七个转为hex之后，再与之前的字符串异或。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;v1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06250329&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.03175719&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.07759199&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06697077&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.07234655&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06832236&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06709087&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.05971248&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06165134&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.06444911&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.03756588&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.01704236&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.03614729&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.01338584&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unhexlify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unhexlify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hex: &quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;结果是这个字符串（注意中间有不可见字符）&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bing�20_bYtes_her3�
hex: 0442696e67a91432305f62597465735f6865723387
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个 hex 可以转换为对应的 bitcoin opcode :&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Hex&lt;/th&gt;
      &lt;th&gt;opcode&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;04&lt;/td&gt;
      &lt;td&gt;PUSH 4 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;42 69 6e 67&lt;/td&gt;
      &lt;td&gt;[4bytes]”Bing”&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a9&lt;/td&gt;
      &lt;td&gt;OP_HASH160&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;14&lt;/td&gt;
      &lt;td&gt;PUSH 20 bytes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;32 30 5f 62 59 74 65 73 5f 68 65 72 33 87&lt;/td&gt;
      &lt;td&gt;[20bytes]”20_bYtes_her3.”&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;20 bytes！ 听起来有点耳熟？&lt;/p&gt;

&lt;p&gt;看看 (BIP-16)[https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki] 定义的 P2SH 怎么说吧。&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;scriptSig: [signature] {serialized script}
scriptPubKey: OP_HASH160 [20-byte-hash-value] OP_EQUAL&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;😯，20 byte 的 hash！ 不过，是hash什么呢？&lt;/p&gt;

&lt;p&gt;要理解上面的内容，我们就要从最传统的比特币转账交易 P2PKH 开始说起。&lt;/p&gt;

&lt;p&gt;P2PKH中，上面那两个东西长这样：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;scriptSig:   [signature] [pubkeyHash]
scriptPubkey: OP_DUP OP_HASH160 [pubkeyHash] OP_EQUALVERIFY OP_CHECKSIG&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;其中， scriptPubkey 是一把锁，scriptSig 是钥匙。&lt;/p&gt;

&lt;p&gt;scriptPubkey 代表之前一个交易的发起者，将一部分他的 utxo，通过这个加锁脚本锁了起来。只有 PubkeyHash 的私钥持有者，通过验证签名才能解锁。比特币系统在转账时，会将 scriptSig 和 scriptPubkey 拼接起来，如果完全执行成功，说明解锁成功。&lt;/p&gt;

&lt;p&gt;拼接起来长这样:
[signature] [pubkeyHash] OP_DUP OP_HASH160 [pubkeyHash] OP_EQUALVERIFY OP_CHECKSIG&lt;/p&gt;

&lt;p&gt;举个例子吧，假设 A 转账给你一笔比特币，那么，他需要在输出的 utxo 中，把你的公钥写在 scriptPubkey 上，然后广播出去。这样，所有比特币节点都知道有这么一笔 utxo ，所属权已经转给了 Pubkey 私钥的持有者，如果你有私钥，那么这笔 utxo 你就可以轻松解锁花掉。&lt;/p&gt;

&lt;p&gt;不过， P2PKH 有很多局限性，比如他只能将 utxo 移交给一个 Pubkey。为了应对这种问题，P2SH 出现了。我们经常说的多重签名，实际上指的就是他，不过，P2SH 可以做的可不止多重签名。&lt;/p&gt;

&lt;p&gt;话不多说，我们先把这两拼起来，看看跟 P2PKH 有什么不同:&lt;/p&gt;

&lt;p&gt;[signature] {serialized script} OP_HASH160 [20-byte-hash] OP_EQUALVERIFY&lt;/p&gt;

&lt;p&gt;跟上面opcode对一对，感觉 hex 就是这一段 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{serialized script} OP_HASH160 [20-byte-hash]&lt;/code&gt;，其中构造的script就是42 69 6e 67。&lt;/p&gt;

&lt;p&gt;未完待续。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="ctf" />
      
        <category term="OKEx" />
      
        <category term="blockchain" />
      

      
        <summary type="html">OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">OKEX 藏宝图 第二关 WriteUp</title>
      
      
      <link href="https://umi.cat/2019/09/03/okex-ltc-stage-2/" rel="alternate" type="text/html" title="OKEX 藏宝图 第二关 WriteUp" />
      
      <published>2019-09-03T12:55:08+00:00</published>
      <updated>2019-09-03T12:55:08+00:00</updated>
      <id>https://umi.cat/2019/09/03/okex-ltc-stage-2</id>
      <content type="html" xml:base="https://umi.cat/2019/09/03/okex-ltc-stage-2/">&lt;p&gt;OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。&lt;/p&gt;

&lt;p&gt;此为第二关 writeup。&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;在第一关的最后，我们获得了十二个地址，从这十二个地址转账中我们发现，每一个地址中都有一个交易。这个交易一共有三个 vout 。其中 vout0 为地址的 utxo，vout1为一串可疑的01字符串，vout2为找零。&lt;/p&gt;

&lt;p&gt;那么一个很自然的想法就是先把这些字符串整理出来：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Address&lt;/th&gt;
      &lt;th&gt;LTC&lt;/th&gt;
      &lt;th&gt;Hash&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;LgzYLJQxoo6Tzciahyeru3hEx6RsS2bNSf&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
      &lt;td&gt;e92c06e376876e9218ab9126fcc49f04afaf8e8d87372bf6b03becab01d0a021&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LU5bQkFBcDMS2At6YG1xe44nWtC8VtP6Ms&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
      &lt;td&gt;624ad997f6bed92c446fe4c6419ce392730f330a409b93394c74468da500c53d&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lh17sPSpzNticZTqPgyywEheV8zVs5EMje&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
      &lt;td&gt;00958d203d2040f66ea8d6b2ee209ee787b7329d459d3948fa157324c498d062&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LZD7bL865BGEdtNfsjh32pPtwZZexhcnRc&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
      &lt;td&gt;d223e8271bfb324ae7421ff2ff3561011cfc423a69229733ae65b7f701c24bfc&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LMRQquyyxV3x3oKUNi1XVW2soN3hshurkj&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
      &lt;td&gt;15ff37f72dfccb7f15c3f917bf556db810df8da316fc5ceacdb3a06bfff6b925&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LXDaymVT3MYxFzxxr8z1yRu786dD8u74B8&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
      &lt;td&gt;c86533737c84426d69c690148a1f6a1ebb6cb8dce8af5fabaa62af5139531b21&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LXXASRZp1nojbTGyq1dZrwTRvZyj6QwaMA&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
      &lt;td&gt;acb7447fec1edb10a84f23eaa6de0f098b75d5a87a8d5db87ebc7ebc27969540&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LP8kLTRCUDCeKLjDt7hHBrLpozo6GUUoM2&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
      &lt;td&gt;ee61083111270e87291f3a2a362f2699314cfad9421f9ecb5b9845a7c220c28a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LYMR6SmtqfPgj9gBBJz2rzu8UjujTQroMY&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
      &lt;td&gt;b3c91056ae64eb359efb380db3855c791ef37700b9030c59163008150595a3b1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Ldxzgxbsfob3eaouwL1RAVGDtfBvPjr9Zh&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
      &lt;td&gt;34112eb9ad6e86c016453e6505b9618e3858512260fa5750aa60c6d147ec2adf&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LfGrSFv1Cg2i93b2KburFicpnuRGMBHtm2&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
      &lt;td&gt;fd6e0b4e962f6bbbc90dddf958296564a9c883b8af2a423e81fbc0ace0fd7e7c&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lbzma9yHoKnvUUPzCSCvXtaz9P9pfMdU7p&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
      &lt;td&gt;975a1397b5d04119c57524ce69a2f98cc5c3b8b7f1c488ee90ce8f6a47a69f11&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;[0.0100101, 0.01010001, 0.01000101, 0.01001011, 0.0100101, 0.01010001, 0.01000101, 0.01001011, 0.0100101, 0.01010001, 0.01000101, 0.01001011]&lt;/p&gt;

&lt;p&gt;转为ascii码为’JQEKJQEKJQEK’&lt;/p&gt;

&lt;p&gt;然后我就卡住了。&lt;/p&gt;

&lt;p&gt;参考这个地址，写出了剩余的解题过程&lt;/p&gt;

&lt;p&gt;https://www.chainnode.com/post/360569-24&lt;/p&gt;

&lt;p&gt;首先，我们把每个01字符串看成一个截取规则。
例如，0b3e61cc在01001010截取规则下的结果为b6c。&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0b3e61cc
01001010
 b  6 c  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后我们以12个vout1地址为输入，vout1金额为截取规则，输出12个短字符串k。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Address&lt;/th&gt;
      &lt;th&gt;Vout1&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;MKE34mPVVaMUbV66vybUY8eKgBy2JbGfFb&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MLZDb5gfcnHvuBEHtwquQnVaKw5n1e8qHt&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MV3Do2q6NzsteiB5245usYtywF2onkURTw&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MFUkMzXQK4hNTv69334W5oik6jX1Q1VFQD&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MUmGxvkvJ2b3vTpNFQsLSgqnSPv3Eci5eb&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MQQEMy8tyfZBAz76MqDXZ2RbRpT8cdRuP4&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MMZXU9Xwad5TPQhppe2jBwrhDs2kkzC4Bq&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MB9TKjwtASBsDAr59tLEVXdS7XQJELZFuV&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MPMQvnRaiAwHxQLXWNmUpzfqM8TwThZ751&lt;/td&gt;
      &lt;td&gt;0.01001010&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MTwGBRdXL7L1MLTKoY3gcSKCcheKJekdk7&lt;/td&gt;
      &lt;td&gt;0.01010001&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MVtDH3MKoCRke6NwBaZwj7hW63e4GSjyoM&lt;/td&gt;
      &lt;td&gt;0.01000101&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MTCTCKDHGMBwA6uqbCGZpLtaAyKNE1RUyR&lt;/td&gt;
      &lt;td&gt;0.01001011&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MKE34mPVVaMUbV66vybUY8eKgBy2JbGfFb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MLZDb5gfcnHvuBEHtwquQnVaKw5n1e8qHt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MV3Do2q6NzsteiB5245usYtywF2onkURTw&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MFUkMzXQK4hNTv69334W5oik6jX1Q1VFQD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MUmGxvkvJ2b3vTpNFQsLSgqnSPv3Eci5eb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MQQEMy8tyfZBAz76MqDXZ2RbRpT8cdRuP4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MMZXU9Xwad5TPQhppe2jBwrhDs2kkzC4Bq&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MB9TKjwtASBsDAr59tLEVXdS7XQJELZFuV&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MPMQvnRaiAwHxQLXWNmUpzfqM8TwThZ751&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MTwGBRdXL7L1MLTKoY3gcSKCcheKJekdk7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MVtDH3MKoCRke6NwBaZwj7hW63e4GSjyoM&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;MTCTCKDHGMBwA6uqbCGZpLtaAyKNE1RUyR&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.01001010&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01010001&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01000101&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01001011&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01001010&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01010001&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01000101&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01001011&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01001010&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01010001&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01000101&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;0.01001011&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后，以JQEK为密钥，使用维吉尼亚密码加密，得到最终答案。&lt;/p&gt;

&lt;p&gt;至于为什么是维吉尼亚密码，需要用到一点密码学的小知识。&lt;/p&gt;

&lt;p&gt;观察得到JQEK重复了三次，而维吉尼亚密码中，若密钥不足明文长度的，则重复此密钥直到补足长度为止，所以猜想需要使用维吉尼亚密码。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plaintext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key_as_int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plaintext_int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plaintext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plaintext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isalpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plaintext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ciphertext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plaintext_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plaintext_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_as_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ciphertext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ciphertext&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;JQEK&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bip32_seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;TF&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;UTJ&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;E&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;OCBA&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;DNO&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;ZUX&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;VM&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;KAAD&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;YLV&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;CWB&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;EA&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;CSHR&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TFUTJEOCBADNOZUXVMKAADYLVCWBEACSHR&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;LTSYo5LL7oKopwt62Su2wUqUNcykacj4Fw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;看到LTSYo5LL7oKopwt62Su2wUqUNcykacj4Fw有30个LTC，本关结束。&lt;/p&gt;

&lt;p&gt;从key里扒拉出私钥吧。&lt;/p&gt;

&lt;p&gt;这里有几个自己踩过的坑:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;使用vout0地址而不是vout1地址作为筛选输入&lt;/li&gt;
  &lt;li&gt;使用M开头的找零地址而不是3开头的地址作为输入
    &lt;ul&gt;
      &lt;li&gt;为了防止与比特币的Segwit地址混淆，莱特币启用了M地址，3地址与M地址是等效的。(例：3D1tksyXYTW3nypCq6c8iVPvMVNaJ6CYdd与MKE34mPVVaMUbV66vybUY8eKgBy2JbGfFb)&lt;/li&gt;
      &lt;li&gt;之前有很长一段时间不能理解为什么攻略作者能顺利筛选出来k，而自己死活筛选不出来，后来发现自己使用的区块链浏览器不支持M地址，白忙活了好久。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;维吉尼亚密码不转换数字，因此过滤掉数字&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter(str.isalpha,plaintext)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;字符串要全大写 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.upper()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;与第一关不同，每个字符串间不留空格&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="ctf" />
      
        <category term="OKEx" />
      
        <category term="blockchain" />
      

      
        <summary type="html">OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">OKEX 藏宝图 第一关 WriteUp</title>
      
      
      <link href="https://umi.cat/2019/08/07/okex-ltc-stage-1/" rel="alternate" type="text/html" title="OKEX 藏宝图 第一关 WriteUp" />
      
      <published>2019-08-07T15:30:00+00:00</published>
      <updated>2019-08-07T15:30:00+00:00</updated>
      <id>https://umi.cat/2019/08/07/okex-ltc-stage-1</id>
      <content type="html" xml:base="https://umi.cat/2019/08/07/okex-ltc-stage-1/">&lt;p&gt;OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。&lt;/p&gt;

&lt;p&gt;此为第一关 writeup。&lt;/p&gt;

&lt;h1 id=&quot;规则介绍&quot;&gt;规则介绍&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://support.okex.com/hc/zh-cn/articles/360031392471-%E5%85%B3%E4%BA%8EOKEx%E4%B8%8A%E7%BA%BF-LTC%E8%97%8F%E5%AE%9D%E5%9B%BE-%E6%B4%BB%E5%8A%A8%E7%9A%84%E5%85%AC%E5%91%8A&quot;&gt;“关于OKEx上线-LTC藏宝图-活动的公告”&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;藏宝图中总共藏有142.579436个LTC；&lt;/li&gt;
  &lt;li&gt;藏宝图中隐藏着3道关卡，需要依次破关；&lt;/li&gt;
  &lt;li&gt;关卡的答案对应钱包的密钥，参与者在破关成功后可以将奖励直接转走；&lt;/li&gt;
  &lt;li&gt;藏宝图关卡及奖励分布如下&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;关数&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;奖励&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一关&lt;/td&gt;
      &lt;td&gt;共12.579436 LTC（分布在12个地址内，即最多可有12个用户获得第一关奖励）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二关&lt;/td&gt;
      &lt;td&gt;共30LTC（存放在一个地址内）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三关&lt;/td&gt;
      &lt;td&gt;共100LTC（存放在一个地址内）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;老实说，一开始有点想吐槽最后的“因账户地址包含藏宝图的线索，为保证活动的公平公正，奖励地址会在活动结束后公布“，因为我觉得区块链上的信息应该谁都能获取，对这些信息隐藏没有意义。但实际上我错了，第三关居然用到了这些信息，而隐藏地址显然会增加破解的难度，想要通过区块链上的数据获取目标地址无异于大海捞针。&lt;/p&gt;

&lt;h1 id=&quot;第一关&quot;&gt;第一关&lt;/h1&gt;

&lt;p&gt;图片留意到一段莫斯电码&lt;/p&gt;

&lt;p&gt;…/-/./–./.-/-./—/–./.-./.-/.–./…./-.–&lt;/p&gt;

&lt;p&gt;解得&lt;/p&gt;

&lt;p&gt;steganography&lt;/p&gt;

&lt;p&gt;很明显了，上&lt;a href=&quot;http://www.caesum.com/handbook/Stegsolve.jar&quot;&gt;Stegsolve&lt;/a&gt;。（实际上我一开始根本没看到莫斯电码，直接就上了）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://umiblog.oss-cn-shenzhen.aliyuncs.com/okex-ltc/stage1-1.gif&quot; alt=&quot;stage1-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://umiblog.oss-cn-shenzhen.aliyuncs.com/okex-ltc/solved.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后拿到了第一张图片，之后所有的解谜都从这里开始。&lt;/p&gt;

&lt;p&gt;首先，我们看到在(400,400)处有一个很小的点，这个代表圆心，周围的点和空白分别代表 0 和 1。&lt;/p&gt;

&lt;p&gt;顺时针将这个圆圈上的点都转换为 0 和 1。&lt;/p&gt;

&lt;p&gt;代码如下:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.image&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mpimg&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;binascii&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;I&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mpimg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;./solved.png&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# r = 400
# (x-450) ^2 + (y-450)^2 = 160000
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;360&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;450&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;450&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;1&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;0&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unhexlify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;%x&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;执行结果如下：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;010010000100100100100000010011000101010001000011001000000100100001010101010011100101010001000101010100100010000001010111010001010100110001000011010011110100110101000101001000000011001000100000010011110100101100100000010011000101010001000011001000000100011101000001010011010100010100100000010011110010000001001011001000000100010100100000010110000000000000000000
HI LTC HUNTER WELCOME 2 OK LTC GAME O K E X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;圆圈这个地方实际上第二天就有人解出来了，然后被直接发在了微博底下。大家都不知道怎么把这些单词与助记词联系起来，我甚至还觉得这个可能只是一个热身，然后对着右下角的点阵图案死磕。&lt;/p&gt;

&lt;p&gt;官方在此期间发出的提示有很多：&lt;/p&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;b c d e f g h i j k l a&lt;/td&gt;
      &lt;td&gt;@OKEx&lt;/td&gt;
      &lt;td&gt;7-30 14:44&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;l k j i h g f e d c b a&lt;/td&gt;
      &lt;td&gt;@&lt;a href=&quot;https://weibo.com/LTChome&quot;&gt;莱特币中国社区&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;7-31 00:31&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a c e g i k b d f h j l&lt;/td&gt;
      &lt;td&gt;@OKEx&lt;/td&gt;
      &lt;td&gt;7-31 12:56&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ab bc cd de ef fg gh hi ij jk ka lb&lt;/td&gt;
      &lt;td&gt;@OKEx&lt;/td&gt;
      &lt;td&gt;7-31 16:02&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;j k l a b c d e f g h i&lt;/td&gt;
      &lt;td&gt;@&lt;a href=&quot;https://weibo.com/LTChome&quot;&gt;莱特币中国社区&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;7-31 12:03&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;g h i j k l a b c d e f&lt;/td&gt;
      &lt;td&gt;@OKEx&lt;/td&gt;
      &lt;td&gt;7-31 17:06&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;b d f h j l a c e g i k&lt;/td&gt;
      &lt;td&gt;@OKEx&lt;/td&gt;
      &lt;td&gt;8-01 16:16&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;@&lt;a href=&quot;https://weibo.com/bafanghuzhu&quot;&gt;OKEx&lt;/a&gt; 和 @&lt;a href=&quot;https://weibo.com/LTChome&quot;&gt;莱特币中国社区&lt;/a&gt; 这两个账号要求参加者在对应微博下转发、评论或点赞，达到一定次数时解锁线索。但目前来看，整个区块链生态在微博上应该没有这么高的活跃度，于是不知道哪个大哥去淘宝买了一堆转发，评论和点赞，随着僵尸号把量刷上去之后，这些线索就一个一个地冒出来了。在第七个线索公布时，所有的 LTC 都被拿走，于是线索就没有继续公布。&lt;/p&gt;

&lt;p&gt;那么，如何通过这些线索和上面的单词来取得 LTC 呢？&lt;/p&gt;

&lt;p&gt;这就涉及到了 BIP-32 了。&lt;/p&gt;

&lt;h4 id=&quot;bip-32&quot;&gt;BIP-32&lt;/h4&gt;

&lt;p&gt;首先，BTC 的每个地址都由一个或者多个私钥来控制。但是，若一个人持有多个地址，那么管理对应的私钥则会是一件非常麻烦的事情。 BIP-32 提出了一种名叫 Hierarchical Deterministic Wallets （HD 钱包）的理念，允许一个种子来管理多个私钥。其中，主私钥能够推导出子私钥，反之则不行。&lt;/p&gt;

&lt;p&gt;其中， Master key 的生成方法如下: （参考资料:https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
&lt;img src=&quot;https://learnblockchain.cn/images/3ec7468aa49d907b0ec66b5d8b41a0a1.png&quot; alt=&quot;0*pJlDPg23_yNzMRPa&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们可以发现，虽然正常HD钱包的生成路径中，根种子是固定位数的，但 HMAC-SHA512 是一个哈希函数，这就意味着，我们的输入长度可以不是 128, 256 或 512。&lt;/p&gt;

&lt;p&gt;回过头来观察一下，我们取得了如下字符串:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;HI LTC HUNTER WELCOME 2 OK LTC GAME O K E X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;刚好十二个，而上面的提示也是十二个字母（或字母对）排列组合。
结合一下上面的提示，怎么样？
令 a = “HI” , 以此类推。&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pycoin.symbols.ltc&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;network&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;HI LTC HUNTER WELCOME 2 OK LTC GAME O K E X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;order&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b c d e f g h i j k l a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bip32_seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LgzYLJQxoo6Tzciahyeru3hEx6RsS2bNSf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;到区块链浏览器看一下，有余额，说明第一关宣告结束。其他十一个以此类推。&lt;/p&gt;

&lt;p&gt;seed[0] 从第二个开始:&lt;/p&gt;

&lt;p&gt;“LTC HUNTER WELCOME 2 OK LTC GAME O K E X HI”:&lt;/p&gt;

&lt;p&gt;地址: “LgzYLJQxoo6Tzciahyeru3hEx6RsS2bNSf”&lt;/p&gt;

&lt;p&gt;seed[1] 逆序:&lt;/p&gt;

&lt;p&gt;“X E K O GAME LTC OK 2 WELCOME HUNTER LTC HI”:&lt;/p&gt;

&lt;p&gt;地址: “LU5bQkFBcDMS2At6YG1xe44nWtC8VtP6Ms”&lt;/p&gt;

&lt;p&gt;seed[2] 跳序 :&lt;/p&gt;

&lt;p&gt;“HI HUNTER 2 LTC O E LTC WELCOME OK GAME K X”:&lt;/p&gt;

&lt;p&gt;“Lh17sPSpzNticZTqPgyywEheV8zVs5EMje”&lt;/p&gt;

&lt;p&gt;seed[3] 相邻单词连接 :&lt;/p&gt;

&lt;p&gt;“HILTC LTCHUNTER HUNTERWELCOME WELCOME2 2OK OKLTC LTCGAME GAMEO OK KE EHI XLTC”:&lt;/p&gt;

&lt;p&gt;“LZD7bL865BGEdtNfsjh32pPtwZZexhcnRc”&lt;/p&gt;

&lt;p&gt;seed[4] 从中间开始:&lt;/p&gt;

&lt;p&gt;“LTC GAME O K E X HI LTC HUNTER WELCOME 2 OK”:&lt;/p&gt;

&lt;p&gt;“LMRQquyyxV3x3oKUNi1XVW2soN3hshurkj”&lt;/p&gt;

&lt;p&gt;seed[5] 跳序 * 2 :&lt;/p&gt;

&lt;p&gt;“LTC WELCOME OK GAME K X HI HUNTER 2 LTC O E”:&lt;/p&gt;

&lt;p&gt;“LXDaymVT3MYxFzxxr8z1yRu786dD8u74B8”&lt;/p&gt;

&lt;p&gt;seed[6] 逆序相邻单词连接 :&lt;/p&gt;

&lt;p&gt;“XE EK KO OGAME GAMELTC LTCOK OK2 2WELCOME WELCOMEHUNTER HUNTERLTC LTCHI HIX”:&lt;/p&gt;

&lt;p&gt;“LXXASRZp1nojbTGyq1dZrwTRvZyj6QwaMA”&lt;/p&gt;

&lt;p&gt;seed[7] 用字符串比较的方式排序单词:&lt;/p&gt;

&lt;p&gt;“2 E GAME HI HUNTER K LTC LTC O OK WELCOME X”:&lt;/p&gt;

&lt;p&gt;“LP8kLTRCUDCeKLjDt7hHBrLpozo6GUUoM2”&lt;/p&gt;

&lt;p&gt;seed[8] 反向排序:&lt;/p&gt;

&lt;p&gt;“X WELCOME OK O LTC LTC K HUNTER HI GAME E 2”:&lt;/p&gt;

&lt;p&gt;“LYMR6SmtqfPgj9gBBJz2rzu8UjujTQroMY”&lt;/p&gt;

&lt;p&gt;seed[9] 从第3个单词开始 :&lt;/p&gt;

&lt;p&gt;“WELCOME 2 OK LTC GAME O K E X HI LTC HUNTER”:&lt;/p&gt;

&lt;p&gt;“Ldxzgxbsfob3eaouwL1RAVGDtfBvPjr9Zh”&lt;/p&gt;

&lt;p&gt;seed[10] 从第7个单词开始 :&lt;/p&gt;

&lt;p&gt;“GAME O K E X HI LTC HUNTER WELCOME 2 OK LTC”:&lt;/p&gt;

&lt;p&gt;“LfGrSFv1Cg2i93b2KburFicpnuRGMBHtm2”&lt;/p&gt;

&lt;p&gt;seed[11] 从第9个单词开始 :&lt;/p&gt;

&lt;p&gt;“K E X HI LTC HUNTER WELCOME 2 OK LTC GAME O”:&lt;/p&gt;

&lt;p&gt;“Lbzma9yHoKnvUUPzCSCvXtaz9P9pfMdU7p”&lt;/p&gt;

&lt;p&gt;第一关圆满结束，撒花。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="ctf" />
      
        <category term="OKEx" />
      
        <category term="blockchain" />
      

      
        <summary type="html">OKEx 在 2019 年 7 月 30 日的时候上线了一个” LTC 藏宝图”的活动，这个藏宝图活动与去年 10 月 310 个 BTC 的活动一样，均为 ctf 的 misc 形式，只不过相比 ctf 比赛的 flag，这个活动将 flag 换成了私钥。玩家需要通过各种手段破解藏在图片中的信息，从而获取正确的私钥来取得奖励，现在活动已经完结，作为一个复盘而言，写一下总归是有价值的。这个游戏做的不错，融合了不少比特币相关的知识。</summary>
      

      
      
    </entry>
  
  
  
    <entry xml:lang="cn">
      
      <title type="html">Macbook Pro 与 iPhone 连接抽风的解决方案</title>
      
      
      <link href="https://umi.cat/2019/03/15/iphone-connection-issue-with-macbook/" rel="alternate" type="text/html" title="Macbook Pro 与 iPhone 连接抽风的解决方案" />
      
      <published>2019-03-15T13:25:16+00:00</published>
      <updated>2019-03-15T13:25:16+00:00</updated>
      <id>https://umi.cat/2019/03/15/iphone-connection-issue-with-macbook</id>
      <content type="html" xml:base="https://umi.cat/2019/03/15/iphone-connection-issue-with-macbook/">&lt;p&gt;机器为 2015 Macbook Pro LT2 港版。&lt;/p&gt;

&lt;p&gt;经常进行 iOS 开发，在使用机器左右的 USB 接口连接 iPhone 时，有的时候发现连接不正常，具体表现为：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Macbook 能够识别 iPhone 插入并试图进行握手，此后立即断开，然后反复尝试重新连接，中间可能还会伴有提示升级 iPhone 连接固件并失败的现象。&lt;/li&gt;
  &lt;li&gt;iPhone 进入充电状态，而后在数秒内自行断开。&lt;/li&gt;
  &lt;li&gt;iTunes 自行打开，iPhone 图标出现后消失。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一开始猜测是电流的问题，于是换了一个 USB hub ，把 iPhone 接在上面之后解决。
然后猜测是不是跟线也有关系，于是换了一条原装线，比起之前的品胜线，更大概率能够握手成功，但在调试时断开。&lt;/p&gt;

&lt;h1 id=&quot;解决方案&quot;&gt;解决方案&lt;/h1&gt;
&lt;p&gt;打开活动监视器，找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usbd&lt;/code&gt;进程，强制停止，之后问题解决。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="Apple" />
      
        <category term="Macbook Pro" />
      
        <category term="iPhone" />
      

      
        <summary type="html">机器为 2015 Macbook Pro LT2 港版。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">博客集锦</title>
      
      
      <link href="https://umi.cat/2019/01/01/some-valuable-blog/" rel="alternate" type="text/html" title="博客集锦" />
      
      <published>2019-01-01T00:00:00+00:00</published>
      <updated>2019-01-01T00:00:00+00:00</updated>
      <id>https://umi.cat/2019/01/01/some-valuable-blog</id>
      <content type="html" xml:base="https://umi.cat/2019/01/01/some-valuable-blog/">&lt;p&gt;这里会记录一些个人觉得有价值的博客。&lt;/p&gt;

&lt;p&gt;https://www.nevermoe.com/&lt;/p&gt;

&lt;p&gt;一个安全相关的博客&lt;/p&gt;

&lt;p&gt;https://yihui.name/&lt;/p&gt;

&lt;p&gt;虽然与技术没有太大关系，但是文笔写的非常好&lt;/p&gt;

&lt;p&gt;https://typeblog.net/&lt;/p&gt;

&lt;p&gt;技术流博客&lt;/p&gt;

&lt;p&gt;https://leemeng.tw/&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="Blog" />
      

      
        <summary type="html">这里会记录一些个人觉得有价值的博客。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">「ありがとうございます」と「ありがとごさいました」</title>
      
      
      <link href="https://umi.cat/2018/01/02/the-nuance-of-thankyou-in-japanese/" rel="alternate" type="text/html" title="「ありがとうございます」と「ありがとごさいました」" />
      
      <published>2018-01-02T16:36:59+00:00</published>
      <updated>2018-01-02T16:36:59+00:00</updated>
      <id>https://umi.cat/2018/01/02/the%20nuance%20of%20thankyou%20in%20japanese</id>
      <content type="html" xml:base="https://umi.cat/2018/01/02/the-nuance-of-thankyou-in-japanese/">&lt;p&gt;あるコーヒ屋さんでは「ありがとうございました」と言わないで、「ありがとうございます」と言うようにというマニュアるになっているそうです。理由は、「ありがとうございました」だと「過去」のこととしてお客様との関係が切れてしまうという感じになるから、と聞きました。&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;確かに「ありがとうございました」と言うのは、出来事が一件落着してからです。来店したばかりの客に「ありがとうございました！」と言うのは変です。注文してお金を払って、といった出来事はこれからだからです。感謝の心を持ち続けているから過去形で言わない、という論理はそれはそれとしてわかります。しかし、本当のところはどうでしょうか。&lt;/p&gt;

&lt;p&gt;実は、「ありがとうございます」は少し軽いびょうげん表現でもあります。例えば、「あ、ネクタイ歪んでますよ」と指摘してもらったときに、「ありがとうございました」というとおおげさではないでしょうか。普通は「あ、ありがとうございます」などというように思います。&lt;/p&gt;

&lt;p&gt;「ありがとうございました」の場合、「感謝すべき事態があった」ということを過去のこととして認識し、しっかり表す点で「重さ」があります。例えば、ちょっと道を聞くような場合、「こっちの道だよ」と指示してもらうだけなら、「あ、どうもありがとうございます」で済みそうですが、「わかりにくいから一緒にいってあげよう」などと大変お世話になったような場合、「本当にありがとうございいました」というのではないでしょうか。お店の方の言葉としても、本格的な料亭などでは、「この度ご利用ありがとうございました。お気をつけておかえりくださいませ」などと言ってもらえそうな気がします。&lt;/p&gt;

&lt;p&gt;ですから、「ありがとうございました」は、「過去のこととして関係が切れてしまうような水くさい挨拶」ではなくて、むしろ、「過去のことであっても覚えておくようなしっかりした感謝」ということができるのです。過去形の「ありがとうございました」の気持ちも大切にしたいところです。&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>umi</name>
          
          
        </author>
      

      

      
        <category term="Japanese" />
      

      
        <summary type="html">あるコーヒ屋さんでは「ありがとうございました」と言わないで、「ありがとうございます」と言うようにというマニュアるになっているそうです。理由は、「ありがとうございました」だと「過去」のこととしてお客様との関係が切れてしまうという感じになるから、と聞きました。</summary>
      

      
      
    </entry>
  
  
</feed>
