Cleanup & Abstractify

This commit is contained in:
gpotter2 2022-02-11 18:17:40 +01:00
parent 5b97b738e9
commit 99bafe232d

View file

@ -36,14 +36,56 @@ const SECURITY_BLOB: &[u8; 320] = b"`\x82\x01<\x06\x06+\x06\x01\x05\x05\x02\xa0\
// Common // // Common //
//////////// ////////////
pub trait Packet { /// ### PacketDissector
type PacketState; /// A util class used to dissecate fields.
#[derive(Debug, Clone)]
struct PacketDissector<T> {
i: usize,
state: T,
}
impl<T> PacketDissector<T> {
fn new(initial_state: T) -> PacketDissector<T> {
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_u(&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_ule(&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_u(byte, value as usize, next_state, 2) as u16
}
fn read_ule16(&mut self, byte: &u8, value: u16, next_state: T) -> u16 {
self._read_ule(byte, value as usize, next_state, 2) as u16
}
fn read_ule32(&mut self, byte: &u8, value: u32, next_state: T) -> u32 {
self._read_ule(byte, value as usize, next_state, 4) as u32
}
fn read_ule64(&mut self, byte: &u8, value: u64, next_state: T) -> u64 {
self._read_ule(byte, value as usize, next_state, 8) as u64
}
}
pub trait Packet {
fn new() -> Self; fn new() -> Self;
fn i(&self) -> usize;
fn set_i(&mut self, i: usize);
fn state(&self) -> Self::PacketState;
fn set_state(&mut self, state: Self::PacketState);
fn repl(&self) -> Option<Vec<u8>>; fn repl(&self) -> Option<Vec<u8>>;
fn parse(&mut self, byte: &u8); fn parse(&mut self, byte: &u8);
@ -52,51 +94,6 @@ pub trait Packet {
self.parse(byte); self.parse(byte);
} }
} }
fn next_state(&mut self, state: Self::PacketState) {
self.set_state(state);
self.set_i(0);
}
fn next_state_when_i_reaches(&mut self, state: Self::PacketState, i: usize) {
if self.i() == i {
self.next_state(state);
}
}
fn _read_u(
&mut self,
byte: &u8,
value: usize,
next_state: Self::PacketState,
size: usize,
) -> usize {
self.set_i(self.i() + 1);
self.next_state_when_i_reaches(next_state, size);
(value << 8) + *byte as usize
}
fn _read_ule(
&mut self,
byte: &u8,
value: usize,
next_state: Self::PacketState,
size: usize,
) -> usize {
let ret = value + ((*byte as usize) << (8 * self.i()));
self.set_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: Self::PacketState) -> u16 {
self._read_u(byte, value as usize, next_state, 2) as u16
}
fn read_ule16(&mut self, byte: &u8, value: u16, next_state: Self::PacketState) -> u16 {
self._read_ule(byte, value as usize, next_state, 2) as u16
}
fn read_ule32(&mut self, byte: &u8, value: u32, next_state: Self::PacketState) -> u32 {
self._read_ule(byte, value as usize, next_state, 4) as u32
}
fn read_ule64(&mut self, byte: &u8, value: u64, next_state: Self::PacketState) -> u64 {
self._read_ule(byte, value as usize, next_state, 8) as u64
}
} }
///////////// /////////////
@ -114,8 +111,7 @@ enum NBTSessionState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct NBTSession<T: Packet> { struct NBTSession<T: Packet> {
// DISSECTION // DISSECTION
state: NBTSessionState, d: PacketDissector<NBTSessionState>,
i: usize,
// STRUCT // STRUCT
nb_type: u8, nb_type: u8,
length: u16, length: u16,
@ -123,25 +119,9 @@ struct NBTSession<T: Packet> {
} }
impl<T: Packet> Packet for NBTSession<T> { impl<T: Packet> Packet for NBTSession<T> {
type PacketState = NBTSessionState;
fn i(&self) -> usize {
self.i
}
fn set_i(&mut self, i: usize) {
self.i = i;
}
fn state(&self) -> Self::PacketState {
self.state
}
fn set_state(&mut self, state: Self::PacketState) {
self.state = state;
}
fn new() -> NBTSession<T> { fn new() -> NBTSession<T> {
Self { Self {
state: NBTSessionState::NBType, d: PacketDissector::new(NBTSessionState::NBType),
i: 0,
nb_type: 0, nb_type: 0,
length: 0, length: 0,
payload: None, payload: None,
@ -149,16 +129,16 @@ impl<T: Packet> Packet for NBTSession<T> {
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self.state { match self.d.state {
NBTSessionState::NBType => { NBTSessionState::NBType => {
self.nb_type = *byte; self.nb_type = *byte;
self.next_state(NBTSessionState::Reserved); self.d.next_state(NBTSessionState::Reserved);
} }
NBTSessionState::Reserved => { NBTSessionState::Reserved => {
self.next_state(NBTSessionState::Length); self.d.next_state(NBTSessionState::Length);
} }
NBTSessionState::Length => { NBTSessionState::Length => {
self.length = self.read_u16(byte, self.length, NBTSessionState::End) self.length = self.d.read_u16(byte, self.length, NBTSessionState::End)
} }
NBTSessionState::End => match self.get_payload() { NBTSessionState::End => match self.get_payload() {
Some(pay) => pay.parse(byte), Some(pay) => pay.parse(byte),
@ -214,8 +194,7 @@ enum SMB1HeaderState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SMB1Header { struct SMB1Header {
// DISSECTION // DISSECTION
state: SMB1HeaderState, d: PacketDissector<SMB1HeaderState>,
i: usize,
// STRUCT // STRUCT
start: [u8; 4], start: [u8; 4],
command: u8, command: u8,
@ -232,25 +211,9 @@ struct SMB1Header {
} }
impl Packet for SMB1Header { impl Packet for SMB1Header {
type PacketState = SMB1HeaderState;
fn i(&self) -> usize {
self.i
}
fn set_i(&mut self, i: usize) {
self.i = i;
}
fn state(&self) -> Self::PacketState {
self.state
}
fn set_state(&mut self, state: Self::PacketState) {
self.state = state;
}
fn new() -> SMB1Header { fn new() -> SMB1Header {
Self { Self {
state: SMB1HeaderState::Start, d: PacketDissector::new(SMB1HeaderState::Start),
i: 0,
start: [0; 4], start: [0; 4],
command: 0, command: 0,
status: 0, status: 0,
@ -267,50 +230,55 @@ impl Packet for SMB1Header {
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self.state { match self.d.state {
SMB1HeaderState::Start => { SMB1HeaderState::Start => {
self.start[self.i] = *byte; self.start[self.d.i] = *byte;
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB1HeaderState::Command, 4); self.d
.next_state_when_i_reaches(SMB1HeaderState::Command, 4);
} }
SMB1HeaderState::Command => { SMB1HeaderState::Command => {
self.command = *byte; self.command = *byte;
self.next_state(SMB1HeaderState::Status); self.d.next_state(SMB1HeaderState::Status);
} }
SMB1HeaderState::Status => { SMB1HeaderState::Status => {
self.status = self.read_ule32(byte, self.status, SMB1HeaderState::Flags); self.status = self.d.read_ule32(byte, self.status, SMB1HeaderState::Flags);
} }
SMB1HeaderState::Flags => { SMB1HeaderState::Flags => {
self.flags = *byte; self.flags = *byte;
self.next_state(SMB1HeaderState::Flags2); self.d.next_state(SMB1HeaderState::Flags2);
} }
SMB1HeaderState::Flags2 => { SMB1HeaderState::Flags2 => {
self.flags2 = self.read_ule16(byte, self.flags2, SMB1HeaderState::PIDHigh); self.flags2 = self
.d
.read_ule16(byte, self.flags2, SMB1HeaderState::PIDHigh);
} }
SMB1HeaderState::PIDHigh => { SMB1HeaderState::PIDHigh => {
self.pid_high = self.pid_high =
self.read_ule16(byte, self.pid_high, SMB1HeaderState::SecuritySignature); self.d
.read_ule16(byte, self.pid_high, SMB1HeaderState::SecuritySignature);
} }
SMB1HeaderState::SecuritySignature => { SMB1HeaderState::SecuritySignature => {
self.security_signature[self.i] = *byte; self.security_signature[self.d.i] = *byte;
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB1HeaderState::Reserved, 8); self.d
.next_state_when_i_reaches(SMB1HeaderState::Reserved, 8);
} }
SMB1HeaderState::Reserved => { SMB1HeaderState::Reserved => {
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB1HeaderState::TID, 2); self.d.next_state_when_i_reaches(SMB1HeaderState::TID, 2);
} }
SMB1HeaderState::TID => { SMB1HeaderState::TID => {
self.tid = self.read_ule16(byte, self.tid, SMB1HeaderState::PIDLow); self.tid = self.d.read_ule16(byte, self.tid, SMB1HeaderState::PIDLow);
} }
SMB1HeaderState::PIDLow => { SMB1HeaderState::PIDLow => {
self.pid_low = self.read_ule16(byte, self.pid_low, SMB1HeaderState::UID); self.pid_low = self.d.read_ule16(byte, self.pid_low, SMB1HeaderState::UID);
} }
SMB1HeaderState::UID => { SMB1HeaderState::UID => {
self.uid = self.read_ule16(byte, self.uid, SMB1HeaderState::MID); self.uid = self.d.read_ule16(byte, self.uid, SMB1HeaderState::MID);
} }
SMB1HeaderState::MID => { SMB1HeaderState::MID => {
self.mid = self.read_ule16(byte, self.mid, SMB1HeaderState::End); self.mid = self.d.read_ule16(byte, self.mid, SMB1HeaderState::End);
} }
SMB1HeaderState::End => match self.get_payload() { SMB1HeaderState::End => match self.get_payload() {
Some(pay) => pay.parse(byte), Some(pay) => pay.parse(byte),
@ -380,8 +348,7 @@ enum SMB1NegotiateRequestState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SMB1NegotiateRequest { struct SMB1NegotiateRequest {
// DISSECTION // DISSECTION
state: SMB1NegotiateRequestState, d: PacketDissector<SMB1NegotiateRequestState>,
i: usize,
_tmp_dialect: Option<SMB1Dialect>, _tmp_dialect: Option<SMB1Dialect>,
// STRUCT // STRUCT
word_count: u8, word_count: u8,
@ -390,25 +357,9 @@ struct SMB1NegotiateRequest {
} }
impl Packet for SMB1NegotiateRequest { impl Packet for SMB1NegotiateRequest {
type PacketState = SMB1NegotiateRequestState;
fn i(&self) -> usize {
self.i
}
fn set_i(&mut self, i: usize) {
self.i = i;
}
fn state(&self) -> Self::PacketState {
self.state
}
fn set_state(&mut self, state: Self::PacketState) {
self.state = state;
}
fn new() -> SMB1NegotiateRequest { fn new() -> SMB1NegotiateRequest {
Self { Self {
state: SMB1NegotiateRequestState::WordCount, d: PacketDissector::new(SMB1NegotiateRequestState::WordCount),
i: 0,
_tmp_dialect: None, _tmp_dialect: None,
word_count: 0, word_count: 0,
byte_count: 0, byte_count: 0,
@ -417,24 +368,25 @@ impl Packet for SMB1NegotiateRequest {
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self.state { match self.d.state {
SMB1NegotiateRequestState::WordCount => { SMB1NegotiateRequestState::WordCount => {
self.word_count = *byte; self.word_count = *byte;
self.next_state(SMB1NegotiateRequestState::ByteCount); self.d.next_state(SMB1NegotiateRequestState::ByteCount);
} }
SMB1NegotiateRequestState::ByteCount => { SMB1NegotiateRequestState::ByteCount => {
self.byte_count = self.byte_count =
self.read_ule16(byte, self.byte_count, SMB1NegotiateRequestState::Dialects); self.d
.read_ule16(byte, self.byte_count, SMB1NegotiateRequestState::Dialects);
} }
SMB1NegotiateRequestState::Dialects => { SMB1NegotiateRequestState::Dialects => {
self.i += 1; self.d.i += 1;
match self._tmp_dialect.as_mut() { match self._tmp_dialect.as_mut() {
Some(dial) => { Some(dial) => {
if *byte == 0 { if *byte == 0 {
// Final nul byte: dialect is finished // Final nul byte: dialect is finished
self.dialects.push(dial.clone()); self.dialects.push(dial.clone());
self._tmp_dialect = None; self._tmp_dialect = None;
self.next_state_when_i_reaches( self.d.next_state_when_i_reaches(
SMB1NegotiateRequestState::End, SMB1NegotiateRequestState::End,
self.byte_count as usize, self.byte_count as usize,
); );
@ -454,42 +406,8 @@ impl Packet for SMB1NegotiateRequest {
} }
} }
// fn new(data: &[u8]) -> Option<Self> {
// if data.len() < 15 {
// return None;
// }
// let word_count = data[0];
// let byte_count = LittleEndian::read_u16(&data[1..3]);
// let mut dialects = Vec::new();
// let mut i: usize = 3;
// while i < 3 + byte_count as usize {
// if i + 1 > data.len() {
// break;
// };
// // dialect_string is a string that ends with a \0 char
// let string_term = match data[i + 1..].iter().position(|&x| x == b'\0') {
// Some(x) => x,
// None => break,
// };
// let dialect_string = match std::str::from_utf8(&data[i + 1..i + 1 + string_term]) {
// Ok(x) => x,
// _ => break,
// };
// dialects.push(SMB1Dialect {
// buffer_format: data[i],
// dialect_string: String::from(dialect_string),
// });
// i += 2 + string_term;
// }
// Some(SMB1NegotiateRequest {
// word_count,
// byte_count,
// dialects,
// })
// }
fn repl(&self) -> Option<Vec<u8>> { fn repl(&self) -> Option<Vec<u8>> {
if !matches!(self.state, SMB1NegotiateRequestState::End) { if !matches!(self.d.state, SMB1NegotiateRequestState::End) {
return None; return None;
} }
let mut resp: Vec<u8> = Vec::new(); let mut resp: Vec<u8> = Vec::new();
@ -595,8 +513,7 @@ enum SMB2HeaderState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SMB2Header { struct SMB2Header {
// DISSECTION // DISSECTION
state: SMB2HeaderState, d: PacketDissector<SMB2HeaderState>,
i: usize,
// STRUCT // STRUCT
start: [u8; 4], start: [u8; 4],
structure_size: u16, structure_size: u16,
@ -615,25 +532,9 @@ struct SMB2Header {
} }
impl Packet for SMB2Header { impl Packet for SMB2Header {
type PacketState = SMB2HeaderState;
fn i(&self) -> usize {
self.i
}
fn set_i(&mut self, i: usize) {
self.i = i;
}
fn state(&self) -> Self::PacketState {
self.state
}
fn set_state(&mut self, state: Self::PacketState) {
self.state = state;
}
fn new() -> SMB2Header { fn new() -> SMB2Header {
SMB2Header { SMB2Header {
state: SMB2HeaderState::Start, d: PacketDissector::new(SMB2HeaderState::Start),
i: 0,
start: [0; 4], start: [0; 4],
structure_size: 0, structure_size: 0,
credit_charge: 0, credit_charge: 0,
@ -651,52 +552,67 @@ impl Packet for SMB2Header {
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self.state { match self.d.state {
SMB2HeaderState::Start => { SMB2HeaderState::Start => {
self.start[self.i] = *byte; self.start[self.d.i] = *byte;
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB2HeaderState::StructureSize, 4); self.d
.next_state_when_i_reaches(SMB2HeaderState::StructureSize, 4);
} }
SMB2HeaderState::StructureSize => { SMB2HeaderState::StructureSize => {
self.structure_size = self.structure_size =
self.read_ule16(byte, self.structure_size, SMB2HeaderState::CreditsCharge) self.d
.read_ule16(byte, self.structure_size, SMB2HeaderState::CreditsCharge)
} }
SMB2HeaderState::CreditsCharge => { SMB2HeaderState::CreditsCharge => {
self.credit_charge = self.credit_charge =
self.read_ule16(byte, self.credit_charge, SMB2HeaderState::Status) self.d
.read_ule16(byte, self.credit_charge, SMB2HeaderState::Status)
} }
SMB2HeaderState::Status => { SMB2HeaderState::Status => {
self.status = self.read_ule32(byte, self.status, SMB2HeaderState::Command) self.status = self
.d
.read_ule32(byte, self.status, SMB2HeaderState::Command)
} }
SMB2HeaderState::Command => { SMB2HeaderState::Command => {
self.command = self.command =
self.read_ule16(byte, self.command, SMB2HeaderState::CreditsRequested) self.d
.read_ule16(byte, self.command, SMB2HeaderState::CreditsRequested)
} }
SMB2HeaderState::CreditsRequested => { SMB2HeaderState::CreditsRequested => {
self.credits_requested = self.credits_requested =
self.read_ule16(byte, self.credits_requested, SMB2HeaderState::Flags) self.d
.read_ule16(byte, self.credits_requested, SMB2HeaderState::Flags)
} }
SMB2HeaderState::Flags => { SMB2HeaderState::Flags => {
self.flags = self.read_ule32(byte, self.flags, SMB2HeaderState::NextCommand) self.flags = self
.d
.read_ule32(byte, self.flags, SMB2HeaderState::NextCommand)
} }
SMB2HeaderState::NextCommand => { SMB2HeaderState::NextCommand => {
self.next_command = self.next_command =
self.read_ule32(byte, self.next_command, SMB2HeaderState::MessageId) self.d
.read_ule32(byte, self.next_command, SMB2HeaderState::MessageId)
} }
SMB2HeaderState::MessageId => { SMB2HeaderState::MessageId => {
self.message_id = self.read_ule64(byte, self.message_id, SMB2HeaderState::AsyncId) self.message_id = self
.d
.read_ule64(byte, self.message_id, SMB2HeaderState::AsyncId)
} }
SMB2HeaderState::AsyncId => { SMB2HeaderState::AsyncId => {
self.async_id = self.read_ule64(byte, self.async_id, SMB2HeaderState::SessionId) self.async_id = self
.d
.read_ule64(byte, self.async_id, SMB2HeaderState::SessionId)
} }
SMB2HeaderState::SessionId => { SMB2HeaderState::SessionId => {
self.session_id = self.session_id =
self.read_ule64(byte, self.session_id, SMB2HeaderState::SecuritySignature) self.d
.read_ule64(byte, self.session_id, SMB2HeaderState::SecuritySignature)
} }
SMB2HeaderState::SecuritySignature => { SMB2HeaderState::SecuritySignature => {
self.security_signature[self.i] = *byte; self.security_signature[self.d.i] = *byte;
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB2HeaderState::End, 16); self.d.next_state_when_i_reaches(SMB2HeaderState::End, 16);
} }
SMB2HeaderState::End => match self.get_payload() { SMB2HeaderState::End => match self.get_payload() {
Some(pay) => pay.parse(byte), Some(pay) => pay.parse(byte),
@ -740,10 +656,10 @@ impl SMB2Header {
// Negotiate // Negotiate
SMB2Payload::NegotiateRequest(SMB2NegotiateRequest::new()) SMB2Payload::NegotiateRequest(SMB2NegotiateRequest::new())
} }
// 0x0001 => { 0x0001 => {
// // Setup // Setup
// SMB2Payload::SetupRequest(SMB2SetupRequest::new()) SMB2Payload::SetupRequest(SMB2SetupRequest::new())
// } }
_ => None?, _ => None?,
}); });
self.payload.as_mut() self.payload.as_mut()
@ -766,8 +682,7 @@ enum SMB2NegotiateRequestState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SMB2NegotiateRequest { struct SMB2NegotiateRequest {
// DISSECTION // DISSECTION
state: SMB2NegotiateRequestState, d: PacketDissector<SMB2NegotiateRequestState>,
i: usize,
_tmp_dialect: u16, _tmp_dialect: u16,
// STRUCT // STRUCT
structure_size: u16, structure_size: u16,
@ -780,25 +695,9 @@ struct SMB2NegotiateRequest {
const EPOCH_1601: u64 = 11644473600; const EPOCH_1601: u64 = 11644473600;
impl Packet for SMB2NegotiateRequest { impl Packet for SMB2NegotiateRequest {
type PacketState = SMB2NegotiateRequestState;
fn i(&self) -> usize {
self.i
}
fn set_i(&mut self, i: usize) {
self.i = i;
}
fn state(&self) -> Self::PacketState {
self.state
}
fn set_state(&mut self, state: Self::PacketState) {
self.state = state;
}
fn new() -> Self { fn new() -> Self {
SMB2NegotiateRequest { SMB2NegotiateRequest {
state: SMB2NegotiateRequestState::StructureSize, d: PacketDissector::new(SMB2NegotiateRequestState::StructureSize),
i: 0,
_tmp_dialect: 0, _tmp_dialect: 0,
structure_size: 0, structure_size: 0,
dialect_count: 0, dialect_count: 0,
@ -810,61 +709,64 @@ impl Packet for SMB2NegotiateRequest {
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self.state { match self.d.state {
SMB2NegotiateRequestState::StructureSize => { SMB2NegotiateRequestState::StructureSize => {
self.structure_size = self.read_ule16( self.structure_size = self.d.read_ule16(
byte, byte,
self.structure_size, self.structure_size,
SMB2NegotiateRequestState::DialectCount, SMB2NegotiateRequestState::DialectCount,
); );
} }
SMB2NegotiateRequestState::DialectCount => { SMB2NegotiateRequestState::DialectCount => {
self.dialect_count = self.read_ule16( self.dialect_count = self.d.read_ule16(
byte, byte,
self.dialect_count, self.dialect_count,
SMB2NegotiateRequestState::SecurityMode, SMB2NegotiateRequestState::SecurityMode,
); );
} }
SMB2NegotiateRequestState::SecurityMode => { SMB2NegotiateRequestState::SecurityMode => {
self.security_mode = self.read_ule16( self.security_mode = self.d.read_ule16(
byte, byte,
self.security_mode, self.security_mode,
SMB2NegotiateRequestState::Reserved, SMB2NegotiateRequestState::Reserved,
); );
} }
SMB2NegotiateRequestState::Reserved => { SMB2NegotiateRequestState::Reserved => {
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB2NegotiateRequestState::Capabilities, 2); self.d
.next_state_when_i_reaches(SMB2NegotiateRequestState::Capabilities, 2);
} }
SMB2NegotiateRequestState::Capabilities => { SMB2NegotiateRequestState::Capabilities => {
self.capabilities = self.read_ule32( self.capabilities = self.d.read_ule32(
byte, byte,
self.capabilities, self.capabilities,
SMB2NegotiateRequestState::ClientGUID, SMB2NegotiateRequestState::ClientGUID,
); );
} }
SMB2NegotiateRequestState::ClientGUID => { SMB2NegotiateRequestState::ClientGUID => {
self.client_guid[self.i] = *byte; self.client_guid[self.d.i] = *byte;
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches( self.d.next_state_when_i_reaches(
SMB2NegotiateRequestState::NegotiateAndReserved2, SMB2NegotiateRequestState::NegotiateAndReserved2,
16, 16,
); );
} }
SMB2NegotiateRequestState::NegotiateAndReserved2 => { SMB2NegotiateRequestState::NegotiateAndReserved2 => {
self.i += 1; self.d.i += 1;
self.next_state_when_i_reaches(SMB2NegotiateRequestState::Dialects, 8); self.d
.next_state_when_i_reaches(SMB2NegotiateRequestState::Dialects, 8);
} }
SMB2NegotiateRequestState::Dialects => { SMB2NegotiateRequestState::Dialects => {
self._tmp_dialect = self._tmp_dialect =
self.read_ule16(byte, self._tmp_dialect, SMB2NegotiateRequestState::Dialects); self.d
if self.i == 0 { .read_ule16(byte, self._tmp_dialect, SMB2NegotiateRequestState::Dialects);
if self.d.i == 0 {
// Add to dialects list when finished // Add to dialects list when finished
self.dialects.insert(self._tmp_dialect); self.dialects.insert(self._tmp_dialect);
self._tmp_dialect = 0; self._tmp_dialect = 0;
// Check if dialects list is finished // Check if dialects list is finished
if self.dialects.len() == self.dialect_count as usize { if self.dialects.len() == self.dialect_count as usize {
self.state = SMB2NegotiateRequestState::End; self.d.state = SMB2NegotiateRequestState::End;
} }
} }
} }
@ -874,7 +776,7 @@ impl Packet for SMB2NegotiateRequest {
} }
} }
fn repl(&self) -> Option<Vec<u8>> { fn repl(&self) -> Option<Vec<u8>> {
if !matches!(self.state, SMB2NegotiateRequestState::End) { if !matches!(self.d.state, SMB2NegotiateRequestState::End) {
return None; return None;
} }
let mut resp: Vec<u8> = Vec::new(); let mut resp: Vec<u8> = Vec::new();
@ -912,41 +814,131 @@ impl Packet for SMB2NegotiateRequest {
resp.extend_from_slice(&0x80_u16.to_le_bytes()); // SecurityBloboffset resp.extend_from_slice(&0x80_u16.to_le_bytes()); // SecurityBloboffset
resp.extend_from_slice(&(SECURITY_BLOB.len() as u16).to_le_bytes()); // SecurityBlobLength resp.extend_from_slice(&(SECURITY_BLOB.len() as u16).to_le_bytes()); // SecurityBlobLength
resp.extend_from_slice(&0x0_u32.to_le_bytes()); // NegotiateContextOffset resp.extend_from_slice(&0x0_u32.to_le_bytes()); // NegotiateContextOffset
resp.extend_from_slice(SECURITY_BLOB); // SecurityBlob resp.extend_from_slice(SECURITY_BLOB); // SecurityBlobw
warn!("SMB2 Negotiate-Protocol-Reply ({})", dialect_name); warn!("SMB2 Negotiate-Protocol-Reply ({})", dialect_name);
Some(resp) Some(resp)
} }
} }
// #[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
// struct SMB2SetupRequest {} enum SMB2SetupRequestState {
// impl SMB2SetupRequest { StructureSize,
// fn new() -> Self { Flags,
// SMB2SetupRequest {} SecurityMode,
// } Capabilities,
Channel,
SecurityBufferOffset,
SecurityLen,
PreviousSessionId,
SecurityBlob,
End,
}
// fn repl(&self) -> Option<Vec<u8>> { #[derive(Debug, Clone)]
// (None, None) struct SMB2SetupRequest {
// } // DISSECTION
// } d: PacketDissector<SMB2SetupRequestState>,
// STRUCT
structure_size: u16,
flags: u8,
security_mode: u8,
capabilities: u32,
channel: u32,
security_buffer_offset: u16,
security_len: u16,
previous_session_id: u64,
}
impl Packet for SMB2SetupRequest {
fn new() -> Self {
SMB2SetupRequest {
d: PacketDissector::new(SMB2SetupRequestState::StructureSize),
structure_size: 0,
flags: 0,
security_mode: 0,
capabilities: 0,
channel: 0,
security_buffer_offset: 0,
security_len: 0,
previous_session_id: 0,
}
}
fn parse(&mut self, byte: &u8) {
match self.d.state {
SMB2SetupRequestState::StructureSize => {
self.structure_size =
self.d
.read_ule16(byte, self.structure_size, SMB2SetupRequestState::Flags);
}
SMB2SetupRequestState::Flags => {
self.flags = *byte;
self.d.next_state(SMB2SetupRequestState::SecurityMode);
}
SMB2SetupRequestState::SecurityMode => {
self.security_mode = *byte;
self.d.next_state(SMB2SetupRequestState::Capabilities);
}
SMB2SetupRequestState::Capabilities => {
self.capabilities =
self.d
.read_ule32(byte, self.capabilities, SMB2SetupRequestState::Channel);
}
SMB2SetupRequestState::Channel => {
self.channel = self.d.read_ule32(
byte,
self.channel,
SMB2SetupRequestState::SecurityBufferOffset,
);
}
SMB2SetupRequestState::SecurityBufferOffset => {
self.security_buffer_offset = self.d.read_ule16(
byte,
self.security_buffer_offset,
SMB2SetupRequestState::SecurityLen,
);
}
SMB2SetupRequestState::SecurityLen => {
self.security_len = self.d.read_ule16(
byte,
self.security_len,
SMB2SetupRequestState::PreviousSessionId,
);
}
SMB2SetupRequestState::PreviousSessionId => {
self.previous_session_id =
self.d
.read_ule64(byte, self.previous_session_id, SMB2SetupRequestState::SecurityBlob);
}
SMB2SetupRequestState::SecurityBlob => {
// TODO ? Not super useful TBH, also this is ASN.1 :///
self.d.next_state(SMB2SetupRequestState::End);
},
SMB2SetupRequestState::End => {}
}
}
fn repl(&self) -> Option<Vec<u8>> {
None
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum SMB2Payload { enum SMB2Payload {
NegotiateRequest(SMB2NegotiateRequest), NegotiateRequest(SMB2NegotiateRequest),
// SetupRequest(SMB2SetupRequest), SetupRequest(SMB2SetupRequest),
} }
impl SMB2Payload { impl SMB2Payload {
fn repl(&self) -> Option<Vec<u8>> { fn repl(&self) -> Option<Vec<u8>> {
match self { match self {
SMB2Payload::NegotiateRequest(x) => x.repl(), SMB2Payload::NegotiateRequest(x) => x.repl(),
// SMB2Payload::SetupRequest(x) => x.repl(), SMB2Payload::SetupRequest(x) => x.repl(),
} }
} }
fn parse(&mut self, byte: &u8) { fn parse(&mut self, byte: &u8) {
match self { match self {
SMB2Payload::NegotiateRequest(x) => x.parse(byte), SMB2Payload::NegotiateRequest(x) => x.parse(byte),
// SMB2Payload::SetupRequest(x) => x.repl(), SMB2Payload::SetupRequest(x) => x.parse(byte),
} }
} }
} }
@ -1097,6 +1089,7 @@ mod tests {
assert_eq!(smb2.security_signature, [0; 16]); assert_eq!(smb2.security_signature, [0; 16]);
let neg_request = match smb2.payload.expect("Error while reading payload") { let neg_request = match smb2.payload.expect("Error while reading payload") {
SMB2Payload::NegotiateRequest(x) => x, SMB2Payload::NegotiateRequest(x) => x,
_ => panic!("Invalid payload type"),
}; };
assert_eq!(neg_request.structure_size, 36); assert_eq!(neg_request.structure_size, 36);
assert_eq!(neg_request.dialect_count, 8); assert_eq!(neg_request.dialect_count, 8);