Codebase list dnscat2 / fresh-snapshots/upstream
Import upstream version 0.07+git20200409.8664c0e Kali Janitor 3 years ago
18 changed file(s) with 217 addition(s) and 83 deletion(s). Raw diff Collapse all Expand all
1515 endif
1616
1717 all:
18 @cd client && make
18 @cd client && $(MAKE)
1919 @echo "Compile complete!"
2020 @echo "* Client: client/dnscat"
2121 @echo "* Server: server/dnscat_*.rb"
2222
2323 clean:
24 @cd client && make clean
24 @cd client && $(MAKE) clean
2525
2626 debug:
27 @cd client && make debug
27 @cd client && $(MAKE) debug
2828 @echo "Debug compile complete!"
2929
3030 release:
31 @make clean
31 @$(MAKE) clean
3232 -mkdir dist/
3333 @cd client && make release
3434 @mv client/dnscat .
3939 @echo "Release compile complete!"
4040
4141 source_release:
42 @make clean
42 @$(MAKE) clean
4343 -mkdir dist/
4444 @cp -r client dnscat2_client
4545 @tar -cvvjf dist/dnscat2-${VERSION}-client-source.tar.bz2 dnscat2_client
5151 @rm -rf dnscat2_server
5252
5353 dnscat:
54 @cd client && make dnscat
54 @cd client && $(MAKE) dnscat
5555
0 ***** NOTE: The password for the .zip downloads are all "password"! *****
1
02 # Introduction
13
24 Welcome to dnscat2, a DNS tunnel that WON'T make you sick and kill you!
88 CC?=gcc
99 DEBUG_CFLAGS?=-DTESTMEMORY -Werror -O0
1010 RELEASE_CFLAGS?=-Os
11 CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE -fstack-protector-all -Wformat -Wformat-security -g
12 LIBS=-pie -Wl,-z,relro,-z,now
11 CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE -Wformat -Wformat-security -g
12 LIBS=-pie -Wl,-z,relro,-z,now
13 LDFLAGS=
14
15 OS=$(shell uname -s)
16 ifeq ($(OS),SunOS)
17 # Solaris CC
18 LDFLAGS = -lsocket -lnsl
19 endif
1320
1421 OBJS=controller/packet.o \
1522 controller/session.o \
6572 -rm -rf win32/*.vcproj.*
6673
6774 dnscat: ${DNSCAT_DNS_OBJS}
68 ${CC} ${CFLAGS} -o dnscat ${DNSCAT_DNS_OBJS}
75 ${CC} ${CFLAGS} -o dnscat ${DNSCAT_DNS_OBJS} ${LDFLAGS}
6976 @echo "*** dnscat successfully compiled"
7077
7178 COMMANDS=drivers/command/commands_standard.h \
0 # Makefile
1 # By Ron Bowes
2 # Created January, 2013
3 #
4 # (See LICENSE.md)
5 #
6 # Should work for Linux and BSD make.
7
8 CC=i686-w64-mingw32-gcc
9 DEBUG_CFLAGS?=-DTESTMEMORY -Werror -O0
10 RELEASE_CFLAGS?=-Os
11 # CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE -Wformat -Wformat-security -g -DWIN32=1 -DWINDOWS=1
12 CFLAGS?=-I. -g
13 LIBS=-pie -Wl,-z,relro,-z,now
14 LDFLAGS= -lws2_32 -ldnsapi
15
16 OS=$(shell uname -s)
17 ifeq ($(OS),SunOS)
18 # Solaris CC
19 LDFLAGS = -lsocket -lnsl
20 endif
21
22 OBJS=controller/packet.o \
23 controller/session.o \
24 controller/controller.o \
25 drivers/driver.o \
26 drivers/command/driver_command.o \
27 drivers/command/command_packet.o \
28 drivers/driver_console.o \
29 drivers/driver_exec.o \
30 drivers/driver_ping.o \
31 libs/buffer.o \
32 libs/crypto/encryptor.o \
33 libs/crypto/micro-ecc/uECC.o \
34 libs/crypto/salsa20.o \
35 libs/crypto/sha3.o \
36 libs/dns.o \
37 libs/ll.o \
38 libs/log.o \
39 libs/memory.o \
40 libs/select_group.o \
41 libs/tcp.o \
42 libs/types.o \
43 libs/udp.o \
44 tunnel_drivers/driver_dns.o \
45
46 DNSCAT_DNS_OBJS=${OBJS} dnscat.o
47
48 all: dnscat.exe
49 @echo "*** Build complete! Run 'make debug' to build a debug version!"
50
51 debug: CFLAGS += $(DEBUG_CFLAGS)
52 debug: dnscat
53 @echo "*** Debug build complete"
54
55 release: CFLAGS += ${RELEASE_CFLAGS}
56 release: dnscat
57
58 nocrypto: CFLAGS += -DNO_ENCRYPTION
59 nocrypto: all
60
61 remove:
62 rm -f /usr/local/bin/dnscat
63
64 uninstall: remove
65
66 clean:
67 -rm -f *.o */*.o */*/*.o */*/*/*.o *.exe *.stackdump dnscat tcpcat test driver_tcp driver_dns
68 -rm -rf win32/Debug/
69 -rm -rf win32/Release/
70 -rm -rf win32/*.ncb
71 -rm -rf win32/*.sln
72 -rm -rf win32/*.suo
73 -rm -rf win32/*.vcproj.*
74
75 dnscat.exe: ${DNSCAT_DNS_OBJS}
76 ${CC} ${CFLAGS} -o dnscat.exe ${DNSCAT_DNS_OBJS} ${LDFLAGS}
77 @echo "*** dnscat successfully compiled"
78
79 COMMANDS=drivers/command/commands_standard.h \
80 drivers/command/commands_tunnel.h
81
82 drivers/command/driver_command.o: drivers/command/driver_command.c ${COMMANDS}
83 ${CC} -c ${CFLAGS} -o drivers/command/driver_command.o drivers/command/driver_command.c
1616 #else
1717 #include <getopt.h>
1818 #include <sys/socket.h>
19 #include <sys/wait.h>
20 #include <signal.h>
1921 #endif
2022
2123 #include "controller/controller.h"
416418 /* This is required for win32 support. */
417419 winsock_initialize();
418420
421 #ifndef WIN32
422 /* set the SIGCHLD handler to SIG_IGN causing zombie child processes to be reaped automatically */
423 if(signal(SIGCHLD, SIG_IGN) == SIG_ERR)
424 {
425 perror("Couldn't set SIGCHLD handler to SIG_IGN");
426 exit(1);
427 }
428 #endif
429
419430 /* Set the default log level */
420431 log_set_min_console_level(min_log_level);
421432
543554 usage(argv[0], "Unrecognized argument");
544555 break;
545556 }
557 }
558
559 if(getenv("DNSCAT_DOMAIN")!=NULL) {
560 if(getenv("DNSCAT_SECRET")!=NULL) {
561 session_set_preshared_secret(getenv("DNSCAT_SECRET"));
562 }
563 tunnel_driver = create_dns_driver_internal(group, getenv("DNSCAT_DOMAIN"), "0.0.0.0", 53, DEFAULT_TYPES, NULL);
564 tunnel_driver_created = TRUE;
546565 }
547566
548567 create_drivers(drivers_to_create);
133133 #elif defined(__APPLE__)
134134 # include <libkern/OSByteOrder.h>
135135 # define bswap_64 OSSwapInt64
136 #elif defined(__sun)
137 # include <sys/byteorder.h>
138 # define bswap_64 BSWAP64
136139 #else
137140 # error "bswap_64 unsupported"
138141 #endif
7272 {
7373 if(piece_length & 0x80)
7474 {
75 if(piece_length == 0xc0)
75 if(piece_length & 0xc0)
7676 {
7777 uint8_t relative_pos = buffer_read_int8_at(buffer, offset + pos);
7878 char *new_data;
79
80 relative_pos |= ((piece_length & 0x03) << 8);
7981 pos++;
8082
8183 new_data = buffer_read_dns_name_at(buffer, relative_pos, NULL);
135137 static char *buffer_read_ipv4_address_at(buffer_t *buffer, uint32_t offset, char result[16])
136138 {
137139 #ifdef WIN32
138 printf("NOT IMPLEMENTED!\n");
140 printf("NOT IMPLEMENTED IPv4!\n");
139141 exit(1);
140142 #else
141143 uint8_t addr[4];
179181 static char *buffer_read_ipv6_address_at(buffer_t *buffer, uint32_t offset, char result[40])
180182 {
181183 #ifdef WIN32
182 printf("NOT IMPLEMENTED!\n");
184 printf("NOT IMPLEMENTED IPv6!\n");
183185 exit(1);
184186 #else
185187 uint8_t addr[16];
189189 * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
190190 */
191191
192 #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
192 #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || defined(__MINGW32__) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
193193 #include <stdint.h>
194194 #define _PSTDINT_H_INCLUDED
195195 # ifndef PRINTF_INT64_MODIFIER
2222
2323 # License
2424
25 See LICENSE.md.
25 See [LICENSE.md](../LICENSE.md).
2626
2727 # Challenges
2828
195195 TunnelDrivers.start({
196196 :controller => self,
197197 :driver => DriverDNS,
198 :args => [dns[:host], dns[:port], dns[:domains]]
198 :args => [dns[:host], dns[:port], dns[:domains], opts[:cache]]
199199 })
200200 end
201201 )
99
1010 class CryptoHelper
1111 def CryptoHelper.bignum_to_binary(bn, size=32)
12 if(!bn.is_a?(Bignum))
13 raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
12 if(!bn.is_a?(Integer))
13 raise(ArgumentError, "Expected: Integer; received: #{bn.class}")
1414 end
1515
1616 return [bn.to_s(16).rjust(size*2, "\0")].pack("H*")
1717 end
1818
1919 def CryptoHelper.bignum_to_text(bn, size=32)
20 if(!bn.is_a?(Bignum))
21 raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
20 if(!bn.is_a?(Integer))
21 raise(ArgumentError, "Expected: Integer; received: #{bn.class}")
2222 end
2323
2424 return CryptoHelper.bignum_to_binary(bn, size).unpack("H*").pop()
224224 @public_key_x = params[:public_key_x] || raise(DnscatException, "params[:public_key_x] is required!")
225225 @public_key_y = params[:public_key_y] || raise(DnscatException, "params[:public_key_y] is required!")
226226
227 if(!@public_key_x.is_a?(Bignum) || !@public_key_y.is_a?(Bignum))
228 raise(DnscatException, "Public keys have to be Bignums! (Seen: #{@public_key_x.class} #{@public_key_y.class})")
227 if(!@public_key_x.is_a?(Integer) || !@public_key_y.is_a?(Integer))
228 raise(DnscatException, "Public keys have to be Integers! (Seen: #{@public_key_x.class} #{@public_key_y.class})")
229229 end
230230 elsif(@subtype == SUBTYPE_AUTH)
231231 @authenticator = params[:authenticator] || raise(DnscatException, "params[:authenticator] is required!")
148148 options = 0
149149
150150 # Ignore errant SYNs - they are, at worst, retransmissions that we don't care about
151 if(@state != STATE_NEW)
152 raise(DnscatException, "Duplicate SYN received!")
153 end
151 #if(@state != STATE_NEW)
152 # raise(DnscatException, "Duplicate SYN received!")
153 #end
154154
155155 _do_display_crypto_values()
156156
99 ##
1010
1111 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
12
12 trap "SIGINT" do
13 puts "Ctrl-C is disabled, use exit"
14 end
1315 # Create the window right away so other includes can create their own windows if they want
1416 require 'libs/swindow'
1517 WINDOW = SWindow.new(nil, true, { :prompt => "dnscat2> ", :name => "main" })
8789
8890 opt :firehose, "If set, all output goes to stdout instead of being put in windows.",
8991 :type => :boolean, :default => false
92
93 opt :cache, "If set, caching is enabled on the server.",
94 :type => :boolean, :default => true
9095 end
9196
9297 SWindow.set_firehose(opts[:firehose])
204209 TunnelDrivers.start({
205210 :controller => controller,
206211 :driver => DriverDNS,
207 :args => [dns_settings[:host], dns_settings[:port], dns_settings[:domains]],
212 :args => [dns_settings[:host], dns_settings[:port], dns_settings[:domains], opts[:cache]],
208213 })
209214
210215 # Wait for the input window to finish its thing
104104
105105 if(command_packet.get(:is_request))
106106 tunnel_data_incoming(command_packet)
107 else
108 handler = @handlers.delete(command_packet.get(:request_id))
109 if(handler.nil?)
110 @window.puts("Received a response that we have no record of sending:")
111 @window.puts("#{command_packet}")
112 @window.puts()
113 @window.puts("Here are the responses we're waiting for:")
114 @handlers.each_pair do |request_id, the_handler|
115 @window.puts("#{request_id}: #{the_handler[:request]}")
116 end
117
118 if(handler.get(:command_id) != response.get(:command_id) && command_packet.get(:command_id) != CommandPacket::ERROR)
119 @window.puts("Received a response of a different packet type (that's really weird, please report if you can reproduce!")
120 @window.puts("#{command_packet}")
121 @window.puts()
122 @window.puts("The original packet was:")
123 @window.puts("#{handler}")
124 end
125
126 return
127 end
128
129 handler[:proc].call(handler[:request], command_packet)
107 return
130108 end
131109
110 handler = @handlers.delete(command_packet.get(:request_id))
111 if(handler.nil?)
112 @window.puts("Received a response that we have no record of sending:")
113 @window.puts("#{command_packet}")
114 @window.puts()
115 @window.puts("Here are the responses we're waiting for:")
116 @handlers.each_pair do |request_id, the_handler|
117 @window.puts("#{request_id}: #{the_handler[:request]}")
118 end
119 return
120 end
121
122 if(command_packet.get(:command_id) == CommandPacket::COMMAND_ERROR)
123 @window.puts("Client returned an error: #{command_packet.get(:status)} :: #{command_packet.get(:reason)}")
124 return
125 end
126
127 if(handler[:request].get(:command_id) != command_packet.get(:command_id))
128 @window.puts("Received a response of a different packet type (that's really weird, please report if you can reproduce!")
129 @window.puts("#{command_packet}")
130 @window.puts()
131 @window.puts("The original packet was:")
132 @window.puts("#{handler}")
133 return
134 end
135
136 handler[:proc].call(handler[:request], command_packet)
132137 end
133138
134139 def feed(data)
3838
3939 return out
4040 end
41
42 def shutdown()
43 end
4144 end
375375 attr_accessor :preference, :name
376376
377377 def initialize(name, preference = 10)
378 if(!name.is_a?(String) || !preference.is_a?(Fixnum))
378 if(!name.is_a?(String) || !preference.is_a?(Integer))
379379 raise ArgumentError("Creating an MX record wrong! Please file a bug!")
380380 end
381381 @name = name
803803 @sent = true
804804 end
805805
806 def reply!()
806 def reply!(_="")
807807 raise ArgumentError("Already sent!") if(@sent)
808808
809809 # Cache it if we have a cache
841841 begin
842842 loop do
843843 data = @s.recvfrom(65536)
844
845 # Data is an array where the first element is the actual data, and the second is the host/port
846 request = DNSer::Packet.parse(data[0])
847
848 # Create a transaction object, which we can use to respond
849 transaction = Transaction.new(@s, request, data[1][3], data[1][1], @cache)
850
851 # If caching is enabled, deal with it
852 if(@cache)
853 # This is somewhat expensive, but we aren't using the cache for performance
854 @cache.cleanup!()
855
856 # See if the transaction is cached
857 cached = @cache[request.trn_id]
858
859 # Verify it deeper (for security reasons)
860 if(!cached.nil?)
861 puts("POTENTIAL CACHE HIT")
862 if(request == cached[:request])
863 puts("CACHE HIT")
864 transaction.reply!(cached[:response])
844
845 begin
846 # Data is an array where the first element is the actual data, and the second is the host/port
847 request = DNSer::Packet.parse(data[0])
848
849 # Create a transaction object, which we can use to respond
850 transaction = Transaction.new(@s, request, data[1][3], data[1][1], @cache)
851
852 # If caching is enabled, deal with it
853 if(@cache)
854 # This is somewhat expensive, but we aren't using the cache for performance
855 @cache.cleanup!()
856
857 # See if the transaction is cached
858 cached = @cache[request.trn_id]
859
860 # Verify it deeper (for security reasons)
861 if(!cached.nil?)
862 if(request == cached[:request])
863 puts("CACHE HIT")
864 transaction.reply!(cached[:response])
865 end
865866 end
866867 end
867 end
868
869 if(!transaction.sent)
870 begin
871 proc.call(transaction)
872 rescue StandardError => e
873 puts("Caught an error: #{e}")
874 puts(e.backtrace())
875 transaction.reply!(transaction.response_template({:rcode => DNSer::Packet::RCODE_SERVER_FAILURE}))
868
869 if(!transaction.sent)
870 begin
871 proc.call(transaction)
872 rescue StandardError => e
873 puts("Caught an error: #{e}")
874 puts(e.backtrace())
875 transaction.reply!(transaction.response_template({:rcode => DNSer::Packet::RCODE_SERVER_FAILURE}))
876 end
876877 end
878 rescue StandardError => e
879 puts("Caught an error: #{e}")
880 puts(e.backtrace())
877881 end
878882 end
879883 ensure
241241 return response
242242 end
243243
244 def initialize(parent_window, host, port, domains)
244 def initialize(parent_window, host, port, domains, cache)
245245 if(domains.nil?)
246246 domains = []
247247 end
248248
249249 # Do this as early as we can, so we can fail early
250 @dnser = DNSer.new(host, port, true)
250 @dnser = DNSer.new(host, port, cache)
251251
252252 @id = 'dns%d' % (@@id += 1)
253253 @window = SWindow.new(parent_window, false, {