script (⏱,💰)

script (⏱,💰)

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

ng7 スタート

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

2 番目の配列の長さが非常に小さい数字になるまで、Portal の数を増やし続けると、多くの Gas を消費せずに済みます。次の手順はわかるはずです。

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

結論#

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

ng7 エンド

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