Codebase list dnscat2 / 9b31863 client / libs / dns.h
9b31863

Tree @9b31863 (Download .tar.gz)

dns.h @9b31863raw · history · blame

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
/* dns.c
 * By Ron Bowes
 * Created December, 2009
 *
 * (See LICENSE.md)
 *
 * This module implements a reasonably functional DNS library that can build or
 * parse DNS packets in a platform-agnostic way. It implements a number of
 * record types (A, NS, CNAME, MX, TXT, and AAAA), and can add and parse
 * questions or answers.
 *
 * On Windows, due to IPv6 parsing being unavailable on older systems, I
 * disable AAAA records entirely.
 *
 * In the future I may opt to add more record types and stronger parsing, but
 * for now this was enough.
 */

#ifndef __DNS_H__
#define __DNS_H__

#include "types.h"

/* Define a list of dns types. The initial '_' in all the names here is because Windows
 * defines some of these, and differently than how we want them on occasion. */
typedef enum
{
  /* RFC 1034/1035 */
  _DNS_TYPE_A          = 0x0001,
  _DNS_TYPE_NS         = 0x0002,
  _DNS_TYPE_MD         = 0x0003,
  _DNS_TYPE_MF         = 0x0004,
  _DNS_TYPE_CNAME      = 0x0005,
  _DNS_TYPE_SOA        = 0x0006,
  _DNS_TYPE_MB         = 0x0007,
  _DNS_TYPE_MG         = 0x0008,
  _DNS_TYPE_MR         = 0x0009,
  _DNS_TYPE_NULL       = 0x000a,
  _DNS_TYPE_WKS        = 0x000b,
  _DNS_TYPE_PTR        = 0x000c,
  _DNS_TYPE_HINFO      = 0x000d,
  _DNS_TYPE_MINFO      = 0x000e,
  _DNS_TYPE_MX         = 0x000f,
  _DNS_TYPE_TEXT       = 0x0010,

  /*  RFC 1183 */
  _DNS_TYPE_RP         = 0x0011,
  _DNS_TYPE_AFSDB      = 0x0012,
  _DNS_TYPE_X25        = 0x0013,
  _DNS_TYPE_ISDN       = 0x0014,
  _DNS_TYPE_RT         = 0x0015,

  /*  RFC 1348 */
  _DNS_TYPE_NSAP       = 0x0016,
  _DNS_TYPE_NSAPPTR    = 0x0017,

  /*  RFC 2065 (DNS security) */
  _DNS_TYPE_SIG        = 0x0018,
  _DNS_TYPE_KEY        = 0x0019,

  /*  RFC 1664 (X.400 mail) */
  _DNS_TYPE_PX         = 0x001a,

  /*  RFC 1712 (Geographic position) */
  _DNS_TYPE_GPOS       = 0x001b,

  /*  RFC 1886 (IPv6 Address) */
  _DNS_TYPE_AAAA       = 0x001c,

  /*  RFC 1876 (Geographic location) */
  _DNS_TYPE_LOC        = 0x001d,

  /*  RFC 2065 (Secure negative response) */
  _DNS_TYPE_NXT        = 0x001e,

  /*  Patton (Endpoint Identifier) */
  _DNS_TYPE_EID        = 0x001f,

  /*  Patton (Nimrod Locator) */
/*  _DNS_TYPE_NIMLOC     = 0x0020,*/
  /*  RFC 2052 (Service location) */
/*  _DNS_TYPE_SRV        = 0x0021,*/

  /* NetBIOS. */
  _DNS_TYPE_NB         = 0x0020,

  /* Adapter status. */
  _DNS_TYPE_NBSTAT     = 0x0021,

  /*  ATM Address */
  _DNS_TYPE_ATMA       = 0x0022,

  /*  RFC 2168 (Naming Authority Pointer) */
  _DNS_TYPE_NAPTR      = 0x0023,

  /*  RFC 2230 (Key Exchanger) */
  _DNS_TYPE_KX         = 0x0024,

  /*  RFC 2538 (CERT) */
  _DNS_TYPE_CERT       = 0x0025,

  /*  A6 Draft (A6) */
  _DNS_TYPE_A6         = 0x0026,

  /*  DNAME Draft (DNAME) */
  _DNS_TYPE_DNAME      = 0x0027,

  /*  Eastlake (Kitchen Sink) */
  _DNS_TYPE_SINK       = 0x0028,

  /*  RFC 2671 (EDNS OPT) */
  _DNS_TYPE_OPT        = 0x0029,

  /*  IANA Reserved */

  _DNS_TYPE_UINFO      = 0x0064,
  _DNS_TYPE_UID        = 0x0065,
  _DNS_TYPE_GID        = 0x0066,
  _DNS_TYPE_UNSPEC     = 0x0067,

  /*  Query only types (1035, 1995) */
  _DNS_TYPE_ADDRS      = 0x00f8,
  _DNS_TYPE_TKEY       = 0x00f9,
  _DNS_TYPE_TSIG       = 0x00fa,
  _DNS_TYPE_IXFR       = 0x00fb,
  _DNS_TYPE_AXFR       = 0x00fc,
  _DNS_TYPE_MAILB      = 0x00fd,
  _DNS_TYPE_MAILA      = 0x00fe,
  _DNS_TYPE_ALL        = 0x00ff,
  _DNS_TYPE_ANY        = 0x00ff,
} dns_type_t;

