aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yml57
-rw-r--r--Inveigh/Inveigh.csproj48
-rw-r--r--Inveigh/Listeners/SMBListener.cs4
-rw-r--r--Inveigh/Program.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs52
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs2
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs30
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs29
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs10
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs10
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs27
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs26
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs28
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs12
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs29
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMNegotiateRequest.cs70
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs22
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs31
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs18
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs10
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs21
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj27
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs225
-rw-r--r--Inveigh/Sniffer/Sniffer.cs11
-rw-r--r--Inveigh/Support/Arguments.cs270
-rw-r--r--Inveigh/Support/Control.cs15
-rw-r--r--Inveigh/Support/Output.cs5
27 files changed, 763 insertions, 371 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..b896911
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,57 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - "v*.*.*"
+
+jobs:
+ build:
+ runs-on: windows-latest
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Setup .NET Core SDK
+ uses: actions/setup-dotnet@v2
+ with:
+ dotnet-version: 6.0.x
+
+ - name: Restore Dependencies
+ run: dotnet restore
+
+ - name: Build Windows
+ run: |
+ VERSION=${{ github.ref_name }}
+ dotnet build -c release -p:Version=${VERSION:1}
+
+ - name: Zip
+ run: |
+ 7z a -tzip -mx9 Inveigh-net3.5-win-64-${{ github.ref_name }}.zip $PWD/Inveigh/bin/release/net35/*
+ 7z a -tzip -mx9 Inveigh-net4.6.2-win-64-${{ github.ref_name }}.zip $PWD/Inveigh/bin/release/net462/*
+ 7z a -tzip -mx9 Inveigh-net6.0-win-64-${{ github.ref_name }}.zip $PWD/Inveigh/bin/release/net6.0/* -x!*/
+
+ - name: Publish Linux/macOS
+ run: |
+ VERSION=${{ github.ref_name }}
+ dotnet publish --self-contained=true -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=${VERSION:1} -r linux-x64 -f net6.0 -p:AssemblyName=inveigh -c release
+ dotnet publish --self-contained=true -p:PublishSingleFile=true -p:PublishTrimmed=true -p:Version=${VERSION:1} -r osx-x64 -f net6.0 -p:AssemblyName=inveigh -c release
+
+ - name: Zip macOS
+ run: |
+ tar -czvf Inveigh-net6.0-linux-x64-trimmed-single-${{ github.ref_name }}.tar.gz --directory=$PWD/Inveigh/bin/release/net6.0/linux-x64/publish/ .
+ tar -czvf Inveigh-net6.0-osx-x64-trimmed-single-${{ github.ref_name }}.tar.gz --directory=$PWD/Inveigh/bin/release/net6.0/osx-x64/publish/ .
+
+ - name: Release .zip
+ uses: softprops/action-gh-release@v1
+ with:
+ files: "Inveigh*.zip"
+
+ - name: Release tar.gz
+ uses: softprops/action-gh-release@v1
+ with:
+ files: "Inveigh*.tar.gz"
diff --git a/Inveigh/Inveigh.csproj b/Inveigh/Inveigh.csproj
index b0dbbf3..17f6db6 100644
--- a/Inveigh/Inveigh.csproj
+++ b/Inveigh/Inveigh.csproj
@@ -2,55 +2,35 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
- <TargetFrameworks>net35;net45;net5.0</TargetFrameworks>
+ <TargetFrameworks>net35;net462;net6.0</TargetFrameworks>
</PropertyGroup>
-
-
-
-
- <PropertyGroup>
- <!-- https://github.com/dotnet/msbuild/issues/1333#issuecomment-296346352 -->
- <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35'">$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
- <AutomaticallyUseReferenceAssemblyPackages Condition=" '$(TargetFramework)' == 'net35' ">false</AutomaticallyUseReferenceAssemblyPackages>
- <AssemblyName>Inveigh</AssemblyName>
- <Version>2.0.0</Version>
- </PropertyGroup>
-
-
+
<PropertyGroup Condition="'$(Configuration)|$(TargetFrameworks)|$(Platform)'=='Debug|net35|AnyCPU'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
+ <ItemGroup Condition="'$(TargetFramework)' == 'net35'">
+ <Reference Include="System.DirectoryServices.Protocols">
+ <HintPath>$(WINDIR)\Microsoft.NET\Framework64\v2.0.50727\System.DirectoryServices.Protocols.dll</HintPath>
+ <private>False</private>
+ </Reference>
+ </ItemGroup>
- <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net35|AnyCPU'">
- <DebugType>pdbonly</DebugType>
- <DebugSymbols>true</DebugSymbols>
- </PropertyGroup>
-
- <ItemGroup Condition="'$(TargetFramework)' == 'net35'">
- <Reference Include="System.DirectoryServices.Protocols">
- <HintPath>$(WINDIR)\Microsoft.NET\Framework64\v2.0.50727\System.DirectoryServices.Protocols.dll</HintPath>
- <private>False</private>
- </Reference>
- </ItemGroup>
-
-
- <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
+ <ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<PackageReference Include="System.DirectoryServices.Protocols">
- <Version>5.0.1</Version>
+ <Version>6.0.1</Version>
</PackageReference>
</ItemGroup>
-
- <ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
+ <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="System.DirectoryServices.Protocols">
- <Version>5.0.1</Version>
+ <Version>6.0.1</Version>
</PackageReference>
</ItemGroup>
- <PropertyGroup Condition="'$(TargetFramework)' == 'net5.0'">
- <DefineConstants>ISNET5_0</DefineConstants>
+ <PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
+ <DefineConstants>ISNET6_0</DefineConstants>
</PropertyGroup>
</Project>
diff --git a/Inveigh/Listeners/SMBListener.cs b/Inveigh/Listeners/SMBListener.cs
index e7606ae..a8069f3 100644
--- a/Inveigh/Listeners/SMBListener.cs
+++ b/Inveigh/Listeners/SMBListener.cs
@@ -1,7 +1,7 @@
/*
* BSD 3-Clause License
*
- * Copyright (c) 2021, Kevin Robertson
+ * Copyright (c) 2022, Kevin Robertson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,7 @@ namespace Inveigh
protected override void OutputError(Exception ex, int port)
{
- if (ex.Message.ToString().Equals("An attempt was made to access a socket in a way forbidden by its access permissions"))
+ if (ex.Message.ToString().Equals("An attempt was made to access a socket in a way forbidden by its access permissions."))
{
Output.Queue(String.Format("[!] Failed to start SMB listener on port {0}, check IP and port usage.", port));
}
diff --git a/Inveigh/Program.cs b/Inveigh/Program.cs
index c435fdf..f7d8ef8 100644
--- a/Inveigh/Program.cs
+++ b/Inveigh/Program.cs
@@ -174,7 +174,7 @@ namespace Inveigh
public static string netbiosDomain = Environment.UserDomainName;
public static string dnsDomain = "";
public static ulong smb2Session = 5548434740922023936; // todo check
- public static string version = "2.0.4";
+ public static string version = "2.0.5";
static void Main(string[] arguments)
{
@@ -185,6 +185,7 @@ namespace Inveigh
enabledWindows = false;
}
#endif
+ bool allValid = true;
if (arguments.Length > 0)
{
@@ -584,7 +585,7 @@ namespace Inveigh
if (arguments.Length > 1)
argHelp = arguments[entry.index + 1].ToUpper();
Output.GetHelp(argHelp);
- Environment.Exit(0);
+ allValid &= false;
break;
default:
@@ -606,42 +607,46 @@ namespace Inveigh
Console.WriteLine("{0} error - {1}", argument, ex.Message);
}
- Environment.Exit(0);
+ allValid &= false;
}
}
}
- Arguments.ValidateArguments();
- Arguments.ParseArguments();
- Control.ImportSession();
- Output.StartupOutput();
- Control.StartThreads();
- commandHistoryList.Add("");
+ allValid &= Arguments.ValidateArguments();
- while (isRunning)
+ if (allValid)
{
+ Arguments.ParseArguments();
+ Control.ImportSession();
+ Output.StartupOutput();
+ Control.StartThreads();
+ commandHistoryList.Add("");
- try
+ while (isRunning)
{
- Output.OutputLoop();
- if (isRunning)
+ try
+ {
+ Output.OutputLoop();
+
+ if (isRunning)
+ {
+ Shell.ConsoleLoop();
+ }
+
+ }
+ catch (Exception ex)
{
- Shell.ConsoleLoop();
+ Console.WriteLine(outputList.Count);
+ outputList.Add(String.Format("[-] [{0}] Console error detected - {1}", Output.Timestamp(), ex.ToString()));
}
}
- catch (Exception ex)
- {
- Console.WriteLine(outputList.Count);
- outputList.Add(String.Format("[-] [{0}] Console error detected - {1}", Output.Timestamp(), ex.ToString()));
- }
}
- Environment.Exit(0);
}
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs b/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs
index 55ff74e..27b5493 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs
@@ -29,23 +29,71 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using Quiddity.NetBIOS;
+using Quiddity.SMB;
+using Quiddity.SMB2;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Sockets;
using System.Text;
namespace Quiddity.Clients
{
class SMBClient
{
+ public TCPClient TCPClient { get; set; }
+
+ public static NetworkStream tcpStream;
+
internal void Connect(string ipAddress, int port)
{
- TCPClient tcpClient = new TCPClient(ipAddress, port);
- tcpClient.Connect(ipAddress, port);
+ TCPClient = new TCPClient(ipAddress, port);
+ //TCPClient.Connect(ipAddress, port);
+ tcpStream = TCPClient.GetStream();
}
internal void Negotiate(string ipAddress, int port)
{
+ Connect(ipAddress, port);
+ byte[] readBuffer = new byte[1024];
+
+ SMBHeader smbHeader = new SMBHeader
+ {
+ Command = 0x72,
+ Status = 0,
+ Flags = 0x18,
+ Flags2 = 51283,
+ PIDHigh = 0,
+ SecurityFeatures = new byte[8],
+ TID = 65535,
+ PIDLow = 65279,
+ UID = 0,
+ MID = 0
+ };
+
+ SMBCOMNegotiateRequest smbCOMNegotiateRequest = new SMBCOMNegotiateRequest();
+ byte[] sendBuffer = SMBHelper.GetBytes(new NetBIOSSessionService(), smbHeader, smbCOMNegotiateRequest);
+ tcpStream.Write(sendBuffer, 0, sendBuffer.Length);
+ tcpStream.Flush();
+ tcpStream.Read(readBuffer, 0, readBuffer.Length);
+
+ NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(readBuffer);
+ SMBHelper smbHelper = new SMBHelper();
+
+ if (requestNetBIOSSessionService.Type == 0 || smbHelper.Protocol[0] == 0xfe || smbHelper.Protocol[0] == 0xff)
+ {
+ int sessionServiceIndex = 0;
+
+ if (requestNetBIOSSessionService.Type == 0)
+ {
+ sessionServiceIndex = 4;
+ }
+
+ SMBHeader requestSMBHeader = new SMBHeader();
+ SMB2Header requestSMB2Header = new SMB2Header();
+ smbHelper.ReadBytes(readBuffer, sessionServiceIndex);
+ }
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs b/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs
index 4748eed..895f0dc 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs
@@ -40,7 +40,7 @@ namespace Quiddity.Clients
public TCPClient(string ipAddress, int port) : base(ipAddress, port)
{
this.Client.ReceiveTimeout = 60000;
- this.ExclusiveAddressUse = false;
+ //this.ExclusiveAddressUse = false;
}
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs
index 8d7b90e..3da6ec6 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs
@@ -36,6 +36,7 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
+using System.Threading;
namespace Quiddity
{
@@ -46,6 +47,8 @@ namespace Quiddity
public int Prefix { get; set; }
public int Index { get; set; }
+ public static bool isRunning = false;
+
public DHCPv6Listener()
{
this.Index = 1;
@@ -68,14 +71,33 @@ namespace Quiddity
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 547);
listener.JoinMulticastGroup(IPAddress.Parse("ff02::1:2"));
listener.Client.Bind(ipEndPoint);
+ isRunning = true;
+ IAsyncResult udpAsync;
- while (true)
- {
+ while (isRunning)
+ {
try
{
- byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
- ProcessRequest(receiveBuffer, listener, ipEndPoint, mac, dnsIPv6);
+ udpAsync = listener.BeginReceive(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!udpAsync.IsCompleted);
+
+ if (isRunning)
+ {
+ byte[] receiveBuffer = listener.EndReceive(udpAsync, ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, mac, dnsIPv6);
+ }
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs
index efdd8bd..b2542f4 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs
@@ -34,6 +34,7 @@ using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
namespace Quiddity
{
@@ -45,6 +46,8 @@ namespace Quiddity
public ushort Priority { get; set; }
public ushort Weight { get; set; }
+ public static bool isRunning = false;
+
public DNSListener()
{
this.TTL = 30;
@@ -67,6 +70,8 @@ namespace Quiddity
{
UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 53);
+ isRunning = true;
+ IAsyncResult udpAsync;
if (String.Equals(ipAddress.AddressFamily.ToString(), "InterNetworkV6"))
{
@@ -75,13 +80,31 @@ namespace Quiddity
listener.Client.Bind(ipEndPoint);
- while (true)
+ while (isRunning)
{
try
{
- byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
- ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ udpAsync = listener.BeginReceive(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!udpAsync.IsCompleted);
+
+ if (isRunning)
+ {
+ byte[] receiveBuffer = listener.EndReceive(udpAsync, ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
+
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs
index 2587e90..719eac6 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs
@@ -115,9 +115,13 @@ namespace Quiddity
}
while (!tcpAsync.IsCompleted);
- TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
- object[] parameters = { tcpClient, type, port };
- ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ if (isRunning)
+ {
+ TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { tcpClient, type, port };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs
index 8b6c27c..92ce66a 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs
@@ -82,9 +82,13 @@ namespace Quiddity
}
while (!tcpAsync.IsCompleted);
- TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
- object[] parameters = { tcpClient, port };
- ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ if (isRunning)
+ {
+ TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { tcpClient, port };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs
index a47808b..0fbeec5 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs
@@ -33,6 +33,7 @@ using Quiddity.LLMNR;
using System;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
namespace Quiddity
{
@@ -48,6 +49,8 @@ namespace Quiddity
{
UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 5355);
+ isRunning = true;
+ IAsyncResult udpAsync;
if (String.Equals(ipAddress.AddressFamily.ToString(), "InterNetwork"))
{
@@ -61,13 +64,31 @@ namespace Quiddity
listener.Client.Bind(ipEndPoint);
- while (true)
+ while (isRunning)
{
try
{
- byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
- ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ udpAsync = listener.BeginReceive(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!udpAsync.IsCompleted);
+
+ if (isRunning)
+ {
+ byte[] receiveBuffer = listener.EndReceive(udpAsync, ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
+
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs
index dafe911..bf91738 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs
@@ -33,6 +33,7 @@ using Quiddity.MDNS;
using System;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
namespace Quiddity
{
@@ -55,6 +56,8 @@ namespace Quiddity
{
UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 5353);
+ isRunning = true;
+ IAsyncResult udpAsync;
if (string.Equals(ipAddress.AddressFamily.ToString(), "InterNetwork"))
{
@@ -68,13 +71,30 @@ namespace Quiddity
listener.Client.Bind(ipEndPoint);
- while (true)
+ while (isRunning)
{
try
{
- byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
- ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ udpAsync = listener.BeginReceive(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!udpAsync.IsCompleted);
+
+ if (isRunning)
+ {
+ byte[] receiveBuffer = listener.EndReceive(udpAsync, ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs
index b3dada5..4dda6fd 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs
@@ -33,6 +33,7 @@ using Quiddity.NetBIOS;
using System;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
namespace Quiddity
{
@@ -52,16 +53,35 @@ namespace Quiddity
{
UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 137);
-
+ isRunning = true;
+ IAsyncResult udpAsync;
listener.Client.Bind(ipEndPoint);
- while (true)
+ while (isRunning)
{
try
{
- byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
- ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP);
+ udpAsync = listener.BeginReceive(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!udpAsync.IsCompleted);
+
+ if (isRunning)
+ {
+ byte[] receiveBuffer = listener.EndReceive(udpAsync, ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP);
+ }
+
}
catch (Exception ex)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs
index b9c2197..3f93d71 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs
@@ -85,9 +85,13 @@ namespace Quiddity
}
while (!tcpAsync.IsCompleted);
- tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
- object[] parameters = { guid, tcpClient, port };
- ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ if (isRunning)
+ {
+ tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { guid, tcpClient, port };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+
}
catch (Exception ex)
{
@@ -138,7 +142,7 @@ namespace Quiddity
}
NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(requestData);
- SMBHelper smbHelper = new SMBHelper();
+ SMBHelper smbHelper = new SMBHelper(); // todo check
if (requestNetBIOSSessionService.Type == 0 || smbHelper.Protocol[0] == 0xfe || smbHelper.Protocol[0] == 0xff)
{
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs
index b3081ff..091d591 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs
@@ -163,9 +163,20 @@ namespace Quiddity.NTLM
this.EncryptedRandomSessionKeyMaxLen = packetReader.ReadUInt16();
this.EncryptedRandomSessionKeyBufferOffset = packetReader.ReadUInt32();
this.NegotiateFlags = packetReader.ReadBytes(4);
- this.Version = packetReader.ReadBytes(8);
- this.MIC = packetReader.ReadBytes(16);
- this.Payload = packetReader.ReadBytes(data.Length - 88);
+
+ string flags = Convert.ToString(BitConverter.ToUInt32(this.NegotiateFlags, 0), 2).PadLeft(this.NegotiateFlags.Length * 8, '0');
+
+ if (String.Equals(flags.Substring(6, 1), "1"))
+ {
+ this.Version = packetReader.ReadBytes(8);
+ }
+
+ if (String.Equals(flags.Substring(1, 1), "1"))
+ {
+ this.MIC = packetReader.ReadBytes(16);
+ }
+
+ this.Payload = packetReader.ReadBytes(data.Length - (int)this.DomainNameBufferOffset);
}
}
@@ -203,17 +214,17 @@ namespace Quiddity.NTLM
private void ParseValues()
{
this.DomainName = new byte[this.DomainNameLen];
- Buffer.BlockCopy(this.Payload, (int)(this.DomainNameBufferOffset - 88), this.DomainName, 0, this.DomainNameLen);
+ Buffer.BlockCopy(this.Payload, 0, this.DomainName, 0, this.DomainNameLen);
this.UserName = new byte[this.UserNameLen];
- Buffer.BlockCopy(this.Payload, (int)(this.UserNameBufferOffset - 88), this.UserName, 0, this.UserNameLen);
+ Buffer.BlockCopy(this.Payload, (int)(this.UserNameBufferOffset - this.DomainNameBufferOffset), this.UserName, 0, this.UserNameLen);
this.Workstation = new byte[this.WorkstationLen];
- Buffer.BlockCopy(this.Payload, (int)(this.WorkstationBufferOffset - 88), this.Workstation, 0, this.WorkstationLen);
+ Buffer.BlockCopy(this.Payload, (int)(this.WorkstationBufferOffset - this.DomainNameBufferOffset), this.Workstation, 0, this.WorkstationLen);
this.EncryptedRandomSessionKey = new byte[this.EncryptedRandomSessionKeyLen];
- Buffer.BlockCopy(this.Payload, (int)(this.EncryptedRandomSessionKeyBufferOffset - 88), this.EncryptedRandomSessionKey, 0, this.EncryptedRandomSessionKeyLen);
+ Buffer.BlockCopy(this.Payload, (int)(this.EncryptedRandomSessionKeyBufferOffset - this.DomainNameBufferOffset), this.EncryptedRandomSessionKey, 0, this.EncryptedRandomSessionKeyLen);
this.LmChallengeResponse = new byte[this.LmChallengeResponseLen];
- Buffer.BlockCopy(this.Payload, (int)(this.LmChallengeResponseBufferOffset - 88), this.LmChallengeResponse, 0, this.LmChallengeResponseLen);
+ Buffer.BlockCopy(this.Payload, (int)(this.LmChallengeResponseBufferOffset - this.DomainNameBufferOffset), this.LmChallengeResponse, 0, this.LmChallengeResponseLen);
this.NtChallengeResponse = new byte[this.NtChallengeResponseLen];
- Buffer.BlockCopy(this.Payload, (int)(this.NtChallengeResponseBufferOffset - 88), this.NtChallengeResponse, 0, this.NtChallengeResponseLen);
+ Buffer.BlockCopy(this.Payload, (int)(this.NtChallengeResponseBufferOffset - this.DomainNameBufferOffset), this.NtChallengeResponse, 0, this.NtChallengeResponseLen);
}
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMNegotiateRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMNegotiateRequest.cs
new file mode 100644
index 0000000..ba6bf36
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMNegotiateRequest.cs
@@ -0,0 +1,70 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2022, Kevin Robertson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.SMB
+{
+ class SMBCOMNegotiateRequest
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/25c8c3c9-58fc-4bb8-aa8f-0272dede84c5
+ public byte WordCount { get; set; }
+ public ushort ByteCount { get; set; }
+ public byte[] Dialects{ get; set; }
+
+ public SMBCOMNegotiateRequest()
+ {
+ this.WordCount = 0;
+ this.ByteCount = 120;
+ this.Dialects = new byte[120] { 0x02, 0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30, 0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54, 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00, 0x02, 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x3f, 0x3f, 0x3f, 0x00 };
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.WordCount);
+ packetWriter.Write(this.ByteCount);
+ packetWriter.Write(this.Dialects);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs
index f969b38..1e1a6af 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs
@@ -87,6 +87,28 @@ namespace Quiddity.SMB
}
}
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Protocol);
+ packetWriter.Write(this.Command);
+ packetWriter.Write(this.Status);
+ packetWriter.Write(this.Flags);
+ packetWriter.Write(this.Flags2);
+ packetWriter.Write(this.PIDHigh);
+ packetWriter.Write(this.SecurityFeatures);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.TID);
+ packetWriter.Write(this.PIDLow);
+ packetWriter.Write(this.UID);
+ packetWriter.Write(this.MID);
+ return memoryStream.ToArray();
+ }
+
+ }
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs
index 80bf24d..efc9c84 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs
@@ -29,6 +29,8 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+using Quiddity.NetBIOS;
+using Quiddity.Support;
using System.IO;
namespace Quiddity.SMB
@@ -65,6 +67,35 @@ namespace Quiddity.SMB
}
+ public static byte[] GetBytes(object smbCommand)
+ {
+ NetBIOSSessionService netBIOSSessionService = new NetBIOSSessionService();
+ SMBHeader smbHeader = new SMBHeader();
+ return GetBytes(netBIOSSessionService, smbHeader, smbCommand);
+ }
+
+ public static byte[] GetBytes(NetBIOSSessionService netBIOSSessionService, SMBHeader smbHeader, object smbCommand)
+ {
+ byte[] headerData = smbHeader.GetBytes();
+ byte[] commandData = new byte[0];
+
+ switch (smbHeader.Command)
+ {
+
+ case 0x72:
+ {
+ SMBCOMNegotiateRequest command = (SMBCOMNegotiateRequest)smbCommand;
+ commandData = command.GetBytes();
+ }
+ break;
+
+ }
+
+ netBIOSSessionService.Length = (ushort)(commandData.Length + 32);
+ byte[] netbiosData = netBIOSSessionService.GetBytes();
+ return Utilities.BlockCopy(netbiosData, headerData, commandData);
+ }
+
}
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs
index 3791230..02c9497 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs
@@ -54,6 +54,24 @@ namespace Quiddity.SMB2
public byte[] Padding { get; set; } // todo check
public byte[] NegotiateContextList { get; set; }
+ public SMB2NegotiatelRequest()
+ {
+ this.StructureSize = 65;
+ this.DialectCount = 5;
+ this.SecurityMode = 1;
+ this.Reserved = new byte[2];
+ this.Capabilities = new byte[2];
+ this.ClientGUID = new byte[2];
+ this.NegotiateContextOffset = 0;
+ this.NegotiateContextCount = 0;
+ this.ClientStartTime = BitConverter.GetBytes(DateTime.Now.ToFileTime());
+ this.Capabilities = new byte[4];
+ this.Dialects = new byte[4];
+ this.NegotiateContextOffset = 0;
+ this.Padding = new byte[2]; // todo check
+ this.NegotiateContextList = new byte[0];
+ }
+
public SMB2NegotiatelRequest(byte[] data, int offset)
{
ReadBytes(data, offset);
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs
index c149279..0969c66 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs
@@ -109,16 +109,6 @@ namespace Quiddity.SMB2
return Utilities.BlockCopy(netbiosData, headerData, commandData);
}
- public void NegotiateProtocol()
- {
-
- }
-
- public void SessionSetup()
- {
-
- }
-
}
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs
index af2c092..6639f0e 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs
@@ -32,6 +32,7 @@
using System;
using System.Linq;
using System.IO;
+using System.Text;
namespace Quiddity.SMB2
{
@@ -43,6 +44,9 @@ namespace Quiddity.SMB2
public uint Reserved { get; set; }
public byte[] Data { get; set; }
+ // custom
+ public string NetName { get; set; }
+
public SMB2NegotiateContext()
{
this.ContextType = 0;
@@ -72,7 +76,7 @@ namespace Quiddity.SMB2
packetWriter.Write(this.DataLength);
packetWriter.Write(this.Reserved);
packetWriter.Write(this.Data);
- packetWriter.Write(new byte[2] { 0x000, 0x00 });
+ packetWriter.Write(new byte[2] { 0x00, 0x00 });
}
if (contextTypes.Contains("2"))
@@ -84,7 +88,7 @@ namespace Quiddity.SMB2
packetWriter.Write(this.DataLength);
packetWriter.Write(this.Reserved);
packetWriter.Write(this.Data);
- packetWriter.Write(new byte[4] { 0x000, 0x00, 0x00, 0x00 });
+ packetWriter.Write(new byte[4] { 0x00, 0x00, 0x00, 0x00 });
}
if (contextTypes.Contains("3"))
@@ -98,6 +102,19 @@ namespace Quiddity.SMB2
packetWriter.Write(this.Data);
}
+ if (contextTypes.Contains("5"))
+ {
+ byte[] netName = Encoding.Unicode.GetBytes(this.NetName);
+ this.ContextType = 5;
+ this.DataLength = (ushort)netName.Length;
+ this.Data = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
+ packetWriter.Write(this.ContextType);
+ packetWriter.Write(this.DataLength);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.Data);
+ packetWriter.Write(netName);
+ }
+
return memoryStream.ToArray();
}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj b/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj
index 24400e9..597c46a 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj
@@ -1,13 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>net35;net45;net5.0</TargetFrameworks>
+ <TargetFrameworks>net35;net462;net6.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
- <!-- https://github.com/dotnet/msbuild/issues/1333#issuecomment-296346352 -->
- <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35'">$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
- <AutomaticallyUseReferenceAssemblyPackages Condition=" '$(TargetFramework)' == 'net35' ">false</AutomaticallyUseReferenceAssemblyPackages>
<Version>0.0.0-alpha</Version>
<Authors>Kevin Robertson</Authors>
<Company />
@@ -23,24 +20,22 @@
<FileVersion>0.0.0.0</FileVersion>
</PropertyGroup>
- <ItemGroup Condition="'$(TargetFramework)' == 'net35'">
- <Reference Include="System.DirectoryServices.Protocols">
- <HintPath>$(WINDIR)\Microsoft.NET\Framework64\v2.0.50727\System.DirectoryServices.Protocols.dll</HintPath>
- <private>False</private>
- </Reference>
- </ItemGroup>
-
+ <ItemGroup Condition="'$(TargetFramework)' == 'net35'">
+ <Reference Include="System.DirectoryServices.Protocols">
+ <HintPath>$(WINDIR)\Microsoft.NET\Framework64\v2.0.50727\System.DirectoryServices.Protocols.dll</HintPath>
+ <private>False</private>
+ </Reference>
+ </ItemGroup>
- <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
+ <ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<PackageReference Include="System.DirectoryServices.Protocols">
- <Version>5.0.1</Version>
+ <Version>6.0.1</Version>
</PackageReference>
</ItemGroup>
-
- <ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
+ <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="System.DirectoryServices.Protocols">
- <Version>5.0.1</Version>
+ <Version>6.0.1</Version>
</PackageReference>
</ItemGroup>
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs b/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs
index 272e502..ca1811b 100644
--- a/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs
@@ -33,6 +33,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
using System.Text;
namespace Quiddity.Support
@@ -120,6 +123,228 @@ namespace Quiddity.Support
}
+ public static string GetLocalIPAddress(string ipVersion)
+ {
+
+ List<string> ipAddressList = new List<string>();
+ AddressFamily addressFamily;
+
+ if (string.Equals(ipVersion, "IPv4"))
+ {
+ addressFamily = AddressFamily.InterNetwork;
+ }
+ else
+ {
+ addressFamily = AddressFamily.InterNetworkV6;
+ }
+
+ foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
+ {
+
+ if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
+ {
+
+ foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
+ {
+
+ if (ip.Address.AddressFamily == addressFamily)
+ {
+ ipAddressList.Add(ip.Address.ToString());
+ }
+
+ }
+
+ }
+
+ }
+
+ return ipAddressList.FirstOrDefault();
+ }
+
+ public static string GetLocalMACAddress(string ipAddress)
+ {
+ List<string> macAddressList = new List<string>();
+
+ foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
+ {
+
+ if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
+ {
+
+ foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
+ {
+
+ if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6 && string.Equals(ip.Address.ToString(), ipAddress))
+ {
+ macAddressList.Add(networkInterface.GetPhysicalAddress().ToString());
+ }
+
+ }
+
+ }
+
+ }
+
+ return macAddressList.FirstOrDefault();
+ }
+
+ public static int GetNetworkInterfaceIndex(string ipAddress)
+ {
+ int index = 0;
+
+ foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
+ {
+
+ if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
+ {
+
+ foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
+ {
+
+ if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6 && string.Equals(ip.Address.ToString(), ipAddress))
+ {
+ index = networkInterface.GetIPProperties().GetIPv6Properties().Index;
+ break;
+ }
+ else if (ip.Address.AddressFamily == AddressFamily.InterNetwork && string.Equals(ip.Address.ToString(), ipAddress))
+ {
+ index = networkInterface.GetIPProperties().GetIPv4Properties().Index;
+ break;
+ }
+
+ }
+
+ }
+
+ }
+
+ return index;
+ }
+
+ public static bool ValidateStringArguments(string[] arguments, string[] values, string[] validValues)
+ {
+ int i = 0;
+ foreach (string value in values)
+ {
+
+ if (!validValues.Contains(value))
+ {
+ Console.WriteLine(arguments[i].Substring(3) + " value must be " + string.Join("/", validValues));
+ return false;
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+ public static bool ValidateStringArrayArguments(string argument, string[] values, string[] validValues)
+ {
+
+ foreach (string value in values)
+ {
+
+ if (!validValues.Contains(value))
+ {
+ Console.WriteLine(argument.Substring(3) + " value must be " + string.Join("/", validValues));
+ return false;
+ }
+
+ }
+
+ return true;
+ }
+
+ public static bool ValidateIntArguments(string[] arguments, string[] values)
+ {
+
+ int i = 0;
+ foreach (string value in values)
+ {
+
+ if (!string.IsNullOrEmpty(value))
+ {
+
+ try
+ {
+ Int32.Parse(value);
+ return true;
+
+ }
+ catch
+ {
+ Console.WriteLine(arguments[i].Substring(3) + " value must be an integer");
+ return false;
+ }
+
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+ public static bool ValidateIntArrayArguments(string argument, string[] values)
+ {
+
+ int i = 0;
+ foreach (string value in values)
+ {
+
+ if (!string.IsNullOrEmpty(value))
+ {
+
+ try
+ {
+ int.Parse(value);
+ return true;
+
+ }
+ catch
+ {
+ Console.WriteLine(argument.Substring(3) + " values must be integers");
+ return false;
+ }
+
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+ public static bool ValidateIPAddressArguments(string[] arguments, string[] values)
+ {
+
+ int i = 0;
+ foreach (string value in values)
+ {
+
+ if (!string.IsNullOrEmpty(value))
+ {
+
+ try
+ {
+ IPAddress.Parse(value);
+ return true;
+
+ }
+ catch
+ {
+ Console.WriteLine(arguments[i].Substring(3) + " value must be an IP address");
+ return false;
+ }
+
+ }
+
+ i++;
+ }
+
+ return true;
+ }
}
diff --git a/Inveigh/Sniffer/Sniffer.cs b/Inveigh/Sniffer/Sniffer.cs
index 36106cf..0d04edd 100644
--- a/Inveigh/Sniffer/Sniffer.cs
+++ b/Inveigh/Sniffer/Sniffer.cs
@@ -21,6 +21,8 @@ namespace Inveigh
{
class Sniffer
{
+ public static bool isRunning = false;
+
public static void Start(string protocol, string snifferIP, bool isIPV6)
{
byte[] snifferIn = new byte[4] { 1, 0, 0, 0 };
@@ -68,7 +70,9 @@ namespace Inveigh
snifferIPEndPoint = new IPEndPoint(IPAddress.Parse(snifferIP), 0);
snifferSocket.ReceiveBufferSize = 4096;
snifferSocket.Bind(snifferIPEndPoint);
+ snifferSocket.Blocking = false;
snifferSocket.IOControl(IOControlCode.ReceiveAll, snifferIn, snifferOut);
+
}
catch (Exception ex)
{
@@ -88,8 +92,9 @@ namespace Inveigh
}
int packetLength;
+ isRunning = true;
- while (Program.isRunning)
+ while (isRunning)
{
try
@@ -107,8 +112,8 @@ namespace Inveigh
{
packetLength = 0;
}
-
- if (packetLength > 0)
+
+ if (packetLength > 0 && isRunning)
{
IPHeader ipHeader = new IPHeader();
MemoryStream memoryStream = new MemoryStream(snifferData, 0, packetLength);
diff --git a/Inveigh/Support/Arguments.cs b/Inveigh/Support/Arguments.cs
index 83999c8..4c87530 100644
--- a/Inveigh/Support/Arguments.cs
+++ b/Inveigh/Support/Arguments.cs
@@ -12,7 +12,7 @@ namespace Inveigh
{
class Arguments
{
- public static void ValidateArguments()
+ public static bool ValidateArguments()
{
string[] ynArguments =
@@ -103,28 +103,29 @@ namespace Inveigh
Program.argRunTime
};
- ValidateStringArguments(ynArguments, ynArgumentValues, new string[] { "Y", "N" });
- ValidateStringArguments(new string[] { nameof(Program.argConsole) }, new string[] { Program.argConsole }, new string[] { "0", "1", "2", "3", "4", "5" });
+ bool allValid = true;
+ allValid &= Utilities.ValidateStringArguments(ynArguments, ynArgumentValues, new string[] { "Y", "N" });
+ allValid &= Utilities.ValidateStringArguments(new string[] { nameof(Program.argConsole) }, new string[] { Program.argConsole }, new string[] { "0", "1", "2", "3", "4", "5" });
string[] authArguments = { nameof(Program.argHTTPAuth), nameof(Program.argProxyAuth), nameof(Program.argWPADAuth), nameof(Program.argWebDAVAuth) };
string[] authArgumentValues = { Program.argHTTPAuth, Program.argProxyAuth, Program.argWPADAuth, Program.argWebDAVAuth };
- ValidateStringArguments(authArguments, authArgumentValues, new string[] { "ANONYMOUS", "BASIC", "NTLM" });
- ValidateStringArrayArguments(nameof(Program.argDNSTypes), Program.argDNSTypes, new string[] { "A", "SOA", "SRV" });
- ValidateStringArrayArguments(nameof(Program.argDNSSRV), Program.argDNSSRV, new string[] { "LDAP", "KERBEROS", "KPASSWORD", "GC" });
- ValidateStringArrayArguments(nameof(Program.argNBNSTypes), Program.argNBNSTypes, new string[] { "00", "03", "20", "1B", "1C", "1D", "1E" });
- ValidateStringArrayArguments(nameof(Program.argMDNSQuestions), Program.argMDNSQuestions, new string[] { "QM", "QU" });
- ValidateStringArrayArguments(nameof(Program.argMDNSTypes), Program.argMDNSTypes, new string[] { "A", "AAAA", "ANY" });
- ValidateStringArrayArguments(nameof(Program.argLLMNRTypes), Program.argLLMNRTypes, new string[] { "A", "AAAA", "ANY" });
- ValidateIntArguments(intArguments, intArgumentValues);
+ allValid &= Utilities.ValidateStringArguments(authArguments, authArgumentValues, new string[] { "ANONYMOUS", "BASIC", "NTLM" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argDNSTypes), Program.argDNSTypes, new string[] { "A", "SOA", "SRV" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argDNSSRV), Program.argDNSSRV, new string[] { "LDAP", "KERBEROS", "KPASSWORD", "GC" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argNBNSTypes), Program.argNBNSTypes, new string[] { "00", "03", "20", "1B", "1C", "1D", "1E" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argMDNSQuestions), Program.argMDNSQuestions, new string[] { "QM", "QU" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argMDNSTypes), Program.argMDNSTypes, new string[] { "A", "AAAA", "ANY" });
+ allValid &= Utilities.ValidateStringArrayArguments(nameof(Program.argLLMNRTypes), Program.argLLMNRTypes, new string[] { "A", "AAAA", "ANY" });
+ allValid &= Utilities.ValidateIntArguments(intArguments, intArgumentValues);
string[] ipAddressArguments = { nameof(Program.argSnifferIP), nameof(Program.argSnifferIPv6), nameof(Program.argListenerIP), nameof(Program.argListenerIPv6), nameof(Program.argSpooferIP), nameof(Program.argSpooferIPv6) };
string[] ipAddressArgumentValues = { Program.argSnifferIP, Program.argSnifferIPv6, Program.argListenerIP, Program.argListenerIPv6, Program.argSpooferIP, Program.argSpooferIPv6 };
- ValidateIPAddressArguments(ipAddressArguments, ipAddressArgumentValues);
- ValidateIntArrayArguments(nameof(Program.argHTTPPorts), Program.argHTTPPorts);
+ allValid &= Utilities.ValidateIPAddressArguments(ipAddressArguments, ipAddressArgumentValues);
+ allValid &= Utilities.ValidateIntArrayArguments(nameof(Program.argHTTPPorts), Program.argHTTPPorts);
Regex r = new Regex("^[A-Fa-f0-9]{16}$");
if (!string.IsNullOrEmpty(Program.argChallenge) && !r.IsMatch(Program.argChallenge))
{
Console.WriteLine("Challenge is invalid");
- Environment.Exit(0);
+ allValid = false;
}
r = new Regex("^[A-Fa-f0-9]{12}$");
@@ -132,20 +133,22 @@ namespace Inveigh
if (!string.IsNullOrEmpty(Program.argMAC) && !r.IsMatch(Program.argMAC))
{
Console.WriteLine("MAC address is invalid");
- Environment.Exit(0);
+ allValid = false;
}
if ((Program.argDNSTypes.Contains("SOA") || Program.argDNSTypes.Contains("SRV")) && (string.IsNullOrEmpty(Program.argDNSHost) || Program.argDNSHost.Split('.').Count() < 3))
{
- Console.WriteLine("DNSHost must be specified and fully qualified when using DNSTypes SOA or SRV"); Environment.Exit(0);
+ Console.WriteLine("DNSHost must be specified and fully qualified when using DNSTypes SOA or SRV");
+ allValid = false;
}
if (string.Equals(Program.argFileOutput, "Y") && !Directory.Exists(Program.argFileDirectory))
{
Console.WriteLine("FileOutputDirectory is invalid");
- Environment.Exit(0);
+ allValid = false;
}
+ return allValid;
}
public static void ParseArguments()
@@ -188,7 +191,7 @@ namespace Inveigh
if (string.Equals(Program.argSniffer, "Y")) { Program.enabledSniffer = true; }
if (!Program.enabledWindows) { Program.enabledSniffer = false; }
if (string.Equals(Program.argSMB, "Y")) { Program.enabledSMB = true; }
- if (string.Equals(Program.argWebDAV, "Y")) { Program.enabledWebDAV = true; }
+ if (string.Equals(Program.argWebDAV, "Y") && (string.Equals(Program.argHTTP, "Y") || string.Equals(Program.argHTTPS, "Y"))) { Program.enabledWebDAV = true; }
if (string.Equals(Program.argLocal, "Y")) { Program.enabledLocal = true; }
if (string.Equals(Program.argRepeat, "Y")) { Program.enabledRepeat = true; }
@@ -215,7 +218,7 @@ namespace Inveigh
if (Program.enabledIPv4 && string.IsNullOrEmpty(Program.argSnifferIP))
{
- Program.argSnifferIP = GetLocalIPAddress("IPv4");
+ Program.argSnifferIP = Utilities.GetLocalIPAddress("IPv4");
if (string.IsNullOrEmpty(Program.argSnifferIP))
{
@@ -226,7 +229,7 @@ namespace Inveigh
if (Program.enabledIPv6 && string.IsNullOrEmpty(Program.argSnifferIPv6))
{
- Program.argSnifferIPv6 = GetLocalIPAddress("IPv6");
+ Program.argSnifferIPv6 = Utilities.GetLocalIPAddress("IPv6");
if (string.IsNullOrEmpty(Program.argSnifferIPv6))
{
@@ -258,7 +261,7 @@ namespace Inveigh
}
else
{
- Program.argSpooferIP = GetLocalIPAddress("IPv4");
+ Program.argSpooferIP = Utilities.GetLocalIPAddress("IPv4");
if (string.IsNullOrEmpty(Program.argSpooferIP))
{
@@ -278,7 +281,7 @@ namespace Inveigh
}
else
{
- Program.argSpooferIPv6 = GetLocalIPAddress("IPv6");
+ Program.argSpooferIPv6 = Utilities.GetLocalIPAddress("IPv6");
if (string.IsNullOrEmpty(Program.argSpooferIPv6))
{
@@ -351,11 +354,11 @@ namespace Inveigh
if (string.IsNullOrEmpty(Program.argSnifferIPv6))
{
- Program.argMAC = GetLocalMACAddress(GetLocalIPAddress("IPv6"));
+ Program.argMAC = Utilities.GetLocalMACAddress(Utilities.GetLocalIPAddress("IPv6"));
}
else
{
- Program.argMAC = GetLocalMACAddress(Program.argSnifferIPv6);
+ Program.argMAC = Utilities.GetLocalMACAddress(Program.argSnifferIPv6);
}
}
@@ -365,12 +368,12 @@ namespace Inveigh
if (!string.IsNullOrEmpty(Program.argSnifferIP))
{
- Program.networkInterfaceIndexIPv4 = GetNetworkInterfaceIndex(Program.argSniffer);
+ Program.networkInterfaceIndexIPv4 = Utilities.GetNetworkInterfaceIndex(Program.argSniffer);
}
if (!string.IsNullOrEmpty(Program.argSnifferIPv6))
{
- Program.networkInterfaceIndexIPv6 = GetNetworkInterfaceIndex(Program.argSnifferIPv6);
+ Program.networkInterfaceIndexIPv6 = Utilities.GetNetworkInterfaceIndex(Program.argSnifferIPv6);
}
if (Program.enabledInspect)
@@ -401,221 +404,6 @@ namespace Inveigh
}
}
- public static void ValidateStringArguments(string[] arguments, string[] values, string[] validValues)
- {
- int i = 0;
- foreach (string value in values)
- {
-
- if (!validValues.Contains(value))
- {
- Console.WriteLine(arguments[i].Substring(3) + " value must be " + string.Join("/", validValues));
- Environment.Exit(0);
- }
-
- i++;
- }
-
- }
-
- public static void ValidateStringArrayArguments(string argument, string[] values, string[] validValues)
- {
-
- foreach (string value in values)
- {
-
- if (!validValues.Contains(value))
- {
- Console.WriteLine(argument.Substring(3) + " value must be " + string.Join("/", validValues));
- Environment.Exit(0);
- }
-
- }
-
- }
-
- public static void ValidateIntArguments(string[] arguments, string[] values)
- {
-
- int i = 0;
- foreach (string value in values)
- {
-
- if (!string.IsNullOrEmpty(value))
- {
-
- try
- {
- Int32.Parse(value);
-
- }
- catch
- {
- Console.WriteLine(arguments[i].Substring(3) + " value must be an integer");
- Environment.Exit(0);
- }
-
- }
-
- i++;
- }
-
- }
-
- public static void ValidateIntArrayArguments(string argument, string[] values)
- {
-
- int i = 0;
- foreach (string value in values)
- {
-
- if (!string.IsNullOrEmpty(value))
- {
-
- try
- {
- int.Parse(value);
-
- }
- catch
- {
- Console.WriteLine(argument.Substring(3) + " values must be integers");
- Environment.Exit(0);
- }
-
- }
-
- i++;
- }
-
- }
-
- public static void ValidateIPAddressArguments(string[] arguments, string[] values)
- {
-
- int i = 0;
- foreach (string value in values)
- {
-
- if (!string.IsNullOrEmpty(value))
- {
-
- try
- {
- IPAddress.Parse(value);
-
- }
- catch
- {
- Console.WriteLine(arguments[i].Substring(3) + " value must be an IP address");
- Environment.Exit(0);
- }
-
- }
-
- i++;
- }
-
- }
-
- public static string GetLocalIPAddress(string ipVersion)
- {
-
- List<string> ipAddressList = new List<string>();
- AddressFamily addressFamily;
-
- if (string.Equals(ipVersion, "IPv4"))
- {
- addressFamily = AddressFamily.InterNetwork;
- }
- else
- {
- addressFamily = AddressFamily.InterNetworkV6;
- }
-
- foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
- {
-
- if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
- {
-
- foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
- {
-
- if (ip.Address.AddressFamily == addressFamily)
- {
- ipAddressList.Add(ip.Address.ToString());
- }
-
- }
-
- }
-
- }
-
- return ipAddressList.FirstOrDefault();
- }
-
- public static string GetLocalMACAddress(string ipAddress)
- {
- List<string> macAddressList = new List<string>();
-
- foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
- {
-
- if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
- {
-
- foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
- {
-
- if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6 && string.Equals(ip.Address.ToString(), ipAddress))
- {
- macAddressList.Add(networkInterface.GetPhysicalAddress().ToString());
- }
-
- }
-
- }
-
- }
-
- return macAddressList.FirstOrDefault();
- }
-
- public static int GetNetworkInterfaceIndex(string ipAddress)
- {
- int index = 0;
-
- foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
- {
-
- if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet && networkInterface.OperationalStatus == OperationalStatus.Up)
- {
-
- foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
- {
-
- if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6 && string.Equals(ip.Address.ToString(), ipAddress))
- {
- index = networkInterface.GetIPProperties().GetIPv6Properties().Index;
- break;
- }
- else if (ip.Address.AddressFamily == AddressFamily.InterNetwork && string.Equals(ip.Address.ToString(), ipAddress))
- {
- index = networkInterface.GetIPProperties().GetIPv4Properties().Index;
- break;
- }
-
- }
-
- }
-
- }
-
- return index;
- }
-
}
}
diff --git a/Inveigh/Support/Control.cs b/Inveigh/Support/Control.cs
index 9717f4f..b635763 100644
--- a/Inveigh/Support/Control.cs
+++ b/Inveigh/Support/Control.cs
@@ -123,8 +123,13 @@ namespace Inveigh
Output.Queue(String.Format("[+] Inveigh exited at {0}", DateTime.Now.ToString("s")));
Output.ProcessOutput();
Output.ProcessFileOutput();
- Program.isRunning = false;
+ Sniffer.isRunning = false;
Quiddity.HTTPListener.isRunning = false;
+ Quiddity.LDAPListener.isRunning = false;
+ Quiddity.SMBListener.isRunning = false;
+ Quiddity.DNSListener.isRunning = false;
+ Quiddity.DHCPv6Listener.isRunning = false;
+ Program.isRunning = false;
while (Program.consoleList.Count > 0)
{
@@ -245,6 +250,7 @@ namespace Inveigh
public static void StartThreads()
{
+ Thread llmnrListenerThread = null;
if (Program.enabledSniffer)
{
@@ -294,7 +300,7 @@ namespace Inveigh
if (Program.enabledLLMNR)
{
LLMNRListener llmnrListener = new LLMNRListener(uint.Parse(Program.argLLMNRTTL));
- Thread llmnrListenerThread = new Thread(() => llmnrListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP, Program.argSpooferIPv6));
+ llmnrListenerThread = new Thread(() => llmnrListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP, Program.argSpooferIPv6));
llmnrListenerThread.Start();
}
@@ -308,7 +314,7 @@ namespace Inveigh
if (Program.enabledNBNS)
{
NBNSListener nbnsListener = new NBNSListener(uint.Parse(Program.argNBNSTTL));
- Thread nbnsListenerThread = new Thread(() => nbnsListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP, Program.argSpooferIPv6));
+ Thread nbnsListenerThread = new Thread(() => nbnsListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP));
nbnsListenerThread.Start();
}
@@ -331,7 +337,7 @@ namespace Inveigh
}
- }
+ }
if (Program.enabledIPv6)
{
@@ -386,6 +392,7 @@ namespace Inveigh
}
+
}
if (!Program.enabledInspect)
diff --git a/Inveigh/Support/Output.cs b/Inveigh/Support/Output.cs
index 926682c..d44c10f 100644
--- a/Inveigh/Support/Output.cs
+++ b/Inveigh/Support/Output.cs
@@ -796,6 +796,11 @@ namespace Inveigh
{
bool nullarg = true;
+ if (!string.IsNullOrEmpty(arg))
+ {
+ nullarg = false;
+ }
+
Console.WriteLine();
if (nullarg)