Halifax: Push latest changes

Requires assemble.py from Swiftloke's MSProbe to automatically compile
This commit is contained in:
Val 2023-01-17 19:10:31 -06:00
parent 111dcfddc6
commit 1c9710378b
4 changed files with 159 additions and 186 deletions

3
.gitignore vendored
View File

@ -9,6 +9,9 @@ Saves
# MSProbe - https://github.com/Swiftloke/MSProbe
MSProbe*
# Halifax binary dumps
25-Halifax/*.bin
# Python cache
__pycache__
**/__pycache__

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python
import re, os
from sys import byteorder
import re, os, sys
from hashlib import sha256
from assemble import asmMain
# match this many hexadigits
# must be corroborated within the script
@ -10,45 +10,64 @@ depth = 6
# bytes per message
message_size = 1
internal_sram_hash = input("Internal SRAM Hash: ").lower()
shellcode_asm = 'shellcode.asm'
if len(sys.argv) > 1:
shellcode_asm = sys.argv[1]
target = re.sub(r'\s+', '', input("Encoded Target: ")).lower()
shellcode_out = f'{shellcode_asm}.tmp'
# calculate LUT for given parameters
all_hashes = {}
for i in range (0, 1<<(8*message_size)):
key = sha256(i.to_bytes(length=message_size, byteorder='big', signed=False)).hexdigest()[:depth]
all_hashes[key] = i
dedup = list(dict.fromkeys(all_hashes.keys()))
print(f"distinct values in all_hashes: {len(dedup)}\n")
#Compile shellcode w/ msprobe
asmMain(shellcode_asm, shellcode_out, silent=True)
sram: bytearray = bytearray()
with open(shellcode_out) as file:
shellcode = file.readline()
shellcode_len = len(bytes.fromhex(shellcode));
os.remove(shellcode_out)
# decode
print("Decoded:")
for loc in range (0, len(target), depth*message_size):
key = target[loc:loc+depth]
try:
value = all_hashes[key]
if value:
print(f"6000{shellcode_len:x}{shellcode}")
def main():
internal_sram_hash = input("Internal SRAM Hash: ").lower()
target = re.sub(r'\s+', '', input("\nEncoded Target: ")).lower()
# calculate LUT for given parameters
all_hashes = {}
for i in range (0, 1<<(8*message_size)):
key = sha256(i.to_bytes(length=message_size, byteorder='big', signed=False)).hexdigest()[:depth]
all_hashes[key] = i
dedup = list(dict.fromkeys(all_hashes.keys()))
#print(f"distinct values in all_hashes: {len(dedup)}\n")
sram: bytearray = bytearray()
# decode
print("Decoded:")
for loc in range (0, len(target), depth*message_size):
key = target[loc:loc+depth]
try:
value = all_hashes[key]
print(f"{value:x}", end="")
except KeyError:
value = 0x00
sram.append(value)
except KeyError:
value = 0x00
sram.append(value)
# write to file
with open("carfax.bin", 'wb') as output:
output.write(sram)
# write to file
with open("carfax.bin", 'wb') as output:
output.write(sram)
print("")
# hexdump file
os.system("xxd carfax.bin")
print("")
# hexdump file
os.system("xxd carfax.bin")
# check hash against provided value
while len(sram) < 0x1000:
sram.append (0)
print (f"{sha256(sram).hexdigest()}\n{internal_sram_hash}")
# check hash against provided value
while len(sram) < 0x1000:
sram.append (0)
print (f"\nHash:\nProvided: {internal_sram_hash}\n Decoded: {sha256(sram).hexdigest()}")
if (sha256(sram).hexdigest().lower() == internal_sram_hash.lower()):
print("Hash match!")
if (sha256(sram).hexdigest().lower() == internal_sram_hash.lower()):
print("Hash match!")
if __name__ == "__main__":
main()

View File

