mirror of
https://github.com/ivre/masscanned.git
synced 2025-10-06 08:38:20 +00:00
Cleanup & Abstractify
This commit is contained in:
parent
5b97b738e9
commit
99bafe232d
1 changed files with 252 additions and 259 deletions
511
src/proto/smb.rs
511
src/proto/smb.rs
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue