commit
0d43238b29
11 changed files with 53574 additions and 0 deletions
@ -0,0 +1,20 @@ |
|||
all: game.gbc |
|||
|
|||
%.2bpp: %.png |
|||
rgbgfx --colors embedded -o $@ $< |
|||
|
|||
%.1bpp: %.png |
|||
rgbgfx -d 1 -o $@ $< |
|||
|
|||
game.o: game.asm bank_*.asm |
|||
rgbasm -o game.o game.asm |
|||
|
|||
game.gbc: game.o |
|||
rgblink --tiny -n game.sym -m game.map -o $@ $< |
|||
rgbfix -v -p 255 $@ |
|||
|
|||
@if which md5sum &>/dev/null; then md5sum $@; else md5 $@; fi |
|||
|
|||
clean: |
|||
rm -f game.o game.gbc game.sym game.map |
|||
find . \( -iname '*.1bpp' -o -iname '*.2bpp' \) -exec rm {} + |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||
; Disassembly of "fools.sav" |
|||
; This file was created with: |
|||
; mgbdis v2.0 - Game Boy ROM disassembler by Matt Currie and contributors. |
|||
; https://github.com/mattcurrie/mgbdis |
|||
|
|||
INCLUDE "hardware.inc" |
|||
INCLUDE "bank_000.asm" |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,27 @@ |
|||
Breakpoint at S02:A9E2, modify register A |
|||
|
|||
00: F4660888 (invalid) |
|||
01: 88509D53 |
|||
02: 536A1248 |
|||
03: 48975C04 |
|||
04: 04CAE9E3 |
|||
05: E31DE75F |
|||
06: 5F29D022 |
|||
07: 22AFCABB |
|||
08: BB40762A |
|||
09: 2AA8AE76 |
|||
0a: 768BA8FE |
|||
0b: FE76C776 |
|||
0c: 76B17639 |
|||
0d: 39A82376 |
|||
0e: 76C2A823 |
|||
0f: 23A8C3A8 |
|||
10: A86F767B |
|||
11: 7BA88DB0 |
|||
12: B0AA5BFD |
|||
13: FD4CCC0A |
|||
14: 0A51BCE1 |
|||
15: E1CB6D7D |
|||
16: 7DA1357C |
|||
17: 7C9D0BCE |
|||
18: CE729EFB (invalid) |
@ -0,0 +1,3 @@ |
|||
Stand outside of bill's house |
|||
Address 07:68ff write 06 0B |
|||
Enter the house, don't move and talk to the gem |
@ -0,0 +1,88 @@ |
|||
#include <stdint.h> |
|||
#include <stdbool.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
struct hash { |
|||
uint16_t hl; |
|||
uint16_t bc; |
|||
}; |
|||
|
|||
struct hash hashpass(uint8_t *password) |
|||
{ |
|||
uint8_t c, b, c1; |
|||
|
|||
#define swap(x) (((x & 0x0f) << 4) | ((x & 0xf0) >> 4)) |
|||
c = password[0] & 0xf; |
|||
b = swap(password[0]) & 0x03; |
|||
c = ((password[1] & 0xf) + swap(c)) & 0xff; |
|||
b = ((swap(password[1]) & 0x03) + ((b << 2) & 0xff)) & 0xff; |
|||
c1 = c; |
|||
c = password[2] & 0xf; |
|||
b = ((swap(password[2]) & 0x03) + ((b << 2) & 0xff)) & 0xff; |
|||
c = ((password[3] & 0xf) + swap(c)) & 0xff; |
|||
b = ((swap(password[3]) & 0x03) + ((b << 2) & 0xff)) & 0xff; |
|||
#undef swap |
|||
|
|||
return (struct hash){.hl = (password[4] << 8) | b, .bc = (c << 8) | c1}; |
|||
} |
|||
|
|||
bool validpass(struct hash password) |
|||
{ |
|||
if ((password.hl & 0xe000) != 0) return false; |
|||
if ((password.hl & 0x0007) != 0) return false; |
|||
return true; |
|||
} |
|||
|
|||
char *passchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?!"; |
|||
|
|||
void convpass(char *password, uint8_t *out) |
|||
{ |
|||
for (int x = 0; x < 5; x++) { |
|||
*out++ = strchr(passchars, *password++) - passchars; |
|||
} |
|||
} |
|||
|
|||
void hex_dump(const unsigned char *buf, unsigned size) |
|||
{ |
|||
for (unsigned i = 0; i < size; i += 0x10) { |
|||
printf(" "); |
|||
for (unsigned x = i; x < i + 0x10 && x < size; x++) { |
|||
printf(" %02X", buf[x]); |
|||
} |
|||
printf("\n"); |
|||
} |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
if (argc > 1 && strcmp(argv[1], "valid") == 0) { |
|||
for (char **arg = argv + 2; arg < argv + argc; arg++) { |
|||
uint8_t pwd[5]; |
|||
convpass(*arg, pwd); |
|||
hex_dump(pwd, sizeof(pwd)); |
|||
struct hash hash = hashpass(pwd); |
|||
printf("0x%04x 0x%04x\n", hash.hl, hash.bc); |
|||
if (validpass(hash)) { |
|||
printf("%s\n", *arg); |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
for (uint64_t x = 0; x < 0x40000000; x++) { |
|||
uint8_t pwd[5]; |
|||
uint64_t val = x; |
|||
for (uint8_t *c = pwd; c < pwd + 5; c++) { |
|||
*c = val % 64; |
|||
val /= 64; |
|||
} |
|||
struct hash hash = hashpass(pwd); |
|||
if (validpass(hash)) { |
|||
for (uint8_t *c = pwd; c < pwd + 5; c++) { |
|||
putchar_unlocked(passchars[*c]); |
|||
} |
|||
putchar_unlocked('\n'); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,169 @@ |
|||
#!/usr/bin/env python3 |
|||
|
|||
class RNG: |
|||
def __init__(self): |
|||
self.rng = [0xe3, 0x34, 0xad, 0x30] |
|||
|
|||
def next(self): |
|||
self.rng[0] += 1 |
|||
self.rng[0] &= 0xff |
|||
|
|||
self.rng[1] ^= self.rng[0] |
|||
self.rng[1] ^= self.rng[3] |
|||
self.rng[2] += self.rng[1] |
|||
self.rng[2] &= 0xff |
|||
self.rng[3] += (self.rng[2] >> 1) ^ self.rng[1] |
|||
self.rng[3] &= 0xff |
|||
return self.rng[3] |
|||
|
|||
class FunnyCode: |
|||
def __init__(self): |
|||
self.code = self.gencode() |
|||
self.cache = {} |
|||
|
|||
def __str__(self): |
|||
return " ".join(map(lambda x: "%02x" % x, self.code)) |
|||
|
|||
def gencode(self): |
|||
rng = RNG() |
|||
code = [] |
|||
for x in range(0x400): |
|||
val1 = rng.next() |
|||
while val1 == 0: |
|||
val1 = rng.next() |
|||
|
|||
val2 = rng.next() |
|||
while True: |
|||
val2 &= 0xf8 |
|||
if val2 in [0x00, 0x08, 0xf8]: |
|||
val2 = rng.next() |
|||
continue |
|||
break |
|||
|
|||
code.append(0x0e) # ld c, n8 |
|||
code.append(val1) |
|||
code.append(0x09) # add hl, bc |
|||
code.append(0x15) # dec d |
|||
code.append(0xc8) # ret z |
|||
code.append(0x1d) # dec e |
|||
|
|||
if x < 0x14: |
|||
code.append(0x20) # jr nz, o8 |
|||
code.append(val2 & 0x7f) |
|||
elif x >= 0x400 - 0x14: |
|||
code.append(0x18) # jr o8 |
|||
code.append((val2 & 0x7f) + 0x80) |
|||
else: |
|||
code.append(0x20) # jr nz, o8 |
|||
code.append(val2) |
|||
|
|||
return code |
|||
|
|||
def runcode(self, offset, de): |
|||
key = offset << 16 | de |
|||
if key in self.cache: |
|||
return self.cache[key] |
|||
|
|||
hl = 0 |
|||
bc = 0 |
|||
d = de >> 8 |
|||
e = de & 0xff |
|||
while True: |
|||
# de = d << 8 | e |
|||
# print("0x%04x"%offset, "bc=0x%04x"%bc, "de=0x%04x"%de, "hl=0x%04x"%hl) |
|||
c = self.code[offset + 1] |
|||
bc = (bc & 0xff00) | c |
|||
hl = (hl + bc) & 0xffff |
|||
d -= 1 |
|||
d &= 0xff |
|||
if d == 0: break |
|||
e -= 1 |
|||
e &= 0xff |
|||
if self.code[offset + 6] == 0x20 and e == 0: |
|||
offset += 8 |
|||
else: |
|||
jr = self.code[offset + 7] |
|||
if jr >= 0x80: jr -= 0x100 |
|||
offset = (offset + 8) + jr |
|||
|
|||
self.cache[key] = hl |
|||
return hl |
|||
|
|||
class PasswordHash: |
|||
def __init__(self, password): |
|||
self.hash = self.hashpass(password) |
|||
self.valid = True |
|||
if (self.hash[0] & 0xe000) != 0: |
|||
self.valid = False |
|||
if (self.hash[0] & 0x0007) != 0: |
|||
self.valid = False |
|||
|
|||
def swap(self, val): |
|||
vl = (val & 0xf0) >> 4 |
|||
vh = (val & 0x0f) << 4 |
|||
return vh | vl |
|||
|
|||
def hashpass(self, password): |
|||
c = password[0] & 0xf |
|||
b = self.swap(password[0]) & 0x03 |
|||
c = ((password[1] & 0xf) + self.swap(c)) & 0xff |
|||
b = ((self.swap(password[1]) & 0x03) + ((b << 2) & 0xff)) & 0xff |
|||
c1 = c |
|||
c = password[2] & 0xf |
|||
b = ((self.swap(password[2]) & 0x03) + ((b << 2) & 0xff)) & 0xff |
|||
c = ((password[3] & 0xf) + self.swap(c)) & 0xff |
|||
b = ((self.swap(password[3]) & 0x03) + ((b << 2) & 0xff)) & 0xff |
|||
|
|||
return (password[4] << 8) | b, (c << 8) | c1 |
|||
|
|||
passchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?!" |
|||
def convpass(password): |
|||
return bytearray(passchars.index(x) for x in password) |
|||
|
|||
if __name__ == "__main__": |
|||
wanted = [ |
|||
0xadaa, |
|||
0xac39, |
|||
0x002f |
|||
] |
|||
|
|||
from sys import argv |
|||
if len(argv) > 1 and argv[1] == "valid": |
|||
for x in argv[2:]: |
|||
pwd = convpass(x) |
|||
password = PasswordHash(pwd) |
|||
print(*map(hex, password.hash)) |
|||
if password.valid: |
|||
print(x) |
|||
exit() |
|||
if len(argv) > 1 and argv[1] == "run": |
|||
code = FunnyCode() |
|||
for x in argv[2:]: |
|||
pwd = convpass(x) |
|||
password = PasswordHash(pwd) |
|||
result = code.runcode(*password.hash) |
|||
if result in wanted: |
|||
print(hex(result), x) |
|||
exit() |
|||
|
|||
code = FunnyCode() |
|||
|
|||
pwd = convpass("BEPISBEPISBEPIS") |
|||
password = PasswordHash(pwd) |
|||
print(password.hash) |
|||
if not password.valid: |
|||
print("Password invalid!") |
|||
exit(1) |
|||
print(hex(code.runcode(*password.hash))) |
|||
|
|||
# val = code.runcode(0, 0) |
|||
# print(hex(val)) |
|||
# if val != 0x1a51: |
|||
# exit(1) |
|||
|
|||
# val = code.runcode(0x1200, 0xf814) |
|||
# print(hex(val)) |
|||
# if val != 0x4031: |
|||
# exit(1) |
|||
|
|||
# print("success") |
@ -0,0 +1,4 @@ |
|||
#!/bin/sh |
|||
set -e |
|||
cc -O3 password.c |
|||
./a.out | xargs -P$(nproc) ./password.py run |
Loading…
Reference in new issue