psrp 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/lib/psrp.rb +94 -72
  4. data/lib/version.rb +1 -1
  5. data/test_psrp.rb +28 -4
  6. metadata +2 -3
  7. data/script.ps1 +0 -2958
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 575126720862843abbe6a80daa2231676ea7d7c1
4
- data.tar.gz: af1b27be56d15a5c155013bf3025d9a5013334c4
3
+ metadata.gz: 1c0eb58f46fa0b746b0d8f1fe2157764c22c8586
4
+ data.tar.gz: ad6ab72fdf78ead6c2b1a0a22497ef546529574d
5
5
  SHA512:
6
- metadata.gz: 854431f6a0465b6005fd72788005ac19cbff1df5f65f84fd199a79d7eafddfd04f52ffa1f6ed2608b47172cf4d91bb25cf9e32d197246587bf9c30a8156e7cbc
7
- data.tar.gz: 9bd255a5a9ddad36046255c17c91e9164c1cbd0de9a0a42ad7da71e25586c7a83a222d94b734f210507f677ea00f5ebb34cc628e1588ad5671bc41d1c851ea2b
6
+ metadata.gz: 3f0c16ebb4d24c80d0c13efff3f7a6cd0e6d5f0ff12d850bb2c15fc8750edbafd2afb66efe6bff8970d7fe4a5771619cd233d9339d7008e013866b9583e61357
7
+ data.tar.gz: 7df6cac6ea30fbf62dd765a5aa5d51872ed70df2a216b6fe8ee9c1b2fe0cebda19cc2c1390cf0de98b8315e96e74723b9f1b432b0722e5a980d7294168232716
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  *~
2
2
  .#*
3
- .DS_Store
3
+ .DS_Store
4
+ script.ps1
data/lib/psrp.rb CHANGED
@@ -61,33 +61,30 @@ module PSRP
61
61
  @opts = opts
62
62
 
63
63
  @xfer = HTTP::Negotiate.new(endpoint, @opts[:user], @opts[:pass], @opts)
64
+
65
+ @shell_id = nil
66
+ @generated_shell_id = nil
67
+ @opened = false
64
68
  end
65
69
 
66
- def run_ps(command, shell_opts = {})
67
-
70
+ def open
68
71
  @logger.debug("[WinRM] opening remote runspacepool on #{@session_opts[:endpoint]}")
69
72
  msg = PSRP::WSMV::InitRunspacePool.new(@session_opts)
70
73
 
71
74
  resp_doc = @xfer.send_request(msg.build)
72
75
 
73
- generated_shell_id = msg.shell_id
74
-
75
- shell_id = REXML::XPath.first(resp_doc, "//*[@Name='ShellId']").text
76
- @logger.debug("[WinRM] remote runspace #{shell_id} is open on #{@session_opts[:endpoint]}")
76
+ @generated_shell_id = msg.shell_id
77
77
 
78
+ @shell_id = REXML::XPath.first(resp_doc, "//*[@Name='ShellId']").text
79
+ @logger.debug("[WinRM] remote runspace #{@shell_id} is open on #{@session_opts[:endpoint]}")
78
80
 
79
- # spec says:
80
- # The client sends a wxf:Receive message (section 3.1.5.3.7) to the server to start receiving data from
81
- # the server. After each received wxf:ReceiveResponse message (section 3.2.5.3.8), the client sends another
82
- # wxf:Receive message until the RunspacePool transitions to a Closed or Broken state.
83
-
84
- out_processor = PSRP::WSMV::CommandOutputProcessor.new(@session_opts, @xfer)
81
+ out_processor = PSRP::WSMV::CommandOutputProcessor.new(@session_opts, @xfer)
85
82
 
86
- out_processor.command_output(shell_id, nil)
87
- return nil if out_processor.command_done?
83
+ out_processor.command_output(@shell_id, nil)
84
+ return false if out_processor.command_done?
88
85
 
89
86
  while true
90
- out_processor.command_output(shell_id, nil, true)
87
+ out_processor.command_output(@shell_id, nil, true)
91
88
  if out_processor.command_done?
92
89
  break
93
90
  end
@@ -105,76 +102,101 @@ module PSRP
105
102
  end
106
103
 
107
104
  if runspace_open
108
- @logger.debug('Opened the runspace, sending command')
109
-
110
- command_id = SecureRandom.uuid.to_s.upcase
111
- pipeline = PSRP::MessageEncoder.new(generated_shell_id, command_id, :CREATE_PIPELINE, {command: CGI.escapeHTML(command)})
105
+ @opened = true
106
+ return true
107
+ end
108
+ end
112
109
 
113
- msg = PSRP::WSMV::CreatePipeline.new(@session_opts, shell_id, pipeline.fragments[0])
114
- resp_doc = @xfer.send_request(msg.build)
110
+ return false
111
+ end
115
112
 
116
- command_id = REXML::XPath.first(resp_doc, "//#{PSRP::WSMV::NS_WIN_SHELL}:CommandId").text
113
+ def run_ps(command, shell_opts = {})
117
114
 
