2024-03-30 19:03:15 +00:00
import argparse
import logging
2024-04-01 10:24:00 +00:00
import subprocess
2024-03-30 19:03:15 +00:00
import time
import coloredlogs
2024-03-31 13:27:10 +00:00
from pathlib import Path
2024-03-30 19:03:15 +00:00
2024-04-01 15:46:39 +00:00
import extractor
2024-03-30 19:03:15 +00:00
from extractor . cdm import Cdm
coloredlogs . install (
fmt = ' %(asctime)s [ %(levelname).1s ] %(name)s : %(message)s ' ,
datefmt = ' % Y- % m- %d % H: % M: % S ' ,
level = logging . DEBUG )
if __name__ == ' __main__ ' :
logger = logging . getLogger ( ' KeyDive ' )
# Parse command line arguments for device ID
parser = argparse . ArgumentParser ( description = ' Extract Widevine L3 keys from an Android device. ' )
2024-05-20 03:12:24 +00:00
parser . add_argument ( ' -a ' , ' --auto ' , required = False , action = ' store_true ' , help = ' Open Bitmovin \' s demo automatically. ' )
2024-04-01 16:04:51 +00:00
parser . add_argument ( ' -d ' , ' --device ' , required = False , type = str , help = ' Target Android device ID. ' )
2024-04-06 13:24:58 +00:00
parser . add_argument ( ' -f ' , ' --functions ' , required = False , type = Path , help = ' Path to Ghidra XML functions file. ' )
parser . add_argument ( ' --force ' , required = False , action = ' store_true ' , help = ' Force using the default vendor (skipping analysis). ' )
2024-03-30 19:03:15 +00:00
args = parser . parse_args ( )
try :
2024-04-01 15:46:39 +00:00
logger . info ( ' Version: %s ' , extractor . __version__ )
2024-04-06 13:24:58 +00:00
# Ensure the ADB server is running
2024-05-19 13:41:42 +00:00
sp = subprocess . run ( [ ' adb ' , ' start-server ' ] , capture_output = True )
2024-04-19 19:52:59 +00:00
if sp . returncode != 0 :
2024-04-06 13:24:58 +00:00
raise EnvironmentError ( ' ADB is not recognized as an environment variable, see https://github.com/hyugogirubato/KeyDive/blob/main/docs/PACKAGE.md#adb-android-debug-bridge ' )
2024-03-31 13:27:10 +00:00
2024-04-06 13:24:58 +00:00
# Initialize the CDM handler with the specified or default device
cdm = Cdm ( device = args . device , functions = args . functions , force = args . force )
2024-03-30 19:03:15 +00:00
2024-04-06 13:24:58 +00:00
# Attempt to locate and identify the Widevine process on the target device
pid = cdm . enumerate_processes ( ) . get ( cdm . vendor . process )
if not pid :
raise EnvironmentError ( ' Widevine process not found on the device ' )
logger . info ( ' Process: %s ( %s ) ' , pid , cdm . vendor . process )
2024-03-30 19:03:15 +00:00
2024-04-06 13:24:58 +00:00
# Hook into the identified process for DRM key extraction
if not cdm . hook_process ( pid = pid ) :
raise Exception ( ' Failed to hook into the Widevine process ' )
2024-03-30 19:03:15 +00:00
logger . info ( ' Successfully hooked. To test, play a DRM-protected video: https://bitmovin.com/demos/drm ' )
2024-05-20 03:12:24 +00:00
if args . auto :
subprocess . run ( [ ' adb ' , ' shell ' , ' am ' , ' start ' , ' -a ' , ' android.intent.action.VIEW ' , ' -d ' , ' https://bitmovin.com/demos/drm ' ] )
2024-03-30 19:03:15 +00:00
# Keep script running while extracting keys
while cdm . running :
time . sleep ( 1 )
except KeyboardInterrupt :
pass
except Exception as e :
logger . critical ( e )
logger . info ( ' Exiting ' )