Quantcast
Channel: PS3Hax Network - Playstation 3 and Playstation 4 Hacks and Mods
Viewing all articles
Browse latest Browse all 19236

venturing into the world of python

$
0
0
links:
http://repo.or.cz/w/python-cryptoplus.git
http://pastie.org/private/ykyyrbim7rkotvcnw8m8w
http://ps3devwiki.com/wiki/Talk:Keys...3.60_-_3.61.29
https://pypi.python.org/pypi/pycrypto/2.0.1

doubts:
1st doubt: solved. use 4th link. CryptoPlus works with that version of pycrypto ;)

doubts inpending :)

the unicorns:

alright. let me introduce myself, for those who don't know me from hax :) i'm zecoxao and i'm learning python with these codes :)

i encountered a few problems along the way but i hope we can get along and solve them. the community looks a lot more open and cared than it was a year ago. and i like that :).

i'll start posting doubts and hints right now. all the help is welcome.

Thank you guys (and girls ;) )

the code:

Click here to see full text

Code:

# -*- coding: utf-8 -*-

import sys, os, math, datetime
import struct, hashlib, hmac, ecdsa

from CryptoPlus.Cipher import AES

#------------------------------------------------------------------------------

def aes_encrypt_ecb(key, data):
        crypto = AES.new(key, AES.MODE_ECB)
        return crypto.encrypt(data)

def aes_decrypt_ecb(key, data):
        crypto = AES.new(key, AES.MODE_ECB)
        return crypto.decrypt(data)

def aes_encrypt_cbc(key, iv, data):
        crypto = AES.new(key, AES.MODE_CBC, iv)
        return crypto.encrypt(data)

def aes_decrypt_cbc(key, iv, data):
        crypto = AES.new(key, AES.MODE_CBC, iv)
        return crypto.decrypt(data)

def aes_cmac(key, data):
        crypto = AES.new(key, AES.MODE_CMAC)
        return crypto.encrypt(data)

def calculate_sha1(data):
        return hashlib.sha1(data).digest()

def sha1_hmac(key, data):
        return hmac.new(key=key, msg=data, digestmod=hashlib.sha1).digest()

def load_file_contents(file_path):
        with open(file_path, 'rb') as in_file:
                data = in_file.read()
        return data

def store_file_contents(file_path, data):
        with open(file_path, 'wb') as out_file:
                out_file.write(data)

def xor_data(data1, data2, size):
        return ''.join(chr(ord(data1[i]) ^ ord(data2[i])) for i in xrange(size))

def s2i(s):
        result = 0L
        for c in s:
                result = 256 * result + ord(c)
        return result

def round_up(x, n):
        return (x + (n - 1)) & ~(n - 1);

def get_ecdsa_curve_parameters(type, index):
        if type == 'vsh':
                curves = []
                curve_fmt = '>20s20s20s20s20s20s'
                with open('vsh.curves', 'rb') as in_file:
                        file_data = in_file.read()
                        file_size = len(file_data)
                        num_curves = int(file_size / struct.calcsize(curve_fmt))
                        for i in xrange(num_curves):
                                data = file_data[i * struct.calcsize(curve_fmt):(i + 1) * struct.calcsize(curve_fmt)]
                                inv_data = ''.join([chr((~ord(x)) & 0xff) for x in data])
                                p, a, b, n, gx, gy = struct.unpack(curve_fmt, inv_data)
                                curves.append({ 'p': s2i(p), 'a': s2i(a), 'b': s2i(b), 'n': s2i(n), 'gx': s2i(gx), 'gy': s2i(gy) })
                params = curves[index]
                return params['p'], params['a'], params['b'], params['n'], params['gx'], params['gy']
        else:
                return None

def dump(data, data_size, block_size=16):
        if data_size == 0:
                data_size = len(data)
        num_blocks = int(math.floor(data_size / block_size))
        for i in num_blocks:
                print '\t', data[i * block_size:(i + 1) * block_size].encode('hex')

