From 551af5761412a85db3368c2cf6ee186f7b37961a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eloy=20P=C3=A9rez=20Gonz=C3=A1lez?= Date: Wed, 4 May 2022 10:23:15 +0200 Subject: [PATCH 1/2] smb: complete smb1 command codes constants --- rust/src/smb/smb1.rs | 149 +++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 40 deletions(-) diff --git a/rust/src/smb/smb1.rs b/rust/src/smb/smb1.rs index ad8f53cf6f11..4f0206e0b205 100644 --- a/rust/src/smb/smb1.rs +++ b/rust/src/smb/smb1.rs @@ -53,69 +53,138 @@ pub const SMB1_COMMAND_PROCESS_EXIT: u8 = 0x11; pub const SMB1_COMMAND_SEEK: u8 = 0x12; pub const SMB1_COMMAND_LOCK_AND_READ: u8 = 0x13; pub const SMB1_COMMAND_WRITE_AND_UNLOCK: u8 = 0x14; +pub const SMB1_COMMAND_READ_RAW: u8 = 0x1a; +pub const SMB1_COMMAND_READ_MPX: u8 = 0x1b; +pub const SMB1_COMMAND_READ_MPX_SECONDARY: u8 = 0x1c; +pub const SMB1_COMMAND_WRITE_RAW: u8 = 0x1d; +pub const SMB1_COMMAND_WRITE_MPX: u8 = 0x1e; +pub const SMB1_COMMAND_WRITE_MPX_SECONDARY: u8 = 0x1f; +pub const SMB1_COMMAND_WRITE_COMPLETE: u8 = 0x20; +pub const SMB1_COMMAND_QUERY_SERVER: u8 = 0x21; +pub const SMB1_COMMAND_SET_INFORMATION2: u8 = 0x22; +pub const SMB1_COMMAND_QUERY_INFORMATION2: u8 = 0x23; pub const SMB1_COMMAND_LOCKING_ANDX: u8 = 0x24; pub const SMB1_COMMAND_TRANS: u8 = 0x25; +pub const SMB1_COMMAND_TRANS_SECONDARY: u8 = 0x26; +pub const SMB1_COMMAND_IOCTL: u8 = 0x27; +pub const SMB1_COMMAND_IOCTL_SECONDARY: u8 = 0x28; +pub const SMB1_COMMAND_COPY: u8 = 0x29; +pub const SMB1_COMMAND_MOVE: u8 = 0x2a; pub const SMB1_COMMAND_ECHO: u8 = 0x2b; pub const SMB1_COMMAND_WRITE_AND_CLOSE: u8 = 0x2c; pub const SMB1_COMMAND_OPEN_ANDX: u8 = 0x2d; pub const SMB1_COMMAND_READ_ANDX: u8 = 0x2e; pub const SMB1_COMMAND_WRITE_ANDX: u8 = 0x2f; +pub const SMB1_COMMAND_NEW_FILE_SIZE: u8 = 0x30; +pub const SMB1_COMMAND_CLOSE_AND_TREE_DISC: u8 = 0x31; pub const SMB1_COMMAND_TRANS2: u8 = 0x32; pub const SMB1_COMMAND_TRANS2_SECONDARY: u8 = 0x33; pub const SMB1_COMMAND_FIND_CLOSE2: u8 = 0x34; +pub const SMB1_COMMAND_FIND_NOTIFY_CLOSE: u8 = 0x35; +pub const SMB1_COMMAND_TREE_CONNECT: u8 = 0x70; pub const SMB1_COMMAND_TREE_DISCONNECT: u8 = 0x71; pub const SMB1_COMMAND_NEGOTIATE_PROTOCOL: u8 = 0x72; pub const SMB1_COMMAND_SESSION_SETUP_ANDX: u8 = 0x73; pub const SMB1_COMMAND_LOGOFF_ANDX: u8 = 0x74; pub const SMB1_COMMAND_TREE_CONNECT_ANDX: u8 = 0x75; +pub const SMB1_COMMAND_SECURITY_PACKAGE_ANDX: u8 = 0x7e; pub const SMB1_COMMAND_QUERY_INFO_DISK: u8 = 0x80; +pub const SMB1_COMMAND_SEARCH: u8 = 0x81; +pub const SMB1_COMMAND_FIND: u8 = 0x82; +pub const SMB1_COMMAND_FIND_UNIQUE: u8 = 0x83; +pub const SMB1_COMMAND_FIND_CLOSE: u8 = 0x84; pub const SMB1_COMMAND_NT_TRANS: u8 = 0xa0; +pub const SMB1_COMMAND_NT_TRANS_SECONDARY: u8 = 0xa1; pub const SMB1_COMMAND_NT_CREATE_ANDX: u8 = 0xa2; pub const SMB1_COMMAND_NT_CANCEL: u8 = 0xa4; +pub const SMB1_COMMAND_NT_RENAME: u8 = 0xa5; +pub const SMB1_COMMAND_OPEN_PRINT_FILE: u8 = 0xc0; +pub const SMB1_COMMAND_WRITE_PRINT_FILE: u8 = 0xc1; +pub const SMB1_COMMAND_CLOSE_PRINT_FILE: u8 = 0xc2; +pub const SMB1_COMMAND_GET_PRINT_QUEUE: u8 = 0xc3; +pub const SMB1_COMMAND_READ_BULK: u8 = 0xd8; +pub const SMB1_COMMAND_WRITE_BULK: u8 = 0xd9; +pub const SMB1_COMMAND_WRITE_BULK_DATA: u8 = 0xda; +pub const SMB1_COMMAND_INVALID: u8 = 0xfe; pub const SMB1_COMMAND_NONE: u8 = 0xff; pub fn smb1_command_string(c: u8) -> String { match c { - SMB1_COMMAND_CREATE_DIRECTORY => "SMB1_COMMAND_CREATE_DIRECTORY", - SMB1_COMMAND_DELETE_DIRECTORY => "SMB1_COMMAND_DELETE_DIRECTORY", - SMB1_COMMAND_OPEN => "SMB1_COMMAND_OPEN", - SMB1_COMMAND_CREATE => "SMB1_COMMAND_CREATE", - SMB1_COMMAND_CLOSE => "SMB1_COMMAND_CLOSE", - SMB1_COMMAND_FLUSH => "SMB1_COMMAND_FLUSH", - SMB1_COMMAND_DELETE => "SMB1_COMMAND_DELETE", - SMB1_COMMAND_RENAME => "SMB1_COMMAND_RENAME", - SMB1_COMMAND_QUERY_INFORMATION => "SMB1_COMMAND_QUERY_INFORMATION", - SMB1_COMMAND_SET_INFORMATION => "SMB1_COMMAND_SET_INFORMATION", - SMB1_COMMAND_READ => "SMB1_COMMAND_READ", - SMB1_COMMAND_WRITE => "SMB1_COMMAND_WRITE", - SMB1_COMMAND_LOCK_BYTE_RANGE => "SMB1_COMMAND_LOCK_BYTE_RANGE", - SMB1_COMMAND_UNLOCK_BYTE_RANGE => "SMB1_COMMAND_UNLOCK_BYTE_RANGE", - SMB1_COMMAND_CREATE_TEMPORARY => "SMB1_COMMAND_CREATE_TEMPORARY", - SMB1_COMMAND_CREATE_NEW => "SMB1_COMMAND_CREATE_NEW", - SMB1_COMMAND_CHECK_DIRECTORY => "SMB1_COMMAND_CHECK_DIRECTORY", - SMB1_COMMAND_PROCESS_EXIT => "SMB1_COMMAND_PROCESS_EXIT", - SMB1_COMMAND_SEEK => "SMB1_COMMAND_SEEK", - SMB1_COMMAND_LOCK_AND_READ => "SMB1_COMMAND_LOCK_AND_READ", - SMB1_COMMAND_WRITE_AND_UNLOCK => "SMB1_COMMAND_WRITE_AND_UNLOCK", - SMB1_COMMAND_LOCKING_ANDX => "SMB1_COMMAND_LOCKING_ANDX", - SMB1_COMMAND_ECHO => "SMB1_COMMAND_ECHO", - SMB1_COMMAND_WRITE_AND_CLOSE => "SMB1_COMMAND_WRITE_AND_CLOSE", - SMB1_COMMAND_OPEN_ANDX => "SMB1_COMMAND_OPEN_ANDX", - SMB1_COMMAND_READ_ANDX => "SMB1_COMMAND_READ_ANDX", - SMB1_COMMAND_WRITE_ANDX => "SMB1_COMMAND_WRITE_ANDX", - SMB1_COMMAND_TRANS => "SMB1_COMMAND_TRANS", - SMB1_COMMAND_TRANS2 => "SMB1_COMMAND_TRANS2", - SMB1_COMMAND_TRANS2_SECONDARY => "SMB1_COMMAND_TRANS2_SECONDARY", - SMB1_COMMAND_FIND_CLOSE2 => "SMB1_COMMAND_FIND_CLOSE2", - SMB1_COMMAND_TREE_DISCONNECT => "SMB1_COMMAND_TREE_DISCONNECT", - SMB1_COMMAND_NEGOTIATE_PROTOCOL => "SMB1_COMMAND_NEGOTIATE_PROTOCOL", - SMB1_COMMAND_SESSION_SETUP_ANDX => "SMB1_COMMAND_SESSION_SETUP_ANDX", - SMB1_COMMAND_LOGOFF_ANDX => "SMB1_COMMAND_LOGOFF_ANDX", - SMB1_COMMAND_TREE_CONNECT_ANDX => "SMB1_COMMAND_TREE_CONNECT_ANDX", - SMB1_COMMAND_QUERY_INFO_DISK => "SMB1_COMMAND_QUERY_INFO_DISK", - SMB1_COMMAND_NT_TRANS => "SMB1_COMMAND_NT_TRANS", - SMB1_COMMAND_NT_CREATE_ANDX => "SMB1_COMMAND_NT_CREATE_ANDX", - SMB1_COMMAND_NT_CANCEL => "SMB1_COMMAND_NT_CANCEL", + SMB1_COMMAND_CREATE_DIRECTORY => "SMB1_COMMAND_CREATE_DIRECTORY", + SMB1_COMMAND_DELETE_DIRECTORY => "SMB1_COMMAND_DELETE_DIRECTORY", + SMB1_COMMAND_OPEN => "SMB1_COMMAND_OPEN", + SMB1_COMMAND_CREATE => "SMB1_COMMAND_CREATE", + SMB1_COMMAND_CLOSE => "SMB1_COMMAND_CLOSE", + SMB1_COMMAND_FLUSH => "SMB1_COMMAND_FLUSH", + SMB1_COMMAND_DELETE => "SMB1_COMMAND_DELETE", + SMB1_COMMAND_RENAME => "SMB1_COMMAND_RENAME", + SMB1_COMMAND_QUERY_INFORMATION => "SMB1_COMMAND_QUERY_INFORMATION", + SMB1_COMMAND_SET_INFORMATION => "SMB1_COMMAND_SET_INFORMATION", + SMB1_COMMAND_READ => "SMB1_COMMAND_READ", + SMB1_COMMAND_WRITE => "SMB1_COMMAND_WRITE", + SMB1_COMMAND_LOCK_BYTE_RANGE => "SMB1_COMMAND_LOCK_BYTE_RANGE", + SMB1_COMMAND_UNLOCK_BYTE_RANGE => "SMB1_COMMAND_UNLOCK_BYTE_RANGE", + SMB1_COMMAND_CREATE_TEMPORARY => "SMB1_COMMAND_CREATE_TEMPORARY", + SMB1_COMMAND_CREATE_NEW => "SMB1_COMMAND_CREATE_NEW", + SMB1_COMMAND_CHECK_DIRECTORY => "SMB1_COMMAND_CHECK_DIRECTORY", + SMB1_COMMAND_PROCESS_EXIT => "SMB1_COMMAND_PROCESS_EXIT", + SMB1_COMMAND_SEEK => "SMB1_COMMAND_SEEK", + SMB1_COMMAND_LOCK_AND_READ => "SMB1_COMMAND_LOCK_AND_READ", + SMB1_COMMAND_WRITE_AND_UNLOCK => "SMB1_COMMAND_WRITE_AND_UNLOCK", + SMB1_COMMAND_LOCKING_ANDX => "SMB1_COMMAND_LOCKING_ANDX", + SMB1_COMMAND_ECHO => "SMB1_COMMAND_ECHO", + SMB1_COMMAND_WRITE_AND_CLOSE => "SMB1_COMMAND_WRITE_AND_CLOSE", + SMB1_COMMAND_OPEN_ANDX => "SMB1_COMMAND_OPEN_ANDX", + SMB1_COMMAND_READ_ANDX => "SMB1_COMMAND_READ_ANDX", + SMB1_COMMAND_WRITE_ANDX => "SMB1_COMMAND_WRITE_ANDX", + SMB1_COMMAND_TRANS => "SMB1_COMMAND_TRANS", + SMB1_COMMAND_TRANS2 => "SMB1_COMMAND_TRANS2", + SMB1_COMMAND_TRANS2_SECONDARY => "SMB1_COMMAND_TRANS2_SECONDARY", + SMB1_COMMAND_FIND_CLOSE2 => "SMB1_COMMAND_FIND_CLOSE2", + SMB1_COMMAND_TREE_DISCONNECT => "SMB1_COMMAND_TREE_DISCONNECT", + SMB1_COMMAND_NEGOTIATE_PROTOCOL => "SMB1_COMMAND_NEGOTIATE_PROTOCOL", + SMB1_COMMAND_SESSION_SETUP_ANDX => "SMB1_COMMAND_SESSION_SETUP_ANDX", + SMB1_COMMAND_LOGOFF_ANDX => "SMB1_COMMAND_LOGOFF_ANDX", + SMB1_COMMAND_TREE_CONNECT_ANDX => "SMB1_COMMAND_TREE_CONNECT_ANDX", + SMB1_COMMAND_QUERY_INFO_DISK => "SMB1_COMMAND_QUERY_INFO_DISK", + SMB1_COMMAND_NT_TRANS => "SMB1_COMMAND_NT_TRANS", + SMB1_COMMAND_NT_CREATE_ANDX => "SMB1_COMMAND_NT_CREATE_ANDX", + SMB1_COMMAND_NT_CANCEL => "SMB1_COMMAND_NT_CANCEL", + SMB1_COMMAND_READ_RAW => "SMB1_COMMAND_READ_RAW", + SMB1_COMMAND_READ_MPX => "SMB1_COMMAND_READ_MPX", + SMB1_COMMAND_READ_MPX_SECONDARY => "SMB1_COMMAND_READ_MPX_SECONDARY", + SMB1_COMMAND_WRITE_RAW => "SMB1_COMMAND_WRITE_RAW", + SMB1_COMMAND_WRITE_MPX => "SMB1_COMMAND_WRITE_MPX", + SMB1_COMMAND_WRITE_MPX_SECONDARY => "SMB1_COMMAND_WRITE_MPX_SECONDARY", + SMB1_COMMAND_WRITE_COMPLETE => "SMB1_COMMAND_WRITE_COMPLETE", + SMB1_COMMAND_QUERY_SERVER => "SMB1_COMMAND_QUERY_SERVER", + SMB1_COMMAND_SET_INFORMATION2 => "SMB1_COMMAND_SET_INFORMATION2", + SMB1_COMMAND_QUERY_INFORMATION2 => "SMB1_COMMAND_QUERY_INFORMATION2", + SMB1_COMMAND_TRANS_SECONDARY => "SMB1_COMMAND_TRANS_SECONDARY", + SMB1_COMMAND_IOCTL => "SMB1_COMMAND_IOCTL", + SMB1_COMMAND_IOCTL_SECONDARY => "SMB1_COMMAND_IOCTL_SECONDARY", + SMB1_COMMAND_COPY => "SMB1_COMMAND_COPY", + SMB1_COMMAND_MOVE => "SMB1_COMMAND_MOVE", + SMB1_COMMAND_NEW_FILE_SIZE => "SMB1_COMMAND_NEW_FILE_SIZE", + SMB1_COMMAND_CLOSE_AND_TREE_DISC => "SMB1_COMMAND_CLOSE_AND_TREE_DISC", + SMB1_COMMAND_FIND_NOTIFY_CLOSE => "SMB1_COMMAND_FIND_NOTIFY_CLOSE", + SMB1_COMMAND_TREE_CONNECT => "SMB1_COMMAND_TREE_CONNECT", + SMB1_COMMAND_SECURITY_PACKAGE_ANDX => "SMB1_COMMAND_SECURITY_PACKAGE_ANDX", + SMB1_COMMAND_SEARCH => "SMB1_COMMAND_SEARCH", + SMB1_COMMAND_FIND => "SMB1_COMMAND_FIND", + SMB1_COMMAND_FIND_UNIQUE => "SMB1_COMMAND_FIND_UNIQUE", + SMB1_COMMAND_FIND_CLOSE => "SMB1_COMMAND_FIND_CLOSE", + SMB1_COMMAND_NT_TRANS_SECONDARY => "SMB1_COMMAND_NT_TRANS_SECONDARY", + SMB1_COMMAND_NT_RENAME => "SMB1_COMMAND_NT_RENAME", + SMB1_COMMAND_OPEN_PRINT_FILE => "SMB1_COMMAND_OPEN_PRINT_FILE", + SMB1_COMMAND_WRITE_PRINT_FILE => "SMB1_COMMAND_WRITE_PRINT_FILE", + SMB1_COMMAND_CLOSE_PRINT_FILE => "SMB1_COMMAND_CLOSE_PRINT_FILE", + SMB1_COMMAND_GET_PRINT_QUEUE => "SMB1_COMMAND_GET_PRINT_QUEUE", + SMB1_COMMAND_READ_BULK => "SMB1_COMMAND_READ_BULK", + SMB1_COMMAND_WRITE_BULK => "SMB1_COMMAND_WRITE_BULK", + SMB1_COMMAND_WRITE_BULK_DATA => "SMB1_COMMAND_WRITE_BULK_DATA", + SMB1_COMMAND_INVALID => "SMB1_COMMAND_INVALID", + SMB1_COMMAND_NONE => "SMB1_COMMAND_NONE", _ => { return (c).to_string(); }, }.to_string() } From 7a673447282d5a7133bba4fc2f5fc049ca3247e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eloy=20P=C3=A9rez=20Gonz=C3=A1lez?= Date: Wed, 4 May 2022 10:24:27 +0200 Subject: [PATCH 2/2] smb: add smb.cmd keyword Ticket: 5069 --- doc/userguide/rules/index.rst | 1 + doc/userguide/rules/smb-keywords.rst | 245 +++++++++++++++ rust/src/smb/detect.rs | 432 +++++++++++++++++++++++++++ src/Makefile.am | 2 + src/detect-engine-register.c | 2 + src/detect-engine-register.h | 1 + src/detect-smb-cmd.c | 115 +++++++ src/detect-smb-cmd.h | 23 ++ 8 files changed, 821 insertions(+) create mode 100644 doc/userguide/rules/smb-keywords.rst create mode 100644 src/detect-smb-cmd.c create mode 100644 src/detect-smb-cmd.h diff --git a/doc/userguide/rules/index.rst b/doc/userguide/rules/index.rst index 4ef87bdeb88b..a4bd53c3a6ff 100644 --- a/doc/userguide/rules/index.rst +++ b/doc/userguide/rules/index.rst @@ -26,6 +26,7 @@ Suricata Rules snmp-keywords base64-keywords sip-keywords + smb-keywords rfb-keywords mqtt-keywords ike-keywords diff --git a/doc/userguide/rules/smb-keywords.rst b/doc/userguide/rules/smb-keywords.rst new file mode 100644 index 000000000000..c35b3371062d --- /dev/null +++ b/doc/userguide/rules/smb-keywords.rst @@ -0,0 +1,245 @@ +SMB Keywords +============== + +SMB keywords used in both SMB1 and SMB2 protocols. + +smb.cmd +--------- + +Used to match SMB command. Decimal, Hexadecimal or command names (case +insensitive) values are admitted. + + +The following signature are equivalent:: + + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: 10; sid: 1;) + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: 0xa; sid: 1;) + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: lock; sid: 1;) + + +You can also specify several commands separated by comma:: + + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: 10,create,0x4; sid: 1;) + + +Commands will match with both versions of SMB, so very careful using this rule. +For example, the following rule:: + + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: 1; sid: 1;) + + +It will match with the ``SMB2 Session Setup`` and ``SMB1 Delete Directory`` commands. + +Moreover, some commands names are shared by both SMB1 and SMB2, so they will match both. +That can be useful in certain situations but lead to false positives in others, be aware. +For example this rule:: + + alert smb any any -> any any (msg: "Smb command rule"; smb.cmd: create; sid: 1;) + +It will match with SMB2 0x05 and SMB1 0x03 commands codes. + +SMB2 command names: + +================================ ======================== +SMB2 Command Name Code +================================ ======================== +SMB2_COMMAND_NEGOTIATE_PROTOCOL 0x00 +negotiate 0x00 +SMB2_COMMAND_SESSION_SETUP 0x01 +session_setup 0x01 +SMB2_COMMAND_SESSION_LOGOFF 0x02 +logoff 0x02 +SMB2_COMMAND_TREE_CONNECT 0x03 +tree_connect 0x03 +SMB2_COMMAND_TREE_DISCONNECT 0x04 +tree_disconnect 0x04 +SMB2_COMMAND_CREATE 0x05 +create 0x05 +SMB2_COMMAND_CLOSE 0x06 +close 0x06 +SMB2_COMMAND_FLUSH 0x07 +flush 0x07 +SMB2_COMMAND_READ 0x08 +read 0x08 +SMB2_COMMAND_WRITE 0x09 +write 0x09 +SMB2_COMMAND_LOCK 0x0A +lock 0x0A +SMB2_COMMAND_IOCTL 0x0B +ioctl 0x0B +SMB2_COMMAND_CANCEL 0x0C +cancel 0x0C +SMB2_COMMAND_KEEPALIVE 0x0D +echo 0x0D +keep_alive 0x0D +SMB2_COMMAND_FIND 0x0E +query_directory 0x0E +find 0x0E +SMB2_COMMAND_CHANGE_NOTIFY 0x0F +change_notify 0x0F +SMB2_COMMAND_GET_INFO 0x10 +get_info 0x10 +query_info 0x10 +SMB2_COMMAND_SET_INFO 0x11 +set_info 0x11 +SMB2_COMMAND_OPLOCK_BREAK 0x12 +oplock_break 0x12 +================================ ======================== + + +SMB1 command names: + +================================== ======================== +SMB1 Command Name Code +================================== ======================== +SMB1_COMMAND_CREATE_DIRECTORY 0x00 +create_directory 0x00 +SMB1_COMMAND_DELETE_DIRECTORY 0x01 +delete_directory 0x01 +SMB1_COMMAND_OPEN 0x02 +open 0x02 +SMB1_COMMAND_CREATE 0x03 +create 0x03 +SMB1_COMMAND_CLOSE 0x04 +close 0x04 +SMB1_COMMAND_FLUSH 0x05 +flush 0x05 +SMB1_COMMAND_DELETE 0x06 +delete 0x06 +SMB1_COMMAND_RENAME 0x07 +rename 0x07 +SMB1_COMMAND_QUERY_INFORMATION 0x08 +query_information 0x08 +SMB1_COMMAND_SET_INFORMATION 0x09 +set_information 0x09 +SMB1_COMMAND_READ 0x0A +read 0x0A +SMB1_COMMAND_WRITE 0x0B +write 0x0B +SMB1_COMMAND_LOCK_BYTE_RANGE 0x0C +lock_byte_range 0x0C +SMB1_COMMAND_UNLOCK_BYTE_RANGE 0x0D +unlock_byte_range 0x0D +SMB1_COMMAND_CREATE_TEMPORARY 0x0E +create_temporary 0x0E +SMB1_COMMAND_CREATE_NEW 0x0F +create_new 0x0F +SMB1_COMMAND_CHECK_DIRECTORY 0x10 +check_directory 0x10 +SMB1_COMMAND_PROCESS_EXIT 0x11 +process_exit 0x11 +SMB1_COMMAND_SEEK 0x12 +seek 0x12 +SMB1_COMMAND_LOCK_AND_READ 0x13 +lock_and_read 0x13 +SMB1_COMMAND_WRITE_AND_UNLOCK 0x14 +write_and_unlock 0x14 +SMB1_COMMAND_READ_RAW 0x1A +read_raw 0x1A +SMB1_COMMAND_READ_MPX 0x1B +read_mpx 0x1B +SMB1_COMMAND_READ_MPX_SECONDARY 0x1C +read_mpx_secondary 0x1C +SMB1_COMMAND_WRITE_RAW 0x1D +write_raw 0x1D +SMB1_COMMAND_WRITE_MPX 0x1E +write_mpx 0x1E +SMB1_COMMAND_WRITE_MPX_SECONDARY 0x1F +write_mpx_secondary 0x1F +SMB1_COMMAND_WRITE_COMPLETE 0x20 +write_complete 0x20 +SMB1_COMMAND_QUERY_SERVER 0x21 +query_server 0x21 +SMB1_COMMAND_SET_INFORMATION2 0x22 +set_information2 0x22 +SMB1_COMMAND_QUERY_INFORMATION2 0x23 +query_information2 0x23 +SMB1_COMMAND_LOCKING_ANDX 0x24 +locking_andx 0x24 +SMB1_COMMAND_TRANS 0x25 +transaction 0x25 +SMB1_COMMAND_TRANS_SECONDARY 0x26 +transaction_secondary 0x26 +SMB1_COMMAND_IOCTL 0x27 +ioctl 0x27 +SMB1_COMMAND_IOCTL_SECONDARY 0x28 +ioctl_secondary 0x28 +SMB1_COMMAND_COPY 0x29 +copy 0x29 +SMB1_COMMAND_MOVE 0x2A +move 0x2A +SMB1_COMMAND_ECHO 0x2B +echo 0x2B +SMB1_COMMAND_WRITE_AND_CLOSE 0x2C +write_and_close 0x2C +SMB1_COMMAND_OPEN_ANDX 0x2D +open_andx 0x2D +SMB1_COMMAND_READ_ANDX 0x2E +read_andx 0x2E +SMB1_COMMAND_WRITE_ANDX 0x2F +write_andx 0x2F +SMB1_COMMAND_NEW_FILE_SIZE 0x30 +new_file_size 0x30 +SMB1_COMMAND_CLOSE_AND_TREE_DISC 0x31 +close_and_tree_disc 0x31 +SMB1_COMMAND_TRANS2 0x32 +transaction2 0x32 +SMB1_COMMAND_TRANS2_SECONDARY 0x33 +transaction2_secondary 0x33 +SMB1_COMMAND_FIND_CLOSE2 0x34 +find_close2 0x34 +SMB1_COMMAND_FIND_NOTIFY_CLOSE 0x35 +find_notify_close 0x35 +SMB1_COMMAND_TREE_CONNECT 0x70 +tree_connect 0x70 +SMB1_COMMAND_TREE_DISCONNECT 0x71 +tree_disconnect 0x71 +SMB1_COMMAND_NEGOTIATE_PROTOCOL 0x72 +negotiate 0x72 +SMB1_COMMAND_SESSION_SETUP_ANDX 0x73 +session_setup_andx 0x73 +SMB1_COMMAND_LOGOFF_ANDX 0x74 +logoff_andx 0x74 +SMB1_COMMAND_TREE_CONNECT_ANDX 0x75 +tree_connect_andx 0x75 +SMB1_COMMAND_SECURITY_PACKAGE_ANDX 0x7E +security_package_andx 0x7E +SMB1_COMMAND_QUERY_INFO_DISK 0x80 +query_information_disk 0x80 +SMB1_COMMAND_SEARCH 0x81 +search 0x81 +SMB1_COMMAND_FIND 0x82 +find 0x82 +SMB1_COMMAND_FIND_UNIQUE 0x83 +find_unique 0x83 +SMB1_COMMAND_FIND_CLOSE 0x84 +find_close 0x84 +SMB1_COMMAND_NT_TRANS 0xA0 +nt_transact 0xA0 +SMB1_COMMAND_NT_TRANS_SECONDARY 0xA1 +nt_transact_secondary 0xA1 +SMB1_COMMAND_NT_CREATE_ANDX 0xA2 +nt_create_andx 0xA2 +SMB1_COMMAND_NT_CANCEL 0xA4 +nt_cancel 0xA4 +SMB1_COMMAND_NT_RENAME 0xA5 +nt_rename 0xA5 +SMB1_COMMAND_OPEN_PRINT_FILE 0xC0 +open_print_file 0xC0 +SMB1_COMMAND_WRITE_PRINT_FILE 0xC1 +write_print_file 0xC1 +SMB1_COMMAND_CLOSE_PRINT_FILE 0xC2 +close_print_file 0xC2 +SMB1_COMMAND_GET_PRINT_QUEUE 0xC3 +get_print_queue 0xC3 +SMB1_COMMAND_READ_BULK 0xD8 +read_bulk 0xD8 +SMB1_COMMAND_WRITE_BULK 0xD9 +write_bulk 0xD9 +SMB1_COMMAND_WRITE_BULK_DATA 0xDA +write_bulk_data 0xDA +SMB1_COMMAND_INVALID 0xFE +invalid 0xFE +SMB1_COMMAND_NONE 0xFF +no_andx_command 0xFF +================================== ======================== diff --git a/rust/src/smb/detect.rs b/rust/src/smb/detect.rs index a6e1560a1a08..9c851cb92368 100644 --- a/rust/src/smb/detect.rs +++ b/rust/src/smb/detect.rs @@ -20,6 +20,11 @@ use crate::core::*; use crate::smb::smb::*; use crate::dcerpc::detect::{DCEIfaceData, DCEOpnumData, DETECT_DCE_OPNUM_RANGE_UNINITIALIZED}; use crate::dcerpc::dcerpc::DCERPC_TYPE_REQUEST; +use std::ffi::CStr; +use std::os::raw::{c_char, c_void}; +use std::collections::{HashMap, HashSet}; +use super::smb1; +use super::smb2; #[no_mangle] pub unsafe extern "C" fn rs_smb_tx_get_share(tx: &mut SMBTransaction, @@ -201,3 +206,430 @@ pub extern "C" fn rs_smb_tx_get_dce_iface(state: &mut SMBState, } return 0; } + + +#[no_mangle] +pub unsafe extern "C" fn rs_smb_cmd_match( + tx: &mut SMBTransaction, cmd_valid_codes: &mut SmbCmdValidCodes, +) -> u8 { + + let version = tx.vercmd.get_version(); + let (cmd, valid_codes) = if version == 1 { + (tx.vercmd.get_smb1_cmd().1.into(), &cmd_valid_codes.cmd_codes1) + } else { + (tx.vercmd.get_smb2_cmd().1, &cmd_valid_codes.cmd_codes2) + }; + + SCLogDebug!("rs_smb_cmd_match: version {} cmd {}", version, cmd); + + if valid_codes.contains(&cmd) { + return 1; + } + + return 0; +} + + +#[no_mangle] +pub unsafe extern "C" fn rs_smb_cmd_parse(carg: *const c_char) -> *mut c_void { + if carg.is_null() { + return std::ptr::null_mut(); + } + let arg = match CStr::from_ptr(carg).to_str() { + Ok(arg) => arg, + _ => { + return std::ptr::null_mut(); + } + }; + + match parse_cmd_data(arg) { + Ok(detect) => Box::into_raw(Box::new(detect)) as *mut _, + Err(_) => std::ptr::null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn rs_smb_cmd_free(ptr: *mut c_void) { + if ptr != std::ptr::null_mut() { + std::mem::drop(Box::from_raw(ptr as *mut SmbCmdValidCodes)); + } +} + +/// Stores the SMB command codes used to match with smb.cmd keyword. +/// It includes both valid codes for SMB1 and SMB2. +#[derive(Debug, PartialEq)] +pub struct SmbCmdValidCodes { + cmd_codes1: HashSet, + cmd_codes2: HashSet, +} + +impl SmbCmdValidCodes { + + fn new(cmd_codes1: HashSet, cmd_codes2: HashSet) -> Self { + return Self{cmd_codes1, cmd_codes2}; + } + +} + +fn str_to_u16(v: &str) -> Result { + let size; + if v.starts_with("0x") { + let no_prefix = v.trim_start_matches("0x"); + size = u16::from_str_radix(&no_prefix, 16); + } else { + size = u16::from_str_radix(&v, 10); + } + + return size.map_err(|_| ()); +} + +fn parse_cmd_data(arg: &str) -> Result { + let cmd_names1 = gen_smb1_command_names(); + let cmd_names2 = gen_smb2_command_names(); + + let split_args: Vec<&str> = arg.split(',').collect(); + + let mut cmd_codes1 = HashSet::new(); + let mut cmd_codes2 = HashSet::new(); + + for cmd in split_args.iter() { + let cmd = cmd.trim().to_ascii_lowercase(); + + match str_to_u16(&cmd) { + Ok(cmd_code) => { + cmd_codes1.insert(cmd_code); + cmd_codes2.insert(cmd_code); + } + Err(_) => { + let mut in_any = false; + if let Some(cmd_code) = cmd_names1.get(cmd.as_str()) { + cmd_codes1.insert(*cmd_code); + in_any = true; + } + + if let Some(cmd_code) = cmd_names2.get(cmd.as_str()) { + cmd_codes2.insert(*cmd_code); + in_any = true; + } + + if !in_any { + return Err(()); + } + } + } + } + return Ok(SmbCmdValidCodes::new(cmd_codes1, cmd_codes2)); +} + +fn gen_smb2_command_names() -> HashMap { + let commands = [ + smb2::SMB2_COMMAND_NEGOTIATE_PROTOCOL, + smb2::SMB2_COMMAND_SESSION_SETUP, + smb2::SMB2_COMMAND_SESSION_LOGOFF, + smb2::SMB2_COMMAND_TREE_CONNECT, + smb2::SMB2_COMMAND_TREE_DISCONNECT, + smb2::SMB2_COMMAND_CREATE, + smb2::SMB2_COMMAND_CLOSE, + smb2::SMB2_COMMAND_FLUSH, + smb2::SMB2_COMMAND_READ, + smb2::SMB2_COMMAND_WRITE, + smb2::SMB2_COMMAND_LOCK, + smb2::SMB2_COMMAND_IOCTL, + smb2::SMB2_COMMAND_CANCEL, + smb2::SMB2_COMMAND_KEEPALIVE, + smb2::SMB2_COMMAND_FIND, + smb2::SMB2_COMMAND_CHANGE_NOTIFY, + smb2::SMB2_COMMAND_GET_INFO, + smb2::SMB2_COMMAND_SET_INFO, + smb2::SMB2_COMMAND_OPLOCK_BREAK, + ]; + let mut cmd_names2 = HashMap::new(); + + for cmd in commands { + cmd_names2.insert(smb2::smb2_command_string(cmd), cmd); + } + + cmd_names2.insert("negotiate".into(), smb2::SMB2_COMMAND_NEGOTIATE_PROTOCOL); + cmd_names2.insert( + "smb2_command_session_setup".into(), + smb2::SMB2_COMMAND_SESSION_SETUP, + ); + cmd_names2.insert("session_setup".into(), smb2::SMB2_COMMAND_SESSION_SETUP); + cmd_names2.insert("logoff".into(), smb2::SMB2_COMMAND_SESSION_LOGOFF); + cmd_names2.insert("tree_connect".into(), smb2::SMB2_COMMAND_TREE_CONNECT); + cmd_names2.insert("tree_disconnect".into(), smb2::SMB2_COMMAND_TREE_DISCONNECT); + cmd_names2.insert("create".into(), smb2::SMB2_COMMAND_CREATE); + cmd_names2.insert("close".into(), smb2::SMB2_COMMAND_CLOSE); + cmd_names2.insert("flush".into(), smb2::SMB2_COMMAND_FLUSH); + cmd_names2.insert("read".into(), smb2::SMB2_COMMAND_READ); + cmd_names2.insert("write".into(), smb2::SMB2_COMMAND_WRITE); + cmd_names2.insert("lock".into(), smb2::SMB2_COMMAND_LOCK); + cmd_names2.insert("ioctl".into(), smb2::SMB2_COMMAND_IOCTL); + cmd_names2.insert("cancel".into(), smb2::SMB2_COMMAND_CANCEL); + cmd_names2.insert("echo".into(), smb2::SMB2_COMMAND_KEEPALIVE); + cmd_names2.insert("keep_alive".into(), smb2::SMB2_COMMAND_KEEPALIVE); + cmd_names2.insert("find".into(), smb2::SMB2_COMMAND_FIND); + cmd_names2.insert("query_directory".into(), smb2::SMB2_COMMAND_FIND); + cmd_names2.insert("change_notify".into(), smb2::SMB2_COMMAND_CHANGE_NOTIFY); + cmd_names2.insert("get_info".into(), smb2::SMB2_COMMAND_GET_INFO); + cmd_names2.insert("query_info".into(), smb2::SMB2_COMMAND_GET_INFO); + cmd_names2.insert("set_info".into(), smb2::SMB2_COMMAND_SET_INFO); + cmd_names2.insert("oplock_break".into(), smb2::SMB2_COMMAND_OPLOCK_BREAK); + + return cmd_names2; +} + +fn gen_smb1_command_names() -> HashMap { + let commands = [ + smb1::SMB1_COMMAND_CREATE_DIRECTORY, + smb1::SMB1_COMMAND_DELETE_DIRECTORY, + smb1::SMB1_COMMAND_OPEN, + smb1::SMB1_COMMAND_CREATE, + smb1::SMB1_COMMAND_CLOSE, + smb1::SMB1_COMMAND_FLUSH, + smb1::SMB1_COMMAND_DELETE, + smb1::SMB1_COMMAND_RENAME, + smb1::SMB1_COMMAND_QUERY_INFORMATION, + smb1::SMB1_COMMAND_SET_INFORMATION, + smb1::SMB1_COMMAND_READ, + smb1::SMB1_COMMAND_WRITE, + smb1::SMB1_COMMAND_LOCK_BYTE_RANGE, + smb1::SMB1_COMMAND_UNLOCK_BYTE_RANGE, + smb1::SMB1_COMMAND_CREATE_TEMPORARY, + smb1::SMB1_COMMAND_CREATE_NEW, + smb1::SMB1_COMMAND_CHECK_DIRECTORY, + smb1::SMB1_COMMAND_PROCESS_EXIT, + smb1::SMB1_COMMAND_SEEK, + smb1::SMB1_COMMAND_LOCK_AND_READ, + smb1::SMB1_COMMAND_WRITE_AND_UNLOCK, + smb1::SMB1_COMMAND_READ_RAW, + smb1::SMB1_COMMAND_READ_MPX, + smb1::SMB1_COMMAND_READ_MPX_SECONDARY, + smb1::SMB1_COMMAND_WRITE_RAW, + smb1::SMB1_COMMAND_WRITE_MPX, + smb1::SMB1_COMMAND_WRITE_MPX_SECONDARY, + smb1::SMB1_COMMAND_WRITE_COMPLETE, + smb1::SMB1_COMMAND_QUERY_SERVER, + smb1::SMB1_COMMAND_SET_INFORMATION2, + smb1::SMB1_COMMAND_QUERY_INFORMATION2, + smb1::SMB1_COMMAND_LOCKING_ANDX, + smb1::SMB1_COMMAND_TRANS, + smb1::SMB1_COMMAND_TRANS_SECONDARY, + smb1::SMB1_COMMAND_IOCTL, + smb1::SMB1_COMMAND_IOCTL_SECONDARY, + smb1::SMB1_COMMAND_COPY, + smb1::SMB1_COMMAND_MOVE, + smb1::SMB1_COMMAND_ECHO, + smb1::SMB1_COMMAND_WRITE_AND_CLOSE, + smb1::SMB1_COMMAND_OPEN_ANDX, + smb1::SMB1_COMMAND_READ_ANDX, + smb1::SMB1_COMMAND_WRITE_ANDX, + smb1::SMB1_COMMAND_NEW_FILE_SIZE, + smb1::SMB1_COMMAND_CLOSE_AND_TREE_DISC, + smb1::SMB1_COMMAND_TRANS2, + smb1::SMB1_COMMAND_TRANS2_SECONDARY, + smb1::SMB1_COMMAND_FIND_CLOSE2, + smb1::SMB1_COMMAND_FIND_NOTIFY_CLOSE, + smb1::SMB1_COMMAND_TREE_CONNECT, + smb1::SMB1_COMMAND_TREE_DISCONNECT, + smb1::SMB1_COMMAND_NEGOTIATE_PROTOCOL, + smb1::SMB1_COMMAND_SESSION_SETUP_ANDX, + smb1::SMB1_COMMAND_LOGOFF_ANDX, + smb1::SMB1_COMMAND_TREE_CONNECT_ANDX, + smb1::SMB1_COMMAND_SECURITY_PACKAGE_ANDX, + smb1::SMB1_COMMAND_QUERY_INFO_DISK, + smb1::SMB1_COMMAND_SEARCH, + smb1::SMB1_COMMAND_FIND, + smb1::SMB1_COMMAND_FIND_UNIQUE, + smb1::SMB1_COMMAND_FIND_CLOSE, + smb1::SMB1_COMMAND_NT_TRANS, + smb1::SMB1_COMMAND_NT_TRANS_SECONDARY, + smb1::SMB1_COMMAND_NT_CREATE_ANDX, + smb1::SMB1_COMMAND_NT_CANCEL, + smb1::SMB1_COMMAND_NT_RENAME, + smb1::SMB1_COMMAND_OPEN_PRINT_FILE, + smb1::SMB1_COMMAND_WRITE_PRINT_FILE, + smb1::SMB1_COMMAND_CLOSE_PRINT_FILE, + smb1::SMB1_COMMAND_GET_PRINT_QUEUE, + smb1::SMB1_COMMAND_READ_BULK, + smb1::SMB1_COMMAND_WRITE_BULK, + smb1::SMB1_COMMAND_WRITE_BULK_DATA, + smb1::SMB1_COMMAND_INVALID, + smb1::SMB1_COMMAND_NONE, + ]; + + let mut cmd_names1 = HashMap::new(); + + for cmd in commands { + cmd_names1.insert(smb1::smb1_command_string(cmd), cmd); + } + + cmd_names1.insert( + "create_directory".into(), + smb1::SMB1_COMMAND_CREATE_DIRECTORY, + ); + cmd_names1.insert( + "delete_directory".into(), + smb1::SMB1_COMMAND_DELETE_DIRECTORY, + ); + cmd_names1.insert("open".into(), smb1::SMB1_COMMAND_OPEN); + cmd_names1.insert("create".into(), smb1::SMB1_COMMAND_CREATE); + cmd_names1.insert("close".into(), smb1::SMB1_COMMAND_CLOSE); + cmd_names1.insert("flush".into(), smb1::SMB1_COMMAND_FLUSH); + cmd_names1.insert("delete".into(), smb1::SMB1_COMMAND_DELETE); + cmd_names1.insert("rename".into(), smb1::SMB1_COMMAND_RENAME); + cmd_names1.insert( + "query_information".into(), + smb1::SMB1_COMMAND_QUERY_INFORMATION, + ); + cmd_names1.insert("set_information".into(), smb1::SMB1_COMMAND_SET_INFORMATION); + cmd_names1.insert("read".into(), smb1::SMB1_COMMAND_READ); + cmd_names1.insert("write".into(), smb1::SMB1_COMMAND_WRITE); + cmd_names1.insert("lock_byte_range".into(), smb1::SMB1_COMMAND_LOCK_BYTE_RANGE); + cmd_names1.insert( + "unlock_byte_range".into(), + smb1::SMB1_COMMAND_UNLOCK_BYTE_RANGE, + ); + cmd_names1.insert( + "create_temporary".into(), + smb1::SMB1_COMMAND_CREATE_TEMPORARY, + ); + cmd_names1.insert("create_new".into(), smb1::SMB1_COMMAND_CREATE_NEW); + cmd_names1.insert("check_directory".into(), smb1::SMB1_COMMAND_CHECK_DIRECTORY); + cmd_names1.insert("process_exit".into(), smb1::SMB1_COMMAND_PROCESS_EXIT); + cmd_names1.insert("seek".into(), smb1::SMB1_COMMAND_SEEK); + cmd_names1.insert("lock_and_read".into(), smb1::SMB1_COMMAND_LOCK_AND_READ); + cmd_names1.insert( + "write_and_unlock".into(), + smb1::SMB1_COMMAND_WRITE_AND_UNLOCK, + ); + cmd_names1.insert("read_raw".into(), smb1::SMB1_COMMAND_READ_RAW); + cmd_names1.insert("read_mpx".into(), smb1::SMB1_COMMAND_READ_MPX); + cmd_names1.insert( + "read_mpx_secondary".into(), + smb1::SMB1_COMMAND_READ_MPX_SECONDARY, + ); + cmd_names1.insert("write_raw".into(), smb1::SMB1_COMMAND_WRITE_RAW); + cmd_names1.insert("write_mpx".into(), smb1::SMB1_COMMAND_WRITE_MPX); + cmd_names1.insert( + "write_mpx_secondary".into(), + smb1::SMB1_COMMAND_WRITE_MPX_SECONDARY, + ); + cmd_names1.insert("write_complete".into(), smb1::SMB1_COMMAND_WRITE_COMPLETE); + cmd_names1.insert("query_server".into(), smb1::SMB1_COMMAND_QUERY_SERVER); + cmd_names1.insert( + "set_information2".into(), + smb1::SMB1_COMMAND_SET_INFORMATION2, + ); + cmd_names1.insert( + "query_information2".into(), + smb1::SMB1_COMMAND_QUERY_INFORMATION, + ); + cmd_names1.insert("locking_andx".into(), smb1::SMB1_COMMAND_LOCKING_ANDX); + cmd_names1.insert("transaction".into(), smb1::SMB1_COMMAND_TRANS); + cmd_names1.insert( + "transaction_secondary".into(), + smb1::SMB1_COMMAND_TRANS_SECONDARY, + ); + cmd_names1.insert("ioctl".into(), smb1::SMB1_COMMAND_IOCTL); + cmd_names1.insert("ioctl_secondary".into(), smb1::SMB1_COMMAND_IOCTL_SECONDARY); + cmd_names1.insert("copy".into(), smb1::SMB1_COMMAND_COPY); + cmd_names1.insert("move".into(), smb1::SMB1_COMMAND_MOVE); + cmd_names1.insert("echo".into(), smb1::SMB1_COMMAND_ECHO); + cmd_names1.insert("write_and_close".into(), smb1::SMB1_COMMAND_WRITE_AND_CLOSE); + cmd_names1.insert("open_andx".into(), smb1::SMB1_COMMAND_OPEN_ANDX); + cmd_names1.insert("read_andx".into(), smb1::SMB1_COMMAND_READ_ANDX); + cmd_names1.insert("write_andx".into(), smb1::SMB1_COMMAND_WRITE_ANDX); + cmd_names1.insert("new_file_size".into(), smb1::SMB1_COMMAND_NEW_FILE_SIZE); + cmd_names1.insert( + "close_and_tree_disc".into(), + smb1::SMB1_COMMAND_CLOSE_AND_TREE_DISC, + ); + cmd_names1.insert("transaction2".into(), smb1::SMB1_COMMAND_TRANS2); + cmd_names1.insert( + "transaction2_secondary".into(), + smb1::SMB1_COMMAND_TRANS2_SECONDARY, + ); + cmd_names1.insert("find_close2".into(), smb1::SMB1_COMMAND_FIND_CLOSE2); + cmd_names1.insert( + "find_notify_close".into(), + smb1::SMB1_COMMAND_FIND_NOTIFY_CLOSE, + ); + cmd_names1.insert("tree_connect".into(), smb1::SMB1_COMMAND_TREE_CONNECT); + cmd_names1.insert("tree_disconnect".into(), smb1::SMB1_COMMAND_TREE_DISCONNECT); + cmd_names1.insert("negotiate".into(), smb1::SMB1_COMMAND_NEGOTIATE_PROTOCOL); + cmd_names1.insert( + "session_setup_andx".into(), + smb1::SMB1_COMMAND_SESSION_SETUP_ANDX, + ); + cmd_names1.insert("logoff_andx".into(), smb1::SMB1_COMMAND_LOGOFF_ANDX); + cmd_names1.insert( + "tree_connect_andx".into(), + smb1::SMB1_COMMAND_TREE_CONNECT_ANDX, + ); + cmd_names1.insert( + "security_package_andx".into(), + smb1::SMB1_COMMAND_SECURITY_PACKAGE_ANDX, + ); + cmd_names1.insert( + "query_information_disk".into(), + smb1::SMB1_COMMAND_QUERY_INFO_DISK, + ); + cmd_names1.insert("search".into(), smb1::SMB1_COMMAND_SEARCH); + cmd_names1.insert("find".into(), smb1::SMB1_COMMAND_FIND); + cmd_names1.insert("find_unique".into(), smb1::SMB1_COMMAND_FIND_UNIQUE); + cmd_names1.insert("find_close".into(), smb1::SMB1_COMMAND_FIND_CLOSE); + cmd_names1.insert("nt_transact".into(), smb1::SMB1_COMMAND_NT_TRANS); + cmd_names1.insert( + "nt_transact_secondary".into(), + smb1::SMB1_COMMAND_NT_TRANS_SECONDARY, + ); + cmd_names1.insert("nt_create_andx".into(), smb1::SMB1_COMMAND_NT_CREATE_ANDX); + cmd_names1.insert("nt_cancel".into(), smb1::SMB1_COMMAND_NT_CANCEL); + cmd_names1.insert("nt_rename".into(), smb1::SMB1_COMMAND_NT_RENAME); + cmd_names1.insert("open_print_file".into(), smb1::SMB1_COMMAND_OPEN_PRINT_FILE); + cmd_names1.insert( + "write_print_file".into(), + smb1::SMB1_COMMAND_WRITE_PRINT_FILE, + ); + cmd_names1.insert( + "close_print_file".into(), + smb1::SMB1_COMMAND_CLOSE_PRINT_FILE, + ); + cmd_names1.insert("get_print_queue".into(), smb1::SMB1_COMMAND_GET_PRINT_QUEUE); + cmd_names1.insert("read_bulk".into(), smb1::SMB1_COMMAND_READ_BULK); + cmd_names1.insert("write_bulk".into(), smb1::SMB1_COMMAND_WRITE_BULK); + cmd_names1.insert("write_bulk_data".into(), smb1::SMB1_COMMAND_WRITE_BULK_DATA); + cmd_names1.insert("invalid".into(), smb1::SMB1_COMMAND_INVALID); + cmd_names1.insert("no_andx_command".into(), smb1::SMB1_COMMAND_NONE); + + return cmd_names1.into_iter().map(|(k, v)| (k, v.into())).collect(); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_cmd_data() { + let option = "5,negotiate, 0x8"; + + let cmd_names1 = gen_smb1_command_names(); + let cmd_names2 = gen_smb2_command_names(); + + let mut cmd_codes1 = HashSet::new(); + cmd_codes1.insert(5); + cmd_codes1.insert(*cmd_names1.get("negotiate").unwrap()); + cmd_codes1.insert(0x8); + + let mut cmd_codes2 = HashSet::new(); + cmd_codes2.insert(5); + cmd_codes2.insert(*cmd_names2.get("negotiate").unwrap()); + cmd_codes2.insert(0x8); + + assert_eq!( + SmbCmdValidCodes::new(cmd_codes1, cmd_codes2), + parse_cmd_data(option).unwrap(), + ); + } +} diff --git a/src/Makefile.am b/src/Makefile.am index 013d4dad1eb2..1cf571fa3cb1 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -293,6 +293,7 @@ noinst_HEADERS = \ detect-sip-stat-msg.h \ detect-sip-uri.h \ detect-smb-share.h \ + detect-smb-cmd.h \ detect-snmp-community.h \ detect-snmp-pdu_type.h \ detect-snmp-version.h \ @@ -886,6 +887,7 @@ libsuricata_c_a_SOURCES = \ detect-sip-stat-msg.c \ detect-sip-uri.c \ detect-smb-share.c \ + detect-smb-cmd.c \ detect-snmp-community.c \ detect-snmp-pdu_type.c \ detect-snmp-version.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 4a54e429455d..5539dde598e7 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -74,6 +74,7 @@ #include "detect-config.h" #include "detect-smb-share.h" +#include "detect-smb-cmd.h" #include "detect-base64-decode.h" #include "detect-base64-data.h" @@ -581,6 +582,7 @@ void SigTableSetup(void) DetectDceStubDataRegister(); DetectSmbNamedPipeRegister(); DetectSmbShareRegister(); + DetectSmbCmdRegister(); DetectTlsRegister(); DetectTlsValidityRegister(); DetectTlsVersionRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 57e30bb4d7f8..ba9f01bf0415 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -189,6 +189,7 @@ enum DetectKeywordId { DETECT_DCE_STUB_DATA, DETECT_SMB_NAMED_PIPE, DETECT_SMB_SHARE, + DETECT_SMB_CMD, DETECT_ASN1, diff --git a/src/detect-smb-cmd.c b/src/detect-smb-cmd.c new file mode 100644 index 000000000000..e462a8c528c9 --- /dev/null +++ b/src/detect-smb-cmd.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2022 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "suricata-common.h" + +#include "detect.h" +#include "detect-parse.h" + +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-state.h" +#include "detect-engine-prefilter.h" +#include "detect-engine-content-inspection.h" + +#include "detect-smb-cmd.h" +#include "rust.h" + +static int g_smb_cmd_list_id = 0; + +static void DetectSmbCmdFree(DetectEngineCtx *de_ctx, void *ptr) +{ + SCEnter(); + + SCLogDebug("smb_cmd: DetectSmbCmdFree"); + + rs_smb_cmd_free(ptr); + SCReturn; +} + +static int DetectSmbCmdSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) +{ + SCLogDebug("smb_cmd: DetectSmbCmdSetup"); + + if (DetectSignatureSetAppProto(s, ALPROTO_SMB) < 0) + return -1; + + if (arg == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Error parsing smb_cmd option in " + "signature, it needs a value"); + return -1; + } + + void *dod = rs_smb_cmd_parse(arg); + if (dod == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "Error parsing smb_cmd option in " + "signature"); + return -1; + } + + SigMatch *sm = SigMatchAlloc(); + if (sm == NULL) { + DetectSmbCmdFree(de_ctx, dod); + return -1; + } + + sm->type = DETECT_SMB_CMD; + sm->ctx = (void *)dod; + + SigMatchAppendSMToList(s, sm, g_smb_cmd_list_id); + return 0; +} + +static int DetectSmbCmdMatchRust(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, + void *state, void *txv, const Signature *s, const SigMatchCtx *m) +{ + SCEnter(); + + SCLogDebug("smb_cmd: DetectSmbCmdMatchRust"); + + if (rs_smb_cmd_match(txv, (void *)m) != 1) + SCReturnInt(0); + + SCReturnInt(1); +} + +static int DetectEngineInspectSmbCmd(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, + uint8_t flags, void *alstate, void *txv, uint64_t tx_id) +{ + return DetectEngineInspectGenericList( + de_ctx, det_ctx, s, engine->smd, f, flags, alstate, txv, tx_id); +} + +void DetectSmbCmdRegister(void) +{ + sigmatch_table[DETECT_SMB_CMD].name = "smb.cmd"; + sigmatch_table[DETECT_SMB_CMD].alias = "smb_cmd"; + sigmatch_table[DETECT_SMB_CMD].desc = "Match SMB message type"; + sigmatch_table[DETECT_SMB_CMD].Setup = DetectSmbCmdSetup; + sigmatch_table[DETECT_SMB_CMD].Match = NULL; + sigmatch_table[DETECT_SMB_CMD].AppLayerTxMatch = DetectSmbCmdMatchRust; + sigmatch_table[DETECT_SMB_CMD].Free = DetectSmbCmdFree; + + DetectAppLayerInspectEngineRegister2( + "smb_cmd", ALPROTO_SMB, SIG_FLAG_TOSERVER, 0, DetectEngineInspectSmbCmd, NULL); + + DetectAppLayerInspectEngineRegister2( + "smb_cmd", ALPROTO_SMB, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectSmbCmd, NULL); + + g_smb_cmd_list_id = DetectBufferTypeRegister("smb_cmd"); +} diff --git a/src/detect-smb-cmd.h b/src/detect-smb-cmd.h new file mode 100644 index 000000000000..1fe2d4487216 --- /dev/null +++ b/src/detect-smb-cmd.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2022 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __DETECT_SMB_CMD_H__ +#define __DETECT_SMB_CMD_H__ + +void DetectSmbCmdRegister(void); + +#endif /* __DETECT_SMB_CMD_H__ */