@ -1,34 +1,68 @@
import argparse
import argparse
import os
import os
import sys
import sys
import logging
import logging
import yaml
import yaml
import subprocess
def path_to_aax ( aax : str ) :
def path_to_aax ( aax : str ) :
if not os . path . isfile ( aax ) :
if not os . path . isfile ( aax ) :
raise argparse . ArgumentTypeError ( f " Pfad { aax } ist keine g ü ltige Datei." )
raise argparse . ArgumentTypeError ( f " Pfad { aax } ist keine g ue ltige Datei." )
if not aax . endswith ( ' .aax ' ) :
if not aax . endswith ( ' .aax ' ) :
raise argparse . ArgumentTypeError ( f " Pfad { aax } ist keine g ü ltige aax-Datei." )
raise argparse . ArgumentTypeError ( f " Pfad { aax } ist keine g ue ltige aax-Datei." )
return aax
return aax
def decrypt_aax_file ( aax_path : str , profile : str ) :
logging . info ( " Ich decryyypte... " )
try :
#Probe auf die aax Datei fuer Checksum
cmd_probe = f " ffprobe { aax_path } 2>&1 | grep checksum "
result_probe = subprocess . run ( cmd_probe , shell = True , check = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE , text = True )
tmp_checksum = result_probe . stdout
checksum = tmp_checksum . split ( ' == ' ) [ 1 ]
checksum = checksum . split ( ' \n ' ) [ 0 ] # Ein Line-Break wird am Ende immer noch angehängt -> Muss weg sonst gibts beim nächsten CMD Probleme
logging . debug ( f " Checksum: { checksum } " )
#Decrypt der Checksum via Rainbowtables für UserId
cmd_crack = f " ./rcrack . -h { checksum } | grep hex "
cwd_tables = os . path . join ( os . getcwd ( ) , ' tables ' )
result_crack = subprocess . run ( cmd_crack , shell = True , check = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE , text = True , cwd = cwd_tables )
tmp_profile_id = result_crack . stdout
profile_id = tmp_profile_id . split ( ' hex: ' ) [ 1 ]
profile_id = profile_id . split ( ' \n ' ) [ 0 ] # Ein Line-Break wird am Ende immer noch angehängt -> Muss weg
logging . info ( f " Profile-Id extrahiert: { profile_id } " )
#Erstellen von Profil
with open ( ' profiles.yml ' , ' w ' ) as profile_yaml :
yaml . dump ( { profile : profile_id } , profile_yaml , default_flow_style = False )
except subprocess . CalledProcessError as err :
logging . info ( f " Fehler bei Prozess ausfuehrung. { err } " )
#HowTo-WiemanshinkriegtAbsurdewirklichwissenschaftlicheEmpfehlungenfralleLebenslagen_ep7.aax 2>&1 | grep checksum
def convert_to_m4b ( aax_path : str , profile : str ) :
logging . info ( " Ich converteeee... " )
if __name__ == " __main__ " :
if __name__ == " __main__ " :
argparser = argparse . ArgumentParser ( description = " Dieses Script konvertiert verschlüsselte Audible Bücher zu unverschlüsselte m4b-Audiobooks. " )
argparser = argparse . ArgumentParser ( description = " Dieses Script konvertiert verschl uesselte Audible Buecher zu unverschlue sselte m4b-Audiobooks." )
cmd_parser = argparser . add_subparsers ( dest = ' cmd ' , title = ' Commands ' , description = " Erlaubte Commands " , required = True )
cmd_parser = argparser . add_subparsers ( dest = ' cmd ' , title = ' Commands ' , description = " Erlaubte Commands " , required = True )
decrypt_parser = cmd_parser . add_parser ( ' decrypt ' , help = " Extrahiert die User-spezifische ID zur Profil-Bildung von einer bestehenden aax-Datei. " )
decrypt_parser = cmd_parser . add_parser ( ' decrypt ' , help = " Extrahiert die User-spezifische ID zur Profil-Bildung von einer bestehenden aax-Datei. " )
decrypt_parser . add_argument ( ' aax ' , type = path_to_aax , help = ' Path zu einem zu entschlüsselnden aax file des neuen Profils ' )
decrypt_parser . add_argument ( ' aax ' , type = path_to_aax , help = ' Path zu einem zu entschl ue sselnden aax file des neuen Profils' )
decrypt_parser . add_argument ( ' profile ' , type = str , help = ' Profil-Name, zu welchem die extrahierte ID gespeichert wird. (ID ist notwendig für Entschlüsselung der eigenen Hörbücher) ' )
decrypt_parser . add_argument ( ' profile ' , type = str , help = ' Profil-Name, zu welchem die extrahierte ID gespeichert wird. (ID ist notwendig f uer Entschluesselung der eigenen Hoerbue cher)' )
convert_parser = cmd_parser . add_parser ( ' convert ' , help = " Konvertiert ein aax-Audiobook in ein m4b-Audiobook. " )
convert_parser = cmd_parser . add_parser ( ' convert ' , help = " Konvertiert ein aax-Audiobook in ein m4b-Audiobook. " )
convert_parser . add_argument ( ' aax ' , type = path_to_aax , help = ' Path zu einem zu entschlüsselnden aax file ' )
convert_parser . add_argument ( ' aax ' , type = path_to_aax , help = ' Path zu einem zu entschl ue sselnden aax file' )
convert_parser . add_argument ( ' profile ' , type = str , help = " Zugehöriges Profile für entschlüsselung " )
convert_parser . add_argument ( ' profile ' , type = str , help = " Zugeh oeriges Profile fuer entschlue sselung" )
args : argparse . Namespace = argparser . parse_args ( args = None if sys . argv [ 1 : ] else [ ' --help ' ] )
args : argparse . Namespace = argparser . parse_args ( args = None if sys . argv [ 1 : ] else [ ' --help ' ] )
logging . basicConfig ( level = logging . INFO , format = " %(asctime)s | %(levelname)s | %(message)s " , datefnt = " %d - % m- % Y % H: % M: % S " )
logging . basicConfig ( level = logging . INFO , format = " %(asctime)s | %(levelname)s | %(message)s " , datef m t= " %d - % m- % Y % H: % M: % S " )
profiles = None
profiles = None
try :
try :
@ -39,10 +73,27 @@ if __name__ == "__main__":
profiles = yaml . safe_load ( ' ' )
profiles = yaml . safe_load ( ' ' )
if args . cmd == " decrypt " :
if args . cmd == " decrypt " :
pass
logging . info ( f " Decrypt wird gestartet... " )
aax_file = args . aax
profile = args . profile
if profiles is not None and profiles . get ( args . profile ) is not None :
logging . info ( f " Profil { args . profile } existiert bereits. Konvertierung kann starten. " )
sys . exit ( )
decrypt_aax_file ( aax_file , profile )
elif args . cmd == " convert " :
elif args . cmd == " convert " :
if profiles . get ( args . profile ) is None :
if profiles is None or profiles . get ( args . profiles ) is None or args . profiles not in profiles :
logging . info ( f " Profil { args . profile } existiert nicht. Bitte über decrypt anlegen lassen. " )
logging . info ( f " Profil { args . profile } existiert nicht. Bitte ueber decrypt anlegen lassen. " )
sys . exit ( )
logging . info ( f " Convert wird gestartet... " )
aax_file = args . aax
profile = args . profile
convert_to_m4b ( aax_file , profile )