if len(sys.argv) < 3:
        print 'usage: ps2.py <ISO.BIN.ENC or CONFIG or SCEVMC*.VME> <klicensee file>'
        sys.exit()

CMAC_KEY_SIZE = 0x10
KLICENSEE_KEY_SIZE = 0x10
KLICENSEE_PART_OFFSET = 0x04

HEADER_OFFSET, HEADER_SIZE = 0x00, 0x60
EXTENDED_HEADER_OFFSET, EXTENDED_HEADER_SIZE = 0x00, 0xA0
SIGNATURE_DATA_OFFSET, SIGNATURE_DATA_SIZE = 0x00, 0xD8
META_DATA_SECTION_HASH_SIZE, META_DATA_SECTION_DATA_SIZE, META_DATA_SECTION_EXTENDED_HASH_SIZE = 0x10, 0x10, 0x14
PS2_DEFAULT_SEGMENT_SIZE, PS2_META_ENTRY_SIZE, PS2_VMC_HEADER_SIZE = 0x4000, 0x20, 0x20

NPDRM_OMAC_KEY1 = '????????????????????????????????'.decode('hex') # FIXME: SHA-1: 1DD100602ABC688AC7520EE8168B8B23B0563CF8
NPDRM_OMAC_KEY2 = '????????????????????????????????'.decode('hex') # FIXME: SHA-1: 07DAD1183CEC7ED834AFE8C7590E225484618D7F
NPDRM_OMAC_KEY3 = '????????????????????????????????'.decode('hex') # FIXME: SHA-1: 838633A7E03256F6CCE4E53D0842816013F8AECA

FALLBACK_HEADER_HASH = '00000000000000000000000000000001'.decode('hex')

ATA_KEY_SEED = '????????????????????????????????????????????????????????????????'.decode('hex') # FIXME: SHA-1: 362AA6F834600464B76ECC4E8CBFBEF99A76C1AF

PS2_KEYS = {
        'cex': {
                'meta': '????????????????????????????????'.decode('hex'), # FIXME: SHA-1: B9CACFF9E126F63634DC38AF61040BDF6F370A26
                'data': '????????????????????????????????'.decode('hex'), # FIXME: SHA-1: CB0BAECAAADF9E5C629522B11757F78C7CD5B23C
                'vmc': '????????????????????????????????'.decode('hex')  # FIXME: SHA-1: EB03D83F96E3394A05BCE68F8645DA134CDA5545
        },
        'dex': {
                'meta': '????????????????????????????????'.decode('hex'), # FIXME: SHA-1: 4FCFB6683AC46E73FFFCE49895E3F303A117BE8C
                'data': '????????????????????????????????'.decode('hex'), # FIXME: SHA-1: AEC7A9C13A4023FE268A163FFDC8382F45496928
                'vmc': '????????????????????????????????'.decode('hex')  # FIXME: SHA-1: B41AEE9D3B6C54292469C9C754AE8FE75ACBE958
        }
}
PS2_IV = '00000000000000000000000000000000'.decode('hex')

ECDSA_CURVE_TYPE = 'vsh'
ECDSA_CURVE_INDEX = 2
ECDSA_PUBLIC_KEY = '????????????????????????????????????????????????????????????????????????????????'.decode('hex') # FIXME: SHA-1: 7B365A6A821FC03B1A9A764E5E695DB3599FF7BC

BASE_TICKS = 62135596800000000 # 01/01/1970

#------------------------------------------------------------------------------

input_file_path = sys.argv[1]

klicensee_file_path = sys.argv[2]
klicensee_key = load_file_contents(klicensee_file_path)
if len(klicensee_key) != KLICENSEE_KEY_SIZE:
        print 'Incorrect klicensee key size'
        sys.exit()

console_type = 'cex'

