csaw 2021 final control source by hgarrereyn modified for bbctf 2023 more control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
target | |
ext.bin | |
main.bin | |
main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
from dataclasses import dataclass | |
import struct | |
defs = ''' | |
#define REG_r0_R_DATA (1 << 0) | |
#define REG_r0_W_DATA (1 << 1) | |
#define REG_r0_W_ADDR (1 << 2) | |
#define REG_r1_R_DATA (1 << 3) | |
#define REG_r1_W_DATA (1 << 4) | |
#define REG_r1_W_ADDR (1 << 5) | |
#define REG_r2_R_DATA (1 << 6) | |
#define REG_r2_W_DATA (1 << 7) | |
#define REG_r2_W_ADDR (1 << 8) | |
#define REG_r3_R_DATA (1 << 9) | |
#define REG_r3_W_DATA (1 << 10) | |
#define REG_r3_W_ADDR (1 << 11) | |
#define REG_sp_R_DATA (1 << 12) | |
#define REG_sp_W_DATA (1 << 13) | |
#define REG_sp_W_ADDR (1 << 14) | |
#define ALU_R_X (1 << 15) | |
#define ALU_R_Y (1 << 16) | |
#define ALU_ADD (1 << 18) | |
#define ALU_MUL (1 << 19) | |
#define ALU_SHF (1 << 17) | |
#define ALU_XOR (1 << 20) | |
#define ALU_EQ (1 << 21) | |
#define RAM_R (1 << 22) | |
#define RAM_W (1 << 23) | |
#define OUT_R (1 << 24) | |
#define IN_W (1 << 25) | |
#define ROM_W_IP (1 << 26) | |
#define ROM_W_ADDR (1 << 27) | |
#define IP_ADD_1 (1 << 28) | |
#define IP_ADD_2 (1 << 29) | |
#define IP_R_DATA (1 << 30) | |
#define HLT (1 << 31) | |
''' | |
defs = defs.strip().split('\n') | |
defs = [x for x in defs if x != ''] | |
defs = [x[8:] for x in defs] | |
for d in defs: | |
s = d.split(' ') | |
v = s[0] | |
t = eval(' '.join(s[1:])) | |
globals()[v] = t | |
label_map = {} | |
label_warn = False | |
@dataclass | |
class Label(object): | |
name: str | |
def lookup(lbl): | |
if lbl in label_map: | |
return label_map[lbl] | |
else: | |
if label_warn: | |
print('Label error: ', lbl) | |
return 0 | |
def hlt(): | |
return [(HLT)] | |
def mov(dst, src): | |
return eval(f'''[ | |
(REG_{src}_W_DATA | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def li(dst, val): | |
return eval(f'''[ | |
(REG_{dst}_R_DATA | ROM_W_IP | IP_ADD_2), | |
({val}) | |
]''') | |
def la(dst, lbl): | |
addr = lookup(lbl) | |
return eval(f'''[ | |
(REG_{dst}_R_DATA | ROM_W_IP | IP_ADD_2), | |
({addr}) | |
]''') | |
def addi(dst, val): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({val}), | |
(ALU_ADD | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def add(dst, dst2): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(REG_{dst2}_W_DATA | ALU_R_Y | IP_ADD_1), | |
(ALU_ADD | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def xor(dst, dst2): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(REG_{dst2}_W_DATA | ALU_R_Y | IP_ADD_1), | |
(ALU_XOR | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def xori(dst, val): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({val}), | |
(ALU_XOR | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def mul(dst, dst2): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(REG_{dst2}_W_DATA | ALU_R_Y | IP_ADD_1), | |
(ALU_MUL | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def shifti(dst, val): | |
return eval(f'''[ | |
(REG_{dst}_W_DATA | ALU_R_X | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({val}), | |
(ALU_SHF | REG_{dst}_R_DATA | IP_ADD_1) | |
]''') | |
def push(reg): | |
return eval(f'''[ | |
(REG_{reg}_W_DATA | RAM_R | REG_sp_W_ADDR | IP_ADD_1), | |
*addi('sp', -1) | |
]''') | |
def pushi(val): | |
return eval(f'''[ | |
(ROM_W_IP | RAM_R | REG_sp_W_ADDR | IP_ADD_2), | |
({val}), | |
*addi('sp', -1) | |
]''') | |
def pop(reg): | |
return eval(f'''[ | |
*addi('sp', 1), | |
(REG_{reg}_R_DATA | RAM_W | REG_sp_W_ADDR | IP_ADD_1) | |
]''') | |
def out(reg): | |
return eval(f'''[ | |
(REG_{reg}_W_DATA | OUT_R | IP_ADD_1) | |
]''') | |
def inr(reg): | |
return eval(f'''[ | |
(REG_{reg}_R_DATA | IN_W | IP_ADD_1) | |
]''') | |
def eqi(reg, val, ltrue, lfalse): | |
addr_true = lookup(ltrue) | |
addr_false = lookup(lfalse) | |
return eval(f'''[ | |
(REG_{reg}_W_DATA | ALU_R_X | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({val}), | |
(ALU_R_X | ALU_EQ | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({(addr_true - addr_false) & 0xffffffff}), | |
(ALU_R_X | ALU_MUL | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({addr_false}), | |
(ALU_ADD | IP_R_DATA), | |
]''') | |
def eq(reg, reg2, ltrue, lfalse): | |
addr_true = lookup(ltrue) | |
addr_false = lookup(lfalse) | |
return eval(f'''[ | |
(REG_{reg}_W_DATA | ALU_R_X | IP_ADD_1), | |
(REG_{reg2}_W_DATA | ALU_R_Y | IP_ADD_1), | |
(ALU_R_X | ALU_EQ | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({(addr_true - addr_false) & 0xffffffff}), | |
(ALU_R_X | ALU_MUL | IP_ADD_1), | |
(ROM_W_IP | ALU_R_Y | IP_ADD_2), | |
({addr_false}), | |
(ALU_ADD | IP_R_DATA), | |
]''') | |
def jmp(lbl): | |
addr = lookup(lbl) | |
return eval(f'''[ | |
(ROM_W_IP | IP_R_DATA), | |
({addr}) | |
]''') | |
def ldm(reg, off): | |
return eval(f'''[ | |
(REG_{off}_W_ADDR | ROM_W_ADDR | REG_{reg}_R_DATA | IP_ADD_1) | |
]''') | |
def load(reg, off): | |
return eval(f'''[ | |
(REG_{off}_W_ADDR | RAM_W | REG_{reg}_R_DATA | IP_ADD_1) | |
]''') | |
def store(reg, off): | |
return eval(f'''[ | |
(REG_{off}_W_ADDR | RAM_R | REG_{reg}_W_DATA | IP_ADD_1) | |
]''') | |
def call(lbl, ret_lbl): | |
addr_r = lookup(ret_lbl) | |
return eval(f'''[ | |
*pushi({addr_r}), | |
*jmp("{lbl}") | |
]''') | |
def ret(): | |
return eval(f'''[ | |
*addi('sp', 1), | |
(RAM_W | REG_sp_W_ADDR | IP_R_DATA) | |
]''') | |
def dbs(val): | |
# raw string | |
bs = eval(val) | |
return list(bs) | |
@dataclass | |
class Instruction(object): | |
op: str | |
def enc(self): | |
p = self.op.split(' ')[0] | |
a = ' '.join(self.op.split(' ')[1:]).split(',') | |
a = [x.strip() for x in a] | |
a = [x for x in a if x != ''] | |
if p == 'dbs': | |
a = [' '.join(self.op.split(' ')[1:])] | |
return globals()[p](*a) | |
def preprocess(asm): | |
out = [] | |
ret_idx = 0 | |
for a in asm: | |
if type(a) is Instruction and a.op.startswith('call'): | |
ret_lbl = f'_ret_{ret_idx}' | |
out.append(Instruction(f'{a.op}, {ret_lbl}')) | |
out.append(Label(ret_lbl)) | |
ret_idx += 1 | |
else: | |
out.append(a) | |
return out | |
def assemble(asm): | |
global label_map | |
global label_warn | |
label_map = {} | |
asm = asm.strip().split('\n') | |
asm = [x.strip() for x in asm if x.strip() != '' and not x.strip()[0] == ';'] | |
asm = [x.split(";")[0] for x in asm] | |
asm = [Label(x[:-1]) if x.endswith(':') else Instruction(x) for x in asm] | |
asm = preprocess(asm) | |
# Generate bytecode. | |
label_warn = False | |
code = [] | |
for line in asm: | |
if type(line) is Label: | |
label_map[line.name] = len(code) | |
else: | |
code += line.enc() | |
# Second pass, with full labels. | |
label_warn = True | |
code = [] | |
for line in asm: | |
if type(line) is Label: | |
label_map[line.name] = len(code) | |
else: | |
code += line.enc() | |
enc = b'' | |
for c in code: | |
enc += struct.pack('<I', c & 0xffffffff) | |
return enc | |
def main(args): | |
asm = open(args.input, 'r').read() | |
enc = assemble(asm) | |
open(args.output, 'wb').write(enc) | |
if __name__=='__main__': | |
parser = argparse.ArgumentParser() | |
parser.add_argument('input', help='Input assembly.') | |
parser.add_argument('output', help='Output path.') | |
args = parser.parse_args() | |
main(args) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is automatically @generated by Cargo. | |
# It is not intended for manual editing. | |
version = 3 | |
[[package]] | |
name = "byteorder" | |
version = "1.4.3" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" | |
[[package]] | |
name = "control-rs" | |
version = "0.1.0" | |
dependencies = [ | |
"byteorder", | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "control-rs" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
byteorder = "1.4.3" | |
[[bin]] | |
name = "main" | |
path = "main.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_start: | |
li sp, 0xffff | |
jmp main | |
; Spinloop sleep | |
; r0 : how long to sleep for | |
sleep: | |
_sleep_loop: | |
addi r0, -1 | |
eqi r0, 0, _sleep_done, _sleep_loop | |
_sleep_done: | |
ret | |
; Print a string slowly | |
; r0 : pointer to string | |
slowputs: | |
push r1 | |
ldm r1, r0 | |
_slowputs_loop: | |
push r0 | |
li r0, 0x80000 | |
call sleep | |
pop r0 | |
out r1 | |
addi r0, 1 | |
ldm r1, r0 | |
eqi r1, 0, _slowputs_done, _slowputs_loop | |
_slowputs_done: | |
pop r1 | |
ret | |
; Check if a string equals a fixed template string | |
; r0 : pointer to string (RAM) | |
; r1 : pointer to string (ROM) | |
strcmp: | |
_strcmp_loop: | |
load r2, r0 | |
ldm r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
eqi r3, 0, _strcmp_yes, _strcmp_cont | |
_strcmp_cont: | |
eq r2, r3, _strcmp_loop, _strcmp_no | |
_strcmp_yes: | |
li r0, 1 | |
ret | |
_strcmp_no: | |
li r0, 0 | |
ret | |
; String length. | |
; r0 : string in ram | |
strlen: | |
li r1, 0 | |
_strlen_loop: | |
load r2, r0 | |
eqi r2, 0, _strlen_done, _strlen_cont | |
_strlen_cont: | |
addi r1, 1 | |
addi r0, 1 | |
jmp _strlen_loop | |
_strlen_done: | |
mov r0, r1 | |
ret | |
printline: | |
push r0 | |
li r0, 10 | |
out r0 | |
pop r0 | |
ret | |
printcolon: | |
push r0 | |
li r0, 58 | |
out r0 | |
pop r0 | |
ret | |
; r0 : nibble | |
printnibble: | |
la r1, hextable | |
add r1, r0 | |
ldm r0, r1 | |
out r0 | |
ret | |
; r0 : digit | |
printhex: | |
push r0 | |
shifti r0, 4 | |
call printnibble | |
pop r0 | |
shifti r0, -28 | |
shifti r0, 28 | |
call printnibble | |
ret | |
; r0 : addr | |
setup_mod8: | |
push r1 | |
push r2 | |
push r3 | |
mov r1, r0 | |
li r2, 0 | |
setup_mod8_i_j_loop: | |
eqi r2, 0x20, setup_mod8_i_loop_end, setup_mod8_i_loop_cont | |
setup_mod8_i_loop_cont: | |
li r3, 0 | |
setup_mod8_j_loop: | |
eqi r3, 0x8, setup_mod8_j_loop_end, setup_mod8_j_loop_cont | |
setup_mod8_j_loop_cont: | |
store r3, r1 | |
addi r1, 1 | |
addi r3, 1 | |
jmp setup_mod8_j_loop | |
setup_mod8_j_loop_end: | |
addi r2, 1 | |
jmp setup_mod8_i_j_loop | |
setup_mod8_i_loop_end: | |
pop r3 | |
pop r2 | |
pop r1 | |
ret | |
; r0 : addr | |
setup_mod256: | |
push r1 | |
push r2 | |
push r3 | |
mov r1, r0 | |
li r2, 0 | |
setup_mod256_i_j_loop: | |
eqi r2, 0x2, setup_mod256_i_loop_end, setup_mod256_i_loop_cont | |
setup_mod256_i_loop_cont: | |
li r3, 0 | |
setup_mod256_j_loop: | |
eqi r3, 0x100, setup_mod256_j_loop_end, setup_mod256_j_loop_cont | |
setup_mod256_j_loop_cont: | |
store r3, r1 | |
addi r1, 1 | |
addi r3, 1 | |
jmp setup_mod256_j_loop | |
setup_mod256_j_loop_end: | |
addi r2, 1 | |
jmp setup_mod256_i_j_loop | |
setup_mod256_i_loop_end: | |
pop r3 | |
pop r2 | |
pop r1 | |
ret | |
; x % 8 | |
; r0 : x | |
mod8: | |
push r1 | |
li r1, 0x400 | |
add r1, r0 | |
load r0, r1 | |
pop r1 | |
ret | |
; x % 256 | |
; r0 : x | |
mod256: | |
push r1 | |
li r1, 0x500 | |
add r1, r0 | |
load r0, r1 | |
; call printhex | |
pop r1 | |
ret | |
; r0 : seed | |
srand: | |
; rand val | |
push r1 | |
li r1, 0x60 | |
store r0, r1 | |
pop r1 | |
ret | |
rand: | |
push r1 | |
push r2 | |
li r1, 0x60 | |
load r0, r1 | |
li r2, 1103515245 | |
mul r0, r2 | |
li r2, 12345 | |
add r0, r2 | |
; truncate to 31 bits | |
shifti r0, -1 | |
shifti r0, 1 | |
store r0, r1 | |
shifti r0, -26 | |
shifti r0, 26 | |
pop r2 | |
pop r1 | |
ret | |
; r0/r1 (ram) : pointers | |
swap: | |
push r2 | |
push r3 | |
; push r1 | |
; push r0 | |
; call printhex | |
; call printcolon | |
; pop r1 | |
; pop r0 | |
; call printhex | |
; call printline | |
load r2, r0 | |
load r3, r1 | |
; push r0 | |
; mov r0, r2 | |
; call printhex | |
; call printcolon | |
; mov r0, r3 | |
; call printhex | |
; call printline | |
; pop r0 | |
store r3, r0 | |
store r2, r1 | |
pop r3 | |
pop r2 | |
ret | |
; int KSA(char *key, unsigned char *S) { | |
; int len = strlen(key); | |
; int j = 0; | |
; for(int i = 0; i < N; i++) | |
; S[i] = i; | |
; for(int i = 0; i < N; i++) { | |
; j = (j + S[i] + key[i % len]) % N; | |
; swap(&S[i], &S[j]); | |
; } | |
; return 0; | |
; } | |
; key schedule | |
; r0 : key | |
; r1 : buf | |
ksa: | |
push r3 | |
push r2 | |
push r0 | |
push r1 | |
li r2, 0 | |
_i_j_loop: | |
eqi r2, 0x1, _i_loop_end, _i_loop_cont | |
_i_loop_cont: | |
li r3, 0 | |
pop r1 | |
push r1 | |
_j_loop: | |
eqi r3, 0x100, _j_loop_end, _j_loop_cont | |
_j_loop_cont: | |
store r3, r1 | |
addi r1, 1 | |
addi r3, 1 | |
jmp _j_loop | |
_j_loop_end: | |
addi r2, 1 | |
jmp _i_j_loop | |
_i_loop_end: | |
li r3, 0 ; j | |
li r2, 0 ; i | |
_swap_loop: | |
eqi r2, 0x100, _swap_loop_end, _swap_loop_cont ; i < 0x100 | |
_swap_loop_cont: | |
pop r1 ; buf | |
push r1 | |
add r1, r2 ; buf + i | |
load r0, r1 ; [buf + i] | |
add r0, r3 ; j + [buf + i] | |
call mod256 ; j + [buf + i] % 256 | |
mov r3, r0 | |
pop r1 | |
pop r0 | |
push r0 | |
push r1 | |
mov r1, r0 ; key | |
mov r0, r2 | |
call mod8 ; i % 8 | |
add r1, r0 | |
ldm r0, r1 ; [key + (i % 8)] | |
add r0, r3 | |
call mod256 | |
mov r3, r0 | |
pop r1 | |
pop r0 | |
push r0 | |
push r1 | |
mov r0, r1 | |
add r0, r2 | |
add r1, r3 | |
call swap | |
addi r2, 1 | |
jmp _swap_loop | |
_swap_loop_end: | |
pop r1 | |
pop r0 | |
pop r2 | |
pop r3 | |
ret | |
; int PRGA(unsigned char *S, char *plaintext, unsigned char *ciphertext) { | |
; int i = 0; | |
; int j = 0; | |
; for(size_t n = 0, len = strlen(plaintext); n < len; n++) { | |
; i = (i + 1) % N; | |
; j = (j + S[i]) % N; | |
; swap(&S[i], &S[j]); | |
; int rnd = S[(S[i] + S[j]) % N]; | |
; ciphertext[n] = rnd ^ plaintext[n]; | |
; } | |
; } | |
; r0 : S | |
; r1 : pt | |
; r2 : ct | |
prga: | |
push r3 | |
push r2 | |
push r1 | |
push r0 | |
li r2, 0 ; i | |
li r0, 0x886 | |
store r2, r0 | |
li r3, 0 ; j | |
li r0, 0x887 | |
store r3, r0 | |
li r1, 0 ; n | |
li r0, 0x888 | |
store r1, r0 | |
_main_loop: | |
li r0, 0x888; n | |
load r1, r0 | |
eqi r1, 54, _main_loop_end, _main_loop_cont ; i < 0x100 | |
_main_loop_cont: | |
li r0, 0x886 | |
load r2, r0 | |
addi r2, 1 ; i = i + 1 | |
mov r0, r2 | |
call mod256 | |
mov r2, r0 ; i %= 256 | |
li r0, 0x886 | |
store r2, r0 | |
pop r0 | |
push r0 ; r0 = S | |
add r0, r2 ; r0 = S + i | |
load r0, r0; r0 = S[i] | |
li r2, 0x887 | |
load r3, r2 ; r3 = j | |
add r0, r3 ; r0 = j + S[i] | |
call mod256 | |
mov r3, r0 ; r3 = j + S[i] % 256 | |
li r0, 0x887 | |
store r3, r0 | |
pop r0 ; r0 = S | |
push r0 | |
add r3, r0 ; r3 = S + j | |
li r1, 0x886 | |
load r2, r1; r2 = i | |
add r2, r0 ; r2 = S + i | |
mov r0, r3 | |
mov r1, r2 | |
call swap | |
load r0, r3; r3 = S + j, | |
load r1, r2; r2 = S + i, | |
add r0, r1; r0 = S[i] + S[j] | |
call mod256; r0 = (S[i] + S[j]) % 256 | |
li r2, 0x888 | |
load r1, r2 | |
pop r2 | |
push r2 ; r2 = S | |
add r0, r2 | |
load r0, r0; S[(S[i] + S[j]) % 256] | |
pop r2 ; r2 = S | |
pop r3 ; r3 = pt | |
push r3 | |
push r2 | |
li r1, 0x888; n | |
load r2, r1 | |
add r3, r2 ; r3 = pt + n | |
load r2, r3 ; r2 = pt[n] | |
xor r2, r0 ; r2 = pt[n] ^ rnd | |
pop r0 | |
pop r1 | |
pop r3 ; ct | |
push r3 | |
push r1 | |
push r0 | |
li r0, 0x888; n | |
load r1, r0 | |
add r3, r1; ct + n | |
store r2, r3 | |
li r0, 0x888; n | |
load r1, r0 | |
addi r1, 1 | |
store r1, r0 | |
jmp _main_loop | |
_main_loop_end: | |
pop r0 | |
pop r1 | |
pop r2 | |
pop r3 | |
ret | |
; Read up to N chars into a buffer. | |
; r0 : pointer to buffer | |
; r1 : max chars | |
readline: | |
push r2 | |
_readline_loop: | |
inr r2 | |
eqi r2, 0xa, _readline_done, _readline_ok | |
_readline_ok: | |
store r2, r0 | |
addi r1, -1 | |
addi r0, 1 | |
eqi r1, 0, _readline_done, _readline_loop | |
_readline_done: | |
pop r2 | |
ret | |
; r0 (rom) | |
; r1 (ram) | |
; r2 (len) | |
memcpy_oa: | |
push r3 | |
_memcpy_oa_loop: | |
eqi r2, 0, _memcpy_oa_done, _memcpy_oa_cont | |
_memcpy_oa_cont: | |
ldm r3, r0 | |
store r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
addi r2, -1 | |
jmp _memcpy_oa_loop | |
_memcpy_oa_done: | |
pop r3 | |
ret | |
; Check flag format. | |
; r0 : pointer to flag in RAM | |
check_format: | |
push r0 | |
; Check flag start | |
la r1, flag_pre | |
call strcmp | |
eqi r0, 1, _format_k1, _format_bad | |
_format_k1: | |
; Check length | |
la r0, msg6 | |
call slowputs | |
pop r0 | |
push r0 | |
call strlen | |
eqi r0, 54, _format_k2, _format_bad | |
_format_k2: | |
; Check ending | |
la r0, msg6 | |
call slowputs | |
pop r0 | |
push r0 | |
mov r1, r0 | |
addi r1, 53 | |
load r2, r1 | |
eqi r2, 125, _format_good, _format_bad | |
_format_good: | |
pop r0 | |
li r0, 1 | |
ret | |
_format_bad: | |
pop r0 | |
li r0, 0 | |
ret | |
; r0 (ram) | |
; r1 (ram) | |
; r2 (len) | |
memcmp: | |
push r3 | |
_memcmp_loop: | |
eqi r2, 0, _memcmp_good, _memcmp_cont | |
_memcmp_cont: | |
addi r2, -1 | |
push r2 | |
load r2, r0 | |
load r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
eq r2, r3, _memcmp_cont_2, _memcmp_bad | |
_memcmp_cont_2: | |
pop r2 | |
jmp _memcmp_loop | |
_memcmp_good: | |
li r0, 1 | |
pop r3 | |
ret | |
_memcmp_bad: | |
pop r2 | |
li r0, 0 | |
pop r3 | |
ret | |
; r0 : buf | |
shuf: | |
push r0 | |
li r0, 0x1337 | |
call srand | |
li r3, 0x0 | |
_shuf_start: | |
eqi r3, 0x1337, _shuf_cont, _shuf_end | |
_shuf_cont: | |
pop r1 | |
push r1 | |
mov r2, r1 | |
call rand | |
add r1, r0 | |
call rand | |
add r2, r0 | |
mov r0, r2 | |
call swap | |
addi r3, 1 | |
jmp _shuf_start | |
_shuf_end: | |
pop r0 | |
ret | |
main: | |
; li r0, 0x1 | |
; call srand | |
; call rand | |
; hlt | |
la r0, msg5 | |
call slowputs | |
li r0, 0x400 | |
call setup_mod8 | |
; li r0, 15 | |
; call mod8 | |
li r0, 0x500 | |
call setup_mod256 | |
la r0, msg5 | |
li r1, 0x100 | |
call ksa | |
li r0, 0x0 | |
li r1, 54 | |
call readline | |
li r0, 0x0 | |
call check_format | |
eqi r0, 1, _main_good_format, _main_bad_flag | |
_main_good_format: | |
la r0, msg6 | |
call slowputs | |
li r0, 0x100 | |
li r1, 0x0 | |
li r2, 0x80 | |
call prga | |
li r0, 0 | |
call shuf | |
la r0, enc | |
li r1, 0x900 | |
li r2, 54 | |
call memcpy_oa | |
li r0, 0x900 | |
call shuf | |
li r0, 0x80 ; prga(input) | |
li r1, 0x900 ; memcpy(enc) | |
li r2, 64 | |
call memcmp | |
eqi r0, 1, _main_good_flag, _main_bad_flag | |
_main_good_flag: | |
la r0, s_correct | |
la r1, ansi_green | |
jmp _main_print_result | |
_main_bad_flag: | |
la r0, s_wrong | |
la r1, ansi_red | |
_main_print_result: | |
push r0 | |
mov r0, r1 | |
call slowputs | |
pop r0 | |
call slowputs | |
la r0, ansi_reset | |
call slowputs | |
_main_exit: | |
hlt | |
hlt | |
enc: | |
dbs b'\x32\xfb\x19\xd5\xa1\xdf\x06\x83\xf2\xe6\xf9\xf8\x21\x69\x32\xb3\x33\xa4\x42\x3d\x45\x01\xe0\x40\xe1\x05\x7e\x14\xf3\x80\xe1\x27\x00\xbc\x92\x45\x1e\x87\x1f\xbe\xb9\xea\x65\xa3\x19\x5d\xfa\x95\x8c\xb3\x6c\xd6\xa9\x79' | |
ansi_red: | |
dbs b'\033[31m\x00' | |
ansi_green: | |
dbs b'\033[32m\x00' | |
ansi_reset: | |
dbs b'\033[0m\x00' | |
msg5: | |
dbs b'Give flag: \x00' | |
msg6: | |
dbs b'makes sense\n\x00' | |
hextable: | |
dbs b'0123456789abcdef' | |
flag_pre: | |
dbs b'flag{\x00' | |
s_correct: | |
dbs b'correct\x00' | |
s_wrong: | |
dbs b'wrong\x00' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
flag{th1s_was__a_usele55__rewrite_of_c0ntr0l__to_rust} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_start: | |
li sp, 0xffff | |
jmp main | |
; Print a null terminated string | |
; r0 : pointer to string | |
puts: | |
push r1 | |
ldm r1, r0 | |
_puts_loop: | |
out r1 | |
addi r0, 1 | |
ldm r1, r0 | |
eqi r1, 0, _puts_done, _puts_loop | |
_puts_done: | |
pop r1 | |
ret | |
; Read up to N chars into a buffer. | |
; r0 : pointer to buffer | |
; r1 : max chars | |
readline: | |
push r2 | |
_readline_loop: | |
inr r2 | |
eqi r2, 0xa, _readline_done, _readline_ok | |
_readline_ok: | |
store r2, r0 | |
addi r1, -1 | |
addi r0, 1 | |
eqi r1, 0, _readline_done, _readline_loop | |
_readline_done: | |
pop r2 | |
ret | |
; Print a string slowly | |
; r0 : pointer to string | |
slowputs: | |
push r1 | |
ldm r1, r0 | |
_slowputs_loop: | |
push r0 | |
li r0, 0x80000 | |
call sleep | |
pop r0 | |
out r1 | |
addi r0, 1 | |
ldm r1, r0 | |
eqi r1, 0, _slowputs_done, _slowputs_loop | |
_slowputs_done: | |
pop r1 | |
ret | |
; Check if a string equals a fixed template string | |
; r0 : pointer to string (RAM) | |
; r1 : pointer to string (ROM) | |
strcmp: | |
_strcmp_loop: | |
load r2, r0 | |
ldm r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
eqi r3, 0, _strcmp_yes, _strcmp_cont | |
_strcmp_cont: | |
eq r2, r3, _strcmp_loop, _strcmp_no | |
_strcmp_yes: | |
li r0, 1 | |
ret | |
_strcmp_no: | |
li r0, 0 | |
ret | |
; r0 : nibble | |
printnibble: | |
la r1, hextable | |
add r1, r0 | |
ldm r0, r1 | |
out r0 | |
ret | |
printhex: | |
push r0 | |
shifti r0, 4 | |
call printnibble | |
pop r0 | |
shifti r0, -28 | |
shifti r0, 28 | |
call printnibble | |
ret | |
fake_crash: | |
la r0, fake_crash_pre | |
call puts | |
li r1, 3 | |
load r0, r1 | |
call printhex | |
li r1, 2 | |
load r0, r1 | |
call printhex | |
li r1, 1 | |
load r0, r1 | |
call printhex | |
li r1, 0 | |
load r0, r1 | |
call printhex | |
la r0, fake_crash_post | |
call puts | |
li r0, 0x1000000 | |
call sleep | |
la r0, omg_what | |
call slowputs | |
ret | |
; Spinloop sleep | |
; r0 : how long to sleep for | |
sleep: | |
_sleep_loop: | |
addi r0, -1 | |
eqi r0, 0, _sleep_done, _sleep_loop | |
_sleep_done: | |
ret | |
; String length. | |
; r0 : string in ram | |
strlen: | |
li r1, 0 | |
_strlen_loop: | |
load r2, r0 | |
eqi r2, 0, _strlen_done, _strlen_cont | |
_strlen_cont: | |
addi r1, 1 | |
addi r0, 1 | |
jmp _strlen_loop | |
_strlen_done: | |
mov r0, r1 | |
ret | |
; Check flag format. | |
; r0 : pointer to flag in RAM | |
check_format: | |
push r0 | |
; Check flag start | |
la r1, flag_pre | |
call strcmp | |
eqi r0, 1, _format_k1, _format_bad | |
_format_k1: | |
; Check length | |
pop r0 | |
push r0 | |
call strlen | |
eqi r0, 46, _format_k2, _format_bad | |
_format_k2: | |
; Check ending | |
pop r0 | |
push r0 | |
mov r1, r0 | |
addi r1, 45 | |
load r2, r1 | |
eqi r2, 125, _format_good, _format_bad | |
_format_good: | |
pop r0 | |
li r0, 1 | |
ret | |
_format_bad: | |
pop r0 | |
li r0, 0 | |
ret | |
; r0 : seed | |
srand: | |
; rand val | |
push r1 | |
li r1, 0x60 | |
store r0, r1 | |
pop r1 | |
ret | |
rand: | |
push r1 | |
push r2 | |
li r1, 0x60 | |
load r0, r1 | |
li r2, 1103515245 | |
mul r0, r2 | |
li r2, 12345 | |
add r0, r2 | |
; truncate to 31 bits | |
shifti r0, -1 | |
shifti r0, 1 | |
store r0, r1 | |
pop r2 | |
pop r1 | |
ret | |
; r0 : char value | |
; r1 : bit buffer | |
char_to_bits: | |
push r2 | |
li r2, 0 | |
_char_to_bits_loop: | |
eqi r2, 8, _char_to_bits_done, _char_to_bits_cont | |
_char_to_bits_cont: | |
mov r3, r0 | |
shifti r3, -31 | |
shifti r3, 31 | |
store r3, r1 | |
shifti r0, 1 | |
addi r1, 1 | |
addi r2, 1 | |
jmp _char_to_bits_loop | |
_char_to_bits_done: | |
pop r2 | |
ret | |
; Chars to bit buffer. | |
; r0 (ram): pointer to 8 chars | |
; r1 (ram): pointer to bit buffer | |
chars_to_bits: | |
li r2, 0 | |
_chars_to_bits_loop: | |
eqi r2, 8, _chars_to_bits_done, _chars_to_bits_cont | |
_chars_to_bits_cont: | |
load r3, r0 | |
push r0 | |
push r1 | |
push r2 | |
mov r0, r3 | |
; r1 = bit buffer | |
call char_to_bits | |
pop r2 | |
pop r1 | |
pop r0 | |
addi r0, 1 | |
addi r1, 8 | |
addi r2, 1 | |
jmp _chars_to_bits_loop | |
_chars_to_bits_done: | |
ret | |
; r0 (rom) | |
; r1 (ram) | |
; r2 (len) | |
memcpy_oa: | |
push r3 | |
_memcpy_oa_loop: | |
eqi r2, 0, _memcpy_oa_done, _memcpy_oa_cont | |
_memcpy_oa_cont: | |
ldm r3, r0 | |
store r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
addi r2, -1 | |
jmp _memcpy_oa_loop | |
_memcpy_oa_done: | |
pop r3 | |
ret | |
; r0 (ram) | |
; r1 (ram) | |
; r2 (len) | |
memcmp: | |
push r3 | |
_memcmp_loop: | |
eqi r2, 0, _memcmp_good, _memcmp_cont | |
_memcmp_cont: | |
addi r2, -1 | |
push r2 | |
load r2, r0 | |
load r3, r1 | |
addi r0, 1 | |
addi r1, 1 | |
eq r2, r3, _memcmp_cont_2, _memcmp_bad | |
_memcmp_cont_2: | |
pop r2 | |
jmp _memcmp_loop | |
_memcmp_good: | |
li r0, 1 | |
pop r3 | |
ret | |
_memcmp_bad: | |
pop r2 | |
li r0, 0 | |
pop r3 | |
ret | |
; r0/r1 (ram) : pointers | |
swap: | |
push r2 | |
push r3 | |
load r2, r0 | |
load r3, r1 | |
store r3, r0 | |
store r2, r1 | |
pop r3 | |
pop r2 | |
ret | |
; r0 (ram): bit buffer | |
; r1 : seed | |
mutate: | |
push r2 | |
push r3 | |
mov r3, r0 | |
; set srand seed | |
mov r0, r1 | |
call srand | |
li r2, 0 | |
_mutate_loop_1: | |
eqi r2, 0x1337, _mutate_done_1, _mutate_cont_1 | |
_mutate_cont_1: | |
addi r2, 1 | |
push r2 | |
call rand | |
shifti r0, -26 | |
shifti r0, 26 | |
mov r1, r3 | |
add r1, r0 | |
call rand | |
shifti r0, -26 | |
shifti r0, 26 | |
mov r2, r3 | |
add r2, r0 | |
mov r0, r1 | |
mov r1, r2 | |
call swap | |
pop r2 | |
jmp _mutate_loop_1 | |
_mutate_done_1: | |
li r2, 0 | |
_mutate_loop_2: | |
eqi r2, 0x1337, _mutate_done, _mutate_cont_2 | |
_mutate_cont_2: | |
addi r2, 1 | |
push r2 | |
call rand | |
shifti r0, -26 | |
shifti r0, 26 | |
mov r1, r3 | |
add r1, r0 | |
load r2, r1 | |
xori r2, 1 | |
store r2, r1 | |
pop r2 | |
jmp _mutate_loop_2 | |
_mutate_done: | |
pop r3 | |
pop r2 | |
ret | |
; Check chunk. | |
; r0 : flag chunk | |
; r1 : enc chunk | |
; r2 : seed | |
check_flag_chunk: | |
; start of inner part | |
push r1 | |
push r2 | |
li r1, 0x100 | |
call chars_to_bits | |
li r0, 0x100 | |
pop r1 | |
call mutate | |
pop r0 | |
li r1, 0x200 | |
li r2, 8 | |
call memcpy_oa | |
li r0, 0x200 | |
li r1, 0x208 | |
call chars_to_bits | |
li r0, 0x100 | |
li r1, 0x208 | |
li r2, 64 | |
call memcmp | |
ret | |
; Check whole flag | |
; r0 : flag base | |
; r1 : enc base | |
check_flag: | |
; start of flag | |
addi r0, 5 | |
li r2, 0 | |
_check_flag_loop: | |
eqi r2, 5, _check_flag_good, _check_flag_cont | |
_check_flag_cont: | |
push r0 | |
push r1 | |
push r2 | |
call check_flag_chunk | |
mov r3, r0 | |
pop r2 | |
pop r1 | |
pop r0 | |
eqi r3, 0, _check_flag_bad, _check_flag_cont2 | |
_check_flag_cont2: | |
addi r0, 8 | |
addi r1, 8 | |
addi r2, 1 | |
jmp _check_flag_loop | |
_check_flag_bad: | |
li r0, 0 | |
ret | |
_check_flag_good: | |
li r0, 1 | |
ret | |
main: | |
la r0, msg1 | |
call slowputs | |
la r0, ansi_red | |
call puts | |
la r0, control | |
call puts | |
la r0, ansi_reset | |
call puts | |
la r0, msg2 | |
call puts | |
inr r0 | |
inr r1 | |
eqi r0, 121, _main_has_control, _main_no_control | |
_main_no_control: | |
la r0, msg3 | |
call slowputs | |
hlt | |
_main_has_control: | |
la r0, msg4 | |
call slowputs | |
la r0, ansi_green | |
call puts | |
la r0, a_flag | |
call puts | |
la r0, ansi_reset | |
call puts | |
la r0, msg2 | |
call puts | |
inr r0 | |
inr r1 | |
eqi r0, 121, _main_has_flag, _main_no_flag | |
_main_no_flag: | |
la r0, msg3 | |
call slowputs | |
hlt | |
_main_has_flag: | |
la r0, msg5 | |
call puts | |
li r0, 0x0 | |
li r1, 0x30 | |
call readline | |
li r0, 0x0 | |
call check_format | |
eqi r0, 1, _main_no_crash, _main_fake_crash | |
_main_fake_crash: | |
call fake_crash | |
jmp _main_exit | |
_main_no_crash: | |
la r0, checking | |
call slowputs | |
li r0, 0 | |
la r1, target_enc | |
call check_flag | |
eqi r0, 1, _main_good_flag, _main_bad_flag | |
_main_good_flag: | |
la r0, s_correct | |
la r1, ansi_green | |
jmp _main_print_result | |
_main_bad_flag: | |
la r0, s_wrong | |
la r1, ansi_red | |
_main_print_result: | |
push r0 | |
mov r0, r1 | |
call puts | |
pop r0 | |
call puts | |
la r0, ansi_reset | |
call puts | |
_main_exit: | |
hlt | |
; Data section | |
msg1: | |
dbs b'Hello...\nDo you have: \n\x00' | |
control: | |
dbs ' ██████╗ ██████╗ ███╗ ██╗████████╗██████╗ ██████╗ ██╗ ██████╗ \n██╔════╝██╔═══██╗████╗ ██║╚══██╔══╝██╔══██╗██╔═══██╗██║ ╚════██╗\n██║ ██║ ██║██╔██╗ ██║ ██║ ██████╔╝██║ ██║██║ ▄███╔╝\n██║ ██║ ██║██║╚██╗██║ ██║ ██╔══██╗██║ ██║██║ ▀▀══╝ \n╚██████╗╚██████╔╝██║ ╚████║ ██║ ██║ ██║╚██████╔╝███████╗██╗ \n ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ \n\x00'.encode('utf8') | |
ansi_red: | |
dbs b'\033[31m\x00' | |
ansi_green: | |
dbs b'\033[32m\x00' | |
ansi_reset: | |
dbs b'\033[0m\x00' | |
msg2: | |
dbs b'(y/N): \x00' | |
msg3: | |
dbs b'Hmm...\nWell bye then...\n\x00' | |
msg4: | |
dbs b'Nice!\nAnd do you have: \n\x00' | |
a_flag: | |
dbs ' █████╗ ███████╗██╗ █████╗ ██████╗██████╗ \n██╔══██╗ ██╔════╝██║ ██╔══██╗██╔════╝╚════██╗\n███████║ █████╗ ██║ ███████║██║ ███╗ ▄███╔╝\n██╔══██║ ██╔══╝ ██║ ██╔══██║██║ ██║ ▀▀══╝ \n██║ ██║ ██║ ███████╗██║ ██║╚██████╔╝ ██╗ \n╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ \n\x00'.encode('utf8') | |
msg5: | |
dbs b'Give flag: \x00' | |
fake_crash_pre: | |
dbs b'Program received signal SIGSEGV, Segmentation fault.\n0x\x00' | |
fake_crash_post: | |
dbs b' in ?? ()\n\x00' | |
checking: | |
dbs b'Checking flag...\n\x00' | |
omg_what: | |
dbs b'... omg how could you do this to me???\nI thought we were friends!\n\x00' | |
flag_pre: | |
dbs b'flag{\x00' | |
hextable: | |
dbs b'0123456789abcdef' | |
s_correct: | |
dbs ' ██████╗ ██████╗ ██████╗ ██████╗ ███████╗ ██████╗████████╗██╗\n██╔════╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝╚══██╔══╝██║\n██║ ██║ ██║██████╔╝██████╔╝█████╗ ██║ ██║ ██║\n██║ ██║ ██║██╔══██╗██╔══██╗██╔══╝ ██║ ██║ ╚═╝\n╚██████╗╚██████╔╝██║ ██║██║ ██║███████╗╚██████╗ ██║ ██╗\n ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝\n\x00'.encode('utf8') | |
s_wrong: | |
dbs '██╗ ██╗██████╗ ██████╗ ███╗ ██╗ ██████╗ ██╗\n██║ ██║██╔══██╗██╔═══██╗████╗ ██║██╔════╝ ██║\n██║ █╗ ██║██████╔╝██║ ██║██╔██╗ ██║██║ ███╗██║\n██║███╗██║██╔══██╗██║ ██║██║╚██╗██║██║ ██║╚═╝\n╚███╔███╔╝██║ ██║╚██████╔╝██║ ╚████║╚██████╔╝██╗\n ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝\n\x00'.encode('utf8') | |
target_enc: | |
dbs b'\x85\xf5\xdd\xa8\x01\xc8\x08\xba\xaa\xf8\xb8\xc1\x95J[\nL\xb1\x88\xc5\xf7\x990\x02\x92\xe8\x93\x9f\xdb\x0cZ\x81\x97\xfc\xf1\xae\xed1\x91\x9a' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <sys/mman.h> | |
#define DEBUG 0 | |
// Control flags. | |
#define REG_r0_R_DATA (1 << 0) | |
#define REG_r0_W_DATA (1 << 1) | |
#define REG_r0_W_ADDR (1 << 2) | |
#define REG_r1_R_DATA (1 << 3) | |
#define REG_r1_W_DATA (1 << 4) | |
#define REG_r1_W_ADDR (1 << 5) | |
#define REG_r2_R_DATA (1 << 6) | |
#define REG_r2_W_DATA (1 << 7) | |
#define REG_r2_W_ADDR (1 << 8) | |
#define REG_r3_R_DATA (1 << 9) | |
#define REG_r3_W_DATA (1 << 10) | |
#define REG_r3_W_ADDR (1 << 11) | |
#define REG_sp_R_DATA (1 << 12) | |
#define REG_sp_W_DATA (1 << 13) | |
#define REG_sp_W_ADDR (1 << 14) | |
#define ALU_R_X (1 << 15) | |
#define ALU_R_Y (1 << 16) | |
#define ALU_SHF (1 << 17) | |
#define ALU_ADD (1 << 18) | |
#define ALU_MUL (1 << 19) | |
#define ALU_XOR (1 << 20) | |
#define ALU_EQ (1 << 21) | |
#define RAM_R (1 << 22) | |
#define RAM_W (1 << 23) | |
#define OUT_R (1 << 24) | |
#define IN_W (1 << 25) | |
#define ROM_W_IP (1 << 26) | |
#define ROM_W_ADDR (1 << 27) | |
#define IP_ADD_1 (1 << 28) | |
#define IP_ADD_2 (1 << 29) | |
#define IP_R_DATA (1 << 30) | |
#define HLT (1 << 31) | |
static uint32_t r0 = 0; | |
static uint32_t r1 = 0; | |
static uint32_t r2 = 0; | |
static uint32_t r3 = 0; | |
static uint32_t sp = 0; | |
static uint32_t alu_x = 0; | |
static uint32_t alu_y = 0; | |
static uint32_t ip = 0; | |
static uint32_t val = 0; | |
static uint32_t data_bus = 0; | |
static uint32_t addr_bus = 0; | |
uint32_t *rom; | |
uint32_t ram[0x10000]; | |
int main(int argc, char **argv) { | |
setbuf(stdout, NULL); | |
setbuf(stdin, NULL); | |
if (argc != 2) { | |
printf("Usage: %s main.bin\n", argv[0]); | |
exit(0); | |
} | |
FILE *fd = fopen(argv[1], "rb"); | |
fseek(fd, 0, SEEK_END); | |
size_t size = ftell(fd); | |
fseek(fd, 0, SEEK_SET); | |
rom = malloc(size); | |
fread(rom, 1, size, fd); | |
while (!(val & HLT)) { | |
// Load instruction.a | |
val = rom[ip]; | |
#if DEBUG == 1 | |
printf("[%04x] 0x%08x :: 0x%08x ;; \tr0=0x%08x\tr1=0x%08x\tr2=0x%08x\tr3=0x%08x\tsp=0x%08x\tax=0x%08x\tay=0x%08x\t\n", ip, val, rom[ip+1], r0, r1, r2, r3, sp, alu_x, alu_y); | |
printf("Mem: "); | |
for (int i = 0; i < 0x10; ++i) { | |
printf("0x%08x ", ram[i]); | |
} | |
printf("\n"); | |
#endif | |
// Alu op. | |
if (val & ALU_ADD) data_bus = alu_x + alu_y; | |
if (val & ALU_MUL) data_bus = alu_x * alu_y; | |
if (val & ALU_SHF) data_bus = (((int32_t)alu_y)) > 0 ? alu_x >> alu_y : alu_x << (-((int32_t)alu_y)); | |
if (val & ALU_XOR) data_bus = alu_x ^ alu_y; | |
if (val & ALU_EQ) data_bus = (alu_x == alu_y ? 1 : 0); | |
// Address writes. | |
if (val & REG_r0_W_ADDR) addr_bus = r0; | |
if (val & REG_r1_W_ADDR) addr_bus = r1; | |
if (val & REG_r2_W_ADDR) addr_bus = r2; | |
if (val & REG_r3_W_ADDR) addr_bus = r3; | |
if (val & REG_sp_W_ADDR) addr_bus = sp; | |
// Data writes. | |
if (val & REG_r0_W_DATA) data_bus = r0; | |
if (val & REG_r1_W_DATA) data_bus = r1; | |
if (val & REG_r2_W_DATA) data_bus = r2; | |
if (val & REG_r3_W_DATA) data_bus = r3; | |
if (val & REG_sp_W_DATA) data_bus = sp; | |
if (val & RAM_W) data_bus = ram[addr_bus]; | |
if (val & ROM_W_IP) data_bus = rom[ip + 1]; | |
if (val & ROM_W_ADDR) data_bus = rom[addr_bus]; | |
if (val & IN_W) data_bus = getchar(); | |
// Data reads. | |
if (val & REG_r0_R_DATA) r0 = data_bus; | |
if (val & REG_r1_R_DATA) r1 = data_bus; | |
if (val & REG_r2_R_DATA) r2 = data_bus; | |
if (val & REG_r3_R_DATA) r3 = data_bus; | |
if (val & REG_sp_R_DATA) sp = data_bus; | |
if (val & ALU_R_X) alu_x = data_bus; | |
if (val & ALU_R_Y) alu_y = data_bus; | |
if (val & RAM_R) ram[addr_bus] = data_bus; | |
if (val & OUT_R) putchar(data_bus); | |
// IP increment. | |
if (val & IP_ADD_1) ip += 1; | |
if (val & IP_ADD_2) ip += 2; | |
if (val & IP_R_DATA) ip = data_bus; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const REG_R0_R_DATA: u32 = 1 << 0; | |
const REG_R0_W_DATA: u32 = 1 << 1; | |
const REG_R0_W_ADDR: u32 = 1 << 2; | |
const REG_R1_R_DATA: u32 = 1 << 3; | |
const REG_R1_W_DATA: u32 = 1 << 4; | |
const REG_R1_W_ADDR: u32 = 1 << 5; | |
const REG_R2_R_DATA: u32 = 1 << 6; | |
const REG_R2_W_DATA: u32 = 1 << 7; | |
const REG_R2_W_ADDR: u32 = 1 << 8; | |
const REG_R3_R_DATA: u32 = 1 << 9; | |
const REG_R3_W_DATA: u32 = 1 << 10; | |
const REG_R3_W_ADDR: u32 = 1 << 11; | |
const REG_SP_R_DATA: u32 = 1 << 12; | |
const REG_SP_W_DATA: u32 = 1 << 13; | |
const REG_SP_W_ADDR: u32 = 1 << 14; | |
const ALU_R_X: u32 = 1 << 15; | |
const ALU_R_Y: u32 = 1 << 16; | |
const ALU_SHF: u32 = 1 << 17; | |
const ALU_ADD: u32 = 1 << 18; | |
const ALU_MUL: u32 = 1 << 19; | |
const ALU_XOR: u32 = 1 << 20; | |
const ALU_EQ: u32 = 1 << 21; | |
const RAM_R: u32 = 1 << 22; | |
const RAM_W: u32 = 1 << 23; | |
const OUT_R: u32 = 1 << 24; | |
const IN_W: u32 = 1 << 25; | |
const ROM_W_IP: u32 = 1 << 26; | |
const ROM_W_ADDR: u32 = 1 << 27; | |
const IP_ADD_1: u32 = 1 << 28; | |
const IP_ADD_2: u32 = 1 << 29; | |
const IP_R_DATA: u32 = 1 << 30; | |
const HLT: u32 = 1 << 31; | |
extern crate byteorder; | |
use byteorder::{NativeEndian, ReadBytesExt}; | |
use std::{env, io::Read}; | |
use std::io::{stdin, stdout, Write}; | |
fn getchar() -> u32 { | |
let mut c : [u8; 1] = [0]; | |
match stdin().read(&mut c) { | |
Ok(_) => { | |
c[0] as u32 | |
} | |
Err(_) => { | |
0 | |
} | |
} | |
} | |
fn putchar(c: u32) { | |
let c : [u8; 1] = [c as u8]; | |
let _ = stdout().write(&c); | |
stdout().flush().unwrap(); | |
} | |
fn main() { | |
// println!("flag{{wh0_n33ds_opc0des_wh3n_you_h4ve_CONTROL?}}");// flag{wh0_n33ds_opc0des_wh3n_you_h4ve_CONTROL.} | |
let mut r0: u32 = 0; | |
let mut r1: u32 = 0; | |
let mut r2: u32 = 0; | |
let mut r3: u32 = 0; | |
let mut sp: u32 = 0; | |
let mut alu_x: u32 = 0; | |
let mut alu_y: u32 = 0; | |
let mut ip: u32 = 0; | |
let mut val: u32 = 0; | |
let mut data_bus: u32 = 0; | |
let mut addr_bus: u32 = 0; | |
let mut ram: [u32; 0x10000] = [0; 0x10000]; | |
let args: Vec<_> = env::args().collect(); | |
if args.len() < 2 { | |
println!("./{} <bin>", args[0]); | |
return; | |
} | |
let filename = &args[1]; | |
let mut file = std::fs::File::open(filename).expect("file not found"); | |
let flen = file.metadata().unwrap().len() as usize; | |
let mut rom = vec![0u32; flen / 4]; | |
let _ = file.read_u32_into::<NativeEndian>(&mut rom); | |
while val & HLT == 0 { | |
// Load instruction.a | |
val = rom[ip as usize]; | |
// #if DEBUG == 1 | |
// println!("[{:#04x}] {:#08x} :: {:#08x} ;; r0={:#08x}\tr1={:#08x}\tr2={:#08x}\tr3={:#08x}", ip, val, rom[(ip+1) as usize], r0, r1, r2, r3); | |
// Alu op. | |
if (val & ALU_ADD) != 0 { | |
data_bus = alu_x + alu_y; | |
} | |
if (val & ALU_MUL) != 0 { | |
data_bus = alu_x * alu_y; | |
} | |
if (val & ALU_SHF) != 0 { | |
data_bus = if (alu_y as i32) > 0 { | |
alu_x >> alu_y | |
} else { | |
alu_x << (-(alu_y as i32)) | |
}; | |
} | |
if (val & ALU_XOR) != 0 { | |
data_bus = alu_x ^ alu_y; | |
} | |
if (val & ALU_EQ) != 0 { | |
data_bus = if alu_x == alu_y { 1 } else { 0 }; | |
} | |
// Address writes. | |
if (val & REG_R0_W_ADDR) != 0 { | |
addr_bus = r0; | |
} | |
if (val & REG_R1_W_ADDR) != 0 { | |
addr_bus = r1; | |
} | |
if (val & REG_R2_W_ADDR) != 0 { | |
addr_bus = r2; | |
} | |
if (val & REG_R3_W_ADDR) != 0 { | |
addr_bus = r3; | |
} | |
if (val & REG_SP_W_ADDR) != 0 { | |
addr_bus = sp; | |
} | |
// Data writes. | |
if (val & REG_R0_W_DATA) != 0 { | |
data_bus = r0; | |
} | |
if (val & REG_R1_W_DATA) != 0 { | |
data_bus = r1; | |
} | |
if (val & REG_R2_W_DATA) != 0 { | |
data_bus = r2; | |
} | |
if (val & REG_R3_W_DATA) != 0 { | |
data_bus = r3; | |
} | |
if (val & REG_SP_W_DATA) != 0 { | |
data_bus = sp; | |
} | |
if (val & RAM_W) != 0 { | |
data_bus = ram[addr_bus as usize]; | |
// println!("read ram [{:#08x}] -> {:#08x}", addr_bus, data_bus); | |
} | |
if (val & ROM_W_IP) != 0 { | |
data_bus = rom[(ip + 1) as usize]; | |
} | |
if (val & ROM_W_ADDR) != 0 { | |
data_bus = rom[addr_bus as usize]; | |
// println!("read rom [{:#08x}] -> {:#08x}", addr_bus, data_bus); | |
} | |
if (val & IN_W) != 0 { | |
data_bus = getchar(); | |
} | |
// Data reads. | |
if (val & REG_R0_R_DATA) != 0 { | |
r0 = data_bus; | |
} | |
if (val & REG_R1_R_DATA) != 0 { | |
r1 = data_bus; | |
} | |
if (val & REG_R2_R_DATA) != 0 { | |
r2 = data_bus; | |
} | |
if (val & REG_R3_R_DATA) != 0 { | |
r3 = data_bus; | |
} | |
if (val & REG_SP_R_DATA) != 0 { | |
sp = data_bus; | |
} | |
if (val & ALU_R_X) != 0 { | |
alu_x = data_bus; | |
} | |
if (val & ALU_R_Y) != 0 { | |
alu_y = data_bus; | |
} | |
if (val & RAM_R) != 0 { | |
// println!("write {:#08x} <- {:#08x}", addr_bus, data_bus); | |
ram[addr_bus as usize] = data_bus; | |
} | |
if (val & OUT_R) != 0 { | |
putchar(data_bus); | |
} | |
// IP increment. | |
if (val & IP_ADD_1) != 0 { | |
ip += 1; | |
} | |
if (val & IP_ADD_2) != 0 { | |
ip += 2; | |
} | |
if (val & IP_R_DATA) != 0 { | |
ip = data_bus; | |
} | |
} | |
// println!("[{:#04x}] {:#08x} :: {:#08x} ;; r0={:#08x}\tr1={:#08x}\tr2={:#08x}\tr3={:#08x}", ip, val, rom[(ip+1) as usize], r0, r1, r2, r3); | |
// (0x100..=0x200).for_each(|idx|print!("{:#02x}:", ram[idx])); | |
// println!(""); | |
// (0x400..=0x500).for_each(|idx|print!("{:#02x}:", ram[idx])); | |
// println!(""); | |
// (0x500..=0x700).for_each(|idx|print!("{:#02x}:", ram[idx])); | |
// println!(""); | |
// (0x80..=0x100).for_each(|idx|print!("{:#02x}:", ram[idx])); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment