Skip to content

Commit

Permalink
Add DNS message parsing operation
Browse files Browse the repository at this point in the history
Example:

- Input: `q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB`
- Operations: `From Base64` -> `Parse DNS Message`
- Output:
```
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43981
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.example.com.		IN	A
```
  • Loading branch information
hunts committed Jun 18, 2024
1 parent 4c5577d commit 462cda7
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 0 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"@astronautlabs/amf": "^0.0.6",
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"@dnspect/dns-ts": "^0.3.0",
"@wavesenterprise/crypto-gost-js": "^2.1.0-RC1",
"@xmldom/xmldom": "^0.8.10",
"argon2-browser": "^1.18.0",
Expand Down
1 change: 1 addition & 0 deletions src/core/config/Categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
"Parse UDP",
"Parse SSH Host Key",
"Parse URI",
"Parse DNS Message",
"URL Encode",
"URL Decode",
"Protobuf Decode",
Expand Down
55 changes: 55 additions & 0 deletions src/core/operations/ParseDNSMessage.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @author Minghang Chen [chen@minghang.dev]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { Message } from "@dnspect/dns-ts";

/**
* Parse DNS Message operation
*/
class ParseDNSMessage extends Operation {
/**
* ParseDNSMessage constructor
*/
constructor() {
super();

this.name = "Parse DNS Message";
this.module = "Default";
this.description = "Parse the DNS wireformat binary of a DNS message and return a text representation";
this.infoURL = "https://en.wikipedia.org/wiki/Domain_Name_System#DNS_message_format";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [{
"name": "Output format",
"type": "option",
"value": ["dig-like", "dns-json"]
}];
}

/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const format = args[0];
let msg;
try {
msg = Message.unpack(input);
} catch (e) {
throw new OperationError(`Malformed DNS message: ${e}`);
}

switch (format) {
case "dig-like": return msg.toString();
case "dns-json": return JSON.stringify(msg.toJsonObject(), null, 2);
default: throw new OperationError(`Unsupported output format: ${format}`);
}
}
}

export default ParseDNSMessage;
1 change: 1 addition & 0 deletions tests/operations/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import "./tests/ParseSSHHostKey.mjs";
import "./tests/ParseTCP.mjs";
import "./tests/ParseTLV.mjs";
import "./tests/ParseUDP.mjs";
import "./tests/ParseDNSMessage.mjs";
import "./tests/PEMtoHex.mjs";
import "./tests/PGP.mjs";
import "./tests/PHP.mjs";
Expand Down
84 changes: 84 additions & 0 deletions tests/operations/tests/ParseDNSMessage.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Parse DNS Message tests.
*
* @author Minghang Chen [chen@minghang.dev]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";

TestRegister.addTests([
{
name: "Parse DNS Message: No Data",
input: "",
expectedOutput: "Malformed DNS message: ParseError: insufficient bytes remaining for read: needs 12, have 0",
recipeConfig: [
{
op: "Parse DNS Message",
args: ["dig-like"],
},
],
},
{
name: "Parse DNS Message: Malformed",
input: "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f",
expectedOutput: "Malformed DNS message: RangeError: try to access beyond buffer length: read 3 start from 25",
recipeConfig: [
{
op: "Parse DNS Message",
args: ["dig-like"],
}
],
},
{
name: "Parse DNS Message: dig-like",
input: "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01",
expectedOutput: `;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43981
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.example.com. IN A`,
recipeConfig: [
{
op: "Parse DNS Message",
args: ["dig-like"],
}
],
},
{
name: "Parse DNS Message: dns-json",
input: "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01",
expectedOutput: `{
"Status": 0,
"TC": false,
"RD": true,
"RA": false,
"AD": false,
"CD": false,
"Question": [
{
"name": "www.example.com.",
"type": 1
}
],
"Answer": []
}`,
recipeConfig: [
{
op: "Parse DNS Message",
args: ["dns-json"],
}
],
},
{
name: "Parse DNS Message: unsupported-output-format",
input: "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01",
expectedOutput: "Unsupported output format: invalid",
recipeConfig: [
{
op: "Parse DNS Message",
args: ["invalid"],
}
],
}
]);

0 comments on commit 462cda7

Please sign in to comment.