Skip to content

Commit 5880640

Browse files
author
Noah Potash
committed
Added DNS support
1 parent 9fee956 commit 5880640

File tree

11 files changed

+609
-11
lines changed

11 files changed

+609
-11
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ LibPacketGremlin Supports the following packet types:
3030
* TCP
3131
* UDP
3232
* WakeOnLan
33+
* DNS Query and Reply, c/o [DNS](https://github.com/kapetan/dns)
3334

3435
Beyond basic packet support, it also has some WiFi cryptography functionality:
3536

Diff for: src/LibPacketGremlin/LibPacketGremlin.csproj

+10-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<Copyright>Copyright © 2016 Outbreak Labs</Copyright>
66
<VersionPrefix>1.0.0-rc2-001</VersionPrefix>
77
<Authors>Noah Potash</Authors>
8-
<TargetFramework>netstandard1.3</TargetFramework>
8+
<TargetFramework>netstandard1.5</TargetFramework>
99
<AssemblyName>LibPacketGremlin</AssemblyName>
1010
<OutputType>Library</OutputType>
1111
<PackageId>LibPacketGremlin</PackageId>
@@ -14,12 +14,18 @@
1414
<PackageProjectUrl>https://github.com/SapientGuardian/LibPacketGremlin</PackageProjectUrl>
1515
<PackageLicenseUrl>http://opensource.org/licenses/MIT</PackageLicenseUrl>
1616
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
17-
<Version>1.1.1</Version>
18-
<AssemblyVersion>0.1.1.1</AssemblyVersion>
19-
<FileVersion>0.1.1.1</FileVersion>
17+
<Version>1.2.0</Version>
18+
<AssemblyVersion>0.1.2.0</AssemblyVersion>
19+
<FileVersion>0.1.2.0</FileVersion>
20+
</PropertyGroup>
21+
22+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
23+
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_5</DefineConstants>
24+
<OutputPath>bin\Debug\netstandard1.5\</OutputPath>
2025
</PropertyGroup>
2126

2227
<ItemGroup>
28+
<PackageReference Include="DNS" Version="2.0.0" />
2329
<PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
2430
<PackageReference Include="System.Collections" Version="4.3.0" />
2531
<PackageReference Include="System.Linq" Version="4.3.0" />
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="DNSQueryFactory.cs" company="Outbreak Labs">
3+
// Copyright (c) Outbreak Labs. All rights reserved.
4+
// </copyright>
5+
// -----------------------------------------------------------------------
6+
7+
namespace OutbreakLabs.LibPacketGremlin.PacketFactories
8+
{
9+
using DNS.Protocol;
10+
using OutbreakLabs.LibPacketGremlin.Packets;
11+
using System;
12+
using System.Collections.Generic;
13+
14+
/// <summary>
15+
/// Factory for producing DNS Query packets
16+
/// </summary>
17+
public class DNSQueryFactory : PacketFactoryBase<DNSQuery>
18+
{
19+
private static readonly Random RANDOM = new Random();
20+
21+
/// <summary>
22+
/// Convenience instance
23+
/// </summary>
24+
public static readonly DNSQueryFactory Instance = new DNSQueryFactory();
25+
26+
/// <summary>
27+
/// Attempts to parse raw data into a structured packet
28+
/// </summary>
29+
/// <param name="buffer">Raw data to parse</param>
30+
/// <param name="packet">Parsed packet</param>
31+
/// <param name="count">The length of the packet in bytes</param>
32+
/// <param name="index">The index into the buffer at which the packet begins</param>
33+
/// <returns>True if parsing was successful, false if it is not.</returns>
34+
public override bool TryParse(byte[] buffer, int index, int count, out DNSQuery packet)
35+
=> DNSQuery.TryParse(buffer, index, count, out packet);
36+
37+
/// <summary>
38+
/// Constructs a packet with default values
39+
/// </summary>
40+
/// <returns>A packet with default values</returns>
41+
public DNSQuery Default()
42+
{
43+
var questions = new List<Question>();
44+
var header = new Header();
45+
46+
header.OperationCode = OperationCode.Query;
47+
header.Response = false;
48+
header.Id = RANDOM.Next(UInt16.MaxValue);
49+
return new DNSQuery(header, questions);
50+
}
51+
}
52+
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="DNSReplyFactory.cs" company="Outbreak Labs">
3+
// Copyright (c) Outbreak Labs. All rights reserved.
4+
// </copyright>
5+
// -----------------------------------------------------------------------
6+
7+
namespace OutbreakLabs.LibPacketGremlin.PacketFactories
8+
{
9+
using DNS.Protocol;
10+
using OutbreakLabs.LibPacketGremlin.Packets;
11+
using System;
12+
using System.Collections.Generic;
13+
14+
/// <summary>
15+
/// Factory for producing DNS Reply packets
16+
/// </summary>
17+
public class DNSReplyFactory : PacketFactoryBase<DNSReply>
18+
{
19+
private static readonly Random RANDOM = new Random();
20+
21+
/// <summary>
22+
/// Convenience instance
23+
/// </summary>
24+
public static readonly DNSReplyFactory Instance = new DNSReplyFactory();
25+
26+
/// <summary>
27+
/// Attempts to parse raw data into a structured packet
28+
/// </summary>
29+
/// <param name="buffer">Raw data to parse</param>
30+
/// <param name="packet">Parsed packet</param>
31+
/// <param name="count">The length of the packet in bytes</param>
32+
/// <param name="index">The index into the buffer at which the packet begins</param>
33+
/// <returns>True if parsing was successful, false if it is not.</returns>
34+
public override bool TryParse(byte[] buffer, int index, int count, out DNSReply packet)
35+
=> DNSReply.TryParse(buffer, index, count, out packet);
36+
37+
/// <summary>
38+
/// Constructs a packet with default values
39+
/// </summary>
40+
/// <returns>A packet with default values</returns>
41+
public DNSReply Default()
42+
{
43+
var reply = new DNSReply();
44+
reply.Id = RANDOM.Next(UInt16.MaxValue);
45+
return reply;
46+
}
47+
}
48+
}

Diff for: src/LibPacketGremlin/Packets/DNSQuery.cs

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="DNSQuery.cs" company="Outbreak Labs">
3+
// Copyright (c) Outbreak Labs. All rights reserved.
4+
// </copyright>
5+
// -----------------------------------------------------------------------
6+
7+
using OutbreakLabs.LibPacketGremlin.Abstractions;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Text;
11+
using System.IO;
12+
using DNS.Protocol;
13+
using System.Linq;
14+
15+
namespace OutbreakLabs.LibPacketGremlin.Packets
16+
{
17+
public class DNSQuery : IPacket
18+
{
19+
/// <summary>
20+
/// The minimum number of bytes required for a successful parse
21+
/// </summary>
22+
private const int MinimumParseableBytes = 12;
23+
24+
private readonly IList<Question> questions;
25+
private Header header;
26+
27+
public IPacket Payload => null;
28+
29+
public IList<Question> Questions => questions;
30+
public int Id
31+
{
32+
get { return header.Id; }
33+
set { header.Id = value; }
34+
}
35+
36+
public OperationCode OperationCode
37+
{
38+
get { return header.OperationCode; }
39+
set { header.OperationCode = value; }
40+
}
41+
public bool RecursionDesired
42+
{
43+
get { return header.RecursionDesired; }
44+
set { header.RecursionDesired = value; }
45+
}
46+
47+
48+
internal DNSQuery()
49+
{
50+
this.questions = new List<Question>();
51+
this.header = new Header();
52+
53+
this.header.OperationCode = OperationCode.Query;
54+
this.header.Response = false;
55+
}
56+
57+
internal DNSQuery(Header header, IList<Question> questions)
58+
{
59+
this.header = header;
60+
this.questions = questions;
61+
}
62+
63+
public void CorrectFields()
64+
{
65+
header.QuestionCount = questions.Count;
66+
}
67+
68+
public long Length()
69+
{
70+
return header.Size + questions.Sum(q => q.Size);
71+
}
72+
73+
public void SetContainer(IPacket container)
74+
{
75+
}
76+
77+
public void WriteToStream(Stream stream)
78+
{
79+
using (var bw = new BinaryWriter(stream, Encoding.UTF8, true))
80+
{
81+
bw.Write(header.ToArray());
82+
foreach (var question in Questions)
83+
{
84+
bw.Write(question.ToArray());
85+
}
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Attempts to parse raw data into a structured packet
91+
/// </summary>
92+
/// <param name="buffer">Raw data to parse</param>
93+
/// <param name="packet">Parsed packet</param>
94+
/// <param name="count">The length of the packet in bytes</param>
95+
/// <param name="index">The index into the buffer at which the packet begins</param>
96+
/// <returns>True if parsing was successful, false if it is not.</returns>
97+
internal static bool TryParse(byte[] buffer, int index, int count, out DNSQuery packet)
98+
{
99+
try
100+
{
101+
if (count < MinimumParseableBytes)
102+
{
103+
packet = null;
104+
return false;
105+
}
106+
107+
using (var ms = new MemoryStream(buffer, index, count, false))
108+
{
109+
using (var br = new BinaryReader(ms))
110+
{
111+
var messageBytes = br.ReadBytes(count);
112+
var header = Header.FromArray(messageBytes);
113+
if (header.Response || header.QuestionCount == 0 ||
114+
header.AdditionalRecordCount + header.AnswerRecordCount + header.AuthorityRecordCount > 0 ||
115+
header.ResponseCode != ResponseCode.NoError)
116+
{
117+
118+
packet = null;
119+
return false;
120+
}
121+
122+
var questions = Question.GetAllFromArray(messageBytes, header.Size, header.QuestionCount);
123+
packet = new DNSQuery(header, questions);
124+
return true;
125+
}
126+
}
127+
}
128+
catch (Exception)
129+
{
130+
packet = null;
131+
return false;
132+
}
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)