diff --git a/Protest/Front/dns-sd.js b/Protest/Front/dns-sd.js index f76ca0dd..7d0c2c85 100644 --- a/Protest/Front/dns-sd.js +++ b/Protest/Front/dns-sd.js @@ -402,7 +402,7 @@ class DnsSD extends Console { const string = document.createElement("div"); string.style.display = "inline-block"; - string.style.paddingRight = "8px"; + string.style.paddingRight = "4px"; string.textContent = json.answer[i].name; box.append(label, string); diff --git a/Protest/Front/hexviewer.js b/Protest/Front/hexviewer.js index 0cab9529..456209d4 100644 --- a/Protest/Front/hexviewer.js +++ b/Protest/Front/hexviewer.js @@ -351,7 +351,7 @@ class HexViewer extends Window { switch (protocol) { case "dns" : this.PopulateDnsLabels(hexContainer, charContainer, data); break; - case "mdns" : this.PopulateMdnsLabels(hexContainer, charContainer, data); break; + case "mdns" : this.PopulateDnsLabels(hexContainer, charContainer, data); break; case "ntp" : this.PopulateNtpLabels(hexContainer, charContainer, data); break; case "dhcp" : this.PopulateDhcpLabels(hexContainer, charContainer, data); break; } @@ -477,7 +477,7 @@ class HexViewer extends Window { return element; } - + PopulateDnsLabels(hexContainer, charContainer, stream) { const transactionId = stream[0].toString(16).padStart(2,"0") + stream[1].toString(16).padStart(2,"0"); this.PopulateLabel(`Transaction ID: 0x${transactionId}`, 0, hexContainer, charContainer, 0, 2); @@ -508,10 +508,10 @@ class HexViewer extends Window { } const qCount = stream[4] << 8 | stream[5]; - this.PopulateLabel(`Questions counter: ${qCount}`, 0, hexContainer, charContainer, 4, 2); + this.PopulateLabel(`Questions: ${qCount}`, 0, hexContainer, charContainer, 4, 2); const anCount = stream[6] << 8 | stream[7]; - this.PopulateLabel(`Answers counter: ${anCount}`, 0, hexContainer, charContainer, 6, 2); + this.PopulateLabel(`Answers RRs: ${anCount}`, 0, hexContainer, charContainer, 6, 2); const auCount = stream[8] << 8 | stream[9]; this.PopulateLabel(`Authority RRs: ${auCount}`, 0, hexContainer, charContainer, 8, 2); @@ -523,23 +523,27 @@ class HexViewer extends Window { let count = 0; while (offset < stream.length && count < qCount) { //questions - let start = offset; - let end = offset; + const start = offset; - switch (stream[offset]) { - case 0xc0: //pointer + let end = start; + if (stream[offset] === 0xC0) { //pointer end += 2; - break; + } + else { + while (end < stream.length && stream[end] !== 0 && stream[end] !== 0xC0) { + end++; + } - default: - while (end < stream.length && stream[end] !== 0) { + if (stream[end] === 0) { //null termination end++; } - break; + else if (stream[end] === 0xC0) { //pointer + end += 2; + } } - const first = this.PopulateLabel("Name", 1, hexContainer, charContainer, start, end - start); - offset = end + 1; + const first = this.PopulateLabel("Name", 1, hexContainer, charContainer, start, end - start - 1); + offset = end; let type = (stream[offset] << 8) | stream[offset+1]; this.PopulateLabel(`Type: ${type} ${HexViewer.DNS_RECORD_TYPES[type] ? `(${HexViewer.DNS_RECORD_TYPES[type]})` : ""}`, 1, hexContainer, charContainer, offset, 2); @@ -556,23 +560,30 @@ class HexViewer extends Window { count++; } - while (offset < stream.length && count < qCount + anCount + auCount + adCount) { //answers + const totalRecords = qCount + anCount + auCount + adCount; + while (offset < stream.length && count < totalRecords) { //records let start = offset; let end = offset; - switch (stream[offset]) { - case 0xc0: //pointer + if (stream[offset] === 0xC0) { //pointer + console.log(this.hexBox.childNodes[offset]); end += 2; - break; + } + else { + while (end < stream.length && stream[end] !== 0 && stream[end] !== 0xC0) { + end++; + } - default: - while (end < stream.length && stream[end] !== 0) { + if (stream[end] === 0) { //null termination end++; } - end++; //null termination - break; + else if (stream[end] === 0xC0) { //pointer + end += 2; + } } + console.log(offset.toString(16).padStart(2, "0"), end.toString(16).padStart(2, "0")); + const first = this.PopulateLabel("Name", 1, hexContainer, charContainer, start, end - start); offset = end; @@ -618,135 +629,8 @@ class HexViewer extends Window { this.PopulateLabel("Answer", 1, hexContainer, charContainer, offset, len); break; } - offset += len; - - end = offset; - - let element; - if (count < qCount + anCount) { - element = this.PopulateLabel("Answer: ", 0, hexContainer, charContainer, start, end - start); - } - else if (count < qCount + anCount + auCount) { - element = this.PopulateLabel("Authority: ", 0, hexContainer, charContainer, start, end - start); - } - else if (count < qCount + anCount + auCount + adCount) { - element = this.PopulateLabel("Additional: ", 0, hexContainer, charContainer, start, end - start); - } - this.list.insertBefore(element, first); - - count++; - } - } - - PopulateMdnsLabels(hexContainer, charContainer, stream, index) { - if (!(stream[index] instanceof Array)) { - this.PopulateDnsLabels(hexContainer, charContainer, stream); - return; - } - - const transactionId = stream[index][0].toString(16).padStart(2,"0") + stream[index][1].toString(16).padStart(2,"0"); - this.PopulateLabel(`Transaction ID: 0x${transactionId}`, 0, hexContainer, charContainer, 0, 2); - - const flags = stream[index][2].toString(16).padStart(2,"0") + stream[index][3].toString(16).padStart(2,"0"); - this.PopulateLabel(`Flags: 0x${flags}`, 0, hexContainer, charContainer, 2, 2); - - let isResponse = (stream[index][2] & 0b10000000) > 0; - let options = (stream[index][2] & 0b01111000) >> 3; - let isAuthoritative = (stream[index][2] & 0b00000100) > 0; - let isTruncated = (stream[index][2] & 0b00000010) > 0; - let isRecursive = (stream[index][2] & 0b00000001) > 0; - this.PopulateLabel(`Response: ${isResponse}`, 1, hexContainer, charContainer, 2, 1); - this.PopulateLabel(`Options: ${options}`, 1, hexContainer, charContainer, 2, 1); - this.PopulateLabel(`Authoritative: ${isAuthoritative}`, 1, hexContainer, charContainer, 2, 1); - this.PopulateLabel(`Truncated: ${isTruncated}`, 1, hexContainer, charContainer, 2, 1); - this.PopulateLabel(`Recursive: ${isRecursive}`, 1, hexContainer, charContainer, 2, 1); - - if (isResponse) { - let isRecursionAvailable = (stream[index][3] & 0b10000000) > 0; - let isAnswerAuthenticated = (stream[index][3] & 0b00100000) > 0; - let nonAuthenticatedData = (stream[index][3] & 0b00010000) > 0; - let replyCode = stream[index][3] & 0b00001111; - this.PopulateLabel(`Recursion is available: ${isRecursionAvailable}`, 1, hexContainer, charContainer, 3, 1); - this.PopulateLabel(`Answer is authenticated: ${isAnswerAuthenticated}`, 1, hexContainer, charContainer, 3, 1); - this.PopulateLabel(`Non authenticated data: ${nonAuthenticatedData}`, 1, hexContainer, charContainer, 3, 1); - this.PopulateLabel(`Reply code: ${replyCode}`, 1, hexContainer, charContainer, 3, 1); - } - - const qCount = stream[index][4] << 8 | stream[index][5]; - this.PopulateLabel(`Questions counter: ${qCount}`, 0, hexContainer, charContainer, 4, 2); - - const anCount = stream[index][6] << 8 | stream[index][7]; - this.PopulateLabel(`Answers counter: ${anCount}`, 0, hexContainer, charContainer, 6, 2); - - const auCount = stream[index][8] << 8 | stream[index][9]; - this.PopulateLabel(`Authority RRs: ${auCount}`, 0, hexContainer, charContainer, 8, 2); - - const adCount = stream[index][10] << 8 | stream[index][11]; - this.PopulateLabel(`Additional RRs: ${adCount}`, 0, hexContainer, charContainer, 10, 2); - - let offset = 12; - let count = 0; - while (offset < stream[index].length && count < qCount + anCount + auCount + adCount) { - let start = offset; - let end = offset; - - switch (stream[index][offset]) { - case 0xc0: //pointer - end += 2; - break; - - default: - while (end < stream[index].length && stream[index][end] !== 0) { - end++; - } - break; - } - - const first = this.PopulateLabel("Name", 1, hexContainer, charContainer, start, end - start); - - offset = end + 1; - - let type = (stream[index][offset] << 8) | stream[index][offset+1]; - this.PopulateLabel(`Type: ${type} ${HexViewer.DNS_RECORD_TYPES[type] ? `(${HexViewer.DNS_RECORD_TYPES[type]})` : ""}`, 1, hexContainer, charContainer, offset, 2); - offset += 2; - - let class_ = (stream[index][offset] << 8) | stream[index][offset+1]; - this.PopulateLabel(`Class: ${class_} ${HexViewer.DNS_CLASSES[class_] ? `(${HexViewer.DNS_CLASSES[class_]})` : ""}`, 1, hexContainer, charContainer, offset, 2); - offset += 2; - - let ttl = (stream[index][offset] << 24) | (stream[index][offset+1] << 16) | (stream[index][offset+2] << 8) | stream[index][offset+3]; - this.PopulateLabel(`TTL: ${ttl}`, 1, hexContainer, charContainer, offset, 4); - offset += 4; - - let len = (stream[index][offset] << 8) | stream[index][offset+1]; - this.PopulateLabel(`Length: ${len}`, 1, hexContainer, charContainer, offset, 2); - offset += 2; - - let data; - switch (type) { - case 1: //A - if (len === 4) { - data = `${stream[index][offset]}.${stream[index][offset+1]}.${stream[index][offset+2]}.${stream[index][offset+3]}`; - this.PopulateLabel(data, 1, hexContainer, charContainer, offset, len); - } - break; - case 28: //AAAA - if (len === 16) { - data = ""; - for (let j = 0; j < 16; j+=2) { - if (j > 0) data += ":"; - data += stream[index][offset + j].toString(16).padStart(2, "0"); - data += stream[index][offset + j + 1].toString(16).padStart(2, "0"); - } - this.PopulateLabel(data, 1, hexContainer, charContainer, offset, len); - } - break; - - default: - this.PopulateLabel("Answer", 1, hexContainer, charContainer, offset, len); - break; - } +//console.log("offset = " + offset + " + " + len); offset += len; end = offset; diff --git a/Protest/Http/Listener.cs b/Protest/Http/Listener.cs index 68c4aa61..65850349 100644 --- a/Protest/Http/Listener.cs +++ b/Protest/Http/Listener.cs @@ -205,6 +205,11 @@ public void Stop() { } private void ListenerCallback(IAsyncResult result) { +#if !DEBUG + try +#endif + { + HttpListenerContext ctx = listener.EndGetContext(result); //Cross Site Request Forgery protection @@ -290,6 +295,11 @@ private void ListenerCallback(IAsyncResult result) { ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; ctx.Response.Close(); + + } +#if !DEBUG + catch { } +#endif } private static Dictionary ParseQuery(string queryString) { diff --git a/Protest/Protocols/Mdns.cs b/Protest/Protocols/Mdns.cs index c32e8062..bdb141ca 100644 --- a/Protest/Protocols/Mdns.cs +++ b/Protest/Protocols/Mdns.cs @@ -126,7 +126,7 @@ public static byte[] Resolve(string queryString, int timeout = 2000, RecordType List matchingData = new List(); List answers = new List(); - try { + /*try*/ { for (int i = 0; i < receivedData.Count; i++) { byte[] response = receivedData[i]; ushort answerCount, authorityCount, additionalCount; @@ -145,9 +145,9 @@ public static byte[] Resolve(string queryString, int timeout = 2000, RecordType } } } - catch { + /*catch { return "{\"error\":\"unknown error\",\"errorcode\":\"0\"}"u8.ToArray(); - } + }*/ return Serialize(query, matchingData, answers); } @@ -213,19 +213,27 @@ private static Answer[] DeconstructResponse(byte[] response, RecordType queryTyp answerCount = 0; authorityCount = 0; additionalCount = 0; - return new Answer[] { new Answer { error = 254 } }; + return new Answer[] { }; + } + + byte error = (byte)(response[3] & 0b00001111); + if (error > 0) { + answerCount = 0; + authorityCount = 0; + additionalCount = 0; + return new Answer[] { }; } - //ushort transactionId = BitConverter.ToUInt16(response, 0); - //ushort flags = BitConverter.ToUInt16(response, 2); ushort questionCount = (ushort)((response[4] << 8) | response[5]); answerCount = (ushort)((response[6] << 8) | response[7]); authorityCount = (ushort)((response[8] << 8) | response[9]); additionalCount = (ushort)((response[10] << 8) | response[11]); - byte error = (byte)(response[3] & 0b00001111); - if (error > 0) { - return new Answer[] { new Answer { error = error } }; + if (remoteEndPoint.ToString() != "192.168.169.51") { + answerCount = 0; + authorityCount = 0; + additionalCount = 0; + return new Answer[] { }; } int index = 12; @@ -236,38 +244,50 @@ private static Answer[] DeconstructResponse(byte[] response, RecordType queryTyp if (len == 0) break; index += len; } - index += 4; //skip type and class + index += 4; //skip type, class amd null byte } List result = new List(); - for (int i = 0; i < answerCount + authorityCount + additionalCount; i++) { - if (index >= response.Length) { - break; - } + int totalRecords = answerCount + authorityCount + additionalCount; + for (int i = 0; i < totalRecords; i++) { - Answer ans = new Answer(); - ans.remote = remoteEndPoint; + Console.WriteLine($"Starting at: {index.ToString("x2")}"); - int nameStartIndex; + if (index + 4 >= response.Length) { break; } + int nameStartIndex; if ((response[index] & 0xFF) == 0xC0) { //pointer - nameStartIndex = response[index+1]; + nameStartIndex = response[index + 1]; index += 2; } else { nameStartIndex = index; - while (index < response.Length && response[index] != 0) { + + while (index < response.Length && response[index] != 0 && response[index] != 0xC0) { index += response[index] + 1; } - index++; //null-termination byte + + if (index >= response.Length) { break; } + + if (response[index] == 0) { //null-termination byte + index++; + } + else if (response[index] == 0xC0) { //pointer + index += 2; + } } + Answer ans = new Answer(); + ans.remote = remoteEndPoint; + if (index + 10 > response.Length) { ans.error = 254; break; } + ans.questionString = ExtractName(response, nameStartIndex); + ans.type = (RecordType)((response[index] << 8) | response[index + 1]); index += 2; @@ -303,10 +323,17 @@ private static Answer[] DeconstructResponse(byte[] response, RecordType queryTyp } break; + case RecordType.TXT: + if (index + ans.length < response.Length) { + ans.answerString = Encoding.UTF8.GetString(response, index, ans.length); + } + break; + case RecordType.CNAME: case RecordType.NS: case RecordType.PTR: ans.answerString = ExtractName(response, index); + index += ans.length; break; default: @@ -315,13 +342,6 @@ private static Answer[] DeconstructResponse(byte[] response, RecordType queryTyp break; } - //if (ans.length > response.Length - ans.length) { - // ans.error = 254; - // break; - //} - - ans.questionString = ExtractName(response, nameStartIndex); - if (i >= answerCount + authorityCount) { ans.isAdditional = true; } @@ -340,8 +360,7 @@ private static string ExtractName(byte[] response, int startIndex) { int index = startIndex; while (response[index] != 0) { - if ((response[index] & 0xC0) == 0xC0) { - //compressed name + if ((response[index] & 0xFF) == 0xC0) { //compressed name int pointer = ((response[index] & 0x3F) << 8) | response[index + 1]; name.Append(ExtractName(response, pointer)); break; @@ -354,9 +373,11 @@ private static string ExtractName(byte[] response, int startIndex) { name.Append('.'); } } + if (name.Length > 0) { name.Length--; //remove trailing dot } + return name.ToString(); }