Skip to content

Instantly share code, notes, and snippets.

@3096
Last active April 5, 2020 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 3096/45c8bb06464e40b20d443c144ba77868 to your computer and use it in GitHub Desktop.
Save 3096/45c8bb06464e40b20d443c144ba77868 to your computer and use it in GitHub Desktop.
Animal Crossing: New Horizons anti cheat mac implement. crypto functions from PyCryptodome package
import struct
from Crypto.Hash import CMAC
from Crypto.Cipher import AES
def u32(x):
return x & 0xFFFFFFFF
class SeadRand:
def __init__(self, seed):
self.seed = u32(seed)
self.state = [self.seed]
for i in range(1, 5):
self.state.append(u32(0x6C078965 * (self.state[-1] ^ (self.state[-1] >> 30)) + i))
self.state = self.state[1:]
def load_state(self, state):
self.state = state[:]
def get_u32(self):
a = u32(self.state[0] ^ (self.state[0] << 11))
self.state[0] = self.state[1]
b = u32(self.state[3])
c = u32(a ^ (a >> 8) ^ b ^ (b >> 19))
self.state[1] = self.state[2]
self.state[2] = b
self.state[3] = c
return c
def get_key(rnd):
crypt_tab = [0xF4A40E4, 0x1BC4B20C, 0x46C243CA, 0x11661DCB, 0x4C763263, 0x721CBD33, 0x26947CA9, 0x73DB5F5,
0xFA257A5B, 0x6D47B509, 0xE8B3FD3C, 0x2CB6FC2, 0xD3ED3A62, 0x835232EB, 0xF47F65A0, 0xAD93B192,
0x1717B068, 0x5C01D0B, 0xA9D2A76, 0x3AB21596, 0x908C7658, 0x95A10907, 0x768C4F5F, 0xDC38FABD,
0x2FF569D4, 0xB281B41C, 0xA663E3A4, 0xBD9508C7, 0x39AA6D68, 0x86341F15, 0x3FF3B2B4, 0x2A3556BD,
0x409EBFBE, 0x6674CC0F, 0xC4B0B467, 0x44B092F2, 0xF166B695, 0x31B20802, 0x70E091DF, 0xB007BA33,
0x741160B8, 0xD5428420, 0xA158993E, 0x2C037904, 0xD3E8C89C, 0x124A3545, 0x77BECF5B, 0x404253F1,
0xD57BDF4D, 0x96D838BA, 0x179DF92D, 0x4512FDF4, 0x4E98C3AC, 0x19D23F2D, 0xE17EF9AB, 0x3351452D,
0xBB5C6548, 0x33FF0E59, 0x255A1A2C, 0x9C9B4B87, 0xC4B50B79, 0xFF35870, 0xFA8DA8D8, 0xBC0C037D]
key = []
for _ in range(4):
k = u32(0)
for _ in range(4):
k <<= 8
k |= u32((crypt_tab[rnd.get_u32() >> 26] >> ((rnd.get_u32() >> 27) & 0x18)) & 0xFF)
key.append(k)
return struct.pack('<IIII', key[0], key[1], key[2], key[3])
def get_cmac(key, data):
# noinspection PyTypeChecker
cmac_generator = CMAC.new(key, ciphermod=AES)
cmac_generator.update(data)
return cmac_generator.hexdigest()
if __name__ == '__main__':
key_rng = SeadRand(0x43080996)
with open(r"text+22c2490.bin", 'rb') as text_mac_data:
print("txt: ", get_cmac(get_key(key_rng), text_mac_data.read()))
with open(r"rodata.2A01660+185b10.bin", 'rb') as text_mac_data:
print("rod: ", get_cmac(get_key(key_rng), text_mac_data.read()))
with open(r"res.bin", 'rb') as text_mac_data:
print("res: ", get_cmac(get_key(key_rng), text_mac_data.read()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment