script (⏱,💰)

script (⏱,💰)

NG#7 - calldata NG#7 - コールデータ

ng7 start

このタスクでは、StarkNet の calldata に関するものです。calldata とは、関数呼び出し時に関数に渡されるデータを指します。StarkNet では、渡されるデータはさまざまなタイプになる可能性がありますが、最終的には複数の felt252 で構成されるスナップショットに変換されます。詳細はcall_contract_syscallを参照してください。

2 つの契約があり、PortalSpell 契約の cast はArray<PortalData>を受け入れます。DrunkenMage 契約の cast は 2 つのArray<felt252>を受け入れます。2 つの Array で構成される calldata とArray<PortalData>の最初の 2 つの PortalData が同じである必要があります(契約コードで検証されています)。

struct PortalData {
  location: felt252,
  details: Array<felt252>
}

// 期待される関数のシグネチャ
cast(portal_data: Array<PortalData>)

// Mageの関数のシグネチャ
cast(origin: Array<felt252>, destination: Array<felt252>)

上記の cast はディスパッチャを介してクロスコントラクト呼び出しを行い、引数の一致を検証する必要はありません。

アプローチ#

まず、StarkNet 契約が calldata をどのように解析するかを理解する必要があります。ウォークスルーには非常に明確に説明されています。

エンコードする目標は Array<PortalData> であり、値は
[ 0: { location: 'TAVERN', details: [ 'OPEN', 'PORTAL' ] }, 1: { location: 'HOME', details: [ 'CLOSE', 'PORTAL' ] } ]

Serde が実装されているため、struct をシリアライズできます。テストで印刷した結果、単一の struct のエンコードは次のようになります。

[DEBUG] TAVERN          (raw: 0x54415645524e
[DEBUG]                 (raw: 0x2
[DEBUG] OPEN            (raw: 0x4f50454e
[DEBUG] PORTAL          (raw: 0x504f5254414c

2 つの PortalData を合わせて、前に 2 を追加すると、最終的なエンコードになります。

drunk_spell.cast(origin, destination) は分けて渡されるため、 origindestination の値を見つける必要があります。これにより、 Array<PortalData> として解釈されると、必要な calldata を反映することができます。

検証する必要があるのは最初の 2 つの Portal のみであり、 ['TAVERN', 2, 'OPEN', 'PORTAL', 'HOME', 2, 'CLOSE', 'PORTAL'] である必要があります。

もし、 PortalData {location: 'VOID', details: ['ANY']} を追加すると、エンコードは [3, 'TAVERN', 2, 'OPEN', 'PORTAL', 'HOME', 2, 'CLOSE', 'PORTAL','VOID', 1 , 'ANY'] になりますが、これも検証に合格します。

しかし、2 つの array に分割して渡す場合、 [3, 'TAVERN', 2, 'OPEN', 'PORTAL']['PORTAL', 'HOME', 2, 'CLOSE', 'PORTAL','VOID', 1 , 'ANY'] になります。 'PORTAL' を felt の 10 進数に変換すると非常に大きな数値になり、details の長さを満たすために details を長くするか、さらに多くの portal を追加する必要があります。テスト実行時にエラーが発生します。

そのため、第二のパラメータの array の長さが非常に小さい数字になるまで、Portal の数を増やすことで、ガスをあまり消費せずに済むようにします。これで書く方法がわかるはずです。

テストに合格した後、ハック契約をデプロイして解読する準備をします。starkli invoke を使用しても配列を渡すことはできませんが、snforge invoke --calldataを使用すると calldata を渡すことができますが、アカウントなどの追加のパラメータをどのように渡すかわかりません。最終的には、Voyager ブラウザを使用して 2 つの calldata を直接送信する方法が最も簡単だとわかりました。

結論#

StarkNet の calldata の構成ルールは非常にシンプルです。この問題の難しいところは、特定の calldata を構成するためにさらに多くの Portal を追加する必要があることです。非常に興味深い CTF 問題です。

ng7 end

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。