ecdsa_signature_fmt = '>20s20s'
ecdsa_curve_p, ecdsa_curve_a, ecdsa_curve_b, ecdsa_curve_n, ecdsa_curve_gx, ecdsa_curve_gy = get_ecdsa_curve_parameters(ECDSA_CURVE_TYPE, ECDSA_CURVE_INDEX)
ecdsa_curve = ecdsa.ellipticcurve.CurveFp(ecdsa_curve_p, ecdsa_curve_a, ecdsa_curve_b)
ecdsa_generator = ecdsa.ellipticcurve.Point(ecdsa_curve, ecdsa_curve_gx, ecdsa_curve_gy, ecdsa_curve_n)
ecdsa_public_qx, ecdsa_public_qy = struct.unpack(ecdsa_signature_fmt, ECDSA_PUBLIC_KEY)
ecdsa_public_qx, ecdsa_public_qy = s2i(ecdsa_public_qx), s2i(ecdsa_public_qy)
ecdsa_public_point = ecdsa.ellipticcurve.Point(ecdsa_curve, ecdsa_public_qx, ecdsa_public_qy)
ecdsa_public_key = ecdsa.ecdsa.Public_key(ecdsa_generator, ecdsa_public_point)

#------------------------------------------------------------------------------

NPD_MAGIC = 'NPD\x00'
PS2_MAGIC = 'PS2\x00'
PS2_VMC_MAGIC = 'Sony PS2 Memory Card Format'

FILE_FLAGS_DEBUG = 0x80000000

magic_fmt = '>4s'
header_fmt = '>4sHHII48s16s16s16sQQIIQ16s16s40s20s20s'
meta_data_section_fmt = '>16s'
meta_data_section_extended_fmt = '>16sQIII'

input_file_dir, input_file_name = os.path.split(input_file_path)
input_file_extension = os.path.splitext(input_file_path)[1]

