picoCTF General Skills Guide

here's how to solve Rust fixme 2

Back to the General Skills Guides

Rust fixme 2

Name: Rust fixme 2
Description: The Rust saga continues? I ask you, can I borrow that, pleeeeeaaaasseeeee? Download the Rust code here.
Author: Taylor McCampbell
Tags: Easy, General Skills, picoCTF 2025
Challenge from: picoCTF 2025
Files: fixme2.tar.gz
Hints:
1. https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html

Theory

According to the description, to get the flag we to download some rust code, and fix the errors. Before doing that, comes the hard part, setting up rust. I used Replit, which is a platform to run many programming languages online, including rust, and believe me, I tried installing rust at first, but was met with a lot of dead ends, downloaded 4.5 gigabytes of content, and didn't really get to actually run it, so I just used Replit, which everything is already set up, and I just had to paste the code and libraries (which it downloads automatically) from the tar file. And when you create the project, it's instantly public, which I am so sorry, but I missed that for the entire competition, I literally had the rust codes public on my Replit already solved and with the flags on it, so I could've been disqualified, but luckily nobody noticed my mistake, which you can find here, just ignore the name of the repl. Anyways, onto the actual challenge.

Solution

First let's paste our code:

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?
}

So right off the bat, we can see that there are four comments highlighting the four errors in the code. How do we pass values to a function that we want to change? With a mutation to `borrowed_string`. How do we return in rust? That `return;` is already correct wtf. Is this variable changeable? Yes, so make it mutable. Is this the correct way to pass a value to a function so that it can be changed? No, it also has to be mutable. Also I'm gonna remove all the comments for no reason at all:

use xor_cryptor::XORCryptor;

fn decrypt(encrypted_buffer: Vec<u8>, borrowed_string: &mut String) {
    let key = String::from("CSUCKS");

    borrowed_string.push_str("PARTY FOUL! Here is your flag: ");

    let res = XORCryptor::new(&key);
    if res.is_err() {
        return;
    }
    let xrc = res.unwrap();

    let decrypted_buffer = xrc.decrypt_vec(encrypted_buffer);
    borrowed_string.push_str(&String::from_utf8_lossy(&decrypted_buffer));
    println!("{}", borrowed_string);
}

fn main() {
    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"];

    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);
}

And when we run this code:

    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
   Compiling rust_proj v0.1.0 (/home/runner/workspace)
    Building [=======================>   ] 11/12: rust_proj(bin)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.30s
     Running `target/debug/rust_proj`
"Using memory unsafe languages is a: PARTY FOUL! Here is your flag: picoCTF{4r3_y0u_h4v1n5_fun_y31?}"

There we go! That's the flag.

I rated this level as "good"! :3


https://play.picoctf.org/practice/challenge/462