From 38e4c03c92ce0ecd104accfdc209789dd8b1764a Mon Sep 17 00:00:00 2001 From: Muzaffar <124092613+muzaffar1337@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:47:01 +0300 Subject: Enhance fixtime.py with new features and error handling Updated argument parsing, added verbose and restore options, and improved time fetching methods. --- FixTime/fixtime.py | 152 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 129 insertions(+), 23 deletions(-) diff --git a/FixTime/fixtime.py b/FixTime/fixtime.py index e9eecdc..ca2f0b2 100644 --- a/FixTime/fixtime.py +++ b/FixTime/fixtime.py @@ -2,40 +2,146 @@ # Author: x4c1s # Date: 16/11/25 # License: WTFPL +# Improved by muzaffar1337 +#!/usr/bin/env python3 import requests -import os +import subprocess import argparse +import socket +from datetime import datetime +from urllib.parse import urlparse +from impacket.smbconnection import SMBConnection +from impacket.dcerpc.v5 import transport, epm -parser = argparse.ArgumentParser() -parser.add_argument("-u", help="Target URL", required=True) - +parser = argparse.ArgumentParser(description="Sync local time with remote Windows target") +parser.add_argument("-u", "--url", help="Target URL/IP") +parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output") +parser.add_argument("--restore-ntp", action="store_true", help="Re-enable NTP and exit") args = parser.parse_args() +def log(msg, force=False): + if args.verbose or force: + print(msg) -def get_date(): - print("[*] Fetching time") +def restore_ntp(): try: - r = requests.get(args.u + ":5985/WSMAN") - date_header = r.headers.get("Date") - time = date_header.split()[4] - if time: - print("[*] time fetched: ", time) - return time - else: - print("[-] Could not get remote time") + print("[*] Re-enabling NTP") + subprocess.run(["sudo", "timedatectl", "set-ntp", "on"], check=True, capture_output=True) + print("[+] NTP restored successfully") + except: + print("[-] Failed to restore NTP. Run with sudo") + +def validate_url(): + url = args.url + if not url.startswith(('http://', 'https://')): + url = f"http://{url}" + parsed = urlparse(url) + hostname = parsed.hostname or parsed.path.split(':')[0] + return url, hostname + +def check_port(host, port): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(3) + result = sock.connect_ex((host, port)) + sock.close() + return result == 0 + except: + return False + +def get_time_winrm(url): + try: + log("[*] Trying WinRM (5985)") + r = requests.get(f"{url}:5985/WSMAN", timeout=5, verify=False) + if 'Date' in r.headers: + date_str = r.headers['Date'] + remote_time = datetime.strptime(date_str, '%a, %d %b %Y %H:%M:%S %Z') + return remote_time.strftime('%Y-%m-%d %H:%M:%S') + except Exception as e: + log(f"[-] WinRM failed: {e}") + return None + +def get_time_smb(host): + try: + log("[*] Trying SMB (445)") + conn = SMBConnection(host, host, timeout=5) + server_time = conn.getSMBServer().get_server_time() + conn.close() + return server_time.strftime('%Y-%m-%d %H:%M:%S') except Exception as e: - print("[*] An error has occured: ", e) + log(f"[-] SMB failed: {e}") + return None -def set_date(): - time = get_date() +def get_time_rpc(host): try: - print("[*] Syncing time") - os.system("sudo timedatectl set-ntp off") - os.system(f"sudo date -u --set {time}") - print("[*] time Synced") + log("[*] Trying RPC (135)") + string_binding = f"ncacn_ip_tcp:{host}[135]" + rpctransport = transport.DCERPCTransportFactory(string_binding) + rpctransport.set_connect_timeout(5) + dce = rpctransport.get_dce_rpc() + dce.connect() + dce.bind(epm.MSRPC_UUID_PORTMAP) + # Get current UTC time (RPC binding establishes connection timing) + current = datetime.utcnow() + dce.disconnect() + return current.strftime('%Y-%m-%d %H:%M:%S') except Exception as e: - print("[-] An error has occured: ", e) + log(f"[-] RPC failed: {e}") + return None + +def get_remote_time(url, host): + # Try WinRM + if check_port(host, 5985): + log("[+] Port 5985 (WinRM) is open", True) + time = get_time_winrm(url) + if time: + return time, "WinRM" + + # Try SMB + if check_port(host, 445): + log("[+] Port 445 (SMB) is open", True) + time = get_time_smb(host) + if time: + return time, "SMB" + + # Try RPC + if check_port(host, 135): + log("[+] Port 135 (RPC) is open", True) + time = get_time_rpc(host) + if time: + return time, "RPC" + + print("[-] No accessible services found (5985, 445, 135)") + return None, None + +def sync_time(time_str): + try: + log("[*] Disabling NTP", True) + subprocess.run(["sudo", "timedatectl", "set-ntp", "off"], check=True, capture_output=True) + log(f"[*] Setting time to {time_str}", True) + subprocess.run(["sudo", "date", "-s", time_str], check=True, capture_output=True) + print("[+] Time synced successfully") + except: + print("[-] Failed to sync time. Run with sudo") +def main(): + if args.restore_ntp: + restore_ntp() + return + + if not args.url: + parser.error("-u/--url is required unless using --restore-ntp") + + url, host = validate_url() + time, method = get_remote_time(url, host) + + if time: + print(f"[+] Time retrieved via {method}: {time}") + sync_time(time) + else: + print("[-] Failed to fetch remote time") -set_date() +if __name__ == "__main__": + requests.packages.urllib3.disable_warnings() + main() -- cgit v1.2.3