msg_basic.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package smb
  2. import (
  3. "encoding/binary"
  4. "imuslab.com/smb/driver/mod/smb/encoder"
  5. )
  6. const ProtocolSmb = "\xFFSMB"
  7. const ProtocolSmb2 = "\xFESMB"
  8. // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/6ab6ca20-b404-41fd-b91a-2ed39e3762ea
  9. type Status uint32
  10. const (
  11. StatusOk Status = 0x00000000
  12. STATUS_PENDING Status = 0x00000103
  13. StatusMoreProcessingRequired Status = 0xc0000016
  14. StatusInvalidParameter Status = 0xc000000d
  15. StatusLogonFailure Status = 0xc000006d
  16. StatusUserSessionDeleted Status = 0xc0000203
  17. STATUS_INVALID_SMB Status = 0x00010002
  18. STATUS_SMB_BAD_TID Status = 0x00050002
  19. STATUS_SMB_BAD_COMMAND Status = 0x00160002
  20. STATUS_SMB_BAD_UID Status = 0x005B0002
  21. STATUS_BUFFER_OVERFLOW Status = 0x80000005
  22. STATUS_NO_MORE_FILES Status = 0x80000006
  23. STATUS_NO_SUCK_FILE Status = 0xC000000f
  24. STATUS_STOPPED_ON_SYMLINK Status = 0x8000002D
  25. STATUS_NOT_IMPLEMENTED Status = 0xC0000002
  26. STATUS_INVALID_PARAMETER Status = 0xC000000D
  27. STATUS_MORE_PROCESSING_REQUIRED Status = 0xC0000016
  28. STATUS_ACCESS_DENIED Status = 0xC0000022
  29. STATUS_BUFFER_TOO_SMALL Status = 0xC0000023
  30. STATUS_OBJECT_NAME_NOT_FOUND Status = 0xC0000034
  31. STATUS_OBJECT_PATH_NOT_FOUND Status = 0xC000003A
  32. STATUS_IO_TIMEOUT Status = 0xC00000B5
  33. STATUS_FILE_IS_A_DIRECTORY Status = 0xC00000BA
  34. STATUS_NOT_SUPPORTED Status = 0xC00000BB
  35. STATUS_NETWORK_SESSION_EXPIRED Status = 0xC000035C
  36. STATUS_SMB_TOO_MANY_UIDS Status = 0xC000205A
  37. STATUS_NETWORK_NAME_DELETED Status = 0xC00000C9
  38. STATUS_FILE_CLOSED Status = 0xC0000128
  39. STATUS_UNSUCCESSFUL Status = 0xC0000001
  40. STATUS_END_OF_FILE Status = 0xC0000011
  41. )
  42. var StatusMap = map[Status]string{
  43. StatusOk: "OK",
  44. StatusMoreProcessingRequired: "More Processing Required",
  45. StatusInvalidParameter: "Invalid Parameter",
  46. StatusLogonFailure: "Logon failed",
  47. StatusUserSessionDeleted: "User session deleted",
  48. }
  49. // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/fac3655a-7eb5-4337-b0ab-244bbcd014e8
  50. const DialectSmb_2_0_2 = 0x0202
  51. const DialectSmb_2_1 = 0x0210
  52. const DialectSmb_3_0 = 0x0300
  53. const DialectSmb_3_0_2 = 0x0302
  54. const DialectSmb_3_1_1 = 0x0311
  55. const DialectSmb2_ALL = 0x02FF
  56. type Command uint16
  57. const (
  58. CommandNegotiate Command = iota //0
  59. CommandSessionSetup //1
  60. CommandLogoff //2
  61. CommandTreeConnect //3
  62. CommandTreeDisconnect //4
  63. CommandCreate //5
  64. CommandClose //6
  65. CommandFlush //7
  66. CommandRead //8
  67. CommandWrite //9
  68. CommandLock //0xa 10
  69. CommandIOCtl //0xb 11
  70. CommandCancel //0xc 12
  71. CommandEcho //0xd 13
  72. CommandFind //QueryDirectory //0xe 14
  73. CommandChangeNotify //0xf 15
  74. CommandQueryInfo //0x10 16
  75. CommandSetInfo //0x11 17
  76. CommandOplockBreak //0x12 18
  77. )
  78. func (c Command) String() string {
  79. switch c {
  80. case CommandNegotiate:
  81. return "CommandNegotiate"
  82. case CommandSessionSetup:
  83. return "CommandSessionSetup"
  84. case CommandLogoff:
  85. return "CommandLogoff"
  86. case CommandTreeConnect:
  87. return "CommandTreeConnect"
  88. case CommandTreeDisconnect:
  89. return "CommandTreeDisconnect"
  90. case CommandCreate:
  91. return "CommandCreate"
  92. case CommandClose:
  93. return "CommandClose"
  94. case CommandFlush:
  95. return "CommandFlush"
  96. case CommandRead:
  97. return "CommandRead"
  98. case CommandWrite:
  99. return "CommandWrite"
  100. case CommandLock:
  101. return "CommandLock"
  102. case CommandIOCtl:
  103. return "CommandIOCtl"
  104. case CommandCancel:
  105. return "CommandCancel"
  106. case CommandEcho:
  107. return "CommandEcho"
  108. case CommandFind:
  109. return "CommandQueryDirectory"
  110. case CommandChangeNotify:
  111. return "CommandChangeNotify"
  112. case CommandQueryInfo:
  113. return "CommandQueryInfo"
  114. case CommandSetInfo:
  115. return "CommandSetInfo"
  116. case CommandOplockBreak:
  117. return "CommandOplockBreak"
  118. default:
  119. return "NA"
  120. }
  121. }
  122. const (
  123. SecurityModeSigningEnabled = 0x001 //When set, indicates that security signatures are enabled on the client. The server MUST ignore this bit.
  124. SecurityModeSigningRequired = 0x002 //When set, indicates that security signatures are required by the client.
  125. )
  126. // const (
  127. // _ byte = iota
  128. // ShareTypeDisk
  129. // ShareTypePipe
  130. // ShareTypePrint
  131. // )
  132. // const (
  133. // ShareFlagManualCaching uint32 = 0x00000000
  134. // ShareFlagAutoCaching uint32 = 0x00000010
  135. // ShareFlagVDOCaching uint32 = 0x00000020
  136. // ShareFlagNoCaching uint32 = 0x00000030
  137. // ShareFlagDFS uint32 = 0x00000001
  138. // ShareFlagDFSRoot uint32 = 0x00000002
  139. // ShareFlagRestriceExclusiveOpens uint32 = 0x00000100
  140. // ShareFlagForceSharedDelete uint32 = 0x00000200
  141. // ShareFlagAllowNamespaceCaching uint32 = 0x00000400
  142. // ShareFlagAccessBasedDirectoryEnum uint32 = 0x00000800
  143. // ShareFlagForceLevelIIOplock uint32 = 0x00001000
  144. // ShareFlagEnableHashV1 uint32 = 0x00002000
  145. // ShareFlagEnableHashV2 uint32 = 0x00004000
  146. // ShareFlagEncryptData uint32 = 0x00008000
  147. // )
  148. // const (
  149. // ShareCapDFS uint32 = 0x00000008
  150. // ShareCapContinuousAvailability uint32 = 0x00000010
  151. // ShareCapScaleout uint32 = 0x00000020
  152. // ShareCapCluster uint32 = 0x00000040
  153. // ShareCapAsymmetric uint32 = 0x00000080
  154. // )
  155. type HeadFlags uint32
  156. const (
  157. SMB2_FLAGS_RESPONSE HeadFlags = 0x00000001
  158. SMB2_FLAGS_ASYNC_COMMAND HeadFlags = 0x00000002
  159. SMB2_FLAGS_SIGNED HeadFlags = 0x00000008
  160. SMB2_FLAGS_PRIORITY_MASK HeadFlags = 0x00000070
  161. SMB2_FLAGS_DFS_OPERATIONS HeadFlags = 0x10000000
  162. SMB2_FLAGS_REPLAY_OPERATION HeadFlags = 0x20000000
  163. )
  164. type Header struct {
  165. ProtocolID []byte `smb:"fixed:4"`
  166. HeaderLength uint16 //StructureSize
  167. CreditCharge uint16
  168. Status Status
  169. Command Command
  170. Credits uint16
  171. Flags HeadFlags //HeadFlags
  172. NextCommand uint32 // Chain Offset 就是这段的大小, 最后一段的时候为0,
  173. MessageID uint64
  174. Reserved uint32
  175. TreeID uint32
  176. SessionID uint64
  177. Signature []byte `smb:"fixed:16"`
  178. }
  179. var _ encoder.BinaryMarshallable = HeadFlags(0)
  180. func (c HeadFlags) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
  181. return MarshalBinary(c, meta, c)
  182. }
  183. func (c HeadFlags) UnmarshalBinary(data []byte, meta *encoder.Metadata) (interface{}, error) {
  184. return UnmarshalBinary(c, data, meta, c)
  185. }
  186. var _ encoder.BinaryMarshallable = Status(0)
  187. func (c Status) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
  188. return MarshalBinary(c, meta, c)
  189. }
  190. func (c Status) UnmarshalBinary(data []byte, meta *encoder.Metadata) (interface{}, error) {
  191. return UnmarshalBinary(c, data, meta, c)
  192. }
  193. var _ encoder.BinaryMarshallable = Command(0)
  194. func (c Command) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
  195. return MarshalBinary(c, meta, c)
  196. }
  197. func (c Command) UnmarshalBinary(data []byte, meta *encoder.Metadata) (interface{}, error) {
  198. return UnmarshalBinary(c, data, meta, c)
  199. }
  200. var _ encoder.BinaryMarshallable = Command(0)
  201. func MarshalBinary[
  202. T Command |
  203. Status |
  204. CreateOptions |
  205. FileAttributes |
  206. AccessMask |
  207. HeadFlags |
  208. PDUType |
  209. CreateDisposition |
  210. FileInformationClass |
  211. CompletionFilter |
  212. ShareAccess |
  213. FindFlags |
  214. CreateAction |
  215. InfoType](
  216. base T, meta *encoder.Metadata, check encoder.BinaryMarshallable) ([]byte, error) {
  217. size := binary.Size(base)
  218. switch size {
  219. default:
  220. timestamp := make([]byte, 2)
  221. binary.LittleEndian.PutUint16(timestamp, uint16(base))
  222. return timestamp, nil
  223. case 4:
  224. timestamp := make([]byte, 4)
  225. binary.LittleEndian.PutUint32(timestamp, uint32(base))
  226. return timestamp, nil
  227. case 1:
  228. timestamp := make([]byte, 1)
  229. timestamp[0] = uint8(base)
  230. return timestamp, nil
  231. }
  232. }
  233. func UnmarshalBinary[
  234. T Command |
  235. Status |
  236. CreateOptions |
  237. FileAttributes |
  238. AccessMask |
  239. HeadFlags |
  240. PDUType |
  241. CreateDisposition |
  242. FileInformationClass |
  243. CompletionFilter |
  244. ShareAccess |
  245. FindFlags |
  246. CreateAction |
  247. InfoType](
  248. base T, data []byte, meta *encoder.Metadata, check encoder.BinaryMarshallable) (T, error) {
  249. size := binary.Size(base)
  250. switch size {
  251. default:
  252. num := binary.LittleEndian.Uint16(data)
  253. meta.CurrOffset += uint64(binary.Size(num))
  254. c := T(num)
  255. return c, nil
  256. case 4:
  257. num := binary.LittleEndian.Uint32(data)
  258. meta.CurrOffset += uint64(binary.Size(num))
  259. c := T(num)
  260. return c, nil
  261. case 1:
  262. num := uint8(data[0])
  263. meta.CurrOffset += uint64(binary.Size(num))
  264. c := T(num)
  265. return c, nil
  266. }
  267. }
  268. type ErrResponse struct {
  269. Header
  270. StructureSize uint16
  271. ErrorContextCount uint8
  272. Reserved uint8
  273. ByteCount uint32
  274. ErrorData uint8
  275. }
  276. func ERR(header Header, stat Status) (interface{}, error) {
  277. header.Flags = SMB2_FLAGS_RESPONSE
  278. header.Status = stat
  279. return ErrResponse{
  280. Header: header,
  281. StructureSize: 0x0009,
  282. }, nil
  283. }