From 9b8d504a133fa0b2db38de403d0a3c34bcf3c009 Mon Sep 17 00:00:00 2001 From: Don Barber Date: Tue, 11 May 2021 20:19:10 -0400 Subject: [PATCH] Initial Commit --- README.md | 20 ++- decrypt/StarTrekKobayashi-decrypt.py | 140 ++++++++++++++++ decrypt/SwordOfKadash-decrypt.py | 140 ++++++++++++++++ decrypt/macwars-D-decrypt.py | 199 +++++++++++++++++++++++ decrypt/macwars-_-decrypt.py | 180 ++++++++++++++++++++ decrypt/seven_cities_decrypt.py | 187 +++++++++++++++++++++ decrypt/shanghaiv1-decrypt.py | 143 ++++++++++++++++ patch/SwordOfKadash-postdecrypt-patch.py | 19 +++ patch/macwars-patchT.py | 16 ++ patch/macwars-postdecrypt-patchD.py | 16 ++ patch/macwars-postdecrypt-patch_.py | 16 ++ 11 files changed, 1075 insertions(+), 1 deletion(-) create mode 100755 decrypt/StarTrekKobayashi-decrypt.py create mode 100755 decrypt/SwordOfKadash-decrypt.py create mode 100755 decrypt/macwars-D-decrypt.py create mode 100755 decrypt/macwars-_-decrypt.py create mode 100755 decrypt/seven_cities_decrypt.py create mode 100755 decrypt/shanghaiv1-decrypt.py create mode 100755 patch/SwordOfKadash-postdecrypt-patch.py create mode 100755 patch/macwars-patchT.py create mode 100755 patch/macwars-postdecrypt-patchD.py create mode 100755 patch/macwars-postdecrypt-patch_.py diff --git a/README.md b/README.md index 6e90619..e5562bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,22 @@ # depace 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. + + diff --git a/decrypt/StarTrekKobayashi-decrypt.py b/decrypt/StarTrekKobayashi-decrypt.py new file mode 100755 index 0000000..5ec6362 --- /dev/null +++ b/decrypt/StarTrekKobayashi-decrypt.py @@ -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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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