1010from cryptography .hazmat .primitives .asymmetric import dsa
1111from cryptography .hazmat .primitives .asymmetric .utils import decode_dss_signature
1212from cryptography .hazmat .primitives .hashes import SHA1
13+ # Color support
14+ try :
15+ from colorama import init , Fore , Style
16+ init (autoreset = True )
17+ except ImportError :
18+ class Dummy :
19+ RESET = RED = WHITE = GREEN = LIGHTBLACK_EX = BRIGHT = ''
20+ Fore = Style = Dummy ()
1321
1422def is_admin ():
15- """Check if the script is running with administrator privileges"""
1623 try :
1724 return ctypes .windll .shell32 .IsUserAnAdmin () != 0
1825 except :
1926 return False
2027
2128def run_as_admin ():
22- """Relaunch the script with administrator privileges"""
2329 script = os .path .abspath (sys .argv [0 ])
2430 params = subprocess .list2cmdline (sys .argv [1 :])
25-
26- # Request UAC elevation
2731 ctypes .windll .shell32 .ShellExecuteW (None , "runas" , sys .executable , f'"{ script } " { params } ' , None , 1 )
2832 sys .exit (0 )
2933
@@ -32,7 +36,6 @@ def load_config(filename: str):
3236 with open (filename , 'r' ) as f :
3337 data = json .load (f )
3438
35- # Extract values from JSON
3639 file_path = data .get ("file_path" )
3740 old_signkey = data .get ("old_signkey" )
3841 new_signkey = data .get ("new_signkey" )
@@ -42,7 +45,6 @@ def load_config(filename: str):
4245 authorize_file_output = data .get ('authorize_file_output' , 'Authorize.auz' )
4346 dsa_params = data .get ('dsa_parameters' )
4447
45- # Validate essential keys
4648 if not file_path or not old_signkey or not new_signkey :
4749 raise ValueError ("JSON file must contain 'file_path', 'old_signkey', and 'new_signkey'." )
4850 if len (hwid ) == 24 :
@@ -107,7 +109,6 @@ def replace_signkey_in_file(file_path, old_signkey, new_signkey):
107109 with open (file_path , 'wb' ) as file :
108110 file .write (content )
109111
110- # Verify replacement
111112 if old_signkey_bytes in content :
112113 print ("Error: The old signkey is still present in the file." )
113114 else :
@@ -187,22 +188,20 @@ def generate_all(k: dsa.DSAPrivateKey, edition: str, version: int, hwid: str) ->
187188 for i in range (0x8000 , 0x80ff + 1 ):
188189 yield generate_single (k , i , 0x10 , hwid )
189190
190- # Mapping for the editions
191191EDITIONS = {
192192 "Lite" : 4 ,
193193 "Intro" : 3 ,
194194 "Standard" : 0 ,
195195 "Suite" : 2 ,
196196}
197197
198- # Installation detection functions
199198def get_user_config_dir ():
200199 system = platform .system ()
201200 if system == "Windows" :
202201 return os .getenv ('APPDATA' )
203202 elif system == "Darwin" :
204203 return os .path .join (os .path .expanduser ("~" ), "Library" , "Application Support" )
205- else : # Linux and others
204+ else :
206205 return os .getenv ('XDG_CONFIG_HOME' , os .path .join (os .path .expanduser ("~" ), ".config" ))
207206
208207def find_installations ():
@@ -251,113 +250,120 @@ def find_installation_data():
251250 for entry in os .listdir (base_dir ):
252251 entry_path = os .path .join (base_dir , entry )
253252 if os .path .isdir (entry_path ) and "Live" in entry :
254- # Check if Unlock directory exists or can be created
255253 data_dirs .append ((entry_path , entry ))
256254
257255 return data_dirs
258256
259257def main ():
260- # Request admin on Windows if needed
258+ # Colors
259+ RED = Fore .RED + Style .BRIGHT
260+ WHITE = Fore .WHITE + Style .BRIGHT
261+ GREY = Fore .LIGHTBLACK_EX + Style .NORMAL
262+ LIME = Fore .GREEN + Style .BRIGHT
263+ RESET = Style .RESET_ALL
264+
261265 if platform .system () == "Windows" and not is_admin ():
262- print ("\n This operation requires administrator privileges on Windows." )
263- print ("Relaunching with admin rights..." )
266+ print (RED + "\n This operation requires administrator privileges on Windows." + RESET )
267+ print (GREY + "Relaunching with admin rights..." + RESET )
264268 run_as_admin ()
265269 return
270+ # ASCII art in bright red
271+ print (RED + r"""
272+ ___. .__ __ _________ __
273+ _____ \_ |__ | | _____/ |_ ____ ____ \_ ___ \____________ ____ | | __ ___________
274+ \__ \ | __ \| | _/ __ \ __\/ _ \ / \/ \ \/_ __ \__ \ _/ ___\| |/ // __ \_ __ \
275+ / __ \| \_\ \ |_\ ___/| | ( <_> ) | \ \____| | \// __ \\ \___| <\ ___/| | \/
276+ (____ /___ /____/\___ >__| \____/|___| /\______ /|__| (____ /\___ >__|_ \\___ >__|
277+ \/ \/ \/ \/ \/ \/ \/ \/ \/
278+ """ + RESET )
279+ print (LIME + "Made by devilAPI" + RESET )
280+ print (GREY + "GitHub: " + LIME + "https://github.com/devilAPI/abletonCracker/" + RESET + "\n " )
266281
267- print ("Ableton Live Patcher - Running with administrative privileges\n " )
268-
269- # Load configuration
270282 config_file = 'config.json'
271283 try :
272284 file_path , old_signkey , new_signkey , hwid , edition , version , authorize_file_output , dsa_params = load_config (config_file )
273285 except Exception as e :
274- print (f"Error loading configuration: { e } " )
275- input ("Press Enter to exit..." )
286+ print (RED + f"Error loading configuration: { e } " + RESET )
287+ input (GREY + "Press Enter to exit..." + RESET )
276288 return
277289
278- # Auto-detect installations if needed
279290 if file_path .lower () == "auto" :
280291 installations = find_installations ()
281292 if not installations :
282- print ("\n No Ableton Live installations found. Please specify the path manually." )
283- input ("Press Enter to exit..." )
293+ print (RED + "\n No Ableton Live installations found. Please specify the path manually." + RESET )
294+ input (GREY + "Press Enter to exit..." + RESET )
284295 return
285296
286- print ("\n Found Ableton installations:" )
297+ print (LIME + "\n Found Ableton installations:" + RESET )
287298 for i , (path , name ) in enumerate (installations ):
288- print (f"{ i + 1 } . { name } at { path } " )
299+ print (WHITE + f"{ i + 1 } . " + LIME + f" { name } " + GREY + f" at { path } " + RESET )
289300
290301 try :
291- selection = int (input ("\n Select installation to patch: " )) - 1
302+ selection = int (input (LIME + "\n Select installation to patch: " + RESET )) - 1
292303 if selection < 0 or selection >= len (installations ):
293- print ("Invalid selection. Using first installation." )
304+ print (RED + "Invalid selection. Using first installation." + RESET )
294305 selection = 0
295306 file_path = installations [selection ][0 ]
296- print (f"Selected: { file_path } " )
307+ print (LIME + f"Selected: { file_path } " + RESET )
297308 except ValueError :
298- print ("Invalid input. Using first installation found." )
309+ print (RED + "Invalid input. Using first installation found." + RESET )
299310 file_path = installations [0 ][0 ]
300311
301- # Auto-detect authorization file location if needed
302312 if authorize_file_output .lower () == "auto" :
303313 data_dirs = find_installation_data ()
304314 if not data_dirs :
305- # Create default location if none found
306315 config_dir = get_user_config_dir ()
307316 default_dir = os .path .join (config_dir , "Ableton" , f"Live { version } { edition } " )
308317 unlock_dir = os .path .join (default_dir , "Unlock" )
309318 os .makedirs (unlock_dir , exist_ok = True )
310319 authorize_file_output = os .path .join (unlock_dir , "Authorize.auz" )
311- print (f"\n Using default authorization file location: { authorize_file_output } " )
320+ print (LIME + f"\n Using default authorization file location: " + WHITE + f" { authorize_file_output } " + RESET )
312321 else :
313- print ("\n Found Ableton data directories:" )
322+ print (LIME + "\n Found Ableton data directories:" + RESET )
314323 for i , (path , name ) in enumerate (data_dirs ):
315- print (f"{ i + 1 } . { name } at { path } " )
324+ print (WHITE + f"{ i + 1 } . " + LIME + f" { name } " + GREY + f" at { path } " + RESET )
316325
317326 try :
318- selection = int (input ("\n Select data directory: " )) - 1
327+ selection = int (input (LIME + "\n Select data directory: " + RESET )) - 1
319328 if selection < 0 or selection >= len (data_dirs ):
320- print ("Invalid selection. Using first directory." )
329+ print (RED + "Invalid selection. Using first directory." + RESET )
321330 selection = 0
322331 unlock_dir = os .path .join (data_dirs [selection ][0 ], "Unlock" )
323332 os .makedirs (unlock_dir , exist_ok = True )
324333 authorize_file_output = os .path .join (unlock_dir , "Authorize.auz" )
325- print (f"Selected: { authorize_file_output } " )
334+ print (LIME + f"Selected: " + WHITE + f" { authorize_file_output } " + RESET )
326335 except ValueError :
327- print ("Invalid input. Using first data directory found." )
336+ print (RED + "Invalid input. Using first data directory found." + RESET )
328337 unlock_dir = os .path .join (data_dirs [0 ][0 ], "Unlock" )
329338 os .makedirs (unlock_dir , exist_ok = True )
330339 authorize_file_output = os .path .join (unlock_dir , "Authorize.auz" )
331340
332- # Construct the key from the loaded parameters
333341 try :
334342 team_r2r_key = construct_key (dsa_params )
335343 except Exception as e :
336- print (f"Error constructing DSA key: { e } " )
337- input ("Press Enter to exit..." )
344+ print (RED + f"Error constructing DSA key: { e } " + RESET )
345+ input (GREY + "Press Enter to exit..." + RESET )
338346 return
339347
340- # Generate keys and save the authorize file
341- print ("\n Generating authorization keys..." )
348+ print (LIME + "\n Generating authorization keys..." + RESET )
342349 try :
343350 lines = list (generate_all (team_r2r_key , edition , version , hwid ))
344351 with open (authorize_file_output , "w" , newline = "\n " ) as f :
345352 f .write ("\n " .join (lines ))
346- print (f "Authorization file created: { authorize_file_output } " )
353+ print (LIME + "Authorization file created: " + WHITE + f" { authorize_file_output } " + RESET )
347354 except Exception as e :
348- print (f"Error generating authorization keys: { e } " )
349- input ("Press Enter to exit..." )
355+ print (RED + f"Error generating authorization keys: { e } " + RESET )
356+ input (GREY + "Press Enter to exit..." + RESET )
350357 return
351358
352- # Replace the signkey in the binary file
353- print ("\n Patching executable..." )
359+ print (LIME + "\n Patching executable..." + RESET )
354360 try :
355361 replace_signkey_in_file (file_path , old_signkey , new_signkey )
356- print ("\n Patch completed successfully!" )
357- input ("Press Enter to exit..." )
362+ print (LIME + "\n Patch completed successfully!" + RESET )
363+ input (GREY + "Press Enter to exit..." + RESET )
358364 except Exception as e :
359- print (f"\n Patch failed: { e } " )
360- input ("Press Enter to exit..." )
365+ print (RED + f"\n Patch failed: { e } " + RESET )
366+ input (GREY + "Press Enter to exit..." + RESET )
361367
362368if __name__ == "__main__" :
363369 main ()
0 commit comments