diff --git a/src/proto/dissector.rs b/src/proto/dissector.rs
new file mode 100644
index 0000000..a370e12
--- /dev/null
+++ b/src/proto/dissector.rs
@@ -0,0 +1,92 @@
+// This file is part of masscanned.
+// Copyright 2021 - The IVRE project
+//
+// Masscanned is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Masscanned is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Masscanned. If not, see .
+
+use crate::proto::ClientInfo;
+use crate::proto::TCPControlBlock;
+use crate::Masscanned;
+
+////////////
+// Common //
+////////////
+
+/// ### PacketDissector
+/// A util class used to dissect fields.
+#[derive(Debug, Clone)]
+pub struct PacketDissector {
+ pub i: usize,
+ pub state: T,
+}
+
+impl PacketDissector {
+ pub fn new(initial_state: T) -> PacketDissector {
+ return PacketDissector {
+ i: 0,
+ state: initial_state,
+ };
+ }
+ pub fn next_state(&mut self, state: T) {
+ self.state = state;
+ self.i = 0;
+ }
+ pub fn next_state_when_i_reaches(&mut self, state: T, i: usize) {
+ if self.i == i {
+ self.next_state(state);
+ }
+ }
+ fn _read_usize(&mut self, byte: &u8, value: usize, next_state: T, size: usize) -> usize {
+ self.i += 1;
+ self.next_state_when_i_reaches(next_state, size);
+ (value << 8) + *byte as usize
+ }
+ fn _read_ulesize(&mut self, byte: &u8, value: usize, next_state: T, size: usize) -> usize {
+ let ret = value + ((*byte as usize) << (8 * self.i));
+ self.i += 1;
+ self.next_state_when_i_reaches(next_state, size);
+ ret
+ }
+ pub fn read_u16(&mut self, byte: &u8, value: u16, next_state: T) -> u16 {
+ self._read_usize(byte, value as usize, next_state, 2) as u16
+ }
+ pub fn read_ule16(&mut self, byte: &u8, value: u16, next_state: T) -> u16 {
+ self._read_ulesize(byte, value as usize, next_state, 2) as u16
+ }
+ pub fn read_u32(&mut self, byte: &u8, value: u32, next_state: T) -> u32 {
+ self._read_usize(byte, value as usize, next_state, 4) as u32
+ }
+ pub fn read_ule32(&mut self, byte: &u8, value: u32, next_state: T) -> u32 {
+ self._read_ulesize(byte, value as usize, next_state, 4) as u32
+ }
+ pub fn read_ule64(&mut self, byte: &u8, value: u64, next_state: T) -> u64 {
+ self._read_ulesize(byte, value as usize, next_state, 8) as u64
+ }
+}
+
+pub trait MPacket {
+ fn new() -> Self;
+ fn repl(
+ &self,
+ _masscanned: &Masscanned,
+ _client_info: &ClientInfo,
+ _tcb: Option<&mut TCPControlBlock>,
+ ) -> Option>;
+ fn parse(&mut self, byte: &u8);
+
+ fn parse_all(&mut self, bytes: &[u8]) {
+ for byte in bytes {
+ self.parse(byte);
+ }
+ }
+}
diff --git a/src/proto/smb.rs b/src/proto/smb.rs
index 1d17a3b..2356eb8 100644
--- a/src/proto/smb.rs
+++ b/src/proto/smb.rs
@@ -23,6 +23,8 @@ use crate::client::ClientInfo;
use crate::proto::TCPControlBlock;
use crate::Masscanned;
+use crate::proto::dissector::{MPacket, PacketDissector};
+
// NBTSession + SMB Header
// netbios type (1 byte) + reserved (1 byte) + length (2 bytes) + SMB MAGIC (4 bytes)
//
@@ -33,70 +35,6 @@ pub const SMB2_PATTERN_MAGIC: &[u8; 8] = b"\x00\x00**\xfeSMB";
const SECURITY_BLOB_NEG_PROTO: &[u8] = b"`\x82\x01<\x06\x06+\x06\x01\x05\x05\x02\xa0\x82\x0100\x82\x01,\xa0\x1a0\x18\x06\n+\x06\x01\x04\x01\x827\x02\x02\x1e\x06\n+\x06\x01\x04\x01\x827\x02\x02\n\xa2\x82\x01\x0c\x04\x82\x01\x08NEGOEXTS\x01\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00p\x00\x00\x001<*:\xc7+<\xa9m\xac8t\xa7\xdd\x1d[\xf4Rk\x17\x03\x8aK\x91\xc2\t}\x9a\x8f\xe6,\x96\\Q$/\x90MG\xc7\xad\x8f\x87k\"\x02\xbf\xc6\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\\3S\r\xea\xf9\rM\xb2\xecJ\xe3xn\xc3\x08NEGOEXTS\x03\x00\x00\x00\x01\x00\x00\x00@\x00\x00\x00\x98\x00\x00\x001<*:\xc7+<\xa9m\xac8t\xa7\xdd\x1d[\\3S\r\xea\xf9\rM\xb2\xecJ\xe3xn\xc3\x08@\x00\x00\x00X\x00\x00\x000V\xa0T0R0'\x80%0#1!0\x1f\x06\x03U\x04\x03\x13\x18Token Signing Public Key0'\x80%0#1!0\x1f\x06\x03U\x04\x03\x13\x18Token Signing Public Key";
const SECURITY_BLOB_CHALLENGE: &[u8] = b"\xa1\x81\x9c0\x81\x99\xa0\x03\n\x01\x01\xa1\x0c\x06\n+\x06\x01\x04\x01\x827\x02\x02\n\xa2\x81\x83\x04\x81\x80NTLMSSP\x00\x02\x00\x00\x00\x08\x00\x08\x008\x00\x00\x00\x15\x82\x8a\xe2$\x91\xa8\xf6\xf3\x89-4\x00\x00\x00\x00\x00\x00\x00\x00@\x00@\x00@\x00\x00\x00\n\x00aJ\x00\x00\x00\x0fW\x00I\x00N\x001\x00\x02\x00\x08\x00W\x00I\x00N\x001\x00\x01\x00\x08\x00W\x00I\x00N\x001\x00\x04\x00\x08\x00W\x00I\x00N\x001\x00\x03\x00\x08\x00W\x00I\x00N\x001\x00\x07\x00\x08\x00\xff&9\xf5B\x1d\xd8\x01\x00\x00\x00\x00";
-////////////
-// Common //
-////////////
-
-/// ### PacketDissector
-/// A util class used to dissect fields.
-#[derive(Debug, Clone)]
-struct PacketDissector {
- i: usize,
- state: T,
-}
-impl PacketDissector {
- fn new(initial_state: T) -> PacketDissector {
- return PacketDissector {
- i: 0,
- state: initial_state,
- };
- }
- fn next_state(&mut self, state: T) {
- self.state = state;
- self.i = 0;
- }
- fn next_state_when_i_reaches(&mut self, state: T, i: usize) {
- if self.i == i {
- self.next_state(state);
- }
- }
- fn _read_usize(&mut self, byte: &u8, value: usize, next_state: T, size: usize) -> usize {
- self.i += 1;
- self.next_state_when_i_reaches(next_state, size);
- (value << 8) + *byte as usize
- }
- fn _read_ulesize(&mut self, byte: &u8, value: usize, next_state: T, size: usize) -> usize {
- let ret = value + ((*byte as usize) << (8 * self.i));
- self.i += 1;
- self.next_state_when_i_reaches(next_state, size);
- ret
- }
- fn read_u16(&mut self, byte: &u8, value: u16, next_state: T) -> u16 {
- self._read_usize(byte, value as usize, next_state, 2) as u16
- }
- fn read_ule16(&mut self, byte: &u8, value: u16, next_state: T) -> u16 {
- self._read_ulesize(byte, value as usize, next_state, 2) as u16
- }
- fn read_ule32(&mut self, byte: &u8, value: u32, next_state: T) -> u32 {
- self._read_ulesize(byte, value as usize, next_state, 4) as u32
- }
- fn read_ule64(&mut self, byte: &u8, value: u64, next_state: T) -> u64 {
- self._read_ulesize(byte, value as usize, next_state, 8) as u64
- }
-}
-
-pub trait MPacket {
- fn new() -> Self;
- fn repl(&self) -> Option>;
- fn parse(&mut self, byte: &u8);
-
- fn parse_all(&mut self, bytes: &[u8]) {
- for byte in bytes {
- self.parse(byte);
- }
- }
-}
-
/////////////
// Netbios //
/////////////
@@ -148,8 +86,13 @@ impl MPacket for NBTSession {
}
}
- fn repl(&self) -> Option> {
- let payload_resp = self.payload.as_ref()?.repl()?;
+ fn repl(
+ &self,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
+ let payload_resp = self.payload.as_ref()?.repl(masscanned, client_info, tcb)?;
let mut resp: Vec = Vec::new();
let size = payload_resp.len() & 0x1ffff; // 7 first bits are 0
resp.push(0x0);
@@ -288,8 +231,13 @@ impl MPacket for SMB1Header {
}
}
- fn repl(&self) -> Option> {
- let payload_resp = self.payload.as_ref()?.repl()?;
+ fn repl(
+ &self,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
+ let payload_resp = self.payload.as_ref()?.repl(masscanned, client_info, tcb)?;
let mut resp: Vec = Vec::new();
resp.extend_from_slice(b"\xffSMB"); // Start
resp.push(self.command); // Command
@@ -407,7 +355,12 @@ impl MPacket for SMB1NegotiateRequest {
}
}
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ _masscanned: &Masscanned,
+ _client_info: &ClientInfo,
+ _tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
if !matches!(self.d.state, SMB1NegotiateRequestState::End) {
return None;
}
@@ -592,7 +545,12 @@ impl MPacket for SMB1SessionSetupRequest {
SMB1SessionSetupRequestState::End => {}
}
}
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ _masscanned: &Masscanned,
+ _client_info: &ClientInfo,
+ _tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
if !matches!(self.d.state, SMB1SessionSetupRequestState::End) {
return None;
}
@@ -625,10 +583,15 @@ enum SMB1Payload {
}
impl SMB1Payload {
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
match self {
- SMB1Payload::NegotiateRequest(x) => x.repl(),
- SMB1Payload::SessionSetupRequest(x) => x.repl(),
+ SMB1Payload::NegotiateRequest(x) => x.repl(masscanned, client_info, tcb),
+ SMB1Payload::SessionSetupRequest(x) => x.repl(masscanned, client_info, tcb),
}
}
fn parse(&mut self, byte: &u8) {
@@ -771,8 +734,13 @@ impl MPacket for SMB2Header {
}
}
- fn repl(&self) -> Option> {
- let payload_resp = self.payload.as_ref()?.repl()?;
+ fn repl(
+ &self,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
+ let payload_resp = self.payload.as_ref()?.repl(masscanned, client_info, tcb)?;
let mut resp: Vec = Vec::new();
resp.extend_from_slice(b"\xfeSMB"); // Start
resp.extend_from_slice(&64_u16.to_le_bytes()); // StructureSize
@@ -925,7 +893,12 @@ impl MPacket for SMB2NegotiateRequest {
}
}
}
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ _masscanned: &Masscanned,
+ _client_info: &ClientInfo,
+ _tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
if !matches!(self.d.state, SMB2NegotiateRequestState::End) {
return None;
}
@@ -1077,7 +1050,12 @@ impl MPacket for SMB2SessionSetupRequest {
}
}
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ _masscanned: &Masscanned,
+ _client_info: &ClientInfo,
+ _tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
if !matches!(self.d.state, SMB2SetupRequestState::End) {
return None;
}
@@ -1099,10 +1077,15 @@ enum SMB2Payload {
}
impl SMB2Payload {
- fn repl(&self) -> Option> {
+ fn repl(
+ &self,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
+ ) -> Option> {
match self {
- SMB2Payload::NegotiateRequest(x) => x.repl(),
- SMB2Payload::SessionSetupRequest(x) => x.repl(),
+ SMB2Payload::NegotiateRequest(x) => x.repl(masscanned, client_info, tcb),
+ SMB2Payload::SessionSetupRequest(x) => x.repl(masscanned, client_info, tcb),
}
}
fn parse(&mut self, byte: &u8) {
@@ -1119,28 +1102,28 @@ impl SMB2Payload {
pub fn repl_smb1<'a>(
data: &'a [u8],
- _masscanned: &Masscanned,
- _client_info: &ClientInfo,
- _tcb: Option<&mut TCPControlBlock>,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
) -> Option> {
let mut nbtsession: NBTSession = NBTSession::new();
for byte in data {
nbtsession.parse(byte);
}
- nbtsession.repl()
+ nbtsession.repl(masscanned, client_info, tcb)
}
pub fn repl_smb2<'a>(
data: &'a [u8],
- _masscanned: &Masscanned,
- _client_info: &ClientInfo,
- _tcb: Option<&mut TCPControlBlock>,
+ masscanned: &Masscanned,
+ client_info: &ClientInfo,
+ tcb: Option<&mut TCPControlBlock>,
) -> Option> {
let mut nbtsession: NBTSession = NBTSession::new();
for byte in data {
nbtsession.parse(byte);
}
- nbtsession.repl()
+ nbtsession.repl(masscanned, client_info, tcb)
}
///////////