picoCTF Writeup: Rust Fixme 2 - Battling the Borrow Checker
picoCTF Writeup: Rust Fixme 2 - Battling the Borrow Checker
For unzip tar -xzvf fixme2.tar.gz
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?
}
cargo run to tun the progarm
┌──(nirmal㉿NirmalsFLOWX16)-[~/CTF/RustFixme_2/fixme2]
└─$ cargo run
Compiling crossbeam-utils v0.8.20
Compiling rayon-core v1.12.1
Compiling either v1.13.0
Compiling crossbeam-epoch v0.9.18
Compiling crossbeam-deque v0.8.5
Compiling rayon v1.10.0
Compiling xor_cryptor v1.2.3
Compiling rust_proj v0.1.0 (/home/nirmal/CTF/RustFixme_2/fixme2)
error[E0596]: cannot borrow `*borrowed_string` as mutable, as it is behind a `&` reference
--> src/main.rs:9:5
|
9 | borrowed_string.push_str("PARTY FOUL! Here is your flag: ");
| ^^^^^^^^^^^^^^^ `borrowed_string` is a `&` reference, so it cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
3 | fn decrypt(encrypted_buffer:Vec<u8>, borrowed_string: &mut String){ // How do we pass values to a function that we want to change?
| +++
error[E0596]: cannot borrow `*borrowed_string` as mutable, as it is behind a `&` reference
--> src/main.rs:20:5
|
20 | borrowed_string.push_str(&String::from_utf8_lossy(&decrypted_buffer));
| ^^^^^^^^^^^^^^^ `borrowed_string` is a `&` reference, so it cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
3 | fn decrypt(encrypted_buffer:Vec<u8>, borrowed_string: &mut String){ // How do we pass values to a function that we want to change?
| +++
For more information about this error, try `rustc --explain E0596`.
error: could not compile `rust_proj` (bin "rust_proj") due to 2 previous errors
After running the program.
I asked Gemini and...
Passing Values You Want to Change (Mutable References)
In your first snippet, the function signature is currently giving you "read-only" access to the string, and it is entirely consuming the buffer:
-
encrypted_buffer: Vec<u8>: This takes ownership of the vector. Once this function runs, the original vector in the calling code is destroyed (moved). -
borrowed_string: &String: The&symbol means it is an immutable reference. You can read the string, but the compiler will throw an error if you try to modify it.
The Fix: To modify a variable inside a function without destroying the original or triggering a compiler error, you must pass a mutable reference using &mut.
line 19 was changed to this As the compiler suggests.
let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer.to_vec());
line 35 to this. Because we are using mutable ones.
decrypt(&mut encrypted_buffer, &mut party_foul);
and then, let mut encrypted_buffer: and let mut party_foul as the rules.
┌──(nirmal㉿NirmalsFLOWX16)-[~/CTF/RustFixme_2/fixme2]
└─$ cargo run
Compiling rust_proj v0.1.0 (/home/nirmal/CTF/RustFixme_2/fixme2)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
Running `target/debug/rust_proj`
Using memory unsafe languages is a: PARTY FOUL! Here is your flag: picoCTF{4r3_y0u_h4v1n5_fun_y31?}
Got the flag.