diff --git a/flag.txt b/flag.txt new file mode 100644 index 0000000..421376d --- /dev/null +++ b/flag.txt @@ -0,0 +1 @@ +dummy diff --git a/solve/solve b/solve/solve index 5bf9bde..0e5906c 100644 Binary files a/solve/solve and b/solve/solve differ diff --git a/solve/solve.s b/solve/solve.s index c0ede8a..35c0538 100644 --- a/solve/solve.s +++ b/solve/solve.s @@ -1,10 +1,11 @@ ; vim: ft=nasm +s: + %macro i_nop 0 db 0x00 %endmacro %define np i_nop - %macro i_halt 1 db 0x01 db %1 @@ -42,7 +43,8 @@ db 0x50 db %1 db %2 - db %3 + db (%3 >> 8) & 0xff + db %3 & 0xff %endmacro %define jl i_less @@ -53,10 +55,19 @@ db 0x51 db %1 db %2 - db %3 + db (%3 >> 8) & 0xff + db %3 & 0xff %endmacro %define le i_leq +%macro break 0 + sd disp, 0x00 + sd disp, 0x01 + sd disp, 0x02 + sd disp, 0x03 + np +%endmacro + %define inp 0 %define disp 1 %define arith 2 @@ -69,72 +80,324 @@ gt 0x02, inp gt 0x03, inp ; [a, b, c, d] -> mem sd tape, 0x00 -sd tape, 0x01 sd tape, 0x02 +sd tape, 0x01 sd tape, 0x03 ; {a, b, c, d} + + +sd arith, 0x00 +sd arith, 0x03 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x03, arith ; [i[0], i[1], i[2], i[3] + i[0]] ; - add i[3] and i[0] +sd arith, 0x01 +sd arith, 0x03 + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x03, arith ; [i[0], i[1], i[2], (i[3] + i[0]) ^ i[1]] ; - xor i[1] with i[3] + i[0], pop from arith +sd arith, 0x00 +sd arith, 0x01 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith ; [i[0] + i[1], i[1], i[2], (i[3] + i[0]) ^ i[1]] ; - add i[0] and i[1], pop from arith +sd arith, 0x00 +sd arith, 0x02 + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x02, arith ; [i[0] + i[1], i[1], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - xor i[0] + i[1] with i[2], pop from arith + +sd arith, 0x00 +sd arith, 0x02 + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith ; [i[2], i[1], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - xor (i[0] + i[1]) ^ i[2] with i[0] + i[1], pop from arith +sd arith, 0x00 +sd arith, 0x01 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x01, arith +sd arith, 0x01 ; [i[2], i[2] + i[1], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - add i[2] + i[1], pop from arith | store i[2] + i[1] in arith +gt 0x01, tape +sd arith, 0x01 ; [i[2], i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - pop i[3] from tape use previous i[1] + i[2] from arith to xor + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x01, arith ; [i[2], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - use previous i[1] + i[2] from arith to xor and pop +sd arith, 0x00 +gt 0x00, tape ; [i[1], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - put i[2] in arith, pop i[1] from tape +sd arith, 0x00 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith ; [i[2] + i[1], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - put i[1] in arith, add, pop +sd arith, 0x00 +sd arith, 0x01 + + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith + ; [i[3], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - xor i[2] + i[1] with (i[2] + i[1]) ^ i[3] +sd arith, 0x00 +gt 0x00, tape + ; [i[2], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - put i[3] in arith, pop i[2] from tape +sd arith, 0x00 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith + ; [i[2] + i[3], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - put i[2] in arith, add to i[3] +sd arith, 0x00 +gt 0x00, tape ; [i[0], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - put i[2] + i[3] in arith, pop i[0] from tape +sd arith, 0x00 + +sd tape, 0x00 +ld 0x00, 0x03 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith ; [(i[2] + i[3]) ^ i[0], (i[2] + i[1]) ^ i[3], (i[0] + i[1]) ^ i[2], (i[3] + i[0]) ^ i[1]] ; - xor in arith + + +sd tape, 0x00 +sd tape, 0x01 +sd tape, 0x02 +sd tape, 0x03 +gt 0x01, tape +gt 0x02, tape +gt 0x03, tape +gt 0x00, tape + + ; push all to tape ; pop all back into mem in correct spot +; stage 1 done + +; :b [a, b, c, d] (, ,) +sd tape, 0x01 +; :b [a, b, c, d] (b, , ) +sd arith, 0x01 +; :b [a, 0, c, d] (b, 0, +) +ld 0x01, 0x00 +sd arith, 0x01 +ld 0x01, 0x01 +sd arith, 0x01 +; :b [a, t, c, d] (b, 0, +) +sd tape, 0x03 +gt 0x01, tape +; :b t [a, t, c, d] (b, 0, +) +sd tape, 0x01 +; :b t [a, b, c, d] () +gt 0x01, arith + +loop: +; :b t c [a * c, b, 0, d] () +sd tape, 0x02 +sd tape, 0x03 ; :b t c d [a, b, c, d] +sd tape, 0x00 +gt 0x03, tape ; :b t c d [a, b, c, a] + +multip: + + sd arith, 0x02 + ld 0x02, 0x01 + sd arith, 0x02 + ld 0x02, 0x02 ; sub 1 from c + sd arith, 0x02 + gt 0x02, arith + + sd arith, 0x00 + sd arith, 0x03 + ld 0x00, 0x01 ; a + a + sd arith, 0x00 + gt 0x00, arith + sd tape, 0x00 ; :b t c d a+a [a+a, b, c-1, a] -; routine for doing overflowing add -; [a, b] -; [255 - a, b] -; 255 - a < b -; a = b - [255 - a] -; 255 - a >= b -; a = a + b -; + ld 0x00, 0x01 ; :b t c d a+a [1, b, c-1, a] + le 0x02, 0x00, leavemul - s + gt 0x00, tape ; put back a + a + + ; :b t c d [a+a, b, c-1, a] + le 0x00, 0x00, multip - s ; jump to mul + +leavemul: + +gt 0x00, tape +gt 0x03, tape +gt 0x02, tape +; :b t [a * c, b, c, d] () + +sd arith, 0x00 +sd arith, 0x01 + +sd tape, 0x00 +ld 0x00, 0x01 +sd arith, 0x00 +gt 0x00, tape + +gt 0x00, arith +; :b t [a * c + b, b, c, d] () + +modulo: + jl 0x00, 0x03, leavemod - s + + sd arith, 0x00 + sd arith, 0x03 + + sd tape, 0x00 + ld 0x00, 0x02 + sd arith, 0x00 + gt 0x00, tape + + gt 0x00, arith + + le 0x00, 0x00, modulo - s + +leavemod: + +; :b t [(ac + b) % d, b, c, d] () + +gt 0x01, tape +; :b [(ac + b) % d, t, c, d] () +sd arith, 0x01 +ld 0x01, 0x01 +; :b [(ac + b) % d, 1, c, d] (t, ) +sd arith, 0x01 +ld 0x01, 0x02 +sd arith, 0x01 +; :b [(ac + b) % d, 1, c, d] (t, 1, -) +gt 0x01, arith +; :b [(ac + b) % d, t-1, c, d] () +sd tape, 0x02 +ld 0x02, 0x00 +le 0x01, 0x02, finish - s + +gt 0x02, tape +; if t - 1 leq 0 -> jump out +; else -> continue +sd arith, 0x02 +; :b [(ac + b) % d, t-1, c, d] (c, ,) +ld 0x02, 0x00 +sd arith, 0x02 +ld 0x02, 0x01 +sd arith, 0x02 +; :b [(ac + b) % d, t-1, 0, d] (c, 0, +) +gt 0x02, tape +; : [(ac + b) % d, t-1, b, d] (c, 0, +) +sd tape, 0x02 +; :b [(ac + b) % d, t-1, b, d] (c, 0, +) +sd tape, 0x01 +; :b t-1 [(ac + b) % d, t-1, b, d] (c, 0, +) +sd tape, 0x02 +; :b t-1 b [(ac + b) % d, t-1, b, d] (c, 0, +) +gt 0x02, arith +; :b t-1 b [(ac + b) % d, t-1, c, d] () +gt 0x01, tape +; :b t-1 [(ac + b) % d, b, c, d] () +le 0x03, 0x03, loop - s +; if d leq d -> jump loop + +finish: +gt 0x02, tape +gt 0x01, tape - -le 0x00, 0x01, label sd disp, 0x00 -label: - sd disp, 0x01 +sd disp, 0x01 +sd disp, 0x02 +sd disp, 0x03 +; finish things + + + + + + +;le 0x00, 0x01, label +;sd disp, 0x00 +;label: +; sd disp, 0x01 diff --git a/src/device.rs b/src/device.rs index f72b0ec..2c7fa18 100644 --- a/src/device.rs +++ b/src/device.rs @@ -6,19 +6,21 @@ pub trait Device { 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() + self.reader + .bytes() + .next() + .and_then(|result| result.ok()) + .map(|byte| byte as u8) + .unwrap() } - fn send_byte(&mut self, _byte: u8) { - } + fn send_byte(&mut self, _byte: u8) {} } pub struct Tape { @@ -28,13 +30,12 @@ pub struct Tape { 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 + self.tape[self.index] } fn send_byte(&mut self, byte: u8) { @@ -42,7 +43,6 @@ impl Device for Tape { self.index += 1; self.index %= 25000; } - } pub struct Writer<'a> { @@ -67,10 +67,10 @@ pub struct Arithmetic { 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], + 1 => self.buffer[0].overflowing_add(self.buffer[1]).0, + 2 => self.buffer[0].overflowing_sub(self.buffer[1]).0, 3 => self.buffer[0] ^ self.buffer[1], - _ => 0 + _ => 0, } } @@ -80,5 +80,3 @@ impl Device for Arithmetic { self.index %= 3; } } - - diff --git a/src/main.rs b/src/main.rs index 85b7777..e14aba4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,57 +3,76 @@ mod device; mod vm; -use device::{Reader, Arithmetic, Tape, Writer}; -use std::io::Cursor; +use device::{Arithmetic, Reader, Tape, Writer}; use rand::prelude::random; -use std::io::Read; +use std::fs; use std::io; -use vm::{State, vm_run}; - +use std::io::Cursor; +use std::io::Read; +use vm::{vm_run, State}; fn main() { + let program: Vec = io::stdin() + .bytes() + .map(|res| res.unwrap_or_else(|_| std::process::exit(1))) + .collect(); - 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); - } - } + 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(); + if ov != encrypt(iv) { + std::process::exit(1); + } + } + println!( + "{}", + fs::read_to_string("flag.txt").unwrap_or_else(|_| { + println!("Couldn't open flag file, please contact an admin if on the server."); + std::process::exit(1) + }) + ); } - +#[inline(never)] fn encrypt(block: [u8; 4]) -> [u8; 4] { let mut block = block; + #[allow(clippy::clone_on_copy)] + let mut b = block.clone(); + let (i, _) = block[0].overflowing_add(block[3]); - block[1] ^= i; + b[1] ^= i; let (i, _) = block[1].overflowing_add(block[0]); - block[2] ^= i; + b[2] ^= i; let (i, _) = block[2].overflowing_add(block[1]); - block[3] ^= i; + b[3] ^= i; let (i, _) = block[3].overflowing_add(block[2]); - block[0] ^= i; + b[0] ^= i; + + block = b; for _ in 0..block[3] { let (mul, _) = block[2].overflowing_mul(block[0]); diff --git a/src/vm.rs b/src/vm.rs index 0aab1f6..1e18191 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -5,7 +5,7 @@ pub struct State<'a> { pub ip: usize, pub mem: [u8; 4], pub program: Vec, - pub devices: Vec> + pub devices: Vec>, } impl State<'_> { @@ -25,10 +25,10 @@ impl State<'_> { #[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])); + 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 } @@ -43,10 +43,8 @@ pub enum Opcode { Get, Less, LessEq, - } - impl From for Opcode { fn from(v: u8) -> Self { match v { @@ -57,18 +55,16 @@ impl From for Opcode { 0x21 => Opcode::Get, 0x50 => Opcode::Less, 0x51 => Opcode::LessEq, - _ => Opcode::Halt + _ => Opcode::Halt, } } } - pub fn vm_run(mut state: State) -> i32 { loop { if state.ip >= state.program.len() { - return 1 + return 1; } - match Opcode::from(state.program[state.ip]) { Opcode::Nop => { state.ip += 1; @@ -100,7 +96,7 @@ pub fn vm_run(mut state: State) -> i32 { 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; + let jump = state.next_word() as usize; if mem1 < mem2 { state.ip = jump; } @@ -109,12 +105,11 @@ pub fn vm_run(mut state: State) -> i32 { 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; + let jump = state.next_word() as usize; if mem1 <= mem2 { state.ip = jump; } } - } } }