/*
Nepdetect realvnc module by kat
based on netcat dump received from nepenthes honeypot
------------- 01/01/08 katsumi
connecting
receiving 12 bytes (the version string)
< 00000000 52 46 42 20 30 30 33 2e 30 30 38 0a             # RFB 003.008.
sending the version string and receiving then black & white
< 0000000c 01 02                                           # ..
sending the moo !
receiving 4 bytes
< 0000000e 00 00 00 00                                     # ....
and receiving 37 bytes
< 00000012 04 3a 02 ff 20 18 00 01 00 ff 00 ff 00 ff 10 08 # .:.. ...........
< 00000022 00 00 00 00 00 00 00 0d 46 4f 4f 42 41 52 2d 4d # ........FOOBAR-M
< 00000032 55 54 54 45 52                                  # UTTER

  (nepenthes' log crit will print a out_of_sync? message)

just 4 fun 
did you ever got a binary thru vuln-realvnc ??
*/

#include "includes.h"
#include "functions.h"
#include "externs.h"

/*
i kept the TODOs, may be it would be usefull to see how the code had grown up
------------- 04/01/08 katsumi
added related lines from vuln-realvnc as comments
------------- 05/03/08 katsumi
*/

#ifndef NO_VNCMOO

BOOL vncmoo(EXINFO exinfo)
{
	char moobuf[IRCLINE];
	char tosend[] = "RFB 003.008\n"; 
	char moo[] = "moo\n"; //something (at this time moo ;))
	int i = 0;
	char vncbuf1[11];
	char vncbuf2[1];
	char vncbuf3[3];
	char vncbuf4[36];
	//char vncbuf5[] = "8";
	char vncbuf6[15] = "FOOBAR-MUTTER\n";
	
	#define ISVNC 0x52 // version string should start with 0x52
	#define VNC38	0x38	// lookin for 0x38 in version string
	// DONE: (TODO at stage2)
	#define BLACK 0x01 
	#define WHITE 0x02
	#define ZERO  0x00

	SOCKET sock;

	if((sock = socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET) {
		SOCKADDR_IN ssin;
		memset(&ssin, 0, sizeof(ssin));
		ssin.sin_family = AF_INET;
		ssin.sin_addr.s_addr = finet_addr(exinfo.ip);
		ssin.sin_port = fhtons((unsigned short)exinfo.port);
		if(connect(sock, (LPSOCKADDR)&ssin, sizeof(ssin)) != SOCKET_ERROR) {
//			sprintf(moobuf, "[vncmoo]: Connected to %s\r\n", exinfo.ip);
//			irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
//			addlog(moobuf);
			// ok we are connected :)
		//	Sleep(300); // do we need it?
			// ok. i'm a bot . i need to receive ;)
// receive 12 bytes

/* **********************************************************************************************************************
   		from vuln-realvnc.cpp:		
		248 	                logSpam("VNC_HANDSHAKE\n");
		249 	//              g_Nepenthes->getUtilities()->hexdump((byte *)m_Buffer->getData(),m_Buffer->getSize());
		250 	                if (m_Buffer->getSize() >= strlen(rfb_version_003_008) &&
		251 	                        memcmp(m_Buffer->getData(),rfb_version_003_008,strlen(rfb_version_003_008)) == 0)
		252 	                {
		253 	//                      logSpam("got rfb_version_003_008\n");
   ***********************************************************************************************************************/

			if (recv(sock, vncbuf1, 12, 0) > 0 )
			{
//				sprintf(moobuf, "[vncmoo]: receiving version from %s: %s", exinfo.ip, vncbuf1);
//				irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
//				addlog(moobuf);
				#ifdef DEBUG_CONSOLE
				printf("%s: Received at STAGE1:", exinfo.ip);
				for (i=0; i<12; i++) {
					printf("%x,", vncbuf1[i]);
					}
				printf("\n");
				//printf("%x = %x ?\n", vncbuf1[10], VNC38);
				#endif
				// no vnc check start
				if (!( vncbuf1[0] == ISVNC )) 
					{
						#ifdef DEBUG_CONSOLE
						printf("%s: No VNC - closing socket\n", exinfo.ip);
						#endif
						closesocket(sock);
						return TRUE;
					}
				// no vnc check end
//				if ( vncbuf1[10] == VNC38 )
//				{
				if (!( vncbuf1[10] == VNC38 )) 
					{
						#ifdef DEBUG_CONSOLE
						printf("%s: Bad VNC version - closing socket\n", exinfo.ip);
						#endif
						closesocket(sock);
						return TRUE;
					}
// send the version string
				if (send(sock, tosend, 12, 0) > 0 )
				{
//					sprintf(moobuf, "[vncmoo]: Sending RFB client version to %s.", exinfo.ip);
//					irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
//					addlog(moobuf);
					#ifdef DEBUG_CONSOLE
					printf("%s: STAGE1 done.\n", exinfo.ip);
					#endif
/* ********************************************************************************************************************
   		from vuln-realvnc.cpp:
		255 	                        static const char auth_offer[2] = {  01, 02 };
		256 	                        m_Socket->doWrite((char *)auth_offer,2);
		257 	
		258 	                        m_State = VNC_AUTH;
   *********************************************************************************************************************/	
					
					if (recv(sock, vncbuf2, 2, 0) > 0 ) // receive 2 bytes
					{
//						sprintf(moobuf, "[vncmoo]: receiving blacknwhite from %s: %i %i", exinfo.ip, vncbuf2[1], vncbuf2[2]);
//						irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
//						addlog(moobuf);	
						#ifdef DEBUG_CONSOLE
						printf("%s: Received at STAGE2: 0x%x 0x%x\n",exinfo.ip, vncbuf2[0],vncbuf2[1]);
						#endif 
//TODO: if byte 0 is 01 and byte 1 is 02
						//DONE 
						if (!( vncbuf2[0] == BLACK ) || !( vncbuf2[1] == WHITE ))
							{
								#ifdef DEBUG_CONSOLE
								printf("%s: failed black'n'white - closing socket\n", exinfo.ip);
								#endif
								closesocket(sock);
								return TRUE;
							}
						//DONE try todo end
						if (send(sock, moo, 4, 0) > 0 )
						{
//							sprintf(moobuf, "[vncmoo]: Sending moo to %s", exinfo.ip);
//							irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
//							addlog(moobuf);
							#ifdef DEBUG_CONSOLE
							printf("%s: Send at STAGE2:%s \n", exinfo.ip, moo);
							printf("%s: STAGE2 done.\n", exinfo.ip);
							#endif 

/* ********************************************************************************************************
   		from vuln-realvnc.cpp:
		272 	                                unsigned int auth_accept = 0;
		273 	                                m_Socket->doWrite((char *)&auth_accept,4);
		274 	
		275 	                                m_State = VNC_SHARED_DESKTOP;
   *********************************************************************************************************/							
							
							if (recv(sock, vncbuf3, 4, 0) > 0 )// receive 4 bytes
							{
								// may be we really could detect it here
								#ifdef DEBUG_CONSOLE
								printf("%s: Received at STAGE3:", exinfo.ip);
								for (i=0; i<4; i++) { printf	("%i",vncbuf3[i]); }
								printf("\n");
								#endif 
							// TODO: else close socket return false
// TODO: if byte 0-3 is 0 receive 37 bytes
								// we will test byte 0 and 3 
								if (!( vncbuf3[0] == ZERO ) || !( vncbuf3[3] == ZERO ))
								{
									#ifdef DEBUG_CONSOLE
									printf("%s: expected 0000 - closing socket\n", exinfo.ip);
									#endif
									closesocket(sock);
									return TRUE;
								}
						// end TODO

/* ********************************************************************************************************
   		from vuln-realvnc.cpp:
		288 	                        static const char vnc_isupport[] = {
		289 	                                0x04, 0x3a, 0x02, 0xff, 0x20, 0x18, 0x00, 0x01,
		290 	                                0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x10, 0x08,
		291 	                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
		292 	                                0x46, 0x4f, 0x4f, 0x42, 0x41, 0x52, 0x2d, 0x4d,
		293 	                                0x55, 0x54, 0x54, 0x45, 0x52};
		294 	                        m_Socket->doWrite((char *)vnc_isupport,sizeof(vnc_isupport));
		295 	            m_State = VNC_ONLINE;
   *********************************************************************************************************/							
								
								if (recv(sock, vncbuf4, 37, 0) > 0 )
								{
							// consume level lol
									#ifdef DEBUG_CONSOLE
									printf("\n%s: STAGE4 reached.\n", exinfo.ip);
									printf("\n%s: looks like nepenthes vuln-realvnc\n", exinfo.ip);
					//				for (i=0; i<37; i++) {
					//				printf("%i,", vncbuf4[i]);
					//				}
									//printf("\n");
									for (i=24; i<37; i++) 
									{
										//
										printf("%s: collecting bytes to test byte %i: %x %x\n", exinfo.ip, i, vncbuf4[i],vncbuf6[i-24] );
									}
									#endif
									// reaching stage4 typically means we already have detected vuln-realvnc nepenthes modul
									// but we will make a lil test 'cos we had not tested vncbuf3 : 0000
									// still TODO:comparing vncbuf3 //DONE
									sprintf(moobuf, "[vncmoo]: looks like nepenthes vuln-realvnc at: %s\r\n", exinfo.ip);
									irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
									addlog(moobuf);
									//lol
									if ( vncbuf4[35] == vncbuf6[11] ) //easy way. i don't care about false positives
									{
										#ifdef DEBUG_CONSOLE
										printf("%s: found nepenthes vuln-realvnc module\n", exinfo.ip);
										#endif
										sprintf(moobuf, "[vncmoo]: nepenthes detected at %s (FOOBAR-MUTTER) \r\n", exinfo.ip);
										irc_privmsg(exinfo.sock, exinfo.chan, moobuf, exinfo.notice);
										addlog(moobuf);
										exploit[ exinfo.exploit ].stats++; //counting up number of found neps
									}
// TODO: if byte 24-36 is FOOBAR-MUTTER send message to irc //no need TODO
								}
							}
						}

					}
				}
			}
		}
	}
//	}
		Sleep(500);
		closesocket(sock);
return TRUE;
}


#endif