typedef enum
{
  _DNS_CLASS_IN = 1, /* The Internet */
  _DNS_CLASS_CS = 2, /* The CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
  _DNS_CLASS_CH = 3, /* The CHAOS class */
  _DNS_CLASS_HS = 4, /* Hesiod [Dyer 87] */
} dns_class_t;

/* Here are how the opcodes, flags, and rcodes are laid out:
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |                               1  1  1  1  1  1|
 * | 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5|
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 * |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 */
typedef enum
{
  _DNS_OPCODE_QUERY  = 0x0000,
  _DNS_OPCODE_IQUERY = 0x0800,
  _DNS_OPCODE_STATUS = 0x1000,
} dns_opcode_t;

typedef enum
{
  _DNS_FLAG_QR = 0x8000, /* Query response */
  _DNS_FLAG_AA = 0x0400, /* Authoritative answer */
  _DNS_FLAG_TC = 0x0200, /* Truncation */
  _DNS_FLAG_RD = 0x0100, /* Recursion desired */
  _DNS_FLAG_RA = 0x0080, /* Recursion available */
} dns_flag_t;

typedef enum
{
  _DNS_RCODE_SUCCESS         = 0x0000,
  _DNS_RCODE_FORMAT_ERROR    = 0x0001,
  _DNS_RCODE_SERVER_FAILURE  = 0x0002,
  _DNS_RCODE_NAME_ERROR      = 0x0003,
  _DNS_RCODE_NOT_IMPLEMENTED = 0x0004,
  _DNS_RCODE_REFUSED         = 0x0005,
} dns_rcode_t;


/* A DNS question. Questions are simple, they just have a name, type, and class. */
typedef struct
{
  char *name;
  dns_type_t  type;
  dns_class_t class;
} question_t;

/* An answer for an A packet. */
typedef struct
{
  char *address;
  uint8_t bytes[4];
} A_answer_t;

/* Only define AAAA on Linux. */
#ifndef WIN32
typedef struct
{
  char *address;
  uint8_t bytes[16];
} AAAA_answer_t;
#endif

/* Nameserver and CNAME (alias) records simply have a name. */
typedef struct
{
  char *name;
} NS_answer_t, CNAME_answer_t;

/* Mail server requests (MX) have a name and a preference number. */
typedef struct
{
  uint16_t preference;
  char *name;
} MX_answer_t;

/* A text record (TXT) has the text data and a length. Unlike MX, NS, and CNAME, text
 * records aren't encoded as a dns name. */
typedef struct
{
  uint8_t *text;
  uint8_t  length;
} TEXT_answer_t;

/* A NetBIOS answer (NB) is used by Windows on port 137. */
typedef struct
{
  uint16_t  flags;
  char     *address;
} NB_answer_t;

/* One element returned by a NBSTAT query (NBSTAT answers typically contain multiple names). */
typedef struct
{
  char    *name;
  uint8_t  name_type;
  uint16_t name_flags;
} NBSTAT_name_t;

/* A NetBIOS Status answer (NBSTAT or NBTSTAT) is used by Windows to get more information over 137. */
typedef struct
{
  uint8_t        name_count;
  NBSTAT_name_t *names;
  uint8_t        stats[64];
} NBSTAT_answer_t;

/* Let us refer to any kind of answer type together. */
typedef union
{
  A_answer_t      A;
  NS_answer_t     NS;
  CNAME_answer_t  CNAME;
  MX_answer_t     MX;
  TEXT_answer_t   TEXT;
#ifndef WIN32
  AAAA_answer_t   AAAA;
#endif
  NB_answer_t     NB;
  NBSTAT_answer_t NBSTAT;
} answer_types_t;

/* And finally, define a DNS answer. */
typedef struct
{
  char           *question;
  dns_type_t      type;
  dns_class_t     class;
  uint32_t        ttl;
  answer_types_t *answer;
} answer_t;

/* We don't implement authority records. */
typedef struct
{
  /* TODO */
  int dummy;
} authority_t;

/* An additional for an A packet. */
typedef struct
{
  char *address;
} A_additional_t;

/* Only define AAAA on Linux. */
#ifndef WIN32
typedef A_additional_t AAAA_additional_t;
#endif

/* Nameserver and CNAME (alias) records simply have a name. */
typedef struct
{
  char *name;
} NS_additional_t, CNAME_additional_t;

/* Mail server requests (MX) have a name and a preference number. */
typedef struct
{
  uint16_t preference;
  char *name;
} MX_additional_t;

/* A text record (TXT) has the text data and a length. Unlike MX, NS, and CNAME, text
 * records aren't encoded as a dns name. */
typedef struct
{
  uint8_t *text;
  uint8_t  length;
} TEXT_additional_t;