@ -1,78 +0,0 @@
; just
6000 1c 0b43 1e43 3d400080 0f4b b012b645 3d500300 1b53 3b906000 f72b 3041
; where depth = number of nibbles in each truncated hash
; msize = number of bytes per hash
;* depth 8, message size 2
;? completes in 67234 cycles
6000 6c
0b43 2e43 3d400080 0f4b b012b645 3d500400 1b53 3b902000 f72b
0b43 5e4b0080 4f4e 0f11 0f11 0f11 0f11 12c3 3ef00f00 3ff0 0f00 5f4f1047 b0127845 5f4e1047 b0127845 1b53 3b908000 e82b
3e4040003f400090b0126845
0f433d400090b012b645
3f407f00b0125045 3041
get_sram_hashes:
0b43 2e43 3d400080 0f4b b012b645 2d52 1b53 3b902000 f72b
0b43 clr r11 ; loop variable in r11
2e43 mov #2, r14 ; r14 = 2
3d40 0080 mov #0x8000, r13 ; set destination to 0x8000
loop:
0f4b mov r11, r15 ; mov addr r15
b012 b645 call #0x45b6 ; <sha256_internal>
2d52 add #4, r13 ; keep 4 bytes of the output
1b53 inc r11 ; inc r11
3b90 2000 cmp #0x20, r11 ; do that 0x1000 times
f72b jnc $-0xe
print_hex:
0b43 5e4b0080 4f4e 0f11 0f11 0f11 0f11 12c3 3ef00f00 3ff0 0f00 5f4f1047 b0127845 5f4e1047 b0127845 1b53 3b908000 e82b
0b43 clr r11;
5e4b 0080 mov.b 0x8000(r11), r14
4f4e mov.b r14, r15
0f11 rra.b r15
0f11 rra.b r15
0f11 rra.b r15
0f11 rra.b r15
12c3 clrc
3ef0 0f00 and #0xf, r14
3ff0 0f00 and #0xf, r15
5f4f 1047 mov.b 0x4710(r15), r15
b012 7845 call #0x4578 ; <putchar>
5f4e 1047 mov.b 0x4710(r14), r15
b012 7845 call #0x4578 ; <putchar>
1b53 add 0(r3), r11 ; inc r11
3b90 8000 cmp #0x80, r11 ; do that 0x20*4 times
e82b jnc $-0x28
take_input:
3e4040003f400090b0126845
3e40 4000 mov #0x40, r14
3f40 0090 mov #0x9000, r15
b012 6845 call #0x4568; <getsn>
check_password_questionmark:
0f433d400090b012b645
0f43 clr r15
;3e40 0010 mov #0x1000, r14 ; set length to 0x1000
3d40 0090 mov #0x9000, r13 ; set buffer to 0x9000
b012 b645 call #0x45b6 ; <sha256_internal>
unlock7f:
324000ffb0121000 0243 3041
324000ff mov #ff00, sr
b0121000 call #0x10
0243 mov #0, sr
30127f00b0125045
3012 7f00 push 0x7f
b012 5045 call 0x4550
3041 ret

View File

