Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit 96f2328

Browse files
committed
Add scripts
1 parent befa1ec commit 96f2328

File tree

2 files changed

+156
-0
lines changed

2 files changed

+156
-0
lines changed

wc24decrypt.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import os
2+
import sys
3+
from binascii import unhexlify
4+
from Crypto.Cipher import AES
5+
from requests import get
6+
7+
if len(sys.argv) < 4:
8+
print("Usage: python wc24decrypt.py <input file / url> <output file> <key / wc24pubk.mod>")
9+
sys.exit(1)
10+
11+
if sys.argv[1][:4] == "http":
12+
with open("temp", "wb") as f:
13+
f.write(get(sys.argv[1]).content)
14+
f.close()
15+
input = open("temp", "rb")
16+
else:
17+
input = open(sys.argv[1], "rb")
18+
19+
if os.path.exists(sys.argv[3]):
20+
with open(sys.argv[3], "rb") as f:
21+
if os.path.getsize(sys.argv[3]) == 16:
22+
key = f.read()
23+
elif os.path.getsize(sys.argv[3]) == 544:
24+
f.seek(512)
25+
key = f.read(16)
26+
else:
27+
print("Error: Input file is not a 16-byte key or a wc24pubk.mod")
28+
sys.exit(1)
29+
else:
30+
if len(sys.argv[3]) != 32:
31+
print("Error: Key is not 16 bytes")
32+
sys.exit(1)
33+
key = unhexlify(sys.argv[3])
34+
35+
input.seek(48)
36+
iv = input.read(16)
37+
input.seek(320)
38+
data = input.read()
39+
40+
aes = AES.new(key, AES.MODE_OFB, iv=iv)
41+
42+
with open(sys.argv[2], "wb") as f:
43+
f.write(aes.decrypt(data))
44+
f.close()
45+
46+
if os.path.exists("temp"):
47+
os.remove("temp")
48+
49+
print("Completed Successfully")

wc24encrypt.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import argparse
2+
import os
3+
import rsa
4+
import struct
5+
from binascii import unhexlify
6+
from Crypto.Cipher import AES
7+
from nlzss import encode_file
8+
9+
def u8(data):
10+
return struct.pack(">B", data)
11+
12+
13+
def u16(data):
14+
return struct.pack(">H", data)
15+
16+
17+
def u32(data):
18+
return struct.pack(">I", data)
19+
20+
parser = argparse.ArgumentParser(description="Sign / Encrypt WiiConnect24 files.")
21+
parser.add_argument("-t", "--type",
22+
type=str, nargs="+",
23+
help="Type of file. Set either enc for encrypted file, or dec for non-encrypted file.")
24+
parser.add_argument("-in", "--input",
25+
type=str, nargs="+",
26+
help="Input file.")
27+
parser.add_argument("-out", "--output",
28+
type=str, nargs="+",
29+
help="Output file.")
30+
parser.add_argument("-c", "--compress",
31+
type=str, nargs="+",
32+
help="If set, this will compress the file before signing with LZ10.")
33+
parser.add_argument("-key", "--aes-key",
34+
type=str, nargs="+",
35+
help="AES key in hex or a path.")
36+
parser.add_argument("-iv", "--iv-key",
37+
type=str, nargs="+",
38+
help="AES IV in hex or a path.")
39+
parser.add_argument("-rsa", "--rsa-key-path",
40+
type=str, nargs="+",
41+
help="RSA private key path. If not specified, it will use the private key in Private.pem if it exists.")
42+
43+
args = parser.parse_args()
44+
45+
if args.compress is not None:
46+
encode_file(in_path=args.input[0], out_path="temp")
47+
filename = "temp"
48+
else:
49+
filename = args.input[0]
50+
51+
with open(filename, "rb") as f:
52+
data = f.read()
53+
54+
if args.rsa_key_path is not None:
55+
rsa_key_path = args.rsa_key_path[0]
56+
else:
57+
rsa_key_path = "Private.pem"
58+
59+
with open(rsa_key_path, "rb") as source_file:
60+
private_key_data = source_file.read()
61+
62+
private_key = rsa.PrivateKey.load_pkcs1(private_key_data, "PEM")
63+
64+
signature = rsa.sign(data, private_key, "SHA-1")
65+
66+
if args.type[0] == "enc":
67+
if args.iv_key is not None:
68+
try:
69+
iv = unhexlify(args.iv_key[0])
70+
except:
71+
iv = open(args.iv_key[0], "rb").read()
72+
else:
73+
iv = os.urandom(16)
74+
75+
try:
76+
key = unhexlify(args.aes_key[0])
77+
except:
78+
key = open(args.aes_key[0], "rb").read()
79+
80+
aes = AES.new(key, AES.MODE_OFB, iv=iv)
81+
processed = aes.encrypt(data)
82+
elif args.type[0] == "dec":
83+
processed = data
84+
85+
content = {}
86+
87+
content["magic"] = b"WC24" if args.type[0] == "enc" else u32(0)
88+
content["version"] = u32(1) if args.type[0] == "enc" else u32(0)
89+
content["filler"] = u32(0)
90+
content["crypt_type"] = u8(1) if args.type[0] == "enc" else u8(0)
91+
content["pad"] = u8(0) * 3
92+
content["reserved"] = u8(0) * 32
93+
content["iv"] = iv if args.type[0] == "enc" else u8(0) * 16
94+
content["signature"] = signature
95+
content["data"] = processed
96+
97+
if os.path.exists(args.output[0]):
98+
os.remove(args.output[0])
99+
100+
if args.type[0] == "dec":
101+
os.remove("temp")
102+
103+
for values in content.values():
104+
with open(args.output[0], "ab+") as f:
105+
f.write(values)
106+
107+
print("Completed Successfully")

0 commit comments

Comments
 (0)