問題概要
picoCTFの「Rust fixme 2」という問題の解説記事です。
- カテゴリ: General Skills
- 難易度: Easy
問題文
解説
この問題では、与えられたRustコードのコンパイルエラーを修正して、隠されたフラグを表示することが求められます。
ステップ1: ソースコードの確認
まずは、提供されたRustソースコード
fixme2.tar.gz を展開し、内容を確認します。$ tar -xvf fixme2.tar.gz
fixme2/
fixme2/Cargo.toml
fixme2/Cargo.lock
fixme2/src/
fixme2/src/main.rs
展開されたディレクトリに移動し、
fixme2/src/main.rs の内容を確認します。$ cd fixme2
$ cat src/main.rs
use xor_cryptor::XORCryptor;
fn decrypt(encrypted_buffer:Vec<u8>, borrowed_string: &String){ // How do we pass values to a function that we want to change?
// Key for decryption
let key = String::from("CSUCKS");
// Editing our borrowed value
borrowed_string.push_str("PARTY FOUL! Here is your flag: ");
// Create decrpytion object
let res = XORCryptor::new(&key);
if res.is_err() {
return; // How do we return in rust?
}
let xrc = res.unwrap();
// Decrypt flag and print it out
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
borrowed_string.push_str(&String::from_utf8_lossy(&decrypted_buffer));
println!("{}", borrowed_string);
}
fn main() {
// Encrypted flag values
let hex_values = ["41", "30", "20", "63", "4a", "45", "54", "76", "01", "1c", "7e", "59", "63", "e1", "61", "25", "0d", "c4", "60", "f2", "12", "a0", "18", "03", "51", "03", "36", "05", "0e", "f9", "42", "5b"];
// Convert the hexadecimal strings to bytes and collect them into a vector
let encrypted_buffer: Vec<u8> = hex_values.iter()
.map(|&hex| u8::from_str_radix(hex, 16).unwrap())
.collect();
let party_foul = String::from("Using memory unsafe languages is a: "); // Is this variable changeable?
decrypt(encrypted_buffer, &party_foul); // Is this the correct way to pass a value to a function so that it can be changed?
}
この
main.rs は「借用(borrow)と可変参照(mutable reference)」を修正して、フラグを表示できるようにする問題です。まずは一度
cargo run を実行して、コンパイルエラーになることを確認します。$ cargo run
ステップ2: コンパイルエラーを修正
コード中のコメントが、そのまま修正ポイントになっています。
修正ポイント1: 変更したい値は &String ではなく &mut String
borrowed_string.push_str(...) のように文字列を変更するには、引数として 可変参照 を受け取る必要があります。元のコード
fn decrypt(encrypted_buffer: Vec<u8>, borrowed_string: &String)
修正後
fn decrypt(encrypted_buffer: Vec<u8>, borrowed_string: &mut String)
修正ポイント2: 呼び出し側も mut + &mut にする
関数に
&mut String を渡すには、呼び出し側の変数も mut で宣言し、&mut を付けて渡します。元のコード
let party_foul = String::from("Using memory unsafe languages is a: ");
decrypt(encrypted_buffer, &party_foul);
修正後
let mut party_foul = String::from("Using memory unsafe languages is a: ");
decrypt(encrypted_buffer, &mut party_foul);
修正ポイント3: return; はこのままでOK
decrypt() の戻り値は ()(何も返さない)なので、失敗時は return; で関数を抜ければOKです。ステップ3: 修正後のコードで実行
上の修正点を反映すると、
main.rs は次のようになります。use xor_cryptor::XORCryptor;
fn decrypt(encrypted_buffer: Vec<u8>, borrowed_string: &mut String) {
// Key for decryption
let key = String::from("CSUCKS");
// Editing our borrowed value
borrowed_string.push_str("PARTY FOUL! Here is your flag: ");
// Create decrpytion object
let res = XORCryptor::new(&key);
if res.is_err() {
return;
}
let xrc = res.unwrap();
// Decrypt flag and print it out
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
borrowed_string.push_str(&String::from_utf8_lossy(&decrypted_buffer));
println!("{}", borrowed_string);
}
fn main() {
// Encrypted flag values
let hex_values = [
"41", "30", "20", "63", "4a", "45", "54", "76", "01", "1c", "7e", "59", "63", "e1",
"61", "25", "0d", "c4", "60", "f2", "12", "a0", "18", "03", "51", "03", "36", "05",
"0e", "f9", "42", "5b",
];
// Convert the hexadecimal strings to bytes and collect them into a vector
let encrypted_buffer: Vec<u8> = hex_values
.iter()
.map(|&hex| u8::from_str_radix(hex, 16).unwrap())
.collect();
let mut party_foul = String::from("Using memory unsafe languages is a: ");
decrypt(encrypted_buffer, &mut party_foul);
}
実行します。
$ cd fixme2
$ cargo run
出力例
Using memory unsafe languages is a: PARTY FOUL! Here is your flag: picoCTF{xxxxx}
※フラグはマスクしています。
使用したコマンドの軽い解説
tar
tar -xvf fixme2.tar.gz
配布されたアーカイブを展開するコマンドです。
cargo run
cargo run
Rustのビルド&実行をまとめて行います。 コンパイルエラーもここで確認できます。
まとめ
picoCTFの「Rust fixme 2」問題では、関数に渡した文字列を変更できるように 可変参照(
&mut) を使うのがポイントでした。▼ポイントは以下の通りです。
- 関数内で値を変更したいなら、引数は
&Tではなく&mut T - 呼び出し側も
let mut ...で宣言し、&mutを付けて渡す
閲覧ありがとうございました!
NEXT
次におすすめ
読み終わったら、そのまま次へ
【picoCTF】Rust fixme 3 - ライフタイムと可変参照を整理してXOR復号
カテゴリ: General Skills難易度: Easy#picoCTF
次の記事へ →
同じカテゴリ/難易度/picoCTFでの表示順が近い記事を優先しておすすめしています。