1 /***************************************************************************
2  * ncrack_vnc.cc -- ncrack module for the vnc protocol                     *
3  * Coded by rhh                                                            *
4  *  http://rycon.hu/                                                       *
5  *                                                                         *
6  ***********************IMPORTANT NMAP LICENSE TERMS************************
7  *                                                                         *
8  * The Nmap Security Scanner is (C) 1996-2019 Insecure.Com LLC ("The Nmap  *
9  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
10  * This program is free software; you may redistribute and/or modify it    *
11  * under the terms of the GNU General Public License as published by the   *
12  * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE   *
13  * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN.  This guarantees your   *
14  * right to use, modify, and redistribute this software under certain      *
15  * conditions.  If you wish to embed Nmap technology into proprietary      *
16  * software, we sell alternative licenses (contact sales@nmap.com).        *
17  * Dozens of software vendors already license Nmap technology such as      *
18  * host discovery, port scanning, OS detection, version detection, and     *
19  * the Nmap Scripting Engine.                                              *
20  *                                                                         *
21  * Note that the GPL places important restrictions on "derivative works",  *
22  * yet it does not provide a detailed definition of that term.  To avoid   *
23  * misunderstandings, we interpret that term as broadly as copyright law   *
24  * allows.  For example, we consider an application to constitute a        *
25  * derivative work for the purpose of this license if it does any of the   *
26  * following with any software or content covered by this license          *
27  * ("Covered Software"):                                                   *
28  *                                                                         *
29  * o Integrates source code from Covered Software.                         *
30  *                                                                         *
31  * o Reads or includes copyrighted data files, such as Nmap's nmap-os-db   *
32  * or nmap-service-probes.                                                 *
33  *                                                                         *
34  * o Is designed specifically to execute Covered Software and parse the    *
35  * results (as opposed to typical shell or execution-menu apps, which will *
36  * execute anything you tell them to).                                     *
37  *                                                                         *
38  * o Includes Covered Software in a proprietary executable installer.  The *
39  * installers produced by InstallShield are an example of this.  Including *
40  * Nmap with other software in compressed or archival form does not        *
41  * trigger this provision, provided appropriate open source decompression  *
42  * or de-archiving software is widely available for no charge.  For the    *
43  * purposes of this license, an installer is considered to include Covered *
44  * Software even if it actually retrieves a copy of Covered Software from  *
45  * another source during runtime (such as by downloading it from the       *
46  * Internet).                                                              *
47  *                                                                         *
48  * o Links (statically or dynamically) to a library which does any of the  *
49  * above.                                                                  *
50  *                                                                         *
51  * o Executes a helper program, module, or script to do any of the above.  *
52  *                                                                         *
53  * This list is not exclusive, but is meant to clarify our interpretation  *
54  * of derived works with some common examples.  Other people may interpret *
55  * the plain GPL differently, so we consider this a special exception to   *
56  * the GPL that we apply to Covered Software.  Works which meet any of     *
57  * these conditions must conform to all of the terms of this license,      *
58  * particularly including the GPL Section 3 requirements of providing      *
59  * source code and allowing free redistribution of the work as a whole.    *
60  *                                                                         *
61  * As another special exception to the GPL terms, the Nmap Project grants  *
62  * permission to link the code of this program with any version of the     *
63  * OpenSSL library which is distributed under a license identical to that  *
64  * listed in the included docs/licenses/OpenSSL.txt file, and distribute   *
65  * linked combinations including the two.                                  *
66  *                                                                         *
67  * The Nmap Project has permission to redistribute Npcap, a packet         *
68  * capturing driver and library for the Microsoft Windows platform.        *
69  * Npcap is a separate work with it's own license rather than this Nmap    *
70  * license.  Since the Npcap license does not permit redistribution        *
71  * without special permission, our Nmap Windows binary packages which      *
72  * contain Npcap may not be redistributed without special permission.      *
73  *                                                                         *
74  * Any redistribution of Covered Software, including any derived works,    *
75  * must obey and carry forward all of the terms of this license, including *
76  * obeying all GPL rules and restrictions.  For example, source code of    *
77  * the whole work must be provided and free redistribution must be         *
78  * allowed.  All GPL references to "this License", are to be treated as    *
79  * including the terms and conditions of this license text as well.        *
80  *                                                                         *
81  * Because this license imposes special exceptions to the GPL, Covered     *
82  * Work may not be combined (even as part of a larger work) with plain GPL *
83  * software.  The terms, conditions, and exceptions of this license must   *
84  * be included as well.  This license is incompatible with some other open *
85  * source licenses as well.  In some cases we can relicense portions of    *
86  * Nmap or grant special permissions to use it in other open source        *
87  * software.  Please contact fyodor@nmap.org with any such requests.       *
88  * Similarly, we don't incorporate incompatible open source software into  *
89  * Covered Software without special permission from the copyright holders. *
90  *                                                                         *
91  * If you have any questions about the licensing restrictions on using     *
92  * Nmap in other works, we are happy to help.  As mentioned above, we also *
93  * offer an alternative license to integrate Nmap into proprietary         *
94  * applications and appliances.  These contracts have been sold to dozens  *
95  * of software vendors, and generally include a perpetual license as well  *
96  * as providing support and updates.  They also fund the continued         *
97  * development of Nmap.  Please email sales@nmap.com for further           *
98  * information.                                                            *
99  *                                                                         *
100  * If you have received a written license agreement or contract for        *
101  * Covered Software stating terms other than these, you may choose to use  *
102  * and redistribute Covered Software under those terms instead of these.   *
103  *                                                                         *
104  * Source is provided to this software because we believe users have a     *
105  * right to know exactly what a program is going to do before they run it. *
106  * This also allows you to audit the software for security holes.          *
107  *                                                                         *
108  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
109  * and add new features.  You are highly encouraged to send your changes   *
110  * to the dev@nmap.org mailing list for possible incorporation into the    *
111  * main distribution.  By sending these changes to Fyodor or one of the    *
112  * Insecure.Org development mailing lists, or checking them into the Nmap  *
113  * source code repository, it is understood (unless you specify            *
114  * otherwise) that you are offering the Nmap Project the unlimited,        *
115  * non-exclusive right to reuse, modify, and relicense the code.  Nmap     *
116  * will always be available Open Source, but this is important because     *
117  * the inability to relicense code has caused devastating problems for     *
118  * other Free Software projects (such as KDE and NASM).  We also           *
119  * occasionally relicense the code to third parties as discussed above.    *
120  * If you wish to specify special license conditions of your               *
121  * contributions, just say so when you send them.                          *
122  *                                                                         *
123  * This program is distributed in the hope that it will be useful, but     *
124  * WITHOUT ANY WARRANTY; without even the implied warranty of              *
125  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Nmap      *
126  * license file for more details (it's in a COPYING file included with     *
127  * Nmap, and also available from https://svn.nmap.org/nmap/COPYING)        *
128  *                                                                         *
129  ***************************************************************************/
130 
131 
132 #include "ncrack.h"
133 #include "nsock.h"
134 #include "NcrackOps.h"
135 #include "Service.h"
136 #include "modules.h"
137 #include <list>
138 #include <crypto.h>
139 
140 #define TIMEOUT 20000
141 #define MAXPWLEN 8
142 #define CHALLENGESIZE 16
143 
144 #define MAXMSPWLEN 32
145 #define CHALLENGESIZEMS 64
146 
147 #define BYTES_TO_READ 1024
148 
149 extern NcrackOps o;
150 
151 extern void ncrack_read_handler(nsock_pool nsp, nsock_event nse, void *mydata);
152 extern void ncrack_write_handler(nsock_pool nsp, nsock_event nse, void *mydata);
153 extern void ncrack_connect_handler(nsock_pool nsp, nsock_event nse,
154     void *mydata);
155 extern void ncrack_module_end(nsock_pool nsp, void *mydata);
156 
157 enum states { VNC_INIT, VNC_HANDSHAKE, VNC_SECURITY_TYPE, VNC_AUTH, VNC_SECURITY_RESULT };
158 
159 /*
160  * Encrypt CHALLENGESIZE bytes in memory using a password.
161  */
162 static void
vncEncryptBytes(unsigned char * bytes,char * passwd)163 vncEncryptBytes(unsigned char *bytes, char *passwd)
164 {
165     unsigned char key[8];
166     size_t i;
167 
168     /* key is simply password padded with nulls */
169 
170     for (i = 0; i < 8; i++) {
171         if (i < strlen(passwd)) {
172             key[i] = passwd[i];
173         } else {
174             key[i] = 0;
175         }
176     }
177 
178     deskey(key, EN0);
179 
180     for (i = 0; i < CHALLENGESIZE; i += 8) {
181         des(bytes+i, bytes+i);
182     }
183 }
184 
185 
186 static int
buf_check(int n,char * p)187 buf_check(int n, char* p) {
188   int i;
189   for(i=0; i<n; i++)
190     if(p[i] != 0 )
191       return p[i];
192   return 0;
193 }
194 
195 static uint8_t*
str2uint8(char * p,int str_length,int uint_length)196 str2uint8(char* p, int str_length, int uint_length)
197 {
198   uint8_t* retme;
199   retme = new uint8_t[str_length];
200 
201   for(int i=0; i < str_length; i++)
202     retme[i] = (uint8_t)p[i];
203 
204   if(uint_length>str_length)
205     for(int i=str_length; i < uint_length; i++)
206       retme[i] = (uint8_t)0;
207 
208   return retme;
209 }
210 
211 void
ncrack_vnc(nsock_pool nsp,Connection * con)212 ncrack_vnc(nsock_pool nsp, Connection *con)
213 {
214   nsock_iod nsi = con->niod;
215   Service *serv = con->service;
216   char version_test[] = {2,0};
217 
218   switch (con->state)
219   {
220     case VNC_INIT:
221       con->state = VNC_HANDSHAKE;
222 
223       break;
224 
225     case VNC_HANDSHAKE:
226 
227       /* Wait till we receive the server's input */
228       if(con->inbuf == NULL)
229         break;
230 
231       //buf_print(con->inbuf->get_len(), (char*)con->inbuf->get_dataptr());
232 
233       /* We may have hit our limit, so we need to check */
234       if (memsearch((const char *)con->inbuf->get_dataptr(), "Too many authentication failures", con->inbuf->get_len())||
235           memsearch((const char *)con->inbuf->get_dataptr(), "Too many security failures", con->inbuf->get_len())) {
236         if (o.debugging > 5)
237           error("%s Too many authentication failures (a)", serv->HostInfo());
238 
239         con->close_reason = MODULE_ERR;
240         con->force_close = true;
241         return ncrack_module_end(nsp, con);
242       }
243 
244       /* vnc begins with the server sending a version like "RFB 003.008\n" or "RFB 003.003\n"
245        * determine which one to use, and then continue
246        */
247       if (memsearch((const char *)con->inbuf->get_dataptr(), "RFB 003.008", con->inbuf->get_len())) {
248         con->outbuf = new Buf();
249         con->outbuf->snprintf(12 , "RFB 003.008\n");
250         nsock_write(nsp, nsi, ncrack_write_handler, TIMEOUT, con, (const char *)con->outbuf->get_dataptr(), con->outbuf->get_len());
251         con->state = VNC_SECURITY_TYPE;
252       }
253       else {
254         con->outbuf = new Buf();
255         con->outbuf->snprintf(12 , "RFB 003.003\n");
256         nsock_write(nsp, nsi, ncrack_write_handler, TIMEOUT, con, (const char *)con->outbuf->get_dataptr(), con->outbuf->get_len());
257         con->state = VNC_AUTH;
258       }
259       /* We are now waiting for a SECURITY_TYPE response back, which could be several bytes */
260 
261       break;
262 
263     case VNC_SECURITY_TYPE:
264       if(con->inbuf == NULL)
265         break;
266 
267       if (memsearch((const char *)con->inbuf->get_dataptr(), "Too many authentication failures", con->inbuf->get_len())||
268           memsearch((const char *)con->inbuf->get_dataptr(), "Too many security failures", con->inbuf->get_len())) {
269         if (o.debugging > 5)
270           error("%s Too many authentication failures (b)", serv->HostInfo());
271 
272         con->close_reason = MODULE_ERR;
273         con->force_close = true;
274         return ncrack_module_end(nsp, con);
275       }
276 
277       /* At this point in the game, we should have gotten the number of security protocols,
278        * and a list of those protocols (like 0x02, 0x0210)
279        * handling VNC Authentication, which is 0x02, so let's ship that back and be on our way.
280        */
281       if (memsearch((const char *)con->inbuf->get_dataptr(), version_test, con->inbuf->get_len())) {
282         uint8_t sec_version; sec_version = 0x02;
283         con->outbuf = new Buf();
284         con->outbuf->append(&sec_version, sizeof(uint8_t));
285         nsock_write(nsp, nsi, ncrack_write_handler, TIMEOUT, con, (const char *)con->outbuf->get_dataptr(), con->outbuf->get_len());
286         con->state = VNC_AUTH;
287       }
288       /*
289       else {
290         error("%s This VNC server doesn't support VNC Auth.\n", serv->HostInfo());
291         con->service->end.orly = true;
292         //con->service->end.reason = Strndup("This VNC server doesn't support VNC Auth.", 23);
293 
294         con->close_reason = MODULE_ERR;
295         con->force_close = true;
296         return ncrack_module_end(nsp, con);
297       }
298       */
299 
300       /* Now we're waiting to hear back from the server whether we are good to go or not.  0 is go, 1 is fail */
301 
302       break;
303 
304     case VNC_AUTH:
305       /* At this point, we should have gotten a 16-unsigned byte challenege */
306 
307       if(con->inbuf == NULL)
308         break;
309 
310       /* des_data will hold the challenge before vncEncryptBytes() and the response after */
311       uint8_t* des_data;
312 
313       /* if length is 20, we are in protocol version 003.003, which means we've gotten
314        *    back a 4-byte security version number, as well as the challenge.
315        */
316       if(con->inbuf->get_len() == 20) {
317         des_data = str2uint8((char*)con->inbuf->get_dataptr()+4, 16, 16);
318         vncEncryptBytes(des_data, con->pass);
319       }
320       /* if it's exactly 16, we're in 003.007 or 003.008, so we can encrypt the challenge
321        *   and continue
322        */
323       else if(con->inbuf->get_len() == 16) {
324         /* des_data will hold the challenge before vncEncryptBytes() and the response after */
325         des_data = str2uint8((char*)con->inbuf->get_dataptr(), 16, 16);
326         vncEncryptBytes(des_data, con->pass);
327       }
328       /* If we have a 4 byte response, we've received only the version, but not the request yet.  So
329        *   just break, and get the response next go round.
330        */
331       else if(con->inbuf->get_len() == 4) {
332         if (memsearch((const char *)con->inbuf->get_dataptr(), version_test, con->inbuf->get_len()))
333           break;
334         else {
335           if (o.debugging > 5)
336             error("%s The server claims not to support VNC Auth. (Can be an auth limit problem)\n", serv->HostInfo());
337           return ncrack_module_end(nsp, con);
338         }
339       }
340       /* if we don't get 20, 16 or 4, then I'm confused as to what has happened.  I suppose
341        *  we should probably terminate this connection.  Hasn't really come up in my tests.
342        */
343       else {
344         if (o.debugging)
345           error("%s Challenge not the right length (%d, when 16 expected)!\n", serv->HostInfo(), con->inbuf->get_len());
346         return ncrack_module_end(nsp, con);
347       }
348 
349       /* Ship our encrypted challenge back to the server, and await a result */
350       con->outbuf = new Buf();
351       con->outbuf->append(des_data, 16*sizeof(uint8_t));
352       nsock_write(nsp, nsi, ncrack_write_handler, TIMEOUT, con, (const char *)con->outbuf->get_dataptr(), con->outbuf->get_len());
353 
354       con->state = VNC_SECURITY_RESULT;
355 
356       break;
357 
358     case VNC_SECURITY_RESULT:
359 
360       if(con->inbuf == NULL)
361         break;
362 
363       /* okay, at this point, we expect to have at least 4 bytes in response.  If more, then we have a failure message
364        *  However, we'll still check to make sure all bytes are 0 (the OK message) before we set auth_success to true
365        */
366       if(con->inbuf->get_len() >= 4 && buf_check(con->inbuf->get_len(), (char*)con->inbuf->get_dataptr()) == 0)
367         con->auth_success = true;
368 
369       return ncrack_module_end(nsp, con);
370 
371       con->state = VNC_INIT;
372 
373       break;
374 
375   }
376   /* Clean up when we are done with our buffers. */
377   if(con->inbuf)
378     delete con->inbuf;
379   con->inbuf = NULL;
380   if(con->outbuf)
381     delete con->outbuf;
382   con->outbuf = NULL;
383 
384   /* Read the next thrilling chapter from the server */
385   nsock_read(nsp, nsi, ncrack_read_handler, BYTES_TO_READ, con);
386 }
387