118
- # Send remaining fragments, if any
119
- if pipeline.fragments.length > 1
120
- for i in 1..(pipeline.fragments.length - 1)
121
- msg = PSRP::WSMV::SendData.new(@session_opts, shell_id, command_id, pipeline.fragments[i])
122
- resp_doc = @xfer.send_request(msg.build)
123
- end
124
- end
115
+ # spec says:
116
+ # The client sends a wxf:Receive message (section 3.1.5.3.7) to the server to start receiving data from
117
+ # the server. After each received wxf:ReceiveResponse message (section 3.2.5.3.8), the client sends another
118
+ # wxf:Receive message until the RunspacePool transitions to a Closed or Broken state.
119
+ if not @opened
120
+ raise PSRPError.new('This psrp instance is not connected, call .open ')
121
+ end
125
122
 
126
- @logger.debug("Command Sent, waiting on responses")
127
- out_processor.command_output(shell_id, command_id, true)
128
- if out_processor.input_required?
129
- raise PSRPError.new('This Tool Does Not Support Accepting Runtime Input')
130
- end
131
-
132
- # retrieve all of the data from the command
133
- while true
134
- out_processor.command_output(shell_id, command_id)
135
- if out_processor.input_required?
136
- raise PSRPError.new('This Tool Does Not Support Accepting Runtime Input')
137
- end
138
- if out_processor.command_done?
139
- break
140
- end
141
- end
123
+ out_processor = PSRP::WSMV::CommandOutputProcessor.new(@session_opts, @xfer)
124
+
125
+ @logger.debug('Opened the runspace, sending command')
126
+
127
+ command_id = SecureRandom.uuid.to_s.upcase
128
+ pipeline = PSRP::MessageEncoder.new(@generated_shell_id, command_id, :CREATE_PIPELINE, {command: CGI.escapeHTML(command)})
129
+
130
+ msg = PSRP::WSMV::CreatePipeline.new(@session_opts, @shell_id, pipeline.fragments[0])
131
+ resp_doc = @xfer.send_request(msg.build)
132
+
133
+ command_id = REXML::XPath.first(resp_doc, "//#{PSRP::WSMV::NS_WIN_SHELL}:CommandId").text
142
134
 
143
- @logger.debug("Closing shell")
144
- msg = PSRP::WSMV::CloseShell.new(@session_opts, shell_id)
135
+ # Send remaining fragments, if any
136
+ if pipeline.fragments.length > 1
137
+ for i in 1..(pipeline.fragments.length - 1)
138
+ msg = PSRP::WSMV::SendData.new(@session_opts, @shell_id, command_id, pipeline.fragments[i])
145
139
  resp_doc = @xfer.send_request(msg.build)
146
-
147
- # Deal with fragmented return values
148
- datas = out_processor.defragmented
149
-
150
- # Deal With Errors
151
- # But not really doing it well
152
- # PSRP - 2.2.3.15 ErrorRecord
153
- if out_processor.has_error?
154
- datas.each do |msg_id, msg|
155
- if msg[:message_type] == PSRP::Message::MESSAGE_TYPES[:ERROR_RECORD]
156
- raise PSRPError.new(un_psrp_escape(msg[:data]))
157
- end
158
- end
159
- end
140
+ end
141
+ end
160
142
 
161
- data = ''
162
- out_processor.defragmented.each do |msg_id, msg|
163
- xml = REXML::Document.new(msg[:data])
164
- # TODO: do better deserialization based on MS-PSRP 2.2.5
165
- # Right now this only returns String primitives and String Extended Primitives
166
- REXML::XPath.match(xml, "/S|/Obj/S").each do |n|
167
- next if n.text.nil? || n.text.empty?
168
- data += n.text + "\n"
169
- end
143
+ @logger.debug("Command Sent, waiting on responses")
144
+ out_processor.command_output(@shell_id, command_id, true)
145
+ if out_processor.input_required?
146
+ raise PSRPError.new('This Tool Does Not Support Accepting Runtime Input')
147
+ end
148
+
149
+ # retrieve all of the data from the command
150
+ while true
151
+ out_processor.command_output(@shell_id, command_id)
152
+ if out_processor.input_required?
153
+ raise PSRPError.new('This Tool Does Not Support Accepting Runtime Input')
154
+ end
155
+ if out_processor.command_done?
156
+ break
157
+ end
158
+ end
159
+
160
+ # Deal with fragmented return values
161
+ datas = out_processor.defragmented
162
+
163
+ # Deal With Errors
164
+ # But not really doing it well
165
+ # PSRP - 2.2.3.15 ErrorRecord
166
+ if out_processor.has_error?
167
+ datas.each do |msg_id, msg|
168
+ if msg[:message_type] == PSRP::Message::MESSAGE_TYPES[:ERROR_RECORD]
169
+ raise PSRPError.new(un_psrp_escape(msg[:data]))
170
170
  end
171
- return data
172
171
  end
173
172
  end
173
+
174
+ data = ''
175
+ out_processor.defragmented.each do |msg_id, msg|
176
+ xml = REXML::Document.new(msg[:data])
177
+ # TODO: do better deserialization based on MS-PSRP 2.2.5
178
+ # Right now this only returns String primitives and String Extended Primitives
179
+ REXML::XPath.match(xml, "/S|/Obj/S").each do |n|
180
+ next if n.text.nil? || n.text.empty?
181
+ data += n.text + "\n"
182
+ end
183
+ end
184
+ return data
174
185
  end
