initial commit
This commit is contained in:
BIN
Binary file not shown.
Binary file not shown.
+75
@@ -0,0 +1,75 @@
|
|||||||
|
______
|
||||||
|
(_____ \
|
||||||
|
_____) )_____ ____ ____ ___ ___
|
||||||
|
| __ /| ___ | \ / ___) _ \ /___)
|
||||||
|
| | \ \| ____| | | ( (__| |_| |___ |
|
||||||
|
|_| |_|_____)_|_|_|\____)___/(___/
|
||||||
|
|
||||||
|
© BreakingSecurity.net
|
||||||
|
|
||||||
|
|
||||||
|
************************
|
||||||
|
* Zip Password *
|
||||||
|
************************
|
||||||
|
|
||||||
|
Zip Password is: BreakingSecurity.net
|
||||||
|
|
||||||
|
************************
|
||||||
|
* License Activation *
|
||||||
|
************************
|
||||||
|
|
||||||
|
To activate your Remcos Professional Edition license
|
||||||
|
(not needed for Remcos Free Edition):
|
||||||
|
|
||||||
|
1) Open KeyGen.exe
|
||||||
|
2) Insert your BreakingSecurity.net registration email and password
|
||||||
|
3) Click "Generate Key"
|
||||||
|
4) Click "Activate Key"
|
||||||
|
5) License is activated automatically and immediately.
|
||||||
|
You should receive a confirmation email within a minute.
|
||||||
|
|
||||||
|
************************
|
||||||
|
* Quick Setup *
|
||||||
|
************************
|
||||||
|
|
||||||
|
This brief guide will help you out in establishing a successful connection using Remcos.
|
||||||
|
|
||||||
|
For more in-depth instructions, consult:
|
||||||
|
|
||||||
|
Instruction Manual:
|
||||||
|
https://BreakingSecurity.net/remcos/manual
|
||||||
|
|
||||||
|
VideoTutorials:
|
||||||
|
https://BreakingSecurity.net/tutorials
|
||||||
|
|
||||||
|
Support:
|
||||||
|
https://BreakingSecurity.net/support
|
||||||
|
|
||||||
|
|
||||||
|
1) INSTALL REMCOS
|
||||||
|
Remcos is portable and does not require an installation.
|
||||||
|
Just extract Remcos.exe file in any folder and execute it.
|
||||||
|
Zip Password is: BreakingSecurity.net
|
||||||
|
If later on you download a new Remcos update and want to keep all your settings,
|
||||||
|
just place the new Remcos.exe in the same folder.
|
||||||
|
|
||||||
|
2) OPEN LISTENING PORT
|
||||||
|
The first step to do is open a TCP port for Remcos Controller.
|
||||||
|
This port will be used to listen for incoming connections.
|
||||||
|
Go to Local Settings -> Connection
|
||||||
|
to add a listening port.
|
||||||
|
Make sure your firewall allows Remcos connection.
|
||||||
|
|
||||||
|
3) SETUP AGENT CONNECTION
|
||||||
|
Go to Agent Builder -> Connection
|
||||||
|
to specify where your Remcos Agent should connect.
|
||||||
|
You should enter the IP or DNS address and listening port of your Remcos Controller here.
|
||||||
|
|
||||||
|
4) BUILD AGENT
|
||||||
|
Go to Agent Builder -> Build
|
||||||
|
to build a Remcos Agent.
|
||||||
|
Deploy the agent to the remote system and execute it.
|
||||||
|
|
||||||
|
5) ESTABLISH CONNECTION
|
||||||
|
If the above steps were correctly done,
|
||||||
|
your new Remcos connection will popup in the Connections tab.
|
||||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
|||||||
|
Run server_only.py as admin first
|
||||||
|
when thats running then run launch_remcos.py as admin
|
||||||
|
aswell then bara bing bara boom it's cracked
|
||||||
|
|
||||||
|
when launching launch_remcos.py it will give you a bunch
|
||||||
|
of errors just hit on ok until you see the main gui ok.
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
"""
|
||||||
|
Launch Remcos with SSL_CERT_FILE + apply IAT patches.
|
||||||
|
Run WHILE server_only.py is running in another terminal.
|
||||||
|
"""
|
||||||
|
import ctypes, ctypes.wintypes as wt, struct, subprocess, os, sys, time
|
||||||
|
|
||||||
|
PROCESS_ALL_ACCESS = 0x1F0FFF
|
||||||
|
PAGE_EXECUTE_READWRITE = 0x40
|
||||||
|
MEM_COMMIT, MEM_RESERVE = 0x1000, 0x2000
|
||||||
|
UNPACK_ADDR, UNPACK_SIG = 0x8EEED8, b'\x55\x8b\xec\x6a'
|
||||||
|
|
||||||
|
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
|
||||||
|
OpenProcess = kernel32.OpenProcess; OpenProcess.restype = wt.HANDLE
|
||||||
|
ReadProcessMemory = kernel32.ReadProcessMemory; ReadProcessMemory.restype = wt.BOOL
|
||||||
|
WriteProcessMemory = kernel32.WriteProcessMemory; WriteProcessMemory.restype = wt.BOOL
|
||||||
|
VirtualAllocEx = kernel32.VirtualAllocEx; VirtualAllocEx.restype = wt.LPVOID
|
||||||
|
VirtualProtectEx = kernel32.VirtualProtectEx; VirtualProtectEx.restype = wt.BOOL
|
||||||
|
CloseHandle = kernel32.CloseHandle
|
||||||
|
|
||||||
|
def read_mem(h, addr, sz):
|
||||||
|
buf = ctypes.create_string_buffer(sz); n = ctypes.c_size_t(0)
|
||||||
|
return buf.raw[:n.value] if ReadProcessMemory(h, addr, buf, sz, ctypes.byref(n)) else None
|
||||||
|
|
||||||
|
def write_mem(h, addr, data):
|
||||||
|
old = wt.DWORD(0)
|
||||||
|
VirtualProtectEx(h, addr, len(data), PAGE_EXECUTE_READWRITE, ctypes.byref(old))
|
||||||
|
n = ctypes.c_size_t(0); buf = ctypes.create_string_buffer(data)
|
||||||
|
ok = WriteProcessMemory(h, addr, buf, len(data), ctypes.byref(n))
|
||||||
|
VirtualProtectEx(h, addr, len(data), old.value, ctypes.byref(old))
|
||||||
|
return ok and n.value == len(data)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
d = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
exe = os.path.join(d, "Remcos v7.2.2 Pro.exe")
|
||||||
|
|
||||||
|
# Set SSL env
|
||||||
|
ca = os.path.join(d, "certs", "ca_bundle.pem")
|
||||||
|
if os.path.exists(ca):
|
||||||
|
os.environ["SSL_CERT_FILE"] = ca
|
||||||
|
os.environ["SSL_CERT_DIR"] = os.path.join(d, "certs")
|
||||||
|
print(f"[+] SSL_CERT_FILE={ca}")
|
||||||
|
|
||||||
|
# Kill old
|
||||||
|
subprocess.run(['taskkill', '/F', '/IM', 'Remcos v7.2.2 Pro.exe'], capture_output=True)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Launch
|
||||||
|
proc = subprocess.Popen([exe], cwd=d)
|
||||||
|
pid = proc.pid; print(f"[+] PID {pid}")
|
||||||
|
|
||||||
|
h = None
|
||||||
|
for _ in range(30):
|
||||||
|
h = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
|
||||||
|
if h: break
|
||||||
|
time.sleep(0.1)
|
||||||
|
if not h: print("[-] Can't open"); return
|
||||||
|
|
||||||
|
# Wait unpack
|
||||||
|
print("[*] Waiting for unpack...")
|
||||||
|
t0 = time.time()
|
||||||
|
while time.time() - t0 < 45:
|
||||||
|
if proc.poll() is not None: print("[-] Exited early"); CloseHandle(h); return
|
||||||
|
if read_mem(h, UNPACK_ADDR, 4) == UNPACK_SIG: break
|
||||||
|
time.sleep(0.05)
|
||||||
|
else: print("[-] Timeout"); CloseHandle(h); return
|
||||||
|
print(f"[+] Unpacked {time.time()-t0:.1f}s"); time.sleep(0.2)
|
||||||
|
|
||||||
|
# Stubs
|
||||||
|
page = VirtualAllocEx(h, None, 4096, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
|
||||||
|
stub = bytearray(32)
|
||||||
|
stub[0x00] = 0xC3 # ret
|
||||||
|
stub[0x04:0x07] = b'\xC2\x04\x00' # ret 4
|
||||||
|
stub[0x08:0x10] = b'\xB8\x01\x00\x00\x00\xC2\x18\x00' # CryptVerify -> TRUE
|
||||||
|
write_mem(h, page, bytes(stub))
|
||||||
|
|
||||||
|
# Exit hooks
|
||||||
|
for addr, off, name in [(0x9DF18C,0,"Halt"),(0x4C36428,4,"PostQuitMessage"),
|
||||||
|
(0xA1007C,4,"ExitProcess1"),(0x4C36590,4,"ExitProcess2"),(0x4C36AE8,4,"ExitProcess3")]:
|
||||||
|
write_mem(h, addr, struct.pack('<I', page+off)); print(f" [+] {name}")
|
||||||
|
|
||||||
|
# Crypto IAT
|
||||||
|
for addr in [0x9DF0F8, 0x4C364FC]:
|
||||||
|
write_mem(h, addr, struct.pack('<I', page+0x08)); print(" [+] CryptVerify IAT")
|
||||||
|
|
||||||
|
# Builder gate
|
||||||
|
write_mem(h, 0x983F9C, b'\x01'); print(" [+] Builder gate=1")
|
||||||
|
# TLS init
|
||||||
|
write_mem(h, 0x97126C, struct.pack('<I', 1)); print(" [+] TLS flag=1")
|
||||||
|
|
||||||
|
print(f"\n[+] Done. Remcos PID {pid}")
|
||||||
|
print("[*] Enter email in auth dialog. Server handles the rest.")
|
||||||
|
CloseHandle(h)
|
||||||
|
proc.wait()
|
||||||
|
|
||||||
|
if __name__ == "__main__": main()
|
||||||
+383
@@ -0,0 +1,383 @@
|
|||||||
|
"""
|
||||||
|
Standalone fake server + DNS redirect.
|
||||||
|
Stays running until you press Ctrl+C.
|
||||||
|
Launch Remcos/KeyGen yourself while this is running.
|
||||||
|
|
||||||
|
Run as Administrator!
|
||||||
|
"""
|
||||||
|
import http.server
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import socketserver
|
||||||
|
import ssl
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
|
||||||
|
VERSION = "7.2.2"
|
||||||
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
CERT_DIR = os.path.join(SCRIPT_DIR, "certs")
|
||||||
|
CA_CERT = os.path.join(CERT_DIR, "ca.crt")
|
||||||
|
CA_KEY = os.path.join(CERT_DIR, "ca.key")
|
||||||
|
SRV_CERT = os.path.join(CERT_DIR, "server.crt")
|
||||||
|
SRV_KEY = os.path.join(CERT_DIR, "server.key")
|
||||||
|
|
||||||
|
NRPT_BASE = r"HKLM:\System\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig"
|
||||||
|
NRPT_GUIDS = [
|
||||||
|
("{b1a2c3d4-0001-aaaa-bbbb-000000000001}", [".breakingsec.io", "breakingsec.io"]),
|
||||||
|
("{b1a2c3d4-0001-aaaa-bbbb-000000000002}", [".ip-api.com", "pro.ip-api.com", "ip-api.com"]),
|
||||||
|
("{b1a2c3d4-0001-aaaa-bbbb-000000000003}", [".breakingsecurity.net", "breakingsecurity.net"]),
|
||||||
|
]
|
||||||
|
|
||||||
|
REDIRECT_DOMAINS = {"breakingsec.io", "www.breakingsec.io", "breakingsecurity.net",
|
||||||
|
"www.breakingsecurity.net", "pro.ip-api.com"}
|
||||||
|
REAL_DNS = "8.8.8.8"
|
||||||
|
|
||||||
|
GEO_RESPONSE = "\n".join([
|
||||||
|
"success", "US", "United States", "NA", "North America",
|
||||||
|
"CA", "California", "Los Angeles", "Los Angeles", "90001",
|
||||||
|
"34.0522", "-118.2437", "America/Los_Angeles",
|
||||||
|
"ISP", "ISP Corp", "AS0000", "1.2.3.4",
|
||||||
|
])
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SSL Certs
|
||||||
|
# ============================================================
|
||||||
|
def generate_certs():
|
||||||
|
os.makedirs(CERT_DIR, exist_ok=True)
|
||||||
|
if os.path.exists(SRV_CERT) and os.path.exists(CA_CERT):
|
||||||
|
print("[*] Certs exist, reusing.")
|
||||||
|
return True
|
||||||
|
print("[*] Generating SSL certificates...")
|
||||||
|
try:
|
||||||
|
subprocess.run(["openssl", "req", "-x509", "-newkey", "rsa:2048", "-nodes",
|
||||||
|
"-keyout", CA_KEY, "-out", CA_CERT, "-days", "3650",
|
||||||
|
"-subj", "/CN=Remcos Test CA"], capture_output=True, check=True)
|
||||||
|
|
||||||
|
csr = os.path.join(CERT_DIR, "server.csr")
|
||||||
|
ext = os.path.join(CERT_DIR, "ext.cnf")
|
||||||
|
with open(ext, "w") as f:
|
||||||
|
f.write("[v3_req]\nsubjectAltName=DNS:breakingsec.io,DNS:*.breakingsec.io,"
|
||||||
|
"DNS:breakingsecurity.net,DNS:*.breakingsecurity.net,"
|
||||||
|
"DNS:pro.ip-api.com,DNS:*.ip-api.com,DNS:localhost\n"
|
||||||
|
"basicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment\n"
|
||||||
|
"extendedKeyUsage=serverAuth\n")
|
||||||
|
|
||||||
|
subprocess.run(["openssl", "req", "-newkey", "rsa:2048", "-nodes",
|
||||||
|
"-keyout", SRV_KEY, "-out", csr, "-subj", "/CN=breakingsec.io"],
|
||||||
|
capture_output=True, check=True)
|
||||||
|
|
||||||
|
subprocess.run(["openssl", "x509", "-req", "-in", csr, "-CA", CA_CERT,
|
||||||
|
"-CAkey", CA_KEY, "-CAcreateserial", "-out", SRV_CERT, "-days", "3650",
|
||||||
|
"-extfile", ext, "-extensions", "v3_req"], capture_output=True, check=True)
|
||||||
|
|
||||||
|
print("[+] Certificates generated.")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[-] Cert generation failed: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def install_ca():
|
||||||
|
r = subprocess.run(["certutil", "-addstore", "-f", "Root", CA_CERT],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
if r.returncode == 0:
|
||||||
|
print("[+] CA cert installed in trust store.")
|
||||||
|
else:
|
||||||
|
print(f"[-] CA install failed: {r.stderr[:100]}")
|
||||||
|
|
||||||
|
def remove_ca():
|
||||||
|
subprocess.run(["certutil", "-delstore", "Root", "Remcos Test CA"],
|
||||||
|
capture_output=True)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# NRPT
|
||||||
|
# ============================================================
|
||||||
|
def setup_nrpt():
|
||||||
|
print("[*] Setting NRPT rules...")
|
||||||
|
for guid, domains in NRPT_GUIDS:
|
||||||
|
names_str = ",".join(f"'{d}'" for d in domains)
|
||||||
|
ps = f"""
|
||||||
|
$p = '{NRPT_BASE}\\{guid}'
|
||||||
|
New-Item -Path $p -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path $p -Name 'Name' -Value @({names_str}) -Type MultiString
|
||||||
|
Set-ItemProperty -Path $p -Name 'GenericDNSServers' -Value '127.0.0.1' -Type String
|
||||||
|
Set-ItemProperty -Path $p -Name 'ConfigOptions' -Value 8 -Type DWord
|
||||||
|
Set-ItemProperty -Path $p -Name 'Version' -Value 2 -Type DWord
|
||||||
|
"""
|
||||||
|
r = subprocess.run(["powershell", "-Command", ps], capture_output=True, text=True, timeout=10)
|
||||||
|
if r.returncode == 0:
|
||||||
|
print(f" [+] {', '.join(domains)} -> 127.0.0.1")
|
||||||
|
else:
|
||||||
|
print(f" [-] {domains[0]}: {r.stderr.strip()[:80]}")
|
||||||
|
|
||||||
|
subprocess.run(["ipconfig", "/flushdns"], capture_output=True, timeout=10)
|
||||||
|
subprocess.run(["powershell", "-Command", "Clear-DnsClientCache; Register-DnsClient"],
|
||||||
|
capture_output=True, timeout=10)
|
||||||
|
|
||||||
|
def cleanup_nrpt():
|
||||||
|
for guid, _ in NRPT_GUIDS:
|
||||||
|
ps = f"Remove-Item -Path '{NRPT_BASE}\\{guid}' -Recurse -Force -ErrorAction SilentlyContinue"
|
||||||
|
subprocess.run(["powershell", "-Command", ps], capture_output=True, timeout=10)
|
||||||
|
subprocess.run(["ipconfig", "/flushdns"], capture_output=True, timeout=10)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# DNS Server
|
||||||
|
# ============================================================
|
||||||
|
class DNSHandler(socketserver.BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
data = self.request[0]
|
||||||
|
sock = self.request[1]
|
||||||
|
try:
|
||||||
|
domain = self._parse_domain(data).lower().rstrip(".")
|
||||||
|
redirect = any(domain == d or domain.endswith("." + d)
|
||||||
|
for d in REDIRECT_DOMAINS)
|
||||||
|
if redirect:
|
||||||
|
resp = self._build_response(data, "127.0.0.1")
|
||||||
|
sock.sendto(resp, self.client_address)
|
||||||
|
else:
|
||||||
|
fwd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
fwd.settimeout(3)
|
||||||
|
fwd.sendto(data, (REAL_DNS, 53))
|
||||||
|
try:
|
||||||
|
r, _ = fwd.recvfrom(4096)
|
||||||
|
sock.sendto(r, self.client_address)
|
||||||
|
except socket.timeout:
|
||||||
|
pass
|
||||||
|
fwd.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _parse_domain(self, data):
|
||||||
|
parts, idx = [], 12
|
||||||
|
while idx < len(data):
|
||||||
|
l = data[idx]
|
||||||
|
if l == 0: break
|
||||||
|
idx += 1
|
||||||
|
parts.append(data[idx:idx+l].decode("ascii", errors="replace"))
|
||||||
|
idx += l
|
||||||
|
return ".".join(parts)
|
||||||
|
|
||||||
|
def _build_response(self, query, ip):
|
||||||
|
resp = bytearray(query[:2]) + b'\x81\x80' + query[4:6] + b'\x00\x01\x00\x00\x00\x00'
|
||||||
|
idx = 12
|
||||||
|
while idx < len(query):
|
||||||
|
if query[idx] == 0:
|
||||||
|
idx += 5
|
||||||
|
break
|
||||||
|
idx += 1 + query[idx]
|
||||||
|
resp += query[12:idx]
|
||||||
|
resp += b'\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04'
|
||||||
|
resp += socket.inet_aton(ip)
|
||||||
|
return bytes(resp)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# HTTP/HTTPS Server
|
||||||
|
# ============================================================
|
||||||
|
class FakeHandler(http.server.BaseHTTPRequestHandler):
|
||||||
|
def log_message(self, fmt, *args):
|
||||||
|
ts = datetime.now().strftime("%H:%M:%S")
|
||||||
|
print(f" [{ts}] {fmt % args}")
|
||||||
|
|
||||||
|
def send_text(self, text, code=200):
|
||||||
|
data = text.encode("utf-8")
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header("Content-Type", "text/plain")
|
||||||
|
self.send_header("Content-Length", str(len(data)))
|
||||||
|
self.send_header("Connection", "close")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(data)
|
||||||
|
|
||||||
|
def route(self):
|
||||||
|
path = urlparse(self.path).path.lower()
|
||||||
|
host = self.headers.get("Host", "")
|
||||||
|
qs = parse_qs(urlparse(self.path).query)
|
||||||
|
print(f" -> {self.command} {self.path} (Host: {host})")
|
||||||
|
# Dump ALL headers for debugging
|
||||||
|
for h_name, h_val in self.headers.items():
|
||||||
|
print(f" {h_name}: {h_val}")
|
||||||
|
|
||||||
|
if "whitelist" in path:
|
||||||
|
print(f" <- Whitelist: EMPTY")
|
||||||
|
self.send_text("")
|
||||||
|
return
|
||||||
|
if "signalabuse" in path:
|
||||||
|
print(f" <- Abuse absorbed")
|
||||||
|
self.send_text("")
|
||||||
|
return
|
||||||
|
if "licpost" in path or ("keygen" in path and "lic" in path.lower()):
|
||||||
|
lic_raw = qs.get("LIC", [""])[0]
|
||||||
|
parts = lic_raw.split("|")
|
||||||
|
print(f" ***** KeyGen LicPost! *****")
|
||||||
|
print(f" Parts: {parts}")
|
||||||
|
# Try response matching request format: pipe-delimited after "0\n"
|
||||||
|
key = parts[0] if len(parts) > 0 else ""
|
||||||
|
email = parts[1] if len(parts) > 1 else ""
|
||||||
|
# Format: 0\nkey|email|product|expiry|type|version
|
||||||
|
resp = f"0\n{key}|{email}|Remcos|20301231|Pro|7.2.2"
|
||||||
|
print(f" <- Responding: '{resp}'")
|
||||||
|
self.send_text(resp)
|
||||||
|
return
|
||||||
|
if "upd_pro" in path:
|
||||||
|
print(f" <- Version: {VERSION}")
|
||||||
|
self.send_text(VERSION + "\n")
|
||||||
|
return
|
||||||
|
# PeriodicCheck - license validation with hash + expiry
|
||||||
|
if "periodiccheck" in path:
|
||||||
|
lic = qs.get("LIC", ["?"])[0]
|
||||||
|
resp = "49ef9592748fac8986f0d360454dbab0\n20301231\nRemcos"
|
||||||
|
print(f" ***** PeriodicCheck (LIC={lic[:24]}) -> {repr(resp)} *****")
|
||||||
|
self.send_text(resp)
|
||||||
|
return
|
||||||
|
# Auth/license check - sign with our private key
|
||||||
|
if "auth" in path or "check" in path or "verify" in path or "validate" in path:
|
||||||
|
print(f" ***** Auth endpoint: {self.path} *****")
|
||||||
|
self.send_text("0\n20301231\nPro\n7.2.2")
|
||||||
|
return
|
||||||
|
if "onlinecheck" in path:
|
||||||
|
print(f" <- OnlineCheck: {VERSION}")
|
||||||
|
self.send_text(VERSION + "\n")
|
||||||
|
return
|
||||||
|
if "/line" in path or "ip-api" in host:
|
||||||
|
print(f" <- GeoIP")
|
||||||
|
self.send_text(GEO_RESPONSE + "\n")
|
||||||
|
return
|
||||||
|
print(f" *** UNKNOWN ENDPOINT: {self.path} ***")
|
||||||
|
print(f" *** Host: {host} ***")
|
||||||
|
# Return "0" instead of empty - empty might cause range check errors
|
||||||
|
self.send_text("0")
|
||||||
|
|
||||||
|
def do_GET(self): self.route()
|
||||||
|
def do_POST(self):
|
||||||
|
cl = int(self.headers.get("Content-Length", 0))
|
||||||
|
body = self.rfile.read(cl) if cl > 0 else b""
|
||||||
|
if body:
|
||||||
|
try: print(f" POST body: {body[:300].decode('utf-8', errors='replace')}")
|
||||||
|
except: print(f" POST body: {body[:100].hex()}")
|
||||||
|
self.route()
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Main
|
||||||
|
# ============================================================
|
||||||
|
def main():
|
||||||
|
print("=" * 60)
|
||||||
|
print(" Fake Server (standalone) - stays running")
|
||||||
|
print(" Launch Remcos/KeyGen yourself while this runs")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
if not ctypes.windll.shell32.IsUserAnAdmin():
|
||||||
|
print("[-] Need Administrator! Right-click -> Run as admin")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
generate_certs()
|
||||||
|
install_ca()
|
||||||
|
|
||||||
|
# CA bundle for OpenSSL apps
|
||||||
|
ca_bundle = os.path.join(CERT_DIR, "ca_bundle.pem")
|
||||||
|
try:
|
||||||
|
import certifi
|
||||||
|
system_ca = certifi.where()
|
||||||
|
except ImportError:
|
||||||
|
system_ca = None
|
||||||
|
with open(ca_bundle, "w") as out:
|
||||||
|
with open(CA_CERT) as f: out.write(f.read() + "\n")
|
||||||
|
if system_ca and os.path.exists(system_ca):
|
||||||
|
with open(system_ca) as f: out.write(f.read())
|
||||||
|
os.environ["SSL_CERT_FILE"] = ca_bundle
|
||||||
|
os.environ["SSL_CERT_DIR"] = CERT_DIR
|
||||||
|
|
||||||
|
# Start servers
|
||||||
|
dns = socketserver.UDPServer(("127.0.0.1", 53), DNSHandler)
|
||||||
|
threading.Thread(target=dns.serve_forever, daemon=True).start()
|
||||||
|
print("[+] DNS on 127.0.0.1:53")
|
||||||
|
|
||||||
|
http_srv = http.server.HTTPServer(("0.0.0.0", 80), FakeHandler)
|
||||||
|
threading.Thread(target=http_srv.serve_forever, daemon=True).start()
|
||||||
|
print("[+] HTTP on 0.0.0.0:80")
|
||||||
|
|
||||||
|
try:
|
||||||
|
class LoggingHTTPS(http.server.HTTPServer):
|
||||||
|
def handle_error(self, request, client_address):
|
||||||
|
print(f" [SSL ERROR] from {client_address}: {sys.exc_info()[1]}")
|
||||||
|
https_srv = LoggingHTTPS(("0.0.0.0", 443), FakeHandler)
|
||||||
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
ctx.load_cert_chain(SRV_CERT, SRV_KEY)
|
||||||
|
https_srv.socket = ctx.wrap_socket(https_srv.socket, server_side=True)
|
||||||
|
threading.Thread(target=https_srv.serve_forever, daemon=True).start()
|
||||||
|
print("[+] HTTPS on 0.0.0.0:443")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[-] HTTPS failed: {e}")
|
||||||
|
|
||||||
|
# Port 45000 - Viotto packer license validation (raw TCP protocol!)
|
||||||
|
def handle_viotto_client(conn, addr):
|
||||||
|
print(f"\n *** PORT 45000 CONNECTION from {addr} ***")
|
||||||
|
conn.settimeout(5)
|
||||||
|
try:
|
||||||
|
# Read whatever the client sends
|
||||||
|
data = conn.recv(4096)
|
||||||
|
print(f" *** RECEIVED ({len(data)} bytes): {data[:200].hex()}")
|
||||||
|
try:
|
||||||
|
print(f" *** AS TEXT: {data[:200].decode('ascii', errors='replace')}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# Echo back for now - we need to see the protocol first
|
||||||
|
conn.sendall(data)
|
||||||
|
print(f" *** Echoed {len(data)} bytes back")
|
||||||
|
except socket.timeout:
|
||||||
|
print(f" *** PORT 45000: recv timeout (client didn't send data)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" *** PORT 45000 error: {e}")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def viotto_server():
|
||||||
|
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
srv.bind(("0.0.0.0", 45000))
|
||||||
|
srv.listen(5)
|
||||||
|
print("[+] Raw TCP on 0.0.0.0:45000 (Viotto license port!)")
|
||||||
|
while True:
|
||||||
|
conn, addr = srv.accept()
|
||||||
|
threading.Thread(target=handle_viotto_client, args=(conn, addr), daemon=True).start()
|
||||||
|
|
||||||
|
threading.Thread(target=viotto_server, daemon=True).start()
|
||||||
|
|
||||||
|
# NRPT
|
||||||
|
setup_nrpt()
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
time.sleep(1)
|
||||||
|
for domain in ["breakingsec.io", "breakingsecurity.net"]:
|
||||||
|
try:
|
||||||
|
result = socket.getaddrinfo(domain, 443)
|
||||||
|
ip = result[0][4][0]
|
||||||
|
status = "OK" if ip == "127.0.0.1" else f"WRONG ({ip})"
|
||||||
|
print(f" {domain} -> {ip} [{status}]")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" {domain} -> ERROR: {e}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("=" * 60)
|
||||||
|
print(" RUNNING. Now launch KeyGen.exe or Remcos manually.")
|
||||||
|
print(" Press Ctrl+C to stop and clean up.")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
print("\n[*] Cleaning up...")
|
||||||
|
cleanup_nrpt()
|
||||||
|
print("[+] NRPT removed")
|
||||||
|
remove_ca()
|
||||||
|
print("[+] CA removed")
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Zip password is:
|
||||||
|
BreakingSecurity.net
|
||||||
Reference in New Issue
Block a user