From 1b2234c51a23aeceabb97fb90abfb122730a54b1 Mon Sep 17 00:00:00 2001 From: EvilMuffinHa Date: Sat, 11 Jun 2022 17:12:06 -0400 Subject: [PATCH] sync --- .cargo/config | 2 + .gitignore | 1 + Cargo.lock | 75 +++++++++++++++++++++++++++++++ Cargo.toml | 13 ++++++ Makefile | 7 +++ solve/solve | Bin 0 -> 30 bytes solve/solve.s | 81 ++++++++++++++++++++++++++++++++++ src/device.rs | 84 +++++++++++++++++++++++++++++++++++ src/main.rs | 65 +++++++++++++++++++++++++++ src/vm.rs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 448 insertions(+) create mode 100644 .cargo/config create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 solve/solve create mode 100644 solve/solve.s create mode 100644 src/device.rs create mode 100644 src/main.rs create mode 100644 src/vm.rs diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..d67b66e --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[build] +target = "x86_64-unknown-linux-musl" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7724f0f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,75 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "drive" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1e7beb3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "drive" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" + +[profile.release] +panic = "abort" + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bf41281 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +.PHONY: solve + +default: solve + +solve: + nasm -o solve/solve solve/solve.s diff --git a/solve/solve b/solve/solve new file mode 100644 index 0000000000000000000000000000000000000000..93db8d4e2b84799288aadf78169a5bc0235d9c75 GIT binary patch literal 30 gcmWl{feipK48pLaJOckeInDB5vSXpY%{8f19~OK8U;qFB literal 0 HcmV?d00001 diff --git a/solve/solve.s b/solve/solve.s new file mode 100644 index 0000000..6327989 --- /dev/null +++ b/solve/solve.s @@ -0,0 +1,81 @@ +; vim: ft=nasm +%macro i_nop 0 + db 0x00 +%endmacro +%define np i_nop + + +%macro i_halt 1 + db 0x01 + db %1 +%endmacro +%define ht i_halt + +; load +%macro i_load 2 + db 0x10 + db %1 + db %2 +%endmacro +%define ld i_load + +; send +%macro i_send 2 + db 0x20 + db %1 + db %2 +%endmacro +%define sd i_send + +; get +%macro i_get 2 + db 0x21 + db %1 + db %2 +%endmacro +%define gt i_get + + +; jlt , , +; a < b +%macro i_less 3 + db 0x50 + db %1 + db %2 + db %3 +%endmacro +%define jl i_less + + +; jle , , +; a <= b +%macro i_leq 3 + db 0x51 + db %1 + db %2 + db %3 +%endmacro +%define le i_leq + +%define inp 0 +%define disp 1 +%define arith 2 +%define tape 3 + + +gt 0x00, inp +gt 0x01, inp +gt 0x02, inp +gt 0x03, inp +; [a, b, c, d] -> mem +sd tape, 0x00 +sd tape, 0x01 +sd tape, 0x02 +sd tape, 0x03 +; {a, b, c, d} + + + +sd disp, 0x00 +sd disp, 0x01 + diff --git a/src/device.rs b/src/device.rs new file mode 100644 index 0000000..f72b0ec --- /dev/null +++ b/src/device.rs @@ -0,0 +1,84 @@ +use std::io::Read; +use std::io::Write; + +pub trait Device { + fn get_byte(&mut self) -> u8; + fn send_byte(&mut self, byte: u8); +} + + +pub struct Reader<'a> { + pub reader: &'a mut dyn Read, +} + + +impl Device for Reader<'_> { + fn get_byte(&mut self) -> u8 { + self.reader.bytes().next().and_then(|result| result.ok()).map(|byte| byte as u8).unwrap() + } + + fn send_byte(&mut self, _byte: u8) { + } +} + +pub struct Tape { + pub tape: [u8; 25000], + pub index: usize, +} + +impl Device for Tape { + fn get_byte(&mut self) -> u8 { + let i = self.tape[self.index]; + if self.index == 0 { + self.index = 25000; + } + self.index -= 1; + self.index %= 25000; + i + } + + fn send_byte(&mut self, byte: u8) { + self.tape[self.index] = byte; + self.index += 1; + self.index %= 25000; + } + +} + +pub struct Writer<'a> { + pub writer: &'a mut dyn Write, +} + +impl Device for Writer<'_> { + fn get_byte(&mut self) -> u8 { + 0 + } + + fn send_byte(&mut self, byte: u8) { + self.writer.write_all(&[byte]).unwrap(); + } +} + +pub struct Arithmetic { + pub buffer: [u8; 3], + pub index: usize, +} + +impl Device for Arithmetic { + fn get_byte(&mut self) -> u8 { + match self.buffer[2] { + 1 => self.buffer[0] + self.buffer[1], + 2 => self.buffer[0] - self.buffer[1], + 3 => self.buffer[0] ^ self.buffer[1], + _ => 0 + } + } + + fn send_byte(&mut self, byte: u8) { + self.buffer[self.index] = byte; + self.index += 1; + self.index %= 3; + } +} + + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..85b7777 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,65 @@ +#![allow(dead_code)] + +mod device; +mod vm; + +use device::{Reader, Arithmetic, Tape, Writer}; +use std::io::Cursor; +use rand::prelude::random; +use std::io::Read; +use std::io; +use vm::{State, vm_run}; + + +fn main() { + + let program: Vec = io::stdin().bytes().map(|res| res.unwrap_or_else(|_| std::process::exit(1))).collect(); + + + for _ in 0..10 { + let iv: [u8; 4] = random(); + let mut input = Cursor::new(iv); + let mut output = Cursor::new(vec![0,0,0,0]); + + let state = State { + ip: 0usize, + mem: [0; 4], + program: program.clone(), + devices: vec![Box::new(Reader { reader: &mut input } ), + Box::new(Writer { writer: &mut output } ), + Box::new(Arithmetic { buffer: [0; 3], index: 0usize }), + Box::new(Tape { tape: [0; 25000], index: 0usize }),] + }; + vm_run(state); + let ov: [u8; 4] = output.into_inner().try_into().unwrap(); + println!("{:?}", iv); + println!("{:?}", encrypt(iv)); + println!("{:?}", ov); + if ov != encrypt(iv) { + std::process::exit(1); + } + } + +} + + +fn encrypt(block: [u8; 4]) -> [u8; 4] { + let mut block = block; + + let (i, _) = block[0].overflowing_add(block[3]); + block[1] ^= i; + let (i, _) = block[1].overflowing_add(block[0]); + block[2] ^= i; + let (i, _) = block[2].overflowing_add(block[1]); + block[3] ^= i; + let (i, _) = block[3].overflowing_add(block[2]); + block[0] ^= i; + + for _ in 0..block[3] { + let (mul, _) = block[2].overflowing_mul(block[0]); + let (sum, _) = mul.overflowing_add(block[1]); + block[0] = sum % block[3]; + } + + block +} diff --git a/src/vm.rs b/src/vm.rs new file mode 100644 index 0000000..0aab1f6 --- /dev/null +++ b/src/vm.rs @@ -0,0 +1,120 @@ +use crate::device::Device; + +#[repr(C)] +pub struct State<'a> { + pub ip: usize, + pub mem: [u8; 4], + pub program: Vec, + pub devices: Vec> +} + +impl State<'_> { + #[inline(never)] + fn next_byte(&mut self) -> u8 { + let result = self.program[self.ip]; + self.ip += 1; + result + } + + #[inline(never)] + fn next_word(&mut self) -> u16 { + let result = (u16::from(self.program[self.ip]) << 8) | u16::from(self.program[self.ip + 1]); + self.ip += 2; + result + } + + #[inline(never)] + fn next_dword(&mut self) -> u32 { + let result = (u32::from(self.program[self.ip]) << 24) | + (u32::from(self.program[self.ip + 1]) << 16) | + (u32::from(self.program[self.ip + 2]) << 8) | + (u32::from(self.program[self.ip + 3])); + self.ip += 4; + result + } +} + +#[repr(C)] +pub enum Opcode { + Nop, + Halt, + Load, + r#Send, + Get, + Less, + LessEq, + +} + + +impl From for Opcode { + fn from(v: u8) -> Self { + match v { + 0x00 => Opcode::Nop, + 0x01 => Opcode::Halt, + 0x10 => Opcode::Load, + 0x20 => Opcode::r#Send, + 0x21 => Opcode::Get, + 0x50 => Opcode::Less, + 0x51 => Opcode::LessEq, + _ => Opcode::Halt + } + } +} + + +pub fn vm_run(mut state: State) -> i32 { + loop { + if state.ip >= state.program.len() { + return 1 + } + + match Opcode::from(state.program[state.ip]) { + Opcode::Nop => { + state.ip += 1; + } + Opcode::Halt => { + state.ip += 1; + let ret = state.next_byte(); + return ret as i32; + } + Opcode::Load => { + state.ip += 1; + let location = state.next_byte() as usize; + let value = state.next_byte(); + state.mem[location] = value; + } + Opcode::r#Send => { + state.ip += 1; + let device = state.next_byte() as usize; + let mem = state.mem[state.next_byte() as usize]; + state.devices[device].send_byte(mem); + } + Opcode::Get => { + state.ip += 1; + let mem = state.next_byte() as usize; + let device = state.next_byte() as usize; + state.mem[mem] = state.devices[device].get_byte(); + } + Opcode::Less => { + state.ip += 1; + let mem1 = state.mem[state.next_byte() as usize]; + let mem2 = state.mem[state.next_byte() as usize]; + let jump = state.next_byte() as usize; + if mem1 < mem2 { + state.ip = jump; + } + } + Opcode::LessEq => { + state.ip += 1; + let mem1 = state.mem[state.next_byte() as usize]; + let mem2 = state.mem[state.next_byte() as usize]; + let jump = state.next_byte() as usize; + if mem1 <= mem2 { + state.ip = jump; + } + } + + } + } +}