diff --git a/key_detector.py b/key_detector.py index 093338c..bb2bae9 100644 --- a/key_detector.py +++ b/key_detector.py @@ -4,13 +4,14 @@ import tempfile import re import pyfiglet +import argparse def print_banner(): main_banner = pyfiglet.figlet_format("Privia Security") sub_banner = pyfiglet.figlet_format("Key Detector") print(main_banner) print(sub_banner) - + def decompile_apk(apk_path, output_dir): """\033[33m[!] Decompile the APK \033[0m""" try: @@ -20,14 +21,20 @@ def decompile_apk(apk_path, output_dir): sys.exit(1) def is_variable_definition(line, keyword): - """\033[33m[!] Check if a line contains a variable definition with the given keyword.\033[0m""" - - variable_pattern = re.compile(rf"\b\w*{re.escape(keyword)}\w*\b\s*=.*", re.IGNORECASE) + """Check if a line contains a variable definition with the given keyword.""" + variable_pattern = re.compile( + rf"\b(?:[a-zA-Z_]\w*\s+)?\w*{re.escape(keyword)}\w*\b\s*=\s*.+", + re.IGNORECASE + ) return bool(variable_pattern.search(line)) def search_keywords_in_files(directory, keywords): - """\033[33m[!] Search for multiple keywords in all files within a directory and check if they are variables.\033[0m""" + """Search for multiple keywords in all files within a directory and check if they are variables.""" matches = {keyword: [] for keyword in keywords} + total_files = sum([len(files) for _, _, files in os.walk(directory)]) + files_processed = 0 + reported_lines = set() + for root, _, files in os.walk(directory): for file in files: file_path = os.path.join(root, file) @@ -35,42 +42,81 @@ def search_keywords_in_files(directory, keywords): with open(file_path, "r", encoding="utf-8", errors="ignore") as f: for line_no, line in enumerate(f, start=1): for keyword in keywords: - if is_variable_definition(line, keyword): - matches[keyword].append((file_path, line_no, line.strip())) + if (file_path, line_no) not in reported_lines: + if is_variable_definition(line, keyword): + matches[keyword].append((file_path, line_no, line.strip())) + print(f"\033[32m[+] File Found:\033[0m {file_path}, Line: {line_no}, \033[32;1m [+] Match Value: {line.strip()}\033[0m", flush=True) + reported_lines.add((file_path, line_no)) except Exception as e: - print(f"\033[31mCould not read {file_path}: {e}\033[0m") + print(f"Could not read {file_path}: {e}") + + files_processed += 1 + print(f"Searching files: {files_processed}/{total_files} files processed...", end="\r", flush=True) + return matches +def load_keywords_from_file(wordlist_path): + """Load keywords from a wordlist file.""" + try: + with open(wordlist_path, "r", encoding="utf-8") as f: + keywords = [line.strip() for line in f.readlines() if line.strip()] + return keywords + except Exception as e: + print(f"Error loading wordlist file: {e}") + sys.exit(1) + def extract_and_search_apk(apk_path, keywords): - """\033[33m [!] Extract APK contents and search for multiple keywords as variables.\033[0m""" + """Extract APK contents and search for multiple keywords as variables.""" with tempfile.TemporaryDirectory() as temp_dir: - - print("\033[33m [!] Decompiling the APK...\033[0m") + print("Decompiling the APK...") decompiled_dir = os.path.join(temp_dir, "decompiled") decompile_apk(apk_path, decompiled_dir) - print(f"\033[33m[!] Searching for keywords as variables: {', '.join(keywords)}...\033[0m") + print(f"Starting to Search for keywords") matches = search_keywords_in_files(decompiled_dir, keywords) + + matches_found = any(len(match) > 0 for match in matches.values()) + + if not matches_found: + print("\033[31m[-] No matches found.\033[0m") - for keyword, occurrences in matches.items(): - print(f"\n\033[32m[+] Results for keyword '{keyword}':\033[0m") - if occurrences: - for match in occurrences: - print(f"\033[32m[+] File Found:\033[0m {match[0]}, Line: {match[1]}, \033[32;1m [+] Match Value: {match[2]}\033[0m") - else: - print("\033[31m[-] No matches found.\033[0m") +def main(): + parser = argparse.ArgumentParser( + description="APK Key Detector - A tool to detect keywords in APK files, either by direct input or using a wordlist.", + usage="python %(prog)s apk_file \"keyword1,keyword2\" or python %(prog)s apk_file -w wordlist.txt" + ) + parser.add_argument("apk_file", help="Path to the APK file to be scanned.") + parser.add_argument( + "-w", + "--wordlist", + help="Path to a wordlist file containing keywords to search for.", + default=None, + ) + parser.add_argument( + "keywords", + nargs="?", + help="Comma-separated list of keywords to search directly (used when --wordlist is not provided).", + default=None, + ) -if __name__ == "__main__": - if len(sys.argv) != 3: - print("Usage: python apk_reverse_search.py ") + args = parser.parse_args() + + if not os.path.isfile(args.apk_file): + print(f"File not found: {args.apk_file}") sys.exit(1) - apk_file_path = sys.argv[1] - keywords = sys.argv[2].split(',') + print_banner() - if not os.path.isfile(apk_file_path): - print(f"File not found: {apk_file_path}") + if args.wordlist: + keywords = load_keywords_from_file(args.wordlist) + print(f"{len(keywords)} keywords loaded from wordlist.") + elif args.keywords: + keywords = args.keywords.split(',') + else: + print("Error: You must provide either a wordlist or keywords.") sys.exit(1) - print_banner() - extract_and_search_apk(apk_file_path, keywords) + extract_and_search_apk(args.apk_file, keywords) + +if __name__ == "__main__": + main() diff --git a/seclist-env-wordlist.txt b/seclist-env-wordlist.txt new file mode 100644 index 0000000..a917bf5 --- /dev/null +++ b/seclist-env-wordlist.txt @@ -0,0 +1,152 @@ +AWS_ACCESS_KEY_ID +AWS_SECRET_ACCESS_KEY +AMAZON_AWS_ACCESS_KEY_ID +AMAZON_AWS_SECRET_ACCESS_KEY +ALGOLIA_API_KEY +AZURE_CLIENT_ID +AZURE_CLIENT_SECRET +AZURE_USERNAME +AZURE_PASSWORD +MSI_ENDPOINT +MSI_SECRET +binance_api +binance_secret +BITTREX_API_KEY +BITTREX_API_SECRET +CF_PASSWORD +CF_USERNAME +CODECLIMATE_REPO_TOKEN +COVERALLS_REPO_TOKEN +CIRCLE_TOKEN +DIGITALOCEAN_ACCESS_TOKEN +DOCKER_EMAIL +DOCKER_PASSWORD +DOCKER_USERNAME +DOCKERHUB_PASSWORD +FACEBOOK_APP_ID +FACEBOOK_APP_SECRET +FACEBOOK_ACCESS_TOKEN +FIREBASE_TOKEN +FIREBASE_API_TOKEN +FOSSA_API_KEY +GH_TOKEN +GH_ENTERPRISE_TOKEN +CI_DEPLOY_PASSWORD +CI_DEPLOY_USER +GOOGLE_APPLICATION_CREDENTIALS +GOOGLE_API_KEY +ONE_SIGNAL_REST_API_KEY +CI_DEPLOY_USER +CI_DEPLOY_PASSWORD +GITLAB_USER_LOGIN +CI_JOB_JWT +CI_JOB_JWT_V2 +CI_JOB_TOKEN +HEROKU_API_KEY +HEROKU_API_USER +MAILGUN_API_KEY +MCLI_PRIVATE_API_KEY +MCLI_PUBLIC_API_KEY +NGROK_TOKEN +NGROK_AUTH_TOKEN +NPM_AUTH_TOKEN +OKTA_CLIENT_ORGURL +OKTA_CLIENT_TOKEN +OKTA_OAUTH2_CLIENTSECRET +OKTA_OAUTH2_CLIENTID +OKTA_AUTHN_GROUPID +OS_USERNAME +OS_PASSWORD +PERCY_TOKEN +POSTGRES_PASSWORD +SAUCE_ACCESS_KEY +SAUCE_USERNAME +SENTRY_AUTH_TOKEN +SLACK_TOKEN +square_access_token +square_oauth_secret +STRIPE_API_KEY +STRIPE_DEVICE_NAME +SURGE_TOKEN +SURGE_LOGIN +TWILIO_ACCOUNT_SID +CONSUMER_KEY +CONSUMER_SECRET +TRAVIS_SUDO +TRAVIS_OS_NAME +TRAVIS_SECURE_ENV_VARS +TELEGRAM_BOT_TOKEN +VAULT_TOKEN +VAULT_CLIENT_KEY +TOKEN +VULTR_ACCESS +VULTR_SECRET +ConsumerKey +ConsumerSecret +DB_USERNAME +HEROKU_API_KEY +HOMEBREW_GITHUB_API_TOKEN +JEKYLL_GITHUB_TOKEN +PT_TOKEN +SESSION_TOKEN +SF_USERNAME +SLACK_BOT_TOKEN +access-token +access_token +access_token_secret +accesstoken +admin +api-key +api_key +api_secret_key +api_token +auth_token +authkey +authorization +authorization_key +authorization_token +authtoken +aws_access_key_id +aws_secret_access_key +bearer +bot_access_token +bucket +client-secret +client_id +client_key +client_secret +clientsecret +consumer_key +consumer_secret +dbpasswd +email +encryption-key +encryption_key +encryptionkey +id_dsa +irc_pass +key +oauth_token +pass +password +private_key +private-key +privatekey +secret +secret-key +secret_key +secret_token +secretkey +secretkey +session_key +session_secret +slack_api_token +slack_secret_token +slack_token +ssh-key +ssh_key +sshkey +token +username +xoxa-2 +xoxr