Browse Source

fit png format cover & empty meta data #14

pull/16/head
Nzix 6 years ago
parent
commit
cd9201d7f8
  1. 89
      ncmdump.py

89
ncmdump.py

@ -5,18 +5,19 @@ Created on Sun Jul 15 01:05:58 2018
@author: Nzix
"""
import binascii
import struct
import base64
import json
import os
import binascii, struct
import base64, json
import os, traceback
from Crypto.Cipher import AES
from Crypto.Util.strxor import strxor as XOR
from mutagen import mp3, flac, id3
def dump(input_path, output_path = None, skip = True):
output_path = (lambda path, meta : os.path.splitext(path)[0] + '.' + meta['format']) if not output_path else output_path
output_path = (lambda path, meta: os.path.splitext(path)[0] + '.' + meta['format']) if not output_path else output_path
output_path = (lambda path, meta: path) if not callable(output_path) else output_path
core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
unpad = lambda s : s[0:-(s[-1] if type(s[-1]) == int else ord(s[-1]))]
@ -52,13 +53,16 @@ def dump(input_path, output_path = None, skip = True):
meta_length = f.read(4)
meta_length = struct.unpack('<I', bytes(meta_length))[0]
meta_data = bytearray(f.read(meta_length))
meta_data = bytes(bytearray([byte ^ 0x63 for byte in meta_data]))
meta_data = base64.b64decode(meta_data[22:])
if meta_length:
meta_data = bytearray(f.read(meta_length))
meta_data = bytes(bytearray([byte ^ 0x63 for byte in meta_data]))
meta_data = base64.b64decode(meta_data[22:])
cryptor = AES.new(meta_key, AES.MODE_ECB)
meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
meta_data = json.loads(meta_data)
cryptor = AES.new(meta_key, AES.MODE_ECB)
meta_data = unpad(cryptor.decrypt(meta_data)).decode('utf-8')[6:]
meta_data = json.loads(meta_data)
else:
meta_data = {'format': 'flac' if os.fstat(f.fileno()).st_size > 1024 ** 2 * 16 else 'mp3'}
# crc32
crc32 = f.read(4)
@ -68,7 +72,7 @@ def dump(input_path, output_path = None, skip = True):
f.seek(5, 1)
image_size = f.read(4)
image_size = struct.unpack('<I', bytes(image_size))[0]
image_data = f.read(image_size)
image_data = f.read(image_size) if image_size else None
# media data
output_path = output_path(input_path, meta_data)
@ -78,15 +82,6 @@ def dump(input_path, output_path = None, skip = True):
f.close()
# stream cipher (modified RC4 Pseudo-random generation algorithm)
# data = bytearray(data)
# i = 0
# j = 0
# for k, _ in enumerate(data):
# i = (i + 1) % 256
# j = (i + S[i]) % 256 # in RC4, is j = (j + S[i]) % 256
# # S[i], S[j] = S[j], S[i] # no swapping
# data[k] ^= S[(S[i] + S[j]) % 256]
stream = [S[(S[i] + S[(i + S[i]) & 0xFF]) & 0xFF] for i in range(256)]
stream = bytes(bytearray(stream * (len(data) // 256 + 1))[1:1 + len(data)])
data = XOR(data, stream)
@ -96,32 +91,32 @@ def dump(input_path, output_path = None, skip = True):
m.close()
# media tag
if meta_data['format'] == 'flac':
audio = flac.FLAC(output_path)
# audio.delete()
image = flac.Picture()
image.encoding = 0
image.type = 3
image.mime = 'image/jpeg'
image.data = image_data
audio.clear_pictures()
audio.add_picture(image)
elif meta_data['format'] == 'mp3':
audio = mp3.MP3(output_path)
# audio.delete()
image = id3.APIC()
image.encoding = 0
image.type = 3
image.mime = 'image/jpeg'
image.data = image_data
audio.tags.add(image)
def embed(item, content):
item.encoding = 0
item.type = 3
item.mime = 'image/png' if content[0:4] == binascii.a2b_hex('89504E47') else 'image/jpeg'
item.data = content
if image_data:
if meta_data['format'] == 'flac':
audio = flac.FLAC(output_path)
image = flac.Picture()
embed(image, image_data)
audio.clear_pictures()
audio.add_picture(image)
elif meta_data['format'] == 'mp3':
audio = mp3.MP3(output_path)
image = id3.APIC()
embed(image, image_data)
audio.tags.add(image)
audio.save()
audio = mp3.EasyMP3(output_path)
audio['title'] = meta_data['musicName']
audio['album'] = meta_data['album']
audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
audio.save()
if meta_length:
audio = flac.FLAC(output_path) if meta_data['format'] == 'flac' else mp3.EasyMP3(output_path)
audio['title'] = meta_data['musicName']
audio['album'] = meta_data['album']
audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
audio.save()
return output_path
@ -143,5 +138,5 @@ if __name__ == '__main__':
dump(path)
print(os.path.split(path)[-1])
except Exception as e:
print(e)
print(traceback.format_exc())
pass
Loading…
Cancel
Save