@ -1,88 +1,117 @@
; just
6000 1c 0b43 1e43 3d400080 0f4b b012b645 3d500300 1b53 3b906000 f72b 3041
; where depth = number of nibbles in each truncated hash
; msize = number of bytes per hash
;* depth 8, message size 2
;? completes in 67234 cycles
6000 6c
0b432e433d4000800f4bb012b6452d521b533b904000f82b
0b435e4b00804f4e0f110f110f110f1112c33ef00f003ff00f005f4f1047b01278455f4e1047b01278451b533b900001e82b
3e4040003f400090b0126845
0f433d400090b012b645
3f407f00b0125045 3041
;* depth 6, message size 1
;? completes in 61899 cycles
6000 6d
0b431e433d4000800f4bb012b6453d5003001b533b906000f72b
0b435e4b00804f4e0f110f110f110f1112c33ef00f003ff00f005f4f1047b01278455f4e1047b01278451b533b90c000e82b
3e4040003f400090b0126845
0f433d400090b012b645
3f407f00b0125045 3041
; just hash the first 0x140 B and stick them in memory
; 6000 1c 0b43 1e43 3d400080 0f4b b012b645 3d500300 1b53 3b904001 f72b 3041
; Compile with this fork of msprobe:
const:
.define msize 0x1 ; length of each hash in bytes
.define hsize 0x3 ; bytes kept per hash (only needs to be 3 to determine 1 byte of sram)
.define slen 0x140 ; number of bytes in sram to dump
.define olen 0x3c0 ; number of bytes in hash array
.define oaddr 0x7000 ; address of the big hash array
.define iaddr 0x8000 ; address of the sram input buffer
.define kaddr 0x9000 ; address of the key buffer
external_data:
.define HEX_LUT 0x4710; "0123456789ABCDEF"
external_func:
; INT(int interrupt, ...)
.define INT #0x4550
; getsn(void *dest, size_t len)
.define getsn #0x4568
; putchar(char character)
.define putchar #0x4578
; puts(char *str)
.define puts #0x4586
; memcpy(void *dest, void *src, size_t len)
.define memcpy #0x45a4
; sha256_internal(void * sram_addr, size_t sram_len, void * sha_buf)
.define sha256_internal #0x45b6
; memset(void* buf, char value, size_t length)
.define memset #0x45c8
setup_variables:
push r4
push r5
push r6
push r7
mov #msize, r4 ; message_size
mov #hsize, r5 ; bytes_per_hash
mov #slen, r6 ; sram_length
mov #olen, r7 ; output_length
get_sram_hashes:
0b43 1e43 3d400080 0f4b b012b645 3d500300 1b53 3b908000 f72b
0b43 clr r11 ; loop variable in r11
1e43 mov 0(r3), r14 ; r14 = 1
3d40 0080 mov #0x8000, r13 ; set destination to 0x8000
loop:
0f4b mov r11, r15 ; mov addr r15
b012 b645 call #0x45b6 ; <sha256_internal>
3d50 0300 add #3, r13 ; keep 3 bytes of the output
1b53 add 0(r3), r11 ; inc r11
3b90 6000 cmp #0x80, r11 ; do that 0x1000 times
f72b jnc $-0x10
clr r11 ; loop variable in r11
mov r4, r14 ; r14 = 1
mov #oaddr, r13 ; set destination to 0x8000
sr_loop:
mov r11, r15 ; mov addr r15
call sha256_internal; <sha256_internal>
add r5, r13 ; keep 3 bytes of the output
inc r11 ; inc r11
cmp r6, r11 ; do that 0x1000 times
jnc sr_loop
print_hex:
0b43 5e4b0080 4f4e 0f11 0f11 0f11 0f11 12c3 3ef00f00 3ff0 0f00 5f4f1047 b0127845 5f4e1047 b0127845 1b53 3b90 c000 e82b
clr r11;
ph_loop:
mov.b oaddr(r11), r14
mov.b r14, r15
rra r15 ; using rra here instead of rra.b means the value won't roll into the highest bit
rra r15 ; which negates the need to and 0xf, r15
rra r15
rra r15
clrc
and #0xf, r14
mov.b HEX_LUT(r15), r15
call putchar ; <putchar>
mov.b HEX_LUT(r14), r15
call putchar ; <putchar>
inc r11 ; inc r11
cmp r7, r11 ; do that sram_length*3 times
jnc ph_loop
mov.b #0xa, r15 ; '\n'
call #0x4578 ; putchar ('\n')
0b43 clr r11;
5e4b 0080 mov.b 0x8000(r11), r14
4f4e mov.b r14, r15
0f11 rra.b r15
0f11 rra.b r15
0f11 rra.b r15
0f11 rra.b r15
12c3 clrc
3ef0 0f00 and #0xf, r14
3ff0 0f00 and #0xf, r15
5f4f 1047 mov.b 0x4710(r15), r15
b012 7845 call #0x4578 ; <putchar>
5f4e 1047 mov.b 0x4710(r14), r15
b012 7845 call #0x4578 ; <putchar>
1b53 add 0(r3), r11 ; inc r11
3b90 c000 cmp #0x120, r11 ; do that 0x60*3 times
e82b jnc $-0x28
take_input:
3e4040003f400090b0126845
; 3e4040003f400090b0126845
mov r6, r14
mov #iaddr, r15
call getsn ; <getsn>
3e40 4000 mov #0x40, r14
3f40 0090 mov #0x9000, r15
b012 6845 call #0x4568; <getsn>
check_password_questionmark:
0f433d400090b012b645
0f43 clr r15
;3e40 0010 mov #0x1000, r14 ; set length to 0x1000
3d40 0090 mov #0x9000, r13 ; set buffer to 0x9000
b012 b645 call #0x45b6 ; <sha256_internal>
check_all_passwords:
;for i in 0..slen:
clr r9
pw_loop:
; memset(kaddr, 0, 0x20)
mov #20, r13
clr r14
mov #kaddr, r15
call memset
; memcpy(kaddr, iaddr + i, len)
mov #10, r13
mov #iaddr, r14
add r9, r14
mov #kaddr, r15
call memcpy
; sha256_internal(s_addr, len, kaddr)
mov #kaddr, r13 ; set buffer to 0x9000
mov #0x0010, r14 ; set length to 0x10
mov r9, r15
call sha256_internal
; INT(7f)
unlock7f:
324000ffb0121000 0243 3041
mov #0x7f, r15
call INT
324000ff mov #ff00, sr
b0121000 call #0x10
0243 mov #0, sr
inc r9
cmp r6, r9
jl pw_loop
30127f00b0125045
3012 7f00 push 0x7f
b012 5045 call 0x4550
3041 ret
teardown_variables:
pop r7
pop r6
pop r5
pop r4
ret