msg_file_loctl.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package smb
  2. import (
  3. "github.com/izouxv/logx"
  4. "imuslab.com/smb/driver/mod/smb/encoder"
  5. )
  6. // Function属性
  7. const (
  8. FSCTL_DFS_GET_REFERRALS = 0x00060194
  9. FSCTL_PIPE_PEEK = 0x0011400C
  10. FSCTL_PIPE_WAIT = 0x00110018
  11. FSCTL_PIPE_TRANSCEIVE uint32 = 0x0011C017
  12. FSCTL_SRV_COPYCHUNK = 0x001440F2
  13. FSCTL_SRV_ENUMERATE_SNAPSHOTS = 0x00144064
  14. FSCTL_SRV_REQUEST_RESUME_KEY = 0x00140078
  15. FSCTL_SRV_READ_HASH = 0x001441bb
  16. FSCTL_SRV_COPYCHUNK_WRITE = 0x001480F2
  17. FSCTL_LMR_REQUEST_RESILIENCY = 0x001401D4
  18. FSCTL_QUERY_NETWORK_INTERFACE_INFO = 0x001401FC
  19. FSCTL_SET_REPARSE_POINT = 0x000900A4
  20. FSCTL_DFS_GET_REFERRALS_EX = 0x000601B0
  21. FSCTL_FILE_LEVEL_TRIM = 0x00098208
  22. FSCTL_VALIDATE_NEGOTIATE_INFO = 0x00140204
  23. )
  24. // Flags属性
  25. const (
  26. SMB2_0_IOCTL_IS_IOCTL = 0x00000000
  27. SMB2_0_IOCTL_IS_FSCTL = 0x00000001
  28. )
  29. func init() {
  30. commandRequestMap[CommandIOCtl] = func() DataI {
  31. return &IOCTLRequest{}
  32. }
  33. }
  34. // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5c03c9d6-15de-48a2-9835-8fb37f8a79d8
  35. type IOCTLRequest struct {
  36. Header
  37. StructureSize uint16
  38. Reserved uint16
  39. Function uint32
  40. GUIDHandle GUID //GUIDHandle []byte `smb:"fixed:16"`
  41. InputOffset uint32 `smb:"offset:Buffer"`
  42. InputLength uint32 `smb:"len:Buffer"`
  43. MaxInputSize uint32
  44. OutputOffset uint32
  45. OutputLength uint32
  46. MaxOutputSize uint32
  47. Flags uint32
  48. Reserved2 uint32
  49. Buffer []byte
  50. //Buffer interface{}
  51. }
  52. // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/f70eccb6-e1be-4db8-9c47-9ac86ef18dbb
  53. type IOCTLResponse struct {
  54. Header
  55. StructureSize uint16 //always 49
  56. Reserved uint16
  57. Function uint32 //CtlCode
  58. GUIDHandle GUID //FileId []byte `smb:"fixed:16"`
  59. BlobOffset uint32 //InputOffset
  60. BlobLength uint32 //InputCount
  61. BlobOffset2 uint32 //OutputOffset
  62. BlobLength2 uint32 //OutputCount
  63. Flags uint32
  64. Reserved2 uint32
  65. Buffer []byte
  66. }
  67. func (data *IOCTLRequest) ServerAction(ctx *DataCtx) (interface{}, error) {
  68. data.Header.Flags = SMB2_FLAGS_RESPONSE
  69. if data.Flags != SMB2_0_IOCTL_IS_FSCTL {
  70. return ERR(data.Header, STATUS_NOT_SUPPORTED)
  71. }
  72. if !data.GUIDHandle.IsSvrSvc(ctx.session) {
  73. return ERR(data.Header, STATUS_NOT_SUPPORTED)
  74. }
  75. var pdudata []byte
  76. /*
  77. if data.Flags == SMB2_0_IOCTL_IS_FSCTL {
  78. decoded, _ := hex.DecodeString("980000000f000000000000000000000000e1f505000000001700000000000000fe8000000000000000ebcb3570ade0f20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
  79. pdudata = decoded
  80. log.Println(pdudata)
  81. }
  82. */
  83. switch data.Function {
  84. case FSCTL_PIPE_WAIT:
  85. piple := FSCTLPIPEWAITRequestStruct{}
  86. if err := encoder.Unmarshal(data.Buffer, &piple); err != nil {
  87. }
  88. nameStr := string(piple.Name)
  89. logx.Debug("Unmarshalling Ioctl stdin pipe response ["+nameStr+"]", nil)
  90. case FSCTL_PIPE_TRANSCEIVE:
  91. _, err := DcerpcWrite(ctx, &WriteRequest{Data: data.Buffer})
  92. if err != nil {
  93. return ERR(data.Header, STATUS_UNSUCCESSFUL)
  94. }
  95. pdudata, err = DcerpcReadRaw(ctx)
  96. if err != nil {
  97. return ERR(data.Header, STATUS_UNSUCCESSFUL)
  98. }
  99. }
  100. resp := IOCTLResponse{
  101. Header: data.Header,
  102. StructureSize: 0x31,
  103. Function: data.Function,
  104. GUIDHandle: data.GUIDHandle,
  105. BlobOffset2: 0x70,
  106. BlobLength2: uint32(len(pdudata)),
  107. Buffer: pdudata,
  108. }
  109. return &resp, nil
  110. }
  111. // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/f030a3b9-539c-4c7b-a893-86b795b9b711
  112. // 请求服务器等待连接
  113. type FSCTLPIPEWAITRequestStruct struct {
  114. Timeout uint64 // 毫秒单位
  115. NameLength uint32
  116. TimeoutSpecified uint8 // 一个布尔值,指定是否忽略Timeout参数
  117. Padding uint8
  118. Name []byte // 命名管道名称的Unicode字符串,名称不得包含“\pipe\”
  119. }
  120. func (c *SessionC) NewFSCTLPIPEWAITRequest(pipename string) FSCTLPIPEWAITRequestStruct {
  121. pipeName := encoder.ToUnicode(pipename)
  122. return FSCTLPIPEWAITRequestStruct{
  123. NameLength: uint32(len(pipeName)),
  124. TimeoutSpecified: 1,
  125. Padding: 0,
  126. Name: pipeName,
  127. }
  128. }
  129. /*
  130. // 连接并绑定命名管道,并拿到管道句柄
  131. func (c *Session) ConnectAndWriteStdInPipes(pipename string) (treeid uint32, pipehandle []byte, err error) {
  132. timeout := uint64(500000)
  133. treeId, err := c.TreeConnect("IPC$")
  134. if err != nil {
  135. c.Debug("", err)
  136. return 0, nil, err
  137. }
  138. IOCTLRequest := c.NewIOCTLRequest(treeId)
  139. // 使用FSCTL_PIPE_WAIT,FileId必须为0xFFFFFFFFFFFFFFFF
  140. IOCTLRequest.Function = FSCTL_PIPE_WAIT
  141. IOCTLRequest.Flags = SMB2_0_IOCTL_IS_FSCTL
  142. IOCTLRequest.GUIDHandle = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
  143. // 连接管道
  144. FSCTLPIPEWAITRequestIn := c.NewFSCTLPIPEWAITRequest(pipename)
  145. FSCTLPIPEWAITRequestIn.Timeout = timeout
  146. IOCTLRequest.Buffer = FSCTLPIPEWAITRequestIn
  147. c.Debug("Sending Ioctl stdin pipe request ["+pipename+"]", nil)
  148. buf, err := c.Send(IOCTLRequest)
  149. if err != nil {
  150. c.Debug("", err)
  151. return 0, nil, err
  152. }
  153. res := NewIOCTLResponse()
  154. c.Debug("Unmarshalling Ioctl stdin pipe response ["+pipename+"]", nil)
  155. if err = encoder.Unmarshal(buf, &res); err != nil {
  156. c.Debug("Raw:\n"+hex.Dump(buf), err)
  157. return 0, nil, err
  158. }
  159. // 创建管道请求
  160. pipeHander, err := c.CreatePipeRequest(treeId, pipename)
  161. if err != nil {
  162. return 0, nil, err
  163. }
  164. // 将数据写入管道
  165. err = c.WritePipeRequest(treeId, []byte("cmd"), pipeHander)
  166. if err != nil {
  167. return 0, nil, err
  168. }
  169. return treeId, pipeHander, nil
  170. }
  171. // 拿到stdin、out、err句柄
  172. func (c *Session) ConnectAndBindNamedPipes(pipename string) (stdinpipe, stdoutpipe, stderrpipe []byte, err error) {
  173. var stdIn, stdOut, stdErr []byte
  174. timeout := uint64(500000)
  175. treeId, err := c.TreeConnect("IPC$")
  176. if err != nil {
  177. c.Debug("", err)
  178. //return nil, err
  179. }
  180. IOCTLRequest := c.NewIOCTLRequest(treeId)
  181. // 使用FSCTL_PIPE_WAIT,FileId必须为0xFFFFFFFFFFFFFFFF
  182. IOCTLRequest.Function = FSCTL_PIPE_WAIT
  183. IOCTLRequest.Flags = SMB2_0_IOCTL_IS_FSCTL
  184. IOCTLRequest.GUIDHandle = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
  185. // 连接输入管道
  186. pipeIn := pipename + "_in"
  187. FSCTLPIPEWAITRequestIn := c.NewFSCTLPIPEWAITRequest(pipeIn)
  188. FSCTLPIPEWAITRequestIn.Timeout = timeout
  189. IOCTLRequest.Buffer = FSCTLPIPEWAITRequestIn
  190. c.Debug("Sending Ioctl stdin pipe request ["+pipeIn+"]", nil)
  191. buf, err := c.Send(IOCTLRequest)
  192. if err != nil {
  193. c.Debug("", err)
  194. //return nil, err
  195. }
  196. res := NewIOCTLResponse()
  197. c.Debug("Unmarshalling Ioctl stdin pipe response ["+pipeIn+"]", nil)
  198. if err := encoder.Unmarshal(buf, &res); err != nil {
  199. c.Debug("Raw:\n"+hex.Dump(buf), err)
  200. }
  201. stdIn = res.GUIDHandle
  202. c.Debug("Completed Ioctl stdin pipe ["+pipeIn+"]", nil)
  203. // 连接输出管道
  204. pipeOut := pipename + "_out"
  205. FSCTLPIPEWAITRequestOut := c.NewFSCTLPIPEWAITRequest(pipeOut)
  206. FSCTLPIPEWAITRequestOut.Timeout = timeout
  207. IOCTLRequest.Buffer = FSCTLPIPEWAITRequestOut
  208. c.Debug("Sending Ioctl stdout pipe request ["+pipeOut+"]", nil)
  209. buf, err = c.Send(IOCTLRequest)
  210. if err != nil {
  211. c.Debug("", err)
  212. //return nil, err
  213. }
  214. res = NewIOCTLResponse()
  215. c.Debug("Unmarshalling Ioctl stdout pipe response ["+pipeOut+"]", nil)
  216. if err = encoder.Unmarshal(buf, &res); err != nil {
  217. c.Debug("Raw:\n"+hex.Dump(buf), err)
  218. }
  219. c.Debug("Completed Ioctl stdout pipe ["+pipeOut+"]", nil)
  220. // 创建
  221. // 连接错误管道
  222. pipeErr := pipename + "_err"
  223. FSCTLPIPEWAITRequestErr := c.NewFSCTLPIPEWAITRequest(pipeErr)
  224. FSCTLPIPEWAITRequestErr.Timeout = timeout
  225. IOCTLRequest.Buffer = FSCTLPIPEWAITRequestErr
  226. c.Debug("Sending Ioctl stderr pipe request ["+pipeErr+"]", nil)
  227. buf, err = c.Send(IOCTLRequest)
  228. if err != nil {
  229. c.Debug("", err)
  230. //return nil, err
  231. }
  232. res = NewIOCTLResponse()
  233. c.Debug("Unmarshalling Ioctl stderr pipe response ["+pipeErr+"]", nil)
  234. if err = encoder.Unmarshal(buf, &res); err != nil {
  235. c.Debug("Raw:\n"+hex.Dump(buf), err)
  236. }
  237. c.Debug("Completed Ioctl stderr pipe ["+pipeErr+"]", nil)
  238. return stdIn, stdOut, stdErr, nil
  239. }
  240. func NewIOCTLRequest(treeId uint32) IOCTLRequestStruct {
  241. // smb2Header := NewSMB2Header()
  242. // smb2Header.Command = smb.SMB2_IOCTL
  243. // smb2Header.CreditCharge = 1
  244. // smb2Header.MessageId = c.GetMessageId()
  245. // smb2Header.SessionId = c.GetSessionId()
  246. // smb2Header.TreeId = treeId
  247. // smb2Header.Credits = 127
  248. return IOCTLRequestStruct{
  249. Header: Header{
  250. Command: CommandIOCtl.INT(),
  251. Credits: 127,
  252. CreditCharge: 1,
  253. },
  254. StructureSize: 57,
  255. GUIDHandle: make([]byte, 16),
  256. }
  257. }
  258. */