問題概要
picoCTFの「Rust fixme 1」という問題の解説記事です。
- カテゴリ: General Skills
- 難易度: Easy
問題文
解説
この問題では、与えられたRustコードのコンパイルエラーを修正して、隠されたフラグを表示することが求められます。
ステップ1: ソースコードの確認
まずは、提供されたRustソースコード
fixme1.tar.gz を展開し、内容を確認します。$ tar -xvf fixme1.tar.gz
fixme1/
fixme1/Cargo.toml
fixme1/Cargo.lock
fixme1/src/
fixme1/src/main.rs
展開後、
fixme1/src/main.rs ファイルを確認します。$ cat fixme1/src/main.rs
use xor_cryptor::XORCryptor;
fn main() {
// Key for decryption
let key = String::from("CSUCKS") // How do we end statements in Rust?
// Encrypted flag values
let hex_values = ["41", "30", "20", "63", "4a", "45", "54", "76", "01", "1c", "7e", "59", "63", "e1", "61", "25", "7f", "5a", "60", "50", "11", "38", "1f", "3a", "60", "e9", "62", "20", "0c", "e6", "50", "d3", "35"];
// 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();
// Create decrpytion object
let res = XORCryptor::new(&key);
if res.is_err() {
ret; // How do we return in rust?
}
let xrc = res.unwrap();
// Decrypt flag and print it out
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
println!(
":?", // How do we print out a variable in the println function?
String::from_utf8_lossy(&decrypted_buffer)
);
}
この問題は、問題文・コメントの通り「Rustの文法を直してね」というタイプのものです。
まずは一度
cargo run して、コンパイルエラーになることを確認します。$ cd fixme1
$ cargo run
ステップ2: コンパイルエラーを修正
コード中にある「How do we ... ?」のコメントが、そのまま修正ポイントを示しています。
修正ポイント1: 文末のセミコロン(;)
Rustでは、
let などの 文(statement) は基本的に末尾に ; が必要です。以下の行は
; が無いのでエラーになります。let key = String::from("CSUCKS")
修正後
let key = String::from("CSUCKS");
修正ポイント2: ret → return
Rustに
ret というキーワードはありません。
関数から抜けるには return を使います。今回
main() は戻り値が ()(何も返さない)なので、失敗時は単に return; でOKです。修正後
if res.is_err() {
return;
}
なお、よりRustらしく書くなら
match / if let / ? なども使えますが、ここでは最小修正で進めます。修正ポイント3: println! のフォーマット文字列
Rustの
println! は、Pythonのf-stringのように「フォーマット指定子」を使います。{}: 表示用(Display){:?}: デバッグ表示(Debug)
元のコードは
":?" となっており、{} が無いので正しく表示できません。今回
String::from_utf8_lossy(&decrypted_buffer) は文字列として表示したいので、{} を使うのが分かりやすいです。修正後
println!(
"{}",
String::from_utf8_lossy(&decrypted_buffer)
);
ステップ3: 修正後のコードで実行
上の修正点を反映すると、
main.rs は次のようになります。use xor_cryptor::XORCryptor;
fn main() {
// Key for decryption
let key = String::from("CSUCKS");
// Encrypted flag values
let hex_values = [
"41", "30", "20", "63", "4a", "45", "54", "76", "01", "1c", "7e", "59", "63", "e1",
"61", "25", "7f", "5a", "60", "50", "11", "38", "1f", "3a", "60", "e9", "62", "20",
"0c", "e6", "50", "d3", "35",
];
// 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();
// 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);
println!("{}", String::from_utf8_lossy(&decrypted_buffer));
}
実行します。
$ cd fixme1
$ cargo run
出力例
picoCTF{xxxxx}
※フラグはマスクしています。
使用したコマンドの軽い解説
tar
tar -xvf fixme1.tar.gz
配布されたアーカイブを展開するコマンドです。
cargo run
cargo run
Rustのビルド&実行をまとめて行います。 コンパイルエラーもここで確認できます。
まとめ
picoCTFの「Rust fixme 1」問題では、Rustの基本文法(セミコロン、
return、println! のフォーマット)を直すことで、復号処理が動きフラグを取得できました。▼ポイントは以下の通りです。
- Rustの文は基本的に
;で終える - 関数から抜けるなら
return; println!は"{}"や"{:?}"などのフォーマット指定子を使う
閲覧ありがとうございました!
NEXT
次におすすめ
読み終わったら、そのまま次へ
【picoCTF】Rust fixme 3 - ライフタイムと可変参照を整理してXOR復号
カテゴリ: General Skills難易度: Easy#picoCTF
次の記事へ →
同じカテゴリ/難易度/picoCTFでの表示順が近い記事を優先しておすすめしています。