const SMB2_CAPABILITIES: u32 = 0x7F;
const PREAUTH_INTEGRITY_CTX: &[u8] = &[
0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, ];
pub fn build_negotiate_request() -> Vec<u8> {
let dialects: &[u16] = &[0x0311, 0x0300, 0x0210, 0x0202];
let dialect_count = dialects.len() as u16;
let smb2_header_size: usize = 64;
let dialects_size = 2 * dialect_count as usize;
let after_dialects = smb2_header_size + 36 + dialects_size; let neg_ctx_offset = ((after_dialects + 7) & !7) as u32; let padding_size = neg_ctx_offset as usize - after_dialects;
let body_size = 36 + dialects_size + padding_size + PREAUTH_INTEGRITY_CTX.len();
let total = smb2_header_size + body_size;
let mut pkt = vec![0u8; 4 + total];
pkt[1] = ((total >> 16) & 0xFF) as u8;
pkt[2] = ((total >> 8) & 0xFF) as u8;
pkt[3] = (total & 0xFF) as u8;
{
let h = &mut pkt[4..4 + smb2_header_size];
h[0..4].copy_from_slice(b"\xfeSMB"); h[4..6].copy_from_slice(&64u16.to_le_bytes()); h[12..14].copy_from_slice(&0u16.to_le_bytes()); h[18..20].copy_from_slice(&1u16.to_le_bytes()); h[28..36].copy_from_slice(&1u64.to_le_bytes()); }
{
let b = &mut pkt[4 + smb2_header_size..];
b[0..2].copy_from_slice(&36u16.to_le_bytes()); b[2..4].copy_from_slice(&dialect_count.to_le_bytes()); b[4..6].copy_from_slice(&1u16.to_le_bytes()); b[8..12].copy_from_slice(&SMB2_CAPABILITIES.to_le_bytes());
let mut guid = [0u8; 16];
for byte in guid.iter_mut() {
*byte = rand::random();
}
guid[6] = (guid[6] & 0x0F) | 0x40; guid[8] = (guid[8] & 0x3F) | 0x80; b[12..28].copy_from_slice(&guid);
b[28..32].copy_from_slice(&neg_ctx_offset.to_le_bytes()); b[32..34].copy_from_slice(&1u16.to_le_bytes());
for (i, &d) in dialects.iter().enumerate() {
let off = 36 + i * 2;
b[off..off + 2].copy_from_slice(&d.to_le_bytes());
}
let ctx_off = 36 + dialects_size + padding_size;
b[ctx_off..ctx_off + PREAUTH_INTEGRITY_CTX.len()].copy_from_slice(PREAUTH_INTEGRITY_CTX);
}
pkt
}