if input_file_extension.upper() != '.VME':
        with open(input_file_path, 'rb') as npd_file:
                magic, = struct.unpack(magic_fmt, npd_file.read(struct.calcsize(magic_fmt)))
                if magic != NPD_MAGIC and magic != PS2_MAGIC:
                        print 'Not a NPD/PS2 file'
                        sys.exit()

                npd_file.seek(HEADER_OFFSET)
                header = npd_file.read(HEADER_SIZE)

                npd_file.seek(EXTENDED_HEADER_OFFSET)
                extended_header = npd_file.read(EXTENDED_HEADER_SIZE)

                npd_file.seek(SIGNATURE_DATA_OFFSET)
                signature_data = npd_file.read(SIGNATURE_DATA_SIZE)

                npd_file.seek(0)
                magic, version_major, version_minor, license_type, type, content_id, qa_digest, cid_fn_hash, header_hash, time_period_start, time_period_end, file_flags, segment_size, data_size, meta_data_sections_hash, extended_header_hash, unknown_data, signature_r, signature_s = struct.unpack(header_fmt, npd_file.read(struct.calcsize(header_fmt)))
                version = (version_major << 16) | version_minor
                is_ps2_format = magic == PS2_MAGIC

                # Validate hashes
                if (file_flags & FILE_FLAGS_DEBUG) == 0:
                        computed_cid_fn_hash = aes_cmac(NPDRM_OMAC_KEY3, content_id + input_file_name)
                        computed_header_hash = aes_cmac(xor_data(NPDRM_OMAC_KEY1, NPDRM_OMAC_KEY2, CMAC_KEY_SIZE), header)
                else:
                        if type == 1:
                                computed_header_hash = map(ord, FALLBACK_HEADER_HASH)
                        else:
                                computed_header_hash = map(ord, klicensee_key)
                        for i in xrange(struct.calcsize(header_hash_fmt)):
                                computed_header_hash[i] = computed_header_hash[i] ^ ord(qa_digest[i]) ^ 0x55
                        computed_header_hash = ''.join(map(chr, computed_header_hash))
                        computed_cid_fn_hash = ''.join(chr(ord(x) ^ 0xFF) for x in qa_digest)

                if (file_flags & FILE_FLAGS_DEBUG) == 0:
                        if cid_fn_hash != computed_cid_fn_hash:
                                print 'CID FN hash is not correct'
                                sys.exit()

                        if header_hash != computed_header_hash:
                                print 'Header hash is not correct'
                                sys.exit()

                content_id = content_id.rstrip('\x00')
                if time_period_start != 0:
                        time_period_start = datetime.datetime(1, 1, 1) + datetime.timedelta(microseconds=BASE_TICKS + time_period_start * 1000)
                if time_period_end != 0:
                        time_period_end = datetime.datetime(1, 1, 1) + datetime.timedelta(microseconds=BASE_TICKS + time_period_end * 1000)

                if not is_ps2_format:
                        # TODO
                        meta_data_size = 0
                else:
                        meta_data_size = segment_size
                num_segments = int(math.ceil((data_size + segment_size - 1) / segment_size))
                last_segment_size = round_up(data_size - segment_size * (num_segments - 1), 16)

                # Validate ECDSA signature
                if (file_flags & FILE_FLAGS_DEBUG) == 0:
                        signature_hash = calculate_sha1(signature_data)
                        if not ecdsa_public_key.verifies(s2i(signature_hash), ecdsa.ecdsa.Signature(s2i(signature_r), s2i(signature_s))):
                                print 'ECDSA signature is not correct'
                                sys.exit()

                if magic == NPD_MAGIC:
                        print '      Usage: NPD'
                elif magic == PS2_MAGIC:
                        print '      Usage: PS2'
                print '    Version: {0:02}.{1:02}'.format(version_major, version_minor)
                if license_type == 1:
                        print 'License type: Network'
                elif license_type == 2:
                        print 'License type: Local'
                elif license_type == 3:
                        print 'License type: Free'
                print '        Type: {0}'.format(type)
                print '  Content ID: {0}'.format(content_id)
                print '  QA digest: 0x{0}'.format(qa_digest.encode('hex').upper())
                print '  File flags: 0x{0:08X}'.format(file_flags)
                print 'Segment size: {0}'.format(segment_size)
                print '  Data size: {0}'.format(data_size)
                print 'Num segments: {0} (last segment size: {1})'.format(num_segments, last_segment_size)
                if time_period_start != 0:
                        print '  Time start: {0}'.format(str(time_period_start))
                if time_period_end != 0:
                        print '    Time end: {0}'.format(str(time_period_end))

                if not is_ps2_format:
                        # TODO
                        pass
                else:
                        ps2_meta_key = aes_encrypt_cbc(PS2_KEYS[console_type]['meta'], PS2_IV, klicensee_key)
                        ps2_data_key = aes_encrypt_cbc(PS2_KEYS[console_type]['data'], PS2_IV, klicensee_key)

                        output_meta_file_path = os.path.join(input_file_dir, input_file_name + '.meta')
                        output_data_file_path = os.path.join(input_file_dir, input_file_name + '.data')

                        npd_file.seek(segment_size)

                        with open(output_meta_file_path, 'wb') as meta_file:
                                with open(output_data_file_path, 'wb') as data_file:
                                        while True:
                                                meta_data = npd_file.read(meta_data_size)
                                                if not meta_data:
                                                        break
                                                meta_data = aes_decrypt_cbc(ps2_meta_key, PS2_IV, meta_data)
                                                meta_file.write(meta_data)

                                                num_child_segments = int(meta_data_size / PS2_META_ENTRY_SIZE)
                                                for i in xrange(num_child_segments):
                                                        file_data = npd_file.read(segment_size)
                                                        if not file_data:
                                                                break
                                                        file_data = aes_decrypt_cbc(ps2_data_key, PS2_IV, file_data)
                                                        data_file.write(file_data)
                                        data_file.truncate(data_size)