175
186
 
187
+ def close
188
+ @opened = false
189
+ @logger.debug("Closing shell")
190
+ msg = PSRP::WSMV::CloseShell.new(@session_opts, @shell_id)
191
+ resp_doc = @xfer.send_request(msg.build)
192
+ end
193
+
176
194
  def un_psrp_escape(str)
177
- str.gsub(/_x([0-9A-F]{4})_/i) { [Regexp.last_match[1].hex].pack('U') }
195
+ begin
196
+ str.gsub(/_x([0-9A-F]{4})_/i) { [Regexp.last_match[1].hex].pack('U') }
197
+ rescue Encoding::CompatibilityError
198
+ str
199
+ end
178
200
  end
179
201
  end
180
202
  end
data/lib/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # PSRP module
4
4
  module PSRP
5
5
  # The version of the PSRP library
6
- VERSION = '0.0.2'
6
+ VERSION = '0.0.3'
7
7
  end
data/test_psrp.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  require_relative 'lib/psrp'
2
+ require 'zlib'
2
3
 
3
4
  endpoint = 'http://192.168.142.231:5985/wsman'
4
5
  psrp = PSRP::PSRPService.new(endpoint, :user => 'samo-range', :pass => 'somethinglonger12345!', :log_level => :info)
5
6
 
7
+ psrp.open
8
+
6
9
  puts psrp.run_ps('echo "<xml><body>THIS IS NOT THE XML YOU ARE LOOKING FOR</body></xml>" > C:\hello; cat C:\hello')
7
10
  puts psrp.run_ps('systeminfo')
8
11
  puts psrp.run_ps('cat C:\hello')
@@ -12,20 +15,41 @@ puts psrp.run_ps('echo "' + "A" * (32725 + 1) * 30 + '" > C:\hello_A')
12
15
 
13
16
  puts psrp.run_ps('notepad')
14
17
 
15
- data = Base64.strict_encode64(IO.binread('DemoDLL_RemoteProcess-x64.dll'))
16
- ps_script = "$ProcName = notepad\n"
17
- ps_script += "$PEBytes = [System.Convert]::FromBase64String('" + data + "')\n"
18
+ b64_code = Base64.strict_encode64(IO.binread('DemoDLL_RemoteProcess-x64.dll'))
19
+ data_io = StringIO.new()
20
+ gz = Zlib::GzipWriter.new(data_io)
21
+ gz.write(b64_code)
22
+ gz.close()
23
+ data = Base64.strict_encode64(data_io.string())
24
+ ps_script = "$ProcName = lsass\n"
25
+ ps_script += "$data = [System.Convert]::FromBase64String('" + data + "')\n"
26
+ ps_script += "$ms = New-Object System.IO.MemoryStream\n"
27
+ ps_script += "$ms.Write($data, 0, $data.Length)\n"
28
+ ps_script += "$ms.Seek(0,0) | Out-Null\n"
29
+ ps_script += "$sr = New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))\n"
30
+ ps_script += "$PEBytes = [System.Convert]::FromBase64String($sr.ReadToEnd())\n"
31
+
18
32
  ps_script += File.read('Invoke-ReflectivePEInjection.ps1')
19
33
  ps_script += "\nInvoke-ReflectivePEInjection -PEBytes $PEBytes\n"
20
34
  ps_script += "echo 'Command Reflected'\n"
21
35
  IO.binwrite('script.ps1', ps_script)
22
36
  puts psrp.run_ps(File.read('script.ps1'))
23
37
 
38
+ psrp.close
24
39
 
25
40
  endpoint = 'http://192.168.142.232:5985/wsman'
26
41
  begin
27
42
  psrp = PSRP::PSRPService.new(endpoint, :user => 'samo-range', :pass => 'somethinglonger12345!', :log_level => :debug)
28
43
  psrp.run_ps('ipconfig')
44
+ rescue PSRP::PSRPError
45
+ puts 'You should see this'
46
+ end
47
+
48
+ begin
49
+ psrp = PSRP::PSRPService.new(endpoint, :user => 'samo-range', :pass => 'somethinglonger12345!', :log_level => :debug)
50
+ psrp.open
51
+ psrp.run_ps('ipconfig')
29
52
  rescue HTTPClient::ConnectTimeoutError
30
- puts 'Should See A Timeout on Not Able to Connect.'
53
+ puts 'Should See A Timeout on Not Able to Connect.'
31
54
  end
55
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: psrp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Oluwalana
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-23 00:00:00.000000000 Z
11
+ date: 2016-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -153,7 +153,6 @@ files:
153
153
  - lib/wsmv/templates/runspace_availability.xml.erb
154
154
  - lib/wsmv/templates/session_capability.xml.erb
155
155
  - psrp.gemspec
156
- - script.ps1
157
156
  - test_psrp.rb
158
157
  homepage: http://github.com/soluwalana/PSRP-RB
159
158
  licenses: