finished!

This commit is contained in:
EvilMuffinHa 2022-07-13 13:03:54 -04:00
parent 4986e97e2b
commit ed259baee5
6 changed files with 355 additions and 79 deletions

1
flag.txt Normal file
View File

@ -0,0 +1 @@
dummy

Binary file not shown.

View File

@ -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

View File

@ -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;
}
}

View File

@ -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<u8> = io::stdin()
.bytes()
.map(|res| res.unwrap_or_else(|_| std::process::exit(1)))
.collect();
let program: Vec<u8> = 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]);

View File

@ -5,7 +5,7 @@ pub struct State<'a> {
pub ip: usize,
pub mem: [u8; 4],
pub program: Vec<u8>,
pub devices: Vec<Box<dyn Device + 'a>>
pub devices: Vec<Box<dyn Device + 'a>>,
}
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<u8> for Opcode {
fn from(v: u8) -> Self {
match v {
@ -57,18 +55,16 @@ impl From<u8> 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;
}
}
}
}
}