else:
        with open(input_file_path, 'rb') as npd_file:
                segment_size = PS2_DEFAULT_SEGMENT_SIZE

                offset = npd_file.tell()
                file_data = npd_file.read(PS2_VMC_HEADER_SIZE)
                if not file_data:
                        print 'Unable to read file'
                        sys.exit()

                magic = aes_decrypt_cbc(PS2_KEYS[console_type]['vmc'], PS2_IV, file_data)
                if magic[:len(PS2_VMC_MAGIC)] != PS2_VMC_MAGIC:
                        print 'Invalid virtual memory card file'
                        sys.exit()
                npd_file.seek(offset)

                output_file_path = os.path.join(input_file_dir, input_file_name + '.vmc')
                with open(output_file_path, 'wb') as out_file:
                        while True:
                                file_data = npd_file.read(segment_size)
                                if not file_data:
                                        break
                                file_data = aes_decrypt_cbc(PS2_KEYS[console_type]['vmc'], PS2_IV, file_data)
                                out_file.write(file_data)



^ flat_z's magic unicorns

Click here to see full text

Code:

from CryptoPlus.Cipher import AES
import hashlib, hmac

def sha1_hmac(key, data):
        return hmac.new(key=key, msg=data, digestmod=hashlib.sha1).digest()

def aes_decrypt_cbc(key, iv, data):
        crypto = AES.new(key, AES.MODE_CBC, iv)
return crypto.decrypt(data)

def unscramble(key, iv, data):
        key = sha1_hmac(root_scramble_key, key)
return aes_decrypt_cbc(key[:16], iv, data)

def unscramble_1(key):
        return unscramble(sk1_key, sk1_iv, key)

def unscramble_2(key):
        return unscramble(sk2_key, sk2_iv, key)

root_scramble_key = '844F80F3C57C455C7F09'.decode('hex')

sk1_key = 'F92C8666EFFBAC7EB583E54A257F7C05'.decode('hex')
sk1_iv = 'F2E70BC4BAC10C3D8DDBB7DC23053F9A'.decode('hex')

sk2_key = 'DDF6A5B143C1141FEED01CDA719705C3'.decode('hex')
sk2_iv = '018E695C3A29AF6E746A73CBF73DBDFD'.decode('hex')

erk_obf = '18097966C3DE8A0D82BF956CB39FAF782295C6CA7F1E547AB30EDFD7EE5CB812'.decode('hex')
riv_obf = '9B32B20FA77280F1095EA13F1C2D5C99'.decode('hex')

erk_dec = unscramble_1(erk_obf)
riv_dec = unscramble_2(riv_obf)

print 'erk_dec:', erk_dec.encode('hex')
print 'riv_dec:', riv_dec.encode('hex')



Click here to see full text

Code:

from CryptoPlus.Cipher import AES
import hashlib, hmac
 
def sha1_hmac(key, data):
        return hmac.new(key=key, msg=data, digestmod=hashlib.sha1).digest()

def aes_encrypt_cbc(key, iv, data):
        crypto = AES.new(key, AES.MODE_CBC, iv)
return crypto.encrypt(data)

def scramble(key, iv, data):
        key = sha1_hmac(root_scramble_key, key)
return aes_encrypt_cbc(key[:16], iv, data)

def scramble_1(key):
        return scramble(sk1_key, sk1_iv, key)

def scramble_2(key):
        return scramble(sk2_key, sk2_iv, key)

root_scramble_key = '844F80F3C57C455C7F09'.decode('hex')

sk1_key = 'F92C8666EFFBAC7EB583E54A257F7C05'.decode('hex')
sk1_iv = 'F2E70BC4BAC10C3D8DDBB7DC23053F9A'.decode('hex')

sk2_key = 'DDF6A5B143C1141FEED01CDA719705C3'.decode('hex')
sk2_iv = '018E695C3A29AF6E746A73CBF73DBDFD'.decode('hex')

erk_dec = '5FF17D836E2C4AD69476E2614F64BDD05B9115389A9A6D055B5B544B1C34E3D5'.decode('hex')
riv_dec = 'DF0F50EC3C4743C5B17839D7B49F24A4'.decode('hex')

erk_obf = scramble_1(erk_dec)
riv_obf = scramble_2(riv_dec)

print 'erk_obf:', erk_obf.encode('hex')
print 'riv_obf:', riv_obf.encode('hex')


^ globaltroll's magic unicorns (unscrambler and scrambler respectively) :)

Viewing all articles
Browse latest Browse all 19236

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>