ruby_smb 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/examples/anonymous_auth.rb +3 -3
  5. data/examples/append_file.rb +10 -8
  6. data/examples/authenticate.rb +9 -5
  7. data/examples/delete_file.rb +8 -6
  8. data/examples/enum_registry_key.rb +5 -4
  9. data/examples/enum_registry_values.rb +5 -4
  10. data/examples/list_directory.rb +8 -6
  11. data/examples/negotiate_with_netbios_service.rb +9 -5
  12. data/examples/net_share_enum_all.rb +6 -4
  13. data/examples/pipes.rb +11 -12
  14. data/examples/query_service_status.rb +64 -0
  15. data/examples/read_file.rb +8 -6
  16. data/examples/read_registry_key_value.rb +6 -5
  17. data/examples/rename_file.rb +9 -7
  18. data/examples/tree_connect.rb +7 -5
  19. data/examples/write_file.rb +9 -7
  20. data/lib/ruby_smb/client.rb +72 -43
  21. data/lib/ruby_smb/client/negotiation.rb +1 -0
  22. data/lib/ruby_smb/dcerpc.rb +2 -0
  23. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  24. data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
  25. data/lib/ruby_smb/dcerpc/request.rb +13 -0
  26. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
  27. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
  28. data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
  29. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
  30. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
  31. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
  32. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
  33. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
  34. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
  35. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
  36. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
  37. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
  38. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
  39. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
  40. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
  41. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
  42. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
  43. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
  44. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
  45. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
  46. data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
  47. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
  48. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
  49. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
  50. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
  51. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
  52. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
  53. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
  54. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
  55. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
  56. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
  57. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
  58. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  59. data/lib/ruby_smb/dispatcher/socket.rb +1 -1
  60. data/lib/ruby_smb/field/stringz16.rb +17 -1
  61. data/lib/ruby_smb/nbss/session_header.rb +4 -4
  62. data/lib/ruby_smb/smb1/file.rb +2 -10
  63. data/lib/ruby_smb/smb1/pipe.rb +2 -0
  64. data/lib/ruby_smb/smb2/file.rb +25 -17
  65. data/lib/ruby_smb/smb2/pipe.rb +3 -0
  66. data/lib/ruby_smb/smb2/tree.rb +9 -3
  67. data/lib/ruby_smb/version.rb +1 -1
  68. data/spec/lib/ruby_smb/client_spec.rb +161 -60
  69. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
  70. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
  71. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
  72. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
  73. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
  74. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
  75. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
  76. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
  77. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
  78. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
  79. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
  80. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
  81. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
  82. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
  83. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
  84. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
  85. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
  86. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
  87. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
  88. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
  89. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
  90. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
  91. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
  92. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
  93. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
  94. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
  95. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
  96. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
  97. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
  98. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
  99. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
  100. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
  101. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +215 -41
  102. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
  103. data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
  104. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
  105. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +7 -0
  106. data/spec/lib/ruby_smb/smb2/file_spec.rb +60 -6
  107. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +7 -0
  108. data/spec/lib/ruby_smb/smb2/tree_spec.rb +35 -1
  109. metadata +72 -2
  110. metadata.gz.sig +0 -0
@@ -27,12 +27,25 @@ module RubySMB
27
27
  open_key_request RubySMB::Dcerpc::Winreg::REG_OPEN_KEY
28
28
  query_info_key_request RubySMB::Dcerpc::Winreg::REG_QUERY_INFO_KEY
29
29
  query_value_request RubySMB::Dcerpc::Winreg::REG_QUERY_VALUE
30
+ create_key_request RubySMB::Dcerpc::Winreg::REG_CREATE_KEY
31
+ save_key_request RubySMB::Dcerpc::Winreg::REG_SAVE_KEY
30
32
  string :default
31
33
  end
32
34
  choice 'Srvsvc', selection: -> { opnum } do
33
35
  net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
