diff --git a/Protest/Front/hexviewer.js b/Protest/Front/hexviewer.js index c5b8b63d..e083bd53 100644 --- a/Protest/Front/hexviewer.js +++ b/Protest/Front/hexviewer.js @@ -339,7 +339,7 @@ class HexViewer extends Window { } hex.onmouseenter = char.onmouseenter = ()=>{ - hex.style.boxShadow = char.style.boxShadow = "#808080 0 0 0 1px inset"; + hex.style.boxShadow = char.style.boxShadow = "#000 0 0 0 2px inset"; this.details.textContent = `0x${j.toString(16).padStart(4, "0")}`; }; @@ -676,7 +676,7 @@ class HexViewer extends Window { 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); + 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); @@ -686,17 +686,17 @@ class HexViewer extends Window { let offset = 12; let count = 0; - while (offset < stream.length && count < qCount + anCount + auCount + adCount) { //answers + while (offset < stream[index].length && count < qCount + anCount + auCount + adCount) { let start = offset; let end = offset; - switch (stream[offset]) { + switch (stream[index][offset]) { case 0xc0: //pointer end += 2; break; default: - while (end < stream.length && stream[end] !== 0) { + while (end < stream[index].length && stream[index][end] !== 0) { end++; } break; @@ -706,27 +706,27 @@ class HexViewer extends Window { offset = end + 1; - let type = (stream[offset] << 8) | stream[offset+1]; + let type = (stream[index][offset] << 8) | stream[index][offset+1]; this.PopulateLabel(`Type: ${type} ${HexViewer.dnsRecordTypes[type] ? `(${HexViewer.dnsRecordTypes[type]})` : ""}`, 1, hexContainer, charContainer, offset, 2); offset += 2; - let class_ = (stream[offset] << 8) | stream[offset+1]; + let class_ = (stream[index][offset] << 8) | stream[index][offset+1]; this.PopulateLabel(`Class: ${class_} ${HexViewer.dnsClasses[class_] ? `(${HexViewer.dnsClasses[class_]})` : ""}`, 1, hexContainer, charContainer, offset, 2); offset += 2; - let ttl = (stream[offset] << 24) | (stream[offset+1] << 16) | (stream[offset+2] << 8) | stream[offset+3]; + 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[offset] << 8) | stream[offset+1]; + 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[offset]}.${stream[offset+1]}.${stream[offset+2]}.${stream[offset+3]}`; + 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; @@ -736,8 +736,8 @@ class HexViewer extends Window { data = ""; for (let j = 0; j < 16; j+=2) { if (j > 0) data += ":"; - data += stream[offset + j].toString(16).padStart(2, "0"); - data += stream[offset + j + 1].toString(16).padStart(2, "0"); + 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); } diff --git a/Protest/Protocols/Mdns.cs b/Protest/Protocols/Mdns.cs index 8b0cee7f..74d58392 100644 --- a/Protest/Protocols/Mdns.cs +++ b/Protest/Protocols/Mdns.cs @@ -20,8 +20,9 @@ private struct Answer { public RecordType type; public int ttl; public ushort length; - public byte[] name; - public string nameString; + public byte[] data; + public string questionString; + public string answerString; public bool isAuthoritative; public bool isAdditional; public byte error; @@ -122,14 +123,14 @@ public static byte[] Resolve(string queryString, int timeout = 2000, RecordType List matchingData = new List(); List answers = new List(); - try { + /*try*/ { foreach (byte[] response in receivedData) { ushort answerCount, authorityCount, additionalCount; Answer[] answer = DeconstructResponse(response, type, out answerCount, out authorityCount, out additionalCount); bool matched = false; for (int i = 0; i < answer.Length; i++) { if (type != RecordType.ANY && answer[i].type != type) { continue; } - if (!answer[i].nameString.Equals(queryString, StringComparison.OrdinalIgnoreCase)) { continue; } + if (!answer[i].questionString.Equals(queryString, StringComparison.OrdinalIgnoreCase)) { continue; } answers.Add(answer[i]); if (!matched) { @@ -139,9 +140,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); } @@ -202,13 +203,7 @@ private static byte[] ConstructQuery(string queryString, RecordType type) { return query; } - private static Answer[] DeconstructResponse( - byte[] response, - RecordType queryType, - out ushort answerCount, - out ushort authorityCount, - out ushort additionalCount) { - + private static Answer[] DeconstructResponse(byte[] response, RecordType queryType, out ushort answerCount, out ushort authorityCount, out ushort additionalCount) { if (response.Length < 12) { answerCount = 0; authorityCount = 0; @@ -230,7 +225,7 @@ private static Answer[] DeconstructResponse( int index = 12; - for (int i = 0; i < questionCount; i++) { //skip questions + for (int i = 0; i < questionCount; i++) { //skip questions section while (index < response.Length) { byte len = response[index++]; if (len == 0) break; @@ -250,17 +245,18 @@ private static Answer[] DeconstructResponse( int nameStartIndex = index; - if ((response[index] & 0xFF) == 0xC0) { + if ((response[index] & 0xFF) == 0xC0) { //pointer index += 2; } else { - while (index + 1 < response.Length && response[index] != 0) { + while (index < response.Length && response[index] != 0) { index += response[index] + 1; } - index++; + index++; //null-termination byte } - if (index >= response.Length) { + if (index + 10 > response.Length) { + ans.error = 254; break; } @@ -275,22 +271,55 @@ private static Answer[] DeconstructResponse( ans.length = (ushort)((response[index] << 8) | response[index + 1]); index += 2; - if (ans.type == RecordType.MX) { - ans.length -= 2; - index += 2; //skip preference + + + + switch (ans.type) { + case RecordType.A: + if (ans.length == 4 && index + 4 <= response.Length) { + ans.answerString = $"{response[index]}.{response[index + 1]}.{response[index + 2]}.{response[index + 3]}"; + index += 4; + } + break; + + case RecordType.AAAA: + if (ans.length == 16 && index + 16 <= response.Length) { + ans.answerString = string.Join(":", Enumerable.Range(0, 8) + .Select(j => ((response[index + 2 * j] << 8) | response[index + 2 * j + 1]).ToString("x4"))); + index += 16; + } + break; + + case RecordType.MX: + if (index + 2 <= response.Length) { + //preference = (ushort)((response[index] << 8) | response[index + 1]); + index += 2; + ans.answerString = ExtractName(response, index); + } + break; + + case RecordType.CNAME: + case RecordType.NS: + case RecordType.PTR: + ans.answerString = ExtractName(response, index); + break; + + default: + ans.answerString = String.Empty; //BitConverter.ToString(response, index, ans.length); + index += ans.length; + break; } if (ans.length > response.Length - index) { ans.error = 254; break; } - ans.name = new byte[ans.length]; - Array.Copy(response, index, ans.name, 0, ans.length); + + ans.data = new byte[ans.length]; + Array.Copy(response, index, ans.data, 0, ans.length); index += ans.length; - //extract name from the response - string responseName = ExtractName(response, nameStartIndex); - ans.nameString = responseName; + ans.questionString = ExtractName(response, nameStartIndex); if (i >= answerCount + authorityCount) { ans.isAdditional = true; @@ -387,42 +416,42 @@ private static byte[] Serialize(byte[] query, List data, List an switch (answers[i].type) { case RecordType.A: builder.Append("\"type\":\"A\","); - builder.Append($"\"name\":\"{String.Join(".", answers[i].name)}\","); + builder.Append($"\"name\":\"{String.Join(".", answers[i].data)}\","); break; case RecordType.NS: builder.Append("\"type\":\"NS\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.CNAME: builder.Append("\"type\":\"CNAME\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.SOA: builder.Append("\"type\":\"SOA\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.PTR: builder.Append("\"type\":\"PTR\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.MX: builder.Append("\"type\":\"MX\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.TXT: builder.Append("\"type\":\"TXT\","); - builder.Append($"\"name\":\"{answers[i].nameString}\","); + builder.Append($"\"name\":\"{answers[i].answerString}\","); break; case RecordType.AAAA: builder.Append("\"type\":\"AAAA\","); - if (answers[i].name.Length != 16) { + if (answers[i].data.Length != 16) { builder.Append($"\"name\":\"\""); break; } @@ -431,7 +460,7 @@ private static byte[] Serialize(byte[] query, List data, List an for (int j = 0; j < 16; j += 2) { if (j > 0) builder.Append(':'); - ushort word = (ushort)((answers[i].name[j] << 8) | answers[i].name[j + 1]); + ushort word = (ushort)((answers[i].data[j] << 8) | answers[i].data[j + 1]); builder.Append(word.ToString("x4")); } @@ -440,7 +469,7 @@ private static byte[] Serialize(byte[] query, List data, List an case RecordType.SRV: builder.Append("\"type\":\"SRV\","); - builder.Append($"\"name\":\"{String.Join(".", answers[i].name)}\","); + builder.Append($"\"name\":\"{String.Join(".", answers[i].data)}\","); break; }