-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Major update with modularity support
- added support for standalone feature modules in the form of `.toml` files - moved the majority of existing features to a modular format - major cleanup of the polardns codebase - major review of the variables scope and naming conventions in the code - adopting a more object-oriented approach for DNS request and DNS response variables
- Loading branch information
1 parent
5e880c8
commit 91254d0
Showing
76 changed files
with
2,878 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
def main(labels, *args, **kwargs): | ||
""" | ||
name = "afuzz1" | ||
info = "Single A record with arbitrary byte" | ||
desc = "Respond with A record containing arbitrary byte in the middle of the name in the ANSWER section, essentially giving an incorrect answer." | ||
type = "feature" | ||
author = "[email protected]" | ||
""" | ||
if labels[0].startswith("afuzz1"): | ||
# todo: Send A record with a slightly distorted name. | ||
byte = 65 | ||
if req.subdomains[1].isnumeric(): | ||
byte = int(req.subdomains[1]) | ||
if byte > 255: byte = 255 | ||
### DNS header ####### | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
newip = "6.6.6." + str(byte) | ||
tmpdom = convDom2Bin(req.full_domain) # first convert to dns name notation | ||
newdom = tmpdom[0:3] # \ | ||
newdom += struct.pack(">B", byte) # > replace the 3rd char with chosen byte | ||
newdom += tmpdom[4:] # / | ||
# A | ||
buffer += newdom + getTypeBin("A") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
buffer += struct.pack(">H", 4) ## Data length | ||
buffer += socket.inet_aton(newip) ## IP | ||
# log and send | ||
strdom = req.full_domain[0:2] | ||
strdom += "\\x%0.2x" % byte | ||
strdom += req.full_domain[3:] | ||
log("A %s -> %s" % (strdom, newip)) | ||
send_buf(self, buffer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
[module] | ||
name = "afuzz1" | ||
info = "Single A record with arbitrary byte" | ||
desc = "Respond with A record containing arbitrary byte in the middle of the name in the ANSWER section, essentially giving an incorrect answer." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("afuzz1"): | ||
# todo: Send A record with a slightly distorted name. | ||
byte = 65 | ||
if req.subdomains[1].isnumeric(): | ||
byte = int(req.subdomains[1]) | ||
if byte > 255: byte = 255 | ||
### DNS header ####### | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
newip = "6.6.6." + str(byte) | ||
tmpdom = convDom2Bin(req.full_domain) # first convert to dns name notation | ||
newdom = tmpdom[0:3] # \ | ||
newdom += struct.pack(">B", byte) # > replace the 3rd char with chosen byte | ||
newdom += tmpdom[4:] # / | ||
# A | ||
buffer += newdom + getTypeBin("A") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
buffer += struct.pack(">H", 4) ## Data length | ||
buffer += socket.inet_aton(newip) ## IP | ||
# log and send | ||
strdom = req.full_domain[0:2] | ||
strdom += "\\x%0.2x" % byte | ||
strdom += req.full_domain[3:] | ||
log("A %s -> %s" % (strdom, newip)) | ||
send_buf(self, buffer) | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
[module] | ||
name = "afuzz2" | ||
info = "Many bogus A records and legit A record" | ||
desc = "Respond with many bogus A records containing byte values starting from 0 up to 255 max, followed by a legitimate answer (proper A record) in the end." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("afuzz2"): | ||
# Send many A records with a slightly distorted name. In the end, provide the correct one also | ||
# af<01>zz2.dnslabtest1.com A 6.6.6.1 | ||
# af<02>zz2.dnslabtest1.com A 6.6.6.2 | ||
# af<03>zz2.dnslabtest1.com A 6.6.6.3 | ||
# ... | ||
# af<fe>zz2.dnslabtest1.com A 6.6.6.254 | ||
# af<ff>zz2.dnslabtest1.com A 6.6.6.255 | ||
# afuzz2.dnslabtest1.com A 1.2.3.4 | ||
answers = 1 | ||
if req.subdomains[1].isnumeric(): | ||
answers = int(req.subdomains[1]) | ||
if answers > 256: answers = 256 | ||
### DNS header ####### | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers+1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
#for b in range(1, 255): | ||
tmpdom = convDom2Bin(req.full_domain) | ||
# multiple bad A | ||
for b in range(1, answers+1): | ||
newip = "6.6.6." + str(b-1) | ||
newdom = tmpdom[0:3] | ||
newdom += struct.pack(">B", b-1) | ||
newdom += tmpdom[4:] | ||
buffer += newdom + getTypeBin("A") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
buffer += struct.pack(">H", 4) ## Data length | ||
buffer += socket.inet_aton(newip) ## IP | ||
# good A | ||
buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
buffer += struct.pack(">H", 4) ## Data length | ||
buffer += socket.inet_aton("2.3.4.5") ## IP | ||
# log and send | ||
log("%d bogus A records + legit A record" % (answers)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[module] | ||
name = "badcompress1" | ||
info = "Custom offset in Name field" | ||
desc = "Respond with CNAME (always<RANDOM>.yourdomain.com), where you can specify an arbitrary offset in the answer Name field compression pointer." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompress1"): | ||
# Send answer with arbitrary compression pointer in the ANSWER section in the query name | ||
offset = 12 # default offset is 12, which points to the domain name in the question | ||
if req.subdomains[1].isnumeric(): | ||
offset = int(req.subdomains[1]) | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
badcomp = b"\xc0" + struct.pack(">B", offset) ## arbitrary offset in the answer in the Name | ||
buffer += badcomp + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = "always" + str(random.randint(1,100000)) + "." + req.sld_tld_domain | ||
buffer += struct.pack(">H", len(dom)+2) ## Data length | ||
buffer += convDom2Bin(dom) ## CNAME value | ||
# log and send | ||
log("CNAME %s (badcomp 1, answer Name, offset %d)" % (dom, offset)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
[module] | ||
name = "badcompress2" | ||
info = "Custom offset in CNAME field" | ||
desc = "Respond with CNAME (abc.badcompress2.yourdomain.com), where you can specify an arbitrary offset in the answer CNAME field compression pointer." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompress2"): | ||
# Send answer with arbitrary compression pointer in the ANSWER section in the CNAME name | ||
offset = 12 # default offset is 12, which points to the domain name in the question | ||
if req.subdomains[1].isnumeric(): | ||
offset = int(req.subdomains[1]) | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
buffer += b"\xc0\x0c" + getTypeBin("CNAME") + getClassBin("IN") ## using compression here, no problem | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = b"\x03abc" + b"\xc0" + struct.pack(">B", offset) ## arbitrary offset in the answer in the CNAME | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value | ||
# log and send | ||
log("CNAME abc.%s (badcomp 2, CNAME, offset %d)" % (req.full_domain, offset)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[module] | ||
name = "badcompressfwptr1" | ||
info = "Forward pointer in Name field" | ||
desc = "Respond with CNAME (abc.badcompressfwptr1.yourdomain.com) and use a forward pointer in the answer Name field to point to the end (the actual CNAME), where there is \"abc\" + a pointer to the beginning (to the domain name in the query)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressfwptr1"): | ||
# Send answer with a forward compression pointer pointing to another pointer - variant 1 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
offset_to_last_cname = len(req.full_domain) + 12 + 18 ## forward pointer to the CNAME in the end | ||
buffer += b"\xc0" + struct.pack(">B", offset_to_last_cname) + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = b"\x03abc" + b"\xc0\x0c" ## "abc" + pointer to the first domain name (in the query) | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value | ||
# log and send | ||
log("CNAME abc.%s (badcomp with forward pointer 1)" % (req.full_domain)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[module] | ||
name = "badcompressfwptr2" | ||
info = "Double compression pointer" | ||
desc = "Respond with CNAME (abc.badcompressfwptr2.yourdomain.com) and use a forward pointer in the answer Name field to point to the end (the actual CNAME). But, skip the \"abc\" portion so that it will point directly to another pointer pointing to the beginning (to the domain name in the query)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressfwptr2"): | ||
# Send answer with a forward compression pointer pointing to another pointer - variant 2 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
offset_to_last_cname = len(req.full_domain) + 12 + 18 + 4 ## forward pointer to the CNAME in the end, but also | ||
## skipping the "abc" portion, so it's like a small chain | ||
buffer += b"\xc0" + struct.pack(">B", offset_to_last_cname) + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = b"\x03abc" + b"\xc0\x0c" ## "abc" + pointer to the first domain name (in the query) | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value | ||
# log and send | ||
log("CNAME abc.%s (badcomp with forward pointer 2)" % (req.full_domain)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[module] | ||
name = "badcompressloop1" | ||
info = "Pointer loop in Name field 1" | ||
desc = "Respond with CNAME, where the answer Name field only contains a pointer to itself (=> a loop)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressloop1"): | ||
# Send answer with a compression pointer loop in the Answer name - variant 1 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
offset_to_middle_name = len(req.full_domain) + 18 ## forward pointer to the name in the middle | ||
baddom = b"\xc0" + struct.pack(">B", offset_to_middle_name) | ||
buffer += baddom + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = "always" + str(random.randint(1,100000)) + "." + req.sld_tld_domain | ||
buffer += struct.pack(">H", len(dom)+2) ## Data length | ||
buffer += convDom2Bin(dom) ## CNAME value | ||
# log and send | ||
log("CNAME %s (badcomp loop 1, answer Name, <LOOP>)" % (dom)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[module] | ||
name = "badcompressloop2" | ||
info = "Pointer loop in Name field 2" | ||
desc = "Respond with CNAME, where the answer Name field only contains \"abc\" and a pointer to the beginning of the \"abc\" (=> a loop)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressloop2"): | ||
# Send answer with a compression pointer loop in the Answer name - variant 2 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
offset_to_middle_name = len(req.full_domain) + 18 ## forward pointer to the name in the middle | ||
baddom = b"\x03abc" + b"\xc0" + struct.pack(">B", offset_to_middle_name) | ||
buffer += baddom + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
dom = "always" + str(random.randint(1,100000)) + "." + req.sld_tld_domain | ||
buffer += struct.pack(">H", len(dom)+2) ## Data length | ||
buffer += convDom2Bin(dom) ## CNAME value | ||
# log and send | ||
log("CNAME %s (badcomp loop 2, answer Name, abc<LOOP>)" % (dom)) | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[module] | ||
name = "badcompressloop3" | ||
info = "Double pointer loop" | ||
desc = "Respond with CNAME, use a forward pointer in the answer Name field pointing to the end (the actual CNAME). The actual CNAME points to the answer Name field, effectively creating a loop." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressloop3"): | ||
# Send answer with a compression pointer loop involving a forward pointer and a backward pointer | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
offset_to_last_cname = len(req.full_domain) + 12 + 18 ## forward pointer to the CNAME in the end | ||
buffer += b"\xc0" + struct.pack(">B", offset_to_last_cname) + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
offset_to_middle_name = len(req.full_domain) + 18 ## backward pointer to the name in the middle | ||
dom = b"\x03abc" + b"\xc0" + struct.pack(">B", offset_to_middle_name) | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value | ||
# log and send | ||
log("CNAME abc.<LOOP> (badcomp loop 3 in the answer Name and CNAME)") | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[module] | ||
name = "badcompressloop4" | ||
info = "Pointer loop in CNAME field 1" | ||
desc = "Respond with CNAME, where the CNAME only contains a pointer to itself (=> a loop)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressloop4"): | ||
# Send answer with a compression pointer loop in the CNAME - variant 1 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
buffer += b"\xc0\x0c" + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
offset_to_last_cname = len(req.full_domain) + 12 + 18 ## forward pointer to the CNAME in the end | ||
dom = b"\xc0" + struct.pack(">B", offset_to_last_cname) | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value with pointer to itself | ||
# log and send | ||
log("CNAME <LOOP> (badcomp loop 4 in CNAME)") | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[module] | ||
name = "badcompressloop5" | ||
info = "Pointer loop in CNAME field 2" | ||
desc = "Respond with CNAME, where the CNAME only contains \"abc\" + a pointer to the beginning of the \"abc\" (=> a loop)." | ||
type = "feature" | ||
author = "[email protected]" | ||
|
||
code = ''' | ||
if req.first_subdomain.startswith("badcompressloop5"): | ||
# Send answer with a compression pointer loop in the CNAME - variant 2 | ||
### DNS header ######## | ||
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0) | ||
### QUESTION SECTION ######## | ||
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin | ||
### ANSWER SECTION ######## | ||
# CNAME | ||
buffer += b"\xc0\x0c" + getTypeBin("CNAME") + getClassBin("IN") | ||
buffer += struct.pack(">L", resp.TTL) ## TTL | ||
offset_to_last_cname = len(req.full_domain) + 12 + 18 ## forward pointer to the CNAME in the end | ||
dom = b"\x03abc" + b"\xc0" + struct.pack(">B", offset_to_last_cname) | ||
buffer += struct.pack(">H", len(dom)) ## Data length | ||
buffer += dom ## CNAME value with pointer to itself | ||
# log and send | ||
log("CNAME abc<LOOP> (badcomp loop 5 in CNAME)") | ||
send_buf(self, buffer) | ||
##################################################################### | ||
''' |
Oops, something went wrong.