34
36
  string :default
35
37
  end
38
+ choice 'Svcctl', selection: -> { opnum } do
39
+ open_sc_manager_w_request RubySMB::Dcerpc::Svcctl::OPEN_SC_MANAGER_W
40
+ open_service_w_request RubySMB::Dcerpc::Svcctl::OPEN_SERVICE_W
41
+ query_service_status_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS
42
+ query_service_config_w_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_CONFIG_W
43
+ change_service_config_w_request RubySMB::Dcerpc::Svcctl::CHANGE_SERVICE_CONFIG_W
44
+ start_service_w_request RubySMB::Dcerpc::Svcctl::START_SERVICE_W
45
+ control_service_request RubySMB::Dcerpc::Svcctl::CONTROL_SERVICE
46
+ close_service_handle_request RubySMB::Dcerpc::Svcctl::CLOSE_SERVICE_HANDLE
47
+ string :default
48
+ end
36
49
  string :default
37
50
  end
38
51
 
@@ -0,0 +1,34 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+
4
+ # This class represents a RPC_SECURITY_DESCRIPTOR structure as defined in
5
+ # [2.2.8 RPC_SECURITY_DESCRIPTOR](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/9729e781-8eb9-441b-82ca-e898f98d29c2)
6
+ class RpcSecurityDescriptor < BinData::Record
7
+ endian :little
8
+
9
+ ndr_lp_byte_array :lp_security_descriptor
10
+ uint32 :cb_in_security_descriptor
11
+ uint32 :cb_out_security_descriptor
12
+ end
13
+
14
+ # This class represents a RPC_SECURITY_ATTRIBUTES structure as defined in
15
+ # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
16
+ class RpcSecurityAttributes < BinData::Record
17
+ endian :little
18
+
19
+ uint32 :n_length
20
+ rpc_security_descriptor :rpc_security_descriptor
21
+ uint8 :b_inheritHandle
22
+ end
23
+
24
+ # This class represents a pointer to a RPC_SECURITY_ATTRIBUTES structure as defined in
25
+ # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
26
+ class PrpcSecurityAttributes < Ndr::NdrPointer
27
+ endian :little
28
+
29
+ rpc_security_attributes :referent, onlyif: -> { self.referent_id != 0 }
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -8,8 +8,8 @@ module RubySMB
8
8
  class RrpUnicodeString < BinData::Primitive
9
9
  endian :little
10
10
 
11
- uint16 :buffer_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.actual_count * 2 }
12
- uint16 :maximum_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.max_count * 2 }
11
+ uint16 :buffer_length
12
+ uint16 :maximum_length
13
13
  ndr_lp_str :buffer
14
14
 
15
15
  def get
@@ -18,16 +18,19 @@ module RubySMB
18
18
 
19
19
  def set(buf)
20
20
  self.buffer = buf
21
- self.buffer_length = self.buffer.to_s == "\0" ? 0 : self.buffer.actual_count * 2
22
- self.maximum_length = self.buffer.to_s == "\0" ? 0 : self.buffer.max_count * 2
21
+ self.buffer_length = self.buffer == :null ? 0 : self.buffer.referent.actual_count * 2
22
+ # Don't reset maximum_length if the buffer is NULL to make sure we can
23
+ # set it independently of the buffer size
24
+ return if self.maximum_length > 0 && self.buffer == :null
25
+ self.maximum_length = self.buffer.referent.max_count * 2
23
26
  end
24
27
  end
25
28
 
26
29
  # A pointer to a RRP_UNICODE_STRING structure
27
- class PrrpUnicodeString < Ndr::NdrTopLevelFullPointer
30
+ class PrrpUnicodeString < Ndr::NdrPointer
28
31
  endian :little
29
32
 
30
- rrp_unicode_string :referent, onlyif: -> { !is_a_null_pointer? }
33
+ rrp_unicode_string :referent, onlyif: -> { self.referent_id != 0 }
31
34
  end
