Web3 セキュリティ警告丨 チェーン上の新局面、大規模なラグプル手法の解明
著者:CertiK
最近、CertiKのセキュリティ専門家チームは、同じ手法による「ラグプル詐欺」の多発を頻繁に検出しています。これは私たちが一般的に呼ぶRug Pullです。
私たちが深く掘り下げていくと、同じ手法の事件が同じグループを指し示していることがわかり、最終的には200以上のトークンのラグプル詐欺に関連していることが判明しました。これは、大規模な自動化された、ラグプル方式で資産を収奪するハッカーグループを発見した可能性を示唆しています。
これらのラグプル詐欺では、攻撃者は新しいERC20トークンを作成し、作成時に事前に掘り出したトークンと一定量のWETHを用いてUniswap V2の流動性プールを作成します。
チェーン上の新規購入ボットやユーザーがその流動性プールで新しいトークンを一定回数購入した後、攻撃者は無から生成されたトークンを使って流動性プール内のWETHをすべて消費します。
攻撃者が無から取得したトークンは総供給量(totalSupply)に反映されず(Transferイベントも発生しないため)、etherscanでは確認できないため、外部からは認識しにくいのです。
攻撃者は隠蔽性を考慮するだけでなく、初歩的な技術能力を持つユーザーを麻痺させるための二重の罠を設計し、彼らの本当の目的を隠すために小さな問題を使っています……
深掘り詐欺
ここでは、1つのケースを例に取り、ラグプル詐欺の詳細を詳しく解説します。
私たちが検出したのは、実際には攻撃者が大量のトークン(密かにmintされた)を使って流動性プールを枯渇させて利益を得る取引であり、この取引では、プロジェクト側が合計で416,483,104,164,831(約416兆)個のMUMIを交換して約9.736のWETHを得て、プールの流動性を枯渇させました。
しかし、この取引は全体の詐欺の最後の環であり、全体の詐欺を理解するためには、さらに遡る必要があります。
トークンの展開
3月6日午前7時52分(UTC時間、以下同様)、攻撃者アドレス(0x8AF8)が「MUMI」(正式名称はMultiMixer AI)というERC20トークン(アドレスは0x4894)を展開し、420,690,000(約4.2億)個のトークンを事前に掘り出し、すべて契約の展開者に配分しました。
事前に掘り出されたトークンの数量は契約のソースコードに対応しています。
流動性の追加
8時ちょうど(トークン作成から8分後)、攻撃者アドレス(0x8AF8)が流動性を追加し始めました。
攻撃者アドレス(0x8AF8)はトークン契約のopenTrading関数を呼び出し、uniswap v2 factoryを通じてMUMI-WETH流動性プールを作成し、事前に掘り出したすべてのトークンと3つのETHを流動性プールに追加し、最終的に約1.036のLPトークンを取得しました。
取引の詳細から、流動性を追加するために使用された420,690,000(約4.2億)個のトークンのうち、63,103,500(約6300万)個のトークンが再びトークン契約(アドレス0x4894)に送信されたことがわかります。契約のソースコードを確認すると、トークン契約は各転送に対して一定の手数料を徴収し、その手数料を受け取るアドレスはトークン契約自体であることがわかります(具体的には"_transfer関数内"に実装されています)。
奇妙なことに、契約内には税収アドレス0x7ffb(転送手数料を受け取るアドレス)が設定されているにもかかわらず、最終的に手数料はトークン契約自体に送信されました。
そのため、最終的に流動性プールに追加されたMUMIトークンの数量は、税金を差し引いた357,586,500(約3.5億)となり、420,690,000(約4.3億)ではありませんでした。
流動性のロック
8時1分(流動性プール作成から1分後)、攻撃者アドレス(0x8AF8)が流動性追加によって得たすべての1.036のLPトークンをロックしました。
LPがロックされた後、理論的には攻撃者アドレス(0x8AF8)が所有するすべてのMUMIトークンは流動性プール内にロックされることになります(手数料としての部分を除く)。そのため、攻撃者アドレス(0x8AF8)は流動性を取り除いてラグプルを行う能力を持ちません。
新しく発行されたトークンを安心して購入してもらうために、多くのプロジェクトはLPをロックします。つまり、プロジェクト側は「私は逃げません、安心して買ってください!」と言っているのです。しかし、実際はそうではありません。このケースがそのように示しています。分析を続けましょう。
ラグプル
8時10分、新しい攻撃者アドレス②(0x9DF4)が、税収アドレス0x7ffbを展開しました。
ここで注目すべき点が3つあります:
税収アドレスを展開したアドレスとトークンを展開したアドレスは同じではなく、これはプロジェクト側が各操作間のアドレスの関連性を意図的に減少させ、行動の追跡を難しくすることを示唆しています。
税収アドレスの契約はオープンソースではなく、つまり税収アドレスには公開したくない操作が隠されている可能性があります。
税収契約はトークン契約よりも遅れて展開されており、トークン契約内では税収アドレスがハードコーディングされています。これはプロジェクト側が税収契約のアドレスを予知できることを意味します。CREATE命令が作成者アドレスとnonceを確定させた場合、展開される契約アドレスは確定的であるため、プロジェクト側は事前に作成者アドレスを使用して契約アドレスをシミュレーション計算しています。
実際、多くのラグプル詐欺は税収アドレスを通じて行われており、税収アドレスの展開パターンは上記の1、2点に合致しています。
午前11時(トークン作成から3時間後)、攻撃者アドレス②(0x9DF4)がラグプルを実行しました。彼は税収契約(0x77fb)の"swapExactETHForTokens"メソッドを呼び出し、税収アドレス内の416,483,104,164,831(約416兆)個のMUMIトークンを交換して約9.736のETHを得て、プール内の流動性を枯渇させました。
税収契約(0x77fb)はオープンソースではないため、そのバイトコードを逆コンパイルしました。逆コンパイル結果は以下の通りです:
https://app.dedaub.com/decompile?md5=01e2888c7691219bb7ea8c6b6befe11c
税収契約(0x77fb)の"swapExactETHForTokens"メソッドの逆コンパイルコードを確認したところ、実際にはこの関数が実装する主な機能は、uniswapV2ルーターを介して税収契約(0x77fb)が所有するMUMIトークンをETHに交換し、税収アドレスに宣言された"_manualSwap"アドレスに送信することだとわかりました。
manualSwapアドレスが存在するストレージアドレスは0x0であり、json-rpcのgetStorageAtコマンドを使用してクエリしたところ、manualSwapに対応するアドレスは税収契約(0x77fb)の展開者である攻撃者②(0x9DF4)であることがわかりました。
このラグプル取引の入力パラメータxtは420,690,000,000,000,000,000,000で、これは420,690,000,000,000(約420兆)個のMUMIトークンに対応します(MUMIトークンのdecimalは9です)。
つまり、最終的にプロジェクト側は420,690,000,000,000(約420兆)個のMUMIを使って流動性プール内のWETHを枯渇させ、全体のラグプル詐欺を完了させました。
しかし、ここで重要な問題があります。それは、税収契約(0x77fb)にはどこからそんなに多くのMUMIトークンが来たのかということです。
前述の内容から、MUMIトークンの展開時のトークン契約の総供給量は420,690,000(約4.2億)であり、ラグプル詐欺が終了した後、MUMIトークン契約で確認した総供給量は依然として420,690,000(下の図では420,690,000,000,000,000と表示され、decimalに対応する0を引く必要があります。decimalは9です)であり、税収契約(0x77fb)内の総供給量を超えるトークン(420,690,000,000,000、約420兆)はまるで無から現れたかのようです。税収アドレス0x77fbは、MUMIトークンの転送過程で発生した手数料を受け取るために使用されていないことを考えると、税収はトークン契約が受け取っています。
手法の解明
- 税収契約のトークンの出所
税収契約(0x7ffb)のトークンの出所を探るため、ERC20転送イベントの履歴を確認しました。
結果、0x77fbに関する全6件の転送イベントの中で、税収契約(0x7ffb)から転出したイベントのみが存在し、MUMIトークンが転入したイベントは一切ありませんでした。一見すると、税収契約(0x7ffb)のトークンは本当に無から現れたようです。
したがって、税収契約(0x7ffb)アドレスに無から現れた巨額のMUMIトークンには2つの特徴があります:
MUMI契約のtotalSupplyに影響を与えない
トークンの増加はTransferイベントを引き起こさない
したがって、考え方は明確です。つまり、MUMIトークン契約内には必ずバックドアが存在し、このバックドアは直接balance変数を変更し、balanceを変更する際にtotalSupplyを変更せず、Transferイベントも発生させないのです。
つまり、これは標準的でない、あるいは悪意のあるERC20トークンの実装であり、ユーザーは総供給量の変化やイベントからプロジェクト側が密かにトークンをmintしていることを感知できません。
次に、上記の考えを検証するために、MUMIトークン契約のソースコード内でキーワード「balance」を検索しました。
結果、契約内にprivate型の「swapTokensForEth」関数があり、引数はuint256型のtokenAmountです。この関数の5行目で、プロジェクト側は直接taxWallet、つまり税収契約(0x7ffb)のMUMI残高をtokenAmount * 10**decimals、つまりtokenAmountの1,000,000,000(約10億)倍に変更し、その後流動性プールからtokenAmount数量のMUMIをETHに交換してトークン契約(0x4894)に保存します。
次に、キーワード「swapTokenForEth」を検索します。
「swapTokenForEth」関数は「_transfer」関数内で呼び出され、呼び出し条件を詳しく見ると、以下のことがわかります:
転送先アドレスtoがMUMI-WETH流動性プールである場合。
他のアドレスが流動性プールでMUMIトークンを購入する数量が_preventSwapBefore(5回)を超えた場合、「swapTokenForEth」関数が呼び出されます。
引数tokenAmountは、トークンアドレスが所有するMUMIトークン残高と_maxTaxSwapの小さい方の値です。
つまり、契約がユーザーがプール内でWETHを使ってMUMIトークンを5回以上交換したことを検知すると、税収アドレスのために密かに大量のトークンをmintし、一部のトークンをETHに交換してトークン契約内に保存します。
一方で、プロジェクト側は表向きに税金を徴収し、定期的に少量のETHをトークン契約に送ることで、ユーザーに対してこれがプロジェクト側の利益の源であるかのように見せかけています。
他方で、プロジェクト側が実際に行っているのは、ユーザーの取引回数が5回に達した後、直接アカウント残高を変更し、流動性プールをすべて抽出することです。
- どのように利益を得るか
「swapTokenForEth」関数を実行した後、「_transfer」関数はまだsendETHToFeeを実行し、トークンアドレスから税収で得たETHを税収契約(0x77fb)に送信します。
税収契約(0x77fb)内のETHは、その契約内で実装された「rescue」関数を通じて引き出すことができます。
今、ラグプル詐欺の中で最後の利益取引の交換記録を再確認します。
利益取引では、2回の交換が行われました。最初は4,164,831(約416万)個のMUMIトークンを0.349のETHに交換し、2回目は416,483,100,000,000(約416兆)個のMUMIトークンを9.368のETHに交換しました。この2回目の交換は、税収契約(0x7ffb)の"swapExactETHForTokens"関数内で行われたもので、数量が入力パラメータで示された420,690,000,000,000(約420兆)個のトークンと一致しないのは、手数料として一部のトークンがトークン契約(0x4894)に送信されたためです。
最初の交換に対応するのは、2回目の交換中にトークンが税収契約(0x7ffb)からルーター契約に送信される際に、トークン契約内のバックドア関数のトリガー条件を満たしたために発生した「swapTokensForEth」関数による交換であり、重要な操作ではありません。
- 背後にいる大きな刈り取り
上記の内容から、MUMIトークンの展開から流動性プールの作成、ラグプルに至るまで、全体のラグプル詐欺の周期は約3時間であり、約6.5のETHのコスト(3 ETHは流動性追加に使用され、3 ETHは流動性プールからMUMIを交換するために使用され、0.5 ETH未満は契約の展開と取引の開始に使用されました)で9.7のETHを得て、利益は50%を超えました。
攻撃者がETHをMUMIに交換する取引は5件あり、前述の内容では触れていませんでした。取引情報は以下の通りです:
- https://etherscan.io/tx/0x62a59ba219e9b2b6ac14a1c35cb99a5683538379235a68b3a607182d7c814817
- https://etherscan.io/tx/0x0c9af78f983aba6fef85bf2ecccd6cd68a5a5d4e5ef3a4b1e94fb10898fa597e
- https://etherscan.io/tx/0xc0a048e993409d0d68450db6ff3fdc1f13474314c49b734bac3f1b3e0ef39525
- https://etherscan.io/tx/0x9874c19cedafec351939a570ef392140c46a7f7da89b8d125cabc14dc54e7306
- https://etherscan.io/tx/0x9ee3928dc782e54eb99f907fcdddc9fe6232b969a080bc79caa53ca143736f75
流動性中で操作を行ったEOAアドレスを分析したところ、相当数のアドレスがチェーン上の「新規購入ボット」であることがわかりました。全体の詐欺が迅速に進行する特徴を考慮すると、この詐欺はチェーン上で非常に活発なさまざまな新規購入ボットや新規購入スクリプトをターゲットにしていると考えられます。
したがって、トークンが見た目には不必要であるが複雑な契約設計、契約の展開、流動性のロックプロセス、さらには途中で攻撃者が関連アドレスを使用してETHをMUMIトークンに交換する疑わしい行動は、攻撃者がチェーン上のさまざまな新規購入ボットの反詐欺プログラムを欺こうとするための偽装であると理解できます。
資金の流れを追跡した結果、攻撃によって得られた利益は最終的に攻撃アドレス②(0x9dF4)から資金の沈殿アドレス(0xDF1a)に送信されました。
実際、最近検出された多くのラグプル詐欺の初期資金源と最終的な資金の行き先はすべてこのアドレスを指し示しており、このアドレスの取引を大まかに分析し、統計を取りました。
最終的に、このアドレスは約2ヶ月前から活発になり、今日までに7,000件以上の取引を開始しており、このアドレスは200以上のトークンと相互作用しています。
その中の約40のトークン取引記録を分析したところ、私たちが確認したほぼすべてのトークンに対応する流動性プールでは、最終的にトークンの総供給量を大きく超える数量の交換取引が行われ、流動性プール内のETHが枯渇していることがわかりました。また、全体のラグプル詐欺の周期も比較的短いです。
その中の一部のトークン(名煙中华)の展開取引は以下の通りです:
https://etherscan.io/tx/0x324d7c133f079a2318c892ee49a2bcf1cbe9b20a2f5a1f36948641a902a83e17
https://etherscan.io/tx/0x0ca861513dc68eaef3017e7118e7538d999f9b4a53e1b477f1f1ce07d982dc3f
したがって、このアドレスは実際には大規模な自動化された「ラグプル詐欺」の収奪機であり、収奪の対象はチェーン上の新規購入ボットです。
このアドレスは現在も活発です。
最後に
もしトークンがmint時にtotalSupplyを変更せず、Transferイベントを発生させない場合、私たちはプロジェクト側が密かにトークンをmintしているかどうかを感知するのは非常に難しくなります。これにより、「トークンが安全かどうかは、完全にプロジェクト側の自覚に依存する」という現状が悪化します。
したがって、私たちは既存のトークンメカニズムを改善するか、トークンの総量検出の有効なソリューションを導入して、トークン数量の変更の公開と透明性を確保する必要があります。 現在、イベントを利用してトークンの状態変化を捕捉するだけでは不十分です。
また、私たちは警戒する必要があります。現在、皆の詐欺防止意識が高まっていますが、攻撃者の反詐欺手段も向上しています。これは終わりのないゲームであり、私たちは常に学び、考え続けることで、このようなゲームの中で自分自身を守る必要があります。