Browse Source

Upload

master
mid-kid 17 hours ago
commit
0d43238b29
  1. 20
      disassembly/Makefile
  2. 30981
      disassembly/bank_000.asm
  3. 7
      disassembly/game.asm
  4. 1075
      disassembly/hardware.inc
  5. 21199
      disassembly/pokeblue.sym
  6. 27
      flags.txt
  7. 1
      mgbdis
  8. 3
      oob_challenge.txt
  9. 88
      password.c
  10. 169
      password.py
  11. 4
      solve.sh

20
disassembly/Makefile

@ -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 {} +

30981
disassembly/bank_000.asm

File diff suppressed because it is too large

7
disassembly/game.asm

@ -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"

1075
disassembly/hardware.inc

File diff suppressed because it is too large

21199
disassembly/pokeblue.sym

File diff suppressed because it is too large

27
flags.txt

@ -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)

1
mgbdis

@ -0,0 +1 @@
Subproject commit 05be83dce0bc299a3ec0ecaa85a00241012d84f7

3
oob_challenge.txt

@ -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

88
password.c

@ -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');
}
}
}

169
password.py

@ -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")

4
solve.sh

@ -0,0 +1,4 @@
#!/bin/sh
set -e
cc -O3 password.c
./a.out | xargs -P$(nproc) ./password.py run
Loading…
Cancel
Save