32
35
 
33
36
  end
@@ -0,0 +1,479 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ UUID = '367abb81-9844-35f1-ad32-98f038001003'
6
+ VER_MAJOR = 2
7
+ VER_MINOR = 0
8
+
9
+ # Operation numbers
10
+ CLOSE_SERVICE_HANDLE = 0x0000
11
+ CONTROL_SERVICE = 0x0001
12
+ QUERY_SERVICE_STATUS = 0x0006
13
+ CHANGE_SERVICE_CONFIG_W = 0x000B
14
+ OPEN_SC_MANAGER_W = 0x000F
15
+ OPEN_SERVICE_W = 0x0010
16
+ QUERY_SERVICE_CONFIG_W = 0x0011
17
+ START_SERVICE_W = 0x0013
18
+
19
+
20
+ class ScRpcHandle < Ndr::NdrContextHandle; end
21
+
22
+
23
+ #################################
24
+ # Constants #
25
+ #################################
26
+
27
+
28
+ ################
29
+ # Service Access
30
+ # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/0d7a7011-9f41-470d-ad52-8535b47ac282
31
+
32
+ # In addition to all access rights in this table, SERVICE_ALL_ACCESS
33
+ # includes Delete (DE), Read Control (RC), Write DACL (WD), and Write
34
+ # Owner (WO) access, as specified in ACCESS_MASK (section 2.4.3) of
35
+ # [MS-DTYP].
36
+ SERVICE_ALL_ACCESS = 0x000F01FF
37
+ # Required to change the configuration of a service.
38
+ SERVICE_CHANGE_CONFIG = 0x00000002
39
+ # Required to enumerate the services installed on the server.
40
+ SERVICE_ENUMERATE_DEPENDENTS = 0x00000008
41
+ # Required to request immediate status from the service.
42
+ SERVICE_INTERROGATE = 0x00000080
43
+ # Required to pause or continue the service.
44
+ SERVICE_PAUSE_CONTINUE = 0x00000040
45
+ # Required to query the service configuration.
46
+ SERVICE_QUERY_CONFIG = 0x00000001
47
+ # Required to request the service status.
48
+ SERVICE_QUERY_STATUS = 0x00000004
49
+ # Required to start the service.
50
+ SERVICE_START = 0x00000010
51
+ # Required to stop the service.
52
+ SERVICE_STOP = 0x00000020
53
+ # Required to specify a user-defined control code.
54
+ SERVICE_USER_DEFINED_CONTROL = 0x00000100
55
+ # Required for a service to set its status.
56
+ SERVICE_SET_STATUS = 0x00008000
57
+
58
+ # Specific access types for Service Control Manager object:
59
+
60
+ # Required to lock the SCM database.
61
+ SC_MANAGER_LOCK = 0x00000008
62
+ # Required for a service to be created.
63
+ SC_MANAGER_CREATE_SERVICE = 0x00000002
64
+ # Required to enumerate a service.
65
+ SC_MANAGER_ENUMERATE_SERVICE = 0x00000004
66
+ # Required to connect to the SCM.
67
+ SC_MANAGER_CONNECT = 0x00000001
68
+ # Required to query the lock status of the SCM database.
69
+ SC_MANAGER_QUERY_LOCK_STATUS = 0x00000010
70
+ # Required to call the RNotifyBootConfigStatus method.
71
+ SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00000020
72
+
73
+
74
+ ##############
75
+ # Service Type
76
+
77
+ # A driver service. These are services that manage devices on the system.
78
+ SERVICE_KERNEL_DRIVER = 0x00000001
79
+ # A file system driver service. These are services that manage file
80
+ # systems on the system.
81
+ SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
82
+ # A service that runs in its own process.
83
+ SERVICE_WIN32_OWN_PROCESS = 0x00000010
84
+ # A service that shares a process with other services.
85
+ SERVICE_WIN32_SHARE_PROCESS = 0x00000020
86
+
87
+ # The service can interact with the desktop. Only
88
+ # SERVICE_WIN32_OWN_PROCESS and SERVICE_INTERACTIVE_PROCESS OR
89
+ # SERVICE_WIN32_SHARE_PROCESS and SERVICE_INTERACTIVE_PROCESS can be
90
+ # combined.
91
+ SERVICE_INTERACTIVE_PROCESS = 0x00000100
92
+
93
+ ####################
94
+ # Service Start Type
95
+
96
+ # Starts the driver service when the system boots up. This value is valid
97
+ # only for driver services.
98
+ SERVICE_BOOT_START = 0x00000000
99
+ # Starts the driver service when the system boots up. This value is valid
100
+ # only for driver services. The services marked SERVICE_SYSTEM_START are
101
+ # started after all SERVICE_BOOT_START services have been started.
102
+ SERVICE_SYSTEM_START = 0x00000001
103
+ # A service started automatically by the SCM during system startup.
104
+ SERVICE_AUTO_START = 0x00000002
105
+ # Starts the service when a client requests the SCM to start the service.
106
+ SERVICE_DEMAND_START = 0x00000003
107
+ # A service that cannot be started. Attempts to start the service result
108
+ # in the error code ERROR_SERVICE_DISABLED.
109
+ SERVICE_DISABLED = 0x00000004
110
+
111
+
112
+ #######################
113
+ # Service Error Control
114
+
115
+ # The severity of the error if this service fails to start during startup
116
+ # and the action the SCM takes if failure occurs.
117
+
118
+ # The SCM ignores the error and continues the startup operation.
119
+ SERVICE_ERROR_IGNORE = 0x00000000
120
+ # The SCM logs the error in the event log and continues the startup
121
+ # operation.
122
+ SERVICE_ERROR_NORMAL = 0x00000001
123
+ # The SCM logs the error in the event log. If the last-known good
124
+ # configuration is being started, the startup operation continues.
125
+ # Otherwise, the system is restarted with the last-known good
126
+ # configuration.
127
+ SERVICE_ERROR_SEVERE = 0x00000002
128
+ # The SCM SHOULD log the error in the event log if possible. If the
129
+ # last-known good configuration is being started, the startup operation
130
+ # fails. Otherwise, the system is restarted with the last-known good
131
+ # configuration.
132
+ SERVICE_ERROR_CRITICAL = 0x00000003
133
+
134
+
135
+ #########################################
136
+ # Change Service Config specific constant
137
+
138
+ # Service type, start or error control does not change.
139
+ SERVICE_NO_CHANGE = 0xFFFFFFFF
140
+
141
+
142
+ ################
143
+ # Current State
144
+
145
+ SERVICE_PAUSED = 0x00000007
146
+ SERVICE_PAUSE_PENDING = 0x00000006
147
+ SERVICE_CONTINUE_PENDING = 0x00000005
148
+ SERVICE_RUNNING = 0x00000004
149
+ SERVICE_STOP_PENDING = 0x00000003
150
+ SERVICE_START_PENDING = 0x00000002
151
+ SERVICE_STOPPED = 0x00000001
152
+
153
+ ###################
154
+ # Controls Accepted
155
+
156
+ # The control codes that the service accepts and processes in its handler
157
+ # function. One or more of the following values can be set. By default,
158
+ # all services accept the SERVICE_CONTROL_INTERROGATE value. A value of
159
+ # zero indicates that no controls are accepted.
160
+
161
+ # Service can reread its startup parameters without being stopped and
162
+ # restarted. This control code allows the service to receive
163
+ # SERVICE_CONTROL_PARAMCHANGE notifications.
164
+ SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
165
+ # Service can be paused and continued. This control code allows the
166
+ # service to receive SERVICE_CONTROL_PAUSE and SERVICE_CONTROL_CONTINUE
167
+ # notifications.
168
+ SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
169
+ # Service is notified when system shutdown occurs. This control code
170
+ # enables the service to receive SERVICE_CONTROL_SHUTDOWN notifications
171
+ # from the server.
172
+ SERVICE_ACCEPT_SHUTDOWN = 0x00000004
173
+ # Service can be stopped. This control code allows the service to receive
174
+ # SERVICE_CONTROL_STOP notifications.
175
+ SERVICE_ACCEPT_STOP = 0x00000001
176
+ # Service is notified when the computer's hardware profile changes.
177
+ SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
178
+ # Service is notified when the computer's power status changes.
179
+ SERVICE_ACCEPT_POWEREVENT = 0x00000040
180
+ # Service is notified when the computer's session status changes.
181
+ SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
182
+ # The service can perform preshutdown tasks. SERVICE_ACCEPT_PRESHUTDOWN
183
+ # is sent before sending SERVICE_CONTROL_SHUTDOWN to give more time to
184
+ # services that need extra time before shutdown occurs.
185
+ SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
186
+ # Service is notified when the system time changes.
187
+ SERVICE_ACCEPT_TIMECHANGE = 0x00000200
188
+ # Service is notified when an event for which the service has registered
189
+ # occurs.
190
+ SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
191
+
192
+ ###################
193
+ # Controls
194
+
195
+ # Notifies a paused service that it SHOULD resume. The
196
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the caller
197
+ # when the RPC control handle to the service record was created. The
198
+ # service record MUST have the SERVICE_ACCEPT_PAUSE_CONTINUE bit set in
199
+ # the ServiceStatus.dwControlsAccepted field of the service record.
200
+ SERVICE_CONTROL_CONTINUE = 0x00000003
201
+ # Notifies a service that it SHOULD report its current status information
202
+ # to the SCM. The SERVICE_INTERROGATE access right MUST have been granted
203
+ # to the caller when the RPC control handle to the service record was
204
+ # created.
205
+ SERVICE_CONTROL_INTERROGATE = 0x00000004
206
+ # Notifies a service that there is a new component for binding. The
207
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
208
+ # caller when the RPC control handle to the service record was created.
209
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
210
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
211
+ SERVICE_CONTROL_NETBINDADD = 0x00000007
212
+ # Notifies a network service that one of its bindings has been disabled.
213
+ # The SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
214
+ # caller when the RPC control handle to the service record was created.
215
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
216
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
217
+ SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
218
+ # Notifies a network service that a disabled binding has been enabled.
219
+ # The SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
220
+ # caller when the RPC control handle to the service record was created.
221
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
222
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
223
+ SERVICE_CONTROL_NETBINDENABLE = 0x00000009
224
+ # Notifies a network service that a component for binding has been
225
+ # removed. The SERVICE_PAUSE_CONTINUE access right MUST have been granted
226
+ # to the caller when the RPC control handle to the service record was
227
+ # created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE
228
+ # bit set in the ServiceStatus.dwControlsAccepted field of the service
229
+ # record.
230
+ SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
231
+ # Notifies a service that its startup parameters have changed. The
232
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
233
+ # caller when the RPC control handle to the service record was created.
234
+ # The service record MUST have the SERVICE_ACCEPT_PARAMCHANGE bit set in
235
+ # the ServiceStatus.dwControlsAccepted field of the service record.
236
+ SERVICE_CONTROL_PARAMCHANGE = 0x00000006
237
+ # Notifies a service that it SHOULD pause. The SERVICE_PAUSE_CONTINUE
238
+ # access right MUST have been granted to the caller when the RPC control
239
+ # handle to the service record was created. The service record MUST have
240
+ # the SERVICE_ACCEPT_PAUSE_CONTINUE bit set in the
241
+ # ServiceStatus.dwControlsAccepted field of the service record.
242
+ SERVICE_CONTROL_PAUSE = 0x00000002
243
+ # Notifies a service that it SHOULD stop. The SERVICE_STOP access right
244
+ # MUST have been granted to the caller when the RPC control handle to the
245
+ # service record was created. The service record MUST have the
246
+ # SERVICE_ACCEPT_STOP bit set in the ServiceStatus.dwControlsAccepted
247
+ # field of the service record.
248
+ SERVICE_CONTROL_STOP = 0x00000001
249
+
250
+ require 'ruby_smb/dcerpc/svcctl/service_status'
251
+ require 'ruby_smb/dcerpc/svcctl/open_sc_manager_w_request'
252
+ require 'ruby_smb/dcerpc/svcctl/open_sc_manager_w_response'
253
+ require 'ruby_smb/dcerpc/svcctl/open_service_w_request'
254
+ require 'ruby_smb/dcerpc/svcctl/open_service_w_response'
255
+ require 'ruby_smb/dcerpc/svcctl/query_service_status_request'
256
+ require 'ruby_smb/dcerpc/svcctl/query_service_status_response'
257
+ require 'ruby_smb/dcerpc/svcctl/query_service_config_w_request'
258
+ require 'ruby_smb/dcerpc/svcctl/query_service_config_w_response'
259
+ require 'ruby_smb/dcerpc/svcctl/change_service_config_w_request'
260
+ require 'ruby_smb/dcerpc/svcctl/change_service_config_w_response'
261
+ require 'ruby_smb/dcerpc/svcctl/start_service_w_request'
262
+ require 'ruby_smb/dcerpc/svcctl/start_service_w_response'
263
+ require 'ruby_smb/dcerpc/svcctl/control_service_request'
264
+ require 'ruby_smb/dcerpc/svcctl/control_service_response'
265
+ require 'ruby_smb/dcerpc/svcctl/close_service_handle_request'
266
+ require 'ruby_smb/dcerpc/svcctl/close_service_handle_response'
267
+
268
+ # Open the SCM database on the specified server.
269
+ #
270
+ # @param rhost [String] the server's machine name
271
+ # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the newly opened SCM database
272
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenSCManagerWResponse packet
273
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
274
+ def open_sc_manager_w(rhost, access = SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SC_MANAGER_ENUMERATE_SERVICE)
275
+ open_sc_manager_w_request = OpenSCManagerWRequest.new(dw_desired_access: access)
276
+ open_sc_manager_w_request.lp_machine_name = rhost
277
+ open_sc_manager_w_request.lp_database_name = 'ServicesActive'
278
+ response = dcerpc_request(open_sc_manager_w_request)
279
+ begin
280
+ open_sc_manager_w_response = OpenSCManagerWResponse.read(response)
281
+ rescue IOError
282
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenSCManagerWResponse'
283
+ end
284
+ unless open_sc_manager_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
285
+ raise RubySMB::Dcerpc::Error::SvcctlError,
286
+ "Error returned when opening Service Control Manager (SCM): "\
287
+ "#{WindowsError::Win32.find_by_retval(open_sc_manager_w_response.error_status.value).join(',')}"
288
+ end
289
+ open_sc_manager_w_response.lp_sc_handle
290
+ end
291
+
292
+ # Creates an RPC context handle to an existing service record.
293
+ #
294
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the SCM database
295
+ # @param service_name [Srting] the ServiceName of the service record
296
+ # @param access [Integer] access right
297
+ # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the found service record
298
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenServiceWResponse packet
299
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
300
+ def open_service_w(scm_handle, service_name, access = SERVICE_ALL_ACCESS)
301
+ open_service_w_request = OpenServiceWRequest.new(dw_desired_access: access)
302
+ open_service_w_request.lp_sc_handle = scm_handle
303
+ open_service_w_request.lp_service_name = service_name
304
+ response = dcerpc_request(open_service_w_request)
305
+ begin
306
+ open_sercice_w_response = OpenServiceWResponse.read(response)
307
+ rescue IOError
308
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenServiceWResponse'
309
+ end
310
+ unless open_sercice_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
311
+ raise RubySMB::Dcerpc::Error::SvcctlError,
312
+ "Error returned when opening #{service_name} service: "\
313
+ "#{WindowsError::Win32.find_by_retval(open_sercice_w_response.error_status.value).join(',')}"
314
+ end
315
+ open_sercice_w_response.lp_sc_handle
316
+ end
317
+
318
+ # Returns the current status of the specified service
319
+ #
320
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
321
+ # @return [RubySMB::Dcerpc::Svcctl::ServiceStatus] structure that contains the status information for the service
322
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceStatusResponse packet
323
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
324
+ def query_service_status(svc_handle)
325
+ qss_request = QueryServiceStatusRequest.new
326
+ qss_request.h_service = svc_handle
327
+ response = dcerpc_request(qss_request)
328
+ begin
329
+ qss_response = QueryServiceStatusResponse.read(response)
330
+ rescue IOError
331
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceStatusResponse'
332
+ end
333
+ unless qss_response.error_status == WindowsError::Win32::ERROR_SUCCESS
334
+ raise RubySMB::Dcerpc::Error::SvcctlError,
335
+ "Error returned when querying service status: "\
336
+ "#{WindowsError::Win32.find_by_retval(qss_response.error_status.value).join(',')}"
337
+ end
338
+ qss_response.lp_service_status
339
+ end
340
+
341
+ # Returns the configuration parameters of the specified service
342
+ #
343
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
344
+ # @return [RubySMB::Dcerpc::Svcctl::QueryServiceConfigW] structure that contains the configuration parameters for the service
345
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceConfigWResponse packet
346
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
347
+ def query_service_config(svc_handle)
348
+ qsc_request = QueryServiceConfigWRequest.new
349
+ qsc_request.h_service = svc_handle
350
+ qsc_request.cb_buf_size = 0
351
+ response = dcerpc_request(qsc_request)
352
+ begin
353
+ qsc_response = QueryServiceConfigWResponse.read(response)
354
+ rescue IOError
355
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse'
356
+ end
357
+ if qsc_response.error_status == WindowsError::Win32::ERROR_INSUFFICIENT_BUFFER
358
+ qsc_request.cb_buf_size = qsc_response.pcb_bytes_needed
359
+ response = dcerpc_request(qsc_request)
360
+ begin
361
+ qsc_response = QueryServiceConfigWResponse.read(response)
362
+ rescue IOError
363
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse'
364
+ end
365
+ end
366
+ unless qsc_response.error_status == WindowsError::Win32::ERROR_SUCCESS
367
+ raise RubySMB::Dcerpc::Error::SvcctlError,
368
+ "Error returned when querying service configuration: "\
369
+ "#{WindowsError::Win32.find_by_retval(qsc_response.error_status.value).join(',')}"
370
+ end
371
+ qsc_response.lp_service_config
372
+ end
373
+
374
+ # Changes a service's configuration parameters in the SCM database
375
+ #
376
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
377
+ # @param opts [Hash] configuration parameters to change
378
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ChangeServiceConfigWResponse packet
379
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
380
+ def change_service_config_w(svc_handle, opts = {})
381
+ opts = {
382
+ h_service: svc_handle,
383
+ dw_service_type: opts[:service_type] || SERVICE_NO_CHANGE,
384
+ dw_start_type: opts[:start_type] || SERVICE_NO_CHANGE,
385
+ dw_error_control: opts[:error_control] || SERVICE_NO_CHANGE,
386
+ lp_binary_path_name: opts[:binary_path_name] || :null,
387
+ lp_load_order_group: opts[:load_order_group] || :null,
388
+ dw_tag_id: opts[:tag_id] || :null,
389
+ lp_dependencies: opts[:dependencies] || [],
390
+ lp_service_start_name: opts[:service_start_name] || :null,
391
+ lp_password: opts[:password] || [],
392
+ lp_display_name: opts[:display_name] || :null
393
+ }
394
+
395
+ csc_request = ChangeServiceConfigWRequest.new(opts)
396
+ response = dcerpc_request(csc_request)
397
+ begin
398
+ csc_response = ChangeServiceConfigWResponse.read(response)
399
+ rescue IOError
400
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ChangeServiceConfigWResponse'
401
+ end
402
+ unless csc_response.error_status == WindowsError::Win32::ERROR_SUCCESS
403
+ raise RubySMB::Dcerpc::Error::SvcctlError,
404
+ "Error returned when changing the service configuration: "\
405
+ "#{WindowsError::Win32.find_by_retval(csc_response.error_status.value).join(',')}"
406
+ end
407
+ end
408
+
409
+ # Starts a specified service
410
+ #
411
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
412
+ # @param argv [Array<String>] arguments to the service (Array of
413
+ # strings). The first element in argv must be the name of the service.
414
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a StartServiceWResponse packet
415
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
416
+ def start_service_w(svc_handle, argv = [])
417
+ ss_request = StartServiceWRequest.new(h_service: svc_handle)
418
+ unless argv.empty?
419
+ ss_request.argc = argv.size
420
+ ndr_string_ptrsw = RubySMB::Dcerpc::Ndr::NdrStringPtrsw.new
421
+ ndr_string_ptrsw.elements = argv
422
+ ss_request.argv = ndr_string_ptrsw
423
+ end
424
+ response = dcerpc_request(ss_request)
425
+ begin
426
+ ss_response = StartServiceWResponse.read(response)
427
+ rescue IOError
428
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading StartServiceWResponse'
429
+ end
430
+ unless ss_response.error_status == WindowsError::Win32::ERROR_SUCCESS
431
+ raise RubySMB::Dcerpc::Error::SvcctlError,
432
+ "Error returned when starting the service: "\
433
+ "#{WindowsError::Win32.find_by_retval(ss_response.error_status.value).join(',')}"
434
+ end
435
+ end
436
+
437
+ # Send a control code to a specific service handle
438
+ #
439
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
440
+ # @param control [Integer] control code
441
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ControlServiceResponse packet
442
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
443
+ def control_service(svc_handle, control)
444
+ cs_request = ControlServiceRequest.new(h_service: svc_handle, dw_control: control)
445
+ response = dcerpc_request(cs_request)
446
+ begin
447
+ cs_response = ControlServiceResponse.read(response)
448
+ rescue IOError
449
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ControlServiceResponse'
450
+ end
451
+ unless cs_response.error_status == WindowsError::Win32::ERROR_SUCCESS
452
+ raise RubySMB::Dcerpc::Error::SvcctlError,
453
+ "Error returned when sending a control to the service: "\
454
+ "#{WindowsError::Win32.find_by_retval(cs_response.error_status.value).join(',')}"
455
+ end
456
+ end
457
+
458
+ # Releases the handle to the specified service or the SCM database.
459
+ #
460
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record or to the SCM database
461
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CloseServiceHandleResponse packet
462
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
463
+ def close_service_handle(svc_handle)
464
+ csh_request = CloseServiceHandleRequest.new(h_sc_object: svc_handle)
465
+ response = dcerpc_request(csh_request)
466
+ begin
467
+ csh_response = CloseServiceHandleResponse.read(response)
468
+ rescue IOError
469
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading CloseServiceHandleResponse'
470
+ end
471
+ unless csh_response.error_status == WindowsError::Win32::ERROR_SUCCESS
472
+ raise RubySMB::Dcerpc::Error::SvcctlError,
473
+ "Error returned when closing the service: "\
474
+ "#{WindowsError::Win32.find_by_retval(csh_response.error_status.value).join(',')}"
475
+ end
476
+ end
477
+ end
478
+ end
479
+ end