mirror of
https://github.com/barberd/depace.git
synced 2024-06-14 09:29:29 +00:00
Initial Commit
This commit is contained in:
parent
0bf9dde01a
commit
9b8d504a13
20
README.md
20
README.md
|
@ -1,4 +1,22 @@
|
||||||
# depace
|
# depace
|
||||||
Code to remove PACE anti-piracy on select early 68k Macintosh abandonware
|
Code to remove PACE anti-piracy on select early 68k Macintosh abandonware
|
||||||
|
|
||||||
These scripts are written to modify the application stored in MacBinary format, and expect the resource fork to be located at 0x80.
|
In the mid-80s, software publishers sought solutions to prevent copying of software to new floppies. PACE Anti-Piracy, Inc offered a solution for the early Macintoshes. PACE created self-modifying code that would decrypt and execute anti-piracy routines on the fly. These routines would check the floppy disk for the existence of a bad block. If the block was not bad, the software would refuse to run as likely someone had copied the floppy.
|
||||||
|
|
||||||
|
Since the floppy-checking routines were encrypted, it was more difficult to bypass the anti-piracy check. Additionally, a few applications (MacWars and Seven Cities of Gold), the entire application was encrypted, not just the anti-piracy code. The anti-piracy routines also include checks to make sure debugging software is not in use, even going as far as checking how much time has passed between different stages of decryption and rebooting if it detects anything unusual.
|
||||||
|
|
||||||
|
However, as the original disks are failing at 35+ years old and this software is often accessed via emulators today, these anti-piracy routines make the software unusable.
|
||||||
|
|
||||||
|
These scripts decrypt and patch these applications so they can be used again today with new floppies and on emulators.
|
||||||
|
|
||||||
|
Please note these scripts are written to modify the application stored in MacBinary format, and expect the resource fork to be located at 0x80. If you are operating directly on resource fork files, you may need to modify the code to remove the "+0x80" directives in the seek() calls.
|
||||||
|
|
||||||
|
The decrypt/ dir contains the scripts that decrypt the application binaries, so the application code and anti-piracy code is available for inspection in forensic tools/disassemblers/etc. Note that decryption alone is not enough to make the applications usable, as the anti-piracy checks are still in place.
|
||||||
|
|
||||||
|
The patch/ dir contains scripts that modify the application binaries to bypass the anti-piracy routines.
|
||||||
|
|
||||||
|
For MacWars and Seven Cities of Gold, the entire application is encrypted and must be decrypted. For these, run the decryption scripts, then run the patch scripts.
|
||||||
|
|
||||||
|
The other applications only have the anti-piracy routines encrypted, so one can just run the patch scripts without first decrypting, as the patch will bypass the encrypted routines altogether. The decryption scripts for these applications are more of interest for researchers and computer archeologists.
|
||||||
|
|
||||||
|
|
||||||
|
|
140
decrypt/StarTrekKobayashi-decrypt.py
Executable file
140
decrypt/StarTrekKobayashi-decrypt.py
Executable file
|
@ -0,0 +1,140 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(start,end):
|
||||||
|
key = int("0x50414345",0)
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("StarTrek.bin","r+b")
|
||||||
|
key= 0x9ad33b77 #0x1d448
|
||||||
|
write_decrypt2(0x1d498,0x1d498+0x8fe-1,key,0x5a6b7c8d) #0x1d456
|
||||||
|
fh.close()
|
||||||
|
|
140
decrypt/SwordOfKadash-decrypt.py
Executable file
140
decrypt/SwordOfKadash-decrypt.py
Executable file
|
@ -0,0 +1,140 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(start,end):
|
||||||
|
key = int("0x50414345",0)
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("kad_main.bin","r+b")
|
||||||
|
key= 0x997e04cd
|
||||||
|
write_decrypt2(0xaf58,0xaf58+0x8fe-1,key,0x5a6b7c8d) #CODE2's encrypted block
|
||||||
|
write_decrypt2(0xb8e6,0xb8e6+0x8fe-1,key,0x5a6b7c8d) #CODE3's encrypted block
|
||||||
|
fh.close()
|
||||||
|
|
199
decrypt/macwars-D-decrypt.py
Executable file
199
decrypt/macwars-D-decrypt.py
Executable file
|
@ -0,0 +1,199 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(start,end):
|
||||||
|
key = int("0x50414345",0)
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("D.bin","r+b")
|
||||||
|
|
||||||
|
#round 1
|
||||||
|
key= getkey1(0x5204,0x5369) # 0x5234
|
||||||
|
key2 = getkey1(0x5204,0x6d19) # 0x5220
|
||||||
|
write_decrypt1(0x536a,0x6d88-1,key) # 0x524C
|
||||||
|
|
||||||
|
#round 2
|
||||||
|
key= getkey2(0,0x5204,0x56b5,0,0x8005) #0x539E
|
||||||
|
key2 = key2 + getkey2(0x50414345,0x5204,0x6d19,0xFF,0x8005) #0x5406
|
||||||
|
write_decrypt2(0x56b6,0x6d80-1,key,0x776de01d) # 0x5424
|
||||||
|
|
||||||
|
#round 3
|
||||||
|
key= (getkey2(0xAAAAAAAA,0x5204,0x6535,0,0x1021) + 0xF085) & 0xFFFFFFFF #0x5738
|
||||||
|
# the 0xf085 is loaded in at 0x56c8
|
||||||
|
key2 = key2 + getkey2(0x50414345,0x5204,0x6d19,0xFF,0x1021) # 0x595C-0x5960
|
||||||
|
write_decrypt2(0x6536,0x6d7f-1,key,0xdddaac4d) # 0x598E
|
||||||
|
|
||||||
|
#round 4 (jump table and code tables)
|
||||||
|
key= getkey2(0x55555555,0x536a,0x6d19,0xFF,0x8005) # 0x65F4
|
||||||
|
key = (key + key2 + getkey2(0x50414345,0x6536,0x6d19,0x0,0x8005)) & 0xFFFFFFFF # 0x65CE-0x65D2
|
||||||
|
|
||||||
|
#the entire jump table was encrypted, then the first 8 bytes stored in CODE4.
|
||||||
|
#then an entry jumping to the PACE code was put in.
|
||||||
|
#round4 copies these 8 bytes out of CODE4, restoring the entire applications
|
||||||
|
#jump table and then decrypts it
|
||||||
|
#0x66F0 says this is stored in CODE4
|
||||||
|
#0x65ac loads it into memory and copies it over the jump
|
||||||
|
copybytes(0x6d8f,0x114,0xD-0x5)
|
||||||
|
#decryption happens at 0x6654
|
||||||
|
write_decrypt2(0x114,0x114+0x88-1,key,0xd975bb1d)
|
||||||
|
|
||||||
|
#bruteforce this instead of stepping through all the code
|
||||||
|
#between 0x57b0 and 0x492F to figure out what to add at 0x669a
|
||||||
|
#basically, the first byte of a code segment must be \x00, unless
|
||||||
|
#the jump table is over 256 bytes (which it isn't in this case)
|
||||||
|
#so loop until the \x00 has been found.
|
||||||
|
#this only works because the encryption algorithm really only uses the last
|
||||||
|
#single byte of the key...so really there are only 256 possibilities.
|
||||||
|
#no idea why PACE didnt use all 32 bits available to them; it would have
|
||||||
|
#been much more difficult
|
||||||
|
i=0
|
||||||
|
fh.seek(0x1a0 + 0x80) #use the first byte of CODE1 as the target
|
||||||
|
testblock=bytearray(fh.read(1))
|
||||||
|
while i<0xFF:
|
||||||
|
testkey = (key+i)&0xFFFFFFFF
|
||||||
|
outblock=decrypt2(testblock[:],testkey,0xad95322d)
|
||||||
|
if outblock[0]==0:
|
||||||
|
print("Key add:",hex(i),outblock)
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
key=testkey
|
||||||
|
|
||||||
|
#with this key, PACE now decrypts anything in memory at 0x66AE
|
||||||
|
#and then overloads the trap to load a new code segment to decrypt
|
||||||
|
#them on the fly at 0x66C6. This way, it still works when the Macintosh
|
||||||
|
#memory manager swaps code segments in from disk and out from memory.
|
||||||
|
write_decrypt2(0x1a0,0x1a0+0x4544-1,key,0xad95322d) #CODE1
|
||||||
|
write_decrypt2(0x46e8,0x46e8+0x3a4-1,key,0xad95322d) #CODE2
|
||||||
|
write_decrypt2(0x4a90,0x4a90+0x570-1,key,0xad95322d) #CODE3
|
||||||
|
write_decrypt2(0x5004,0x5004+0x46-1,key,0xad95322d) #CODE255
|
||||||
|
|
||||||
|
fh.close()
|
||||||
|
|
180
decrypt/macwars-_-decrypt.py
Executable file
180
decrypt/macwars-_-decrypt.py
Executable file
|
@ -0,0 +1,180 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(start,end):
|
||||||
|
key = int("0x50414345",0)
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("_.bin","r+b")
|
||||||
|
|
||||||
|
#round 1
|
||||||
|
key= getkey1(0xb504,0xb669)
|
||||||
|
key2 = getkey1(0xb504,0xd019)
|
||||||
|
write_decrypt1(0xb66a,0xd088-1,key)
|
||||||
|
|
||||||
|
#round 2
|
||||||
|
key= getkey2(0,0xb504,0xb9b5,0,0x8005)
|
||||||
|
key2 = (key2 + getkey2(0x50414345,0xb504,0xd019,0xFF,0x8005)) & 0xFFFFFFFF
|
||||||
|
write_decrypt2(0xb9b6,0xd080-1,key,0x776de01d)
|
||||||
|
|
||||||
|
#round 3
|
||||||
|
key= (getkey2(0xAAAAAAAA,0xb504,0xc835,0,0x1021) + 0x41BA) & 0xFFFFFFFF
|
||||||
|
key2 = (key2 + getkey2(0x50414345,0xb504,0xd019,0xFF,0x1021)) & 0xFFFFFFFF
|
||||||
|
write_decrypt2(0xc836,0xd07f-1,key,0xdddaac4d)
|
||||||
|
|
||||||
|
#round 4 (jump table and code tables)
|
||||||
|
key= getkey2(0x55555555,0xb66a,0xd019,0xFF,0x8005) & 0xFFFFFFFF
|
||||||
|
key = (key + key2 + getkey2(0x50414345,0xc836,0xd019,0x0,0x8005)) & 0xFFFFFFFF
|
||||||
|
copybytes(0xd08f,0x114,0xD-0x5)
|
||||||
|
write_decrypt2(0x114,0x784-1,key,0xd975bb1d)
|
||||||
|
|
||||||
|
#bruteforce the key. Use CODE1's first byte as the target.
|
||||||
|
i=0
|
||||||
|
fh.seek(0x788 + 0x80)
|
||||||
|
testblock=bytearray(fh.read(1))
|
||||||
|
while i<0xFF:
|
||||||
|
testkey = (key+i)&0xFFFFFFFF
|
||||||
|
outblock=decrypt2(testblock[:],testkey,0xad95322d)
|
||||||
|
if outblock[0]==0:
|
||||||
|
print("Key add:",hex(i),outblock)
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
|
||||||
|
key=testkey
|
||||||
|
write_decrypt2(0x788,0x788+0x23A-1,key,0xad95322d) #CODE1
|
||||||
|
write_decrypt2(0x9c6,0x9c6+0x4bb0-1,key,0xad95322d) #CODE2
|
||||||
|
write_decrypt2(0x557a,0x557a+0x21ec-1,key,0xad95322d) #CODE3
|
||||||
|
write_decrypt2(0x776a,0x776a+0x3282-1,key,0xad95322d) #CODE4
|
||||||
|
write_decrypt2(0xa9f0,0xa9f0+0x352-1,key,0xad95322d) #CODE5
|
||||||
|
write_decrypt2(0xad46,0xad46+0x570-1,key,0xad95322d) #CODE6
|
||||||
|
write_decrypt2(0xb2ba,0xb2ba+0x5e-1,key,0xad95322d) #CODE255
|
||||||
|
|
||||||
|
fh.close()
|
187
decrypt/seven_cities_decrypt.py
Executable file
187
decrypt/seven_cities_decrypt.py
Executable file
|
@ -0,0 +1,187 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(key,start,end):
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("Seven_Cities.bin","r+b")
|
||||||
|
|
||||||
|
#round 1
|
||||||
|
rolling_key=getkey1(0x50414345,0x2dccc,0x305d1)
|
||||||
|
r1key=getkey1(0x50414345,0x2dccc,0x2de67)
|
||||||
|
write_decrypt1(0x2de68,0x30642-1,r1key)
|
||||||
|
|
||||||
|
#round2
|
||||||
|
r2key=getkey2(0,0x2dccc,0x2e247,0,0x8005) #0x2dea4
|
||||||
|
rolling_key+=getkey2(0x50414345,0x2dccc,0x305d1,0xff,0x8005) #0x2df2a
|
||||||
|
write_decrypt2(0x2e248,0x30642-1,r2key,0x776de01d) #0x2df44
|
||||||
|
|
||||||
|
#round3
|
||||||
|
r3key=getkey2(0xAAAAAAAA,0x2dccc,0x2fde5,0,0x1021) #2e2ee -$24(a6)
|
||||||
|
rolling_key+=getkey2(0x50414345,0x2dccc,0x305d1,0xff,0x1021) #0x2e7a8 -$20(a6)
|
||||||
|
r3key=(r3key+0xcb838d42)&0xFFFFFFFF #added from 0x2e810
|
||||||
|
write_decrypt2(0x2fde6,0x30641-1,r3key,0xdddaac4d) #0x2e7d6
|
||||||
|
|
||||||
|
#round4
|
||||||
|
r4key=getkey2(0x55555555,0x2de68,0x305d1,0xFF,0x8005) #2fec4 -$24(a6)
|
||||||
|
rolling_key+=getkey2(0x50414345,0x2fde6,0x305d1,0x0,0x8005) #2fe9e -$20(a6)
|
||||||
|
r4key=(r4key+rolling_key)&0xFFFFFFFF #added at 0x2fecc put in -2C(a6)
|
||||||
|
#replace PACE routine in jump table with application original and decrypt
|
||||||
|
copybytes(0x30667,0x114,0xD-0x5) #2ff02
|
||||||
|
write_decrypt2(0x114,0x114+0x28-1,r4key,0xd975bb1d) #0x2ff32
|
||||||
|
|
||||||
|
#round5
|
||||||
|
#decrypt all application code segments now
|
||||||
|
|
||||||
|
#bruteforce this instead of stepping through all that code to figure it out
|
||||||
|
#basically, the first byte of a code segment must be \x00, unless
|
||||||
|
#the jump table is over 256 bytes (which it isn't in this case)
|
||||||
|
#so loop until the \x00 has been found.
|
||||||
|
fh.seek(0x140+0x80)
|
||||||
|
testbytes=fh.read(1)
|
||||||
|
i=0
|
||||||
|
while True:
|
||||||
|
outbytes=decrypt2(testbytes,(r4key+i)&0xFFFFFFFF,0xad95322d)
|
||||||
|
print(i,outbytes)
|
||||||
|
if outbytes==b'\x00':
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
print("Delta:",i)
|
||||||
|
r5key = (r4key + i)&0xFFFFFFFF
|
||||||
|
|
||||||
|
write_decrypt2(0x140,0x140+0x2260-1,r5key,0xad95322d) #0xCODE1
|
||||||
|
write_decrypt2(0x23a4,0x23a4+0xcb3e-1,r5key,0xad95322d) #0xCODE2
|
||||||
|
write_decrypt2(0xeee6,0xeee6+0xc554-1,r5key,0xad95322d) #0xCODE3
|
||||||
|
write_decrypt2(0x1b43e,0x1b43e+0x6e36-1,r5key,0xad95322d) #0xCODE4
|
||||||
|
write_decrypt2(0x22278,0x22278+0x8b68-1,r5key,0xad95322d) #0xCODE5
|
||||||
|
write_decrypt2(0x2ade4,0x2ade4+0x2d0e-1,r5key,0xad95322d) #0xCODE255
|
||||||
|
|
||||||
|
fh.close()
|
143
decrypt/shanghaiv1-decrypt.py
Executable file
143
decrypt/shanghaiv1-decrypt.py
Executable file
|
@ -0,0 +1,143 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ror = lambda val, r_bits, max_bits: \
|
||||||
|
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
|
||||||
|
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
|
||||||
|
|
||||||
|
rol = lambda val, r_bits, max_bits: \
|
||||||
|
(val << r_bits%max_bits) & (2**max_bits-1) | \
|
||||||
|
((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
|
||||||
|
|
||||||
|
|
||||||
|
def getkey1(start,end):
|
||||||
|
key = int("0x50414345",0)
|
||||||
|
i = start + 0x80
|
||||||
|
while(i<=(end + 0x80)):
|
||||||
|
fh.seek(i);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
key+=ib
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_bit(i):
|
||||||
|
i=i%8
|
||||||
|
return (0x1 << i)
|
||||||
|
|
||||||
|
def getkey2(key,start,end,inflag,obfuscator):
|
||||||
|
i = start
|
||||||
|
while(i<=end):
|
||||||
|
bitnum = 0x80
|
||||||
|
if inflag==0:
|
||||||
|
bitnum=0x1
|
||||||
|
fh.seek(i+0x80);
|
||||||
|
ib = int.from_bytes(fh.read(1),byteorder='big')
|
||||||
|
while True:
|
||||||
|
key = key << 1
|
||||||
|
test_mask=get_bit(bitnum)
|
||||||
|
if key<(2**32):
|
||||||
|
if((test_mask & ib)==0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
else:
|
||||||
|
key = key & 0xFFFFFFFF
|
||||||
|
if((test_mask & ib)!=0):
|
||||||
|
key = key ^ obfuscator
|
||||||
|
if (inflag!=0):
|
||||||
|
bitnum = ror(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x80)!=0):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bitnum = rol(bitnum,1,8)
|
||||||
|
if ((bitnum & 0x1)==0x1):
|
||||||
|
break
|
||||||
|
i+=1
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt1(start,end,key):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
inblock=bytearray(fh.read(end-start+1))
|
||||||
|
outblock=decrypt1(key,inblock[:])
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
fh.write(bytes(outblock))
|
||||||
|
|
||||||
|
def decrypt1(key,block):
|
||||||
|
def rotate_key(d0,d1,d2):
|
||||||
|
if d2==0:
|
||||||
|
d0 = ror(d0,d1,32)
|
||||||
|
else:
|
||||||
|
d0 = rol(d0,d1,32)
|
||||||
|
return d0
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<len(block):
|
||||||
|
key_lb = key&0xFF
|
||||||
|
i_lb = i&0xFF
|
||||||
|
if (i_lb&0x1 == 0):
|
||||||
|
key_lb = key_lb & 0xF
|
||||||
|
else:
|
||||||
|
key_lb = (key_lb >> 4) &0xFFFF
|
||||||
|
key = rotate_key(key,key_lb,0)
|
||||||
|
ib = block[i]
|
||||||
|
key_lb = key&0xFF
|
||||||
|
output = ib ^ key_lb
|
||||||
|
block[i]=output
|
||||||
|
i+=1
|
||||||
|
return block
|
||||||
|
|
||||||
|
|
||||||
|
def write_decrypt2(i,end,key,salt):
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
block=fh.read(end-i+1)
|
||||||
|
fh.seek(i+0x80)
|
||||||
|
fh.write(decrypt2(block,key,salt))
|
||||||
|
|
||||||
|
|
||||||
|
def swap(inbyte):
|
||||||
|
in_th = inbyte>>16
|
||||||
|
in_bh = (inbyte & 0xFFFF)
|
||||||
|
out = (in_bh << 16) + in_th
|
||||||
|
return out
|
||||||
|
|
||||||
|
def decrypt2(block,key,salt):
|
||||||
|
blockarray=bytearray(block)
|
||||||
|
i=0
|
||||||
|
while(i<len(blockarray)):
|
||||||
|
d2=key
|
||||||
|
d4=key
|
||||||
|
d2=swap(d2)
|
||||||
|
key+=d2
|
||||||
|
key=key & 0xFFFF
|
||||||
|
d4=swap(d4)
|
||||||
|
d4=d4 & 0xFFFF0000
|
||||||
|
key+=d4
|
||||||
|
key=swap(key)
|
||||||
|
key+=salt
|
||||||
|
key=key&0xFFFFFFFF
|
||||||
|
ib = blockarray[i]
|
||||||
|
output=ib ^ (key & 0xFF)
|
||||||
|
blockarray[i]=output
|
||||||
|
i+=1
|
||||||
|
return bytes(blockarray)
|
||||||
|
|
||||||
|
def copybytes(source,target,count):
|
||||||
|
fh.seek(source+0x80)
|
||||||
|
block=fh.read(count)
|
||||||
|
fh.seek(target+0x80)
|
||||||
|
fh.write(block)
|
||||||
|
|
||||||
|
def savebytes(filename,start,end):
|
||||||
|
fh.seek(start+0x80)
|
||||||
|
oh=open(filename,"wb")
|
||||||
|
oh.write(fh.read(end-start+1))
|
||||||
|
oh.close()
|
||||||
|
|
||||||
|
fh = open("P1.rsrc","r+b")
|
||||||
|
key= 0x9aee1dcd #key found at 0x15082
|
||||||
|
#inputs set up in 0x1508C
|
||||||
|
#end decryption called at 0x15090
|
||||||
|
write_decrypt2(0x150d6,0x150d6+0x9d8-1,key,0x5a6b7c8d)
|
||||||
|
|
||||||
|
fh.close()
|
||||||
|
|
19
patch/SwordOfKadash-postdecrypt-patch.py
Executable file
19
patch/SwordOfKadash-postdecrypt-patch.py
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
noops = [
|
||||||
|
[0x354,0x35d], #jump to CODE 2 and jump if 0 return
|
||||||
|
[0x40aa,0x40bd], #jump to code 3 and jump if 0 return
|
||||||
|
[0x8fd6,0x8fd7] #control trap used for saving the game to bypass
|
||||||
|
#read-only lock flag on MFS filesystem
|
||||||
|
]
|
||||||
|
|
||||||
|
fh=open("kad_main.bin","r+b")
|
||||||
|
|
||||||
|
for myrange in noops:
|
||||||
|
i=myrange[0]+0x80
|
||||||
|
while i<=(myrange[1]+0x80):
|
||||||
|
fh.seek(i)
|
||||||
|
fh.write((0x4e71).to_bytes(2,'big'))
|
||||||
|
i+=2
|
||||||
|
|
||||||
|
fh.close()
|
16
patch/macwars-patchT.py
Executable file
16
patch/macwars-patchT.py
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
noops = [
|
||||||
|
[0x132e,0x1363]
|
||||||
|
]
|
||||||
|
|
||||||
|
fh=open("T.bin","r+b")
|
||||||
|
|
||||||
|
for myrange in noops:
|
||||||
|
i=myrange[0]+0x80
|
||||||
|
while i<=(myrange[1]+0x80):
|
||||||
|
fh.seek(i)
|
||||||
|
fh.write((0x4e71).to_bytes(2,'big'))
|
||||||
|
i+=2
|
||||||
|
|
||||||
|
fh.close()
|
16
patch/macwars-postdecrypt-patchD.py
Executable file
16
patch/macwars-postdecrypt-patchD.py
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
noops = [
|
||||||
|
[0x50c,0x541]
|
||||||
|
]
|
||||||
|
|
||||||
|
fh=open("D.bin","r+b")
|
||||||
|
|
||||||
|
for myrange in noops:
|
||||||
|
i=myrange[0]+0x80
|
||||||
|
while i<=(myrange[1]+0x80):
|
||||||
|
fh.seek(i)
|
||||||
|
fh.write((0x4e71).to_bytes(2,'big'))
|
||||||
|
i+=2
|
||||||
|
|
||||||
|
fh.close()
|
16
patch/macwars-postdecrypt-patch_.py
Executable file
16
patch/macwars-postdecrypt-patch_.py
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
noops = [
|
||||||
|
[0xa812,0xa843]
|
||||||
|
]
|
||||||
|
|
||||||
|
fh=open("_.bin","r+b")
|
||||||
|
|
||||||
|
for myrange in noops:
|
||||||
|
i=myrange[0]+0x80
|
||||||
|
while i<=(myrange[1]+0x80):
|
||||||
|
fh.seek(i)
|
||||||
|
fh.write((0x4e71).to_bytes(2,'big'))
|
||||||
|
i+=2
|
||||||
|
|
||||||
|
fh.close()
|
Loading…
Reference in New Issue
Block a user