/* A NetBIOS additional (NB) is used by Windows on port 137. */
typedef struct
{
  uint16_t  flags;
  char     *address;
} NB_additional_t;

/* A NetBIOS Status additional (NBSTAT or NBTSTAT) is used by Windows to get more information over 137. */
typedef struct
{
  uint8_t        name_count;
  NBSTAT_name_t *names;
  uint8_t        stats[64];
} NBSTAT_additional_t;

/* Let us refer to any kind of additional type together. */
typedef union
{
  A_additional_t      A;
  NS_additional_t     NS;
  CNAME_additional_t  CNAME;
  MX_additional_t     MX;
  TEXT_additional_t   TEXT;
#ifndef WIN32
  AAAA_additional_t   AAAA;
#endif
  NB_additional_t     NB;
  NBSTAT_additional_t NBSTAT;
} additional_types_t;

/* And finally, define a DNS additional. */
typedef struct
{
  char           *question;
  dns_type_t      type;
  dns_class_t     class;
  uint32_t        ttl;
  additional_types_t *additional;
} additional_t;

/* Define an entire DNS packet. */
typedef struct
{
  uint16_t     trn_id;
  dns_opcode_t opcode;
  dns_flag_t   flags;
  dns_rcode_t  rcode;

  uint16_t question_count;
  uint16_t answer_count;
  uint16_t authority_count;
  uint16_t additional_count;

  question_t   *questions;
  answer_t     *answers;
  authority_t  *authorities;
  additional_t *additionals;
} dns_t;

/* Allocate memory for a blank dns structure. Should be freed with dns_free(). */
dns_t   *dns_create(dns_opcode_t opcode, dns_flag_t flags, dns_rcode_t rcode);

/* Take a DNS packet as a stream of bytes, and create a dns_t structure from it.
 * Should also be cleaned up with dns_destroy(). */
dns_t   *dns_create_from_packet(uint8_t *packet, size_t length);

/* De-allocate memory and resources from a dns object. */
void     dns_destroy(dns_t *dns);

/* Add a question to the DNS packet. A DNS packet can have any number of questions, but
 * I normally limit it to one at a time. */
void     dns_add_question(dns_t *dns, char *name, dns_type_t type, dns_class_t class);

/* Add a NetBIOS question to the DNS packet. This is similar to a normal question but
 * with a couple extra fields and an encoded name. */
void     dns_add_netbios_question(dns_t *dns, char *name, uint8_t name_type, char *scope, dns_type_t type, dns_class_t class);

/* These functions add answers of the various types. */
void     dns_add_answer_A(dns_t *dns,     char *question, dns_class_t class, uint32_t ttl, char *address);
void     dns_add_answer_NS(dns_t *dns,    char *question, dns_class_t class, uint32_t ttl, char *name);
void     dns_add_answer_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
void     dns_add_answer_MX(dns_t *dns,    char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name);
void     dns_add_answer_TEXT(dns_t *dns,  char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length);
#ifndef WIN32
void     dns_add_answer_AAAA(dns_t *dns,  char *question, dns_class_t class, uint32_t ttl, char *address);
#endif
void     dns_add_answer_NB(dns_t *dns,  char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address);

/* These functions add additionals of the various types. */
void     dns_add_additional_A(dns_t *dns,     char *question, dns_class_t class, uint32_t ttl, char *address);
void     dns_add_additional_NS(dns_t *dns,    char *question, dns_class_t class, uint32_t ttl, char *name);
void     dns_add_additional_CNAME(dns_t *dns, char *question, dns_class_t class, uint32_t ttl, char *name);
void     dns_add_additional_MX(dns_t *dns,    char *question, dns_class_t class, uint32_t ttl, uint16_t preference, char *name);
void     dns_add_additional_TEXT(dns_t *dns,  char *question, dns_class_t class, uint32_t ttl, uint8_t *text, uint8_t length);
#ifndef WIN32
void     dns_add_additional_AAAA(dns_t *dns,  char *question, dns_class_t class, uint32_t ttl, char *address);
#endif
void     dns_add_additional_NB(dns_t *dns,  char *question, uint8_t question_type, char *scope, dns_class_t class, uint32_t ttl, uint16_t flags, char *address);

/* Convert a DNS request into a packet that can be sent on port 53. Memory has to be freed. */
uint8_t *dns_to_packet(dns_t *dns, size_t *length);

/* Print the DNS request. Useful for debugging. */
void     dns_print(dns_t *dns);

/* Create a DNS error object. */
dns_t   *dns_create_error(uint16_t trn_id, question_t question);
/* Create a DNS error packet, ready to send. */
uint8_t *dns_create_error_string(uint16_t trn_id, question_t question, size_t *length);

/* Get the first system DNS server. Works on Windows and any system that uses /etc/resolv.conf. */
char *dns_get_system();

/* Runs dnstest and exits. Useful for --test parameters on any of the dns* programs. */
void dns_do_test(char *domain);

int      dns_is_error(dns_t *dns);

#endif