ronin-post_ex 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.document +6 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/API_SPEC.md +235 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +23 -0
  11. data/Gemfile +36 -0
  12. data/README.md +245 -0
  13. data/Rakefile +34 -0
  14. data/examples/bind_shell.rb +19 -0
  15. data/gemspec.yml +25 -0
  16. data/lib/ronin/post_ex/cli/shell_shell.rb +66 -0
  17. data/lib/ronin/post_ex/cli/system_shell.rb +811 -0
  18. data/lib/ronin/post_ex/remote_dir.rb +190 -0
  19. data/lib/ronin/post_ex/remote_file/stat.rb +174 -0
  20. data/lib/ronin/post_ex/remote_file.rb +417 -0
  21. data/lib/ronin/post_ex/remote_process.rb +170 -0
  22. data/lib/ronin/post_ex/resource.rb +144 -0
  23. data/lib/ronin/post_ex/sessions/bind_shell.rb +60 -0
  24. data/lib/ronin/post_ex/sessions/remote_shell_session.rb +48 -0
  25. data/lib/ronin/post_ex/sessions/reverse_shell.rb +67 -0
  26. data/lib/ronin/post_ex/sessions/rpc_session.rb +779 -0
  27. data/lib/ronin/post_ex/sessions/session.rb +73 -0
  28. data/lib/ronin/post_ex/sessions/shell_session.rb +618 -0
  29. data/lib/ronin/post_ex/system/fs.rb +650 -0
  30. data/lib/ronin/post_ex/system/process.rb +422 -0
  31. data/lib/ronin/post_ex/system/shell.rb +1037 -0
  32. data/lib/ronin/post_ex/system.rb +191 -0
  33. data/lib/ronin/post_ex/version.rb +26 -0
  34. data/lib/ronin/post_ex.rb +22 -0
  35. data/ronin-post_ex.gemspec +61 -0
  36. data/spec/sessions/bind_shell_spec.rb +31 -0
  37. data/spec/sessions/remote_shell_session_spec.rb +28 -0
  38. data/spec/sessions/reverse_shell_spec.rb +49 -0
  39. data/spec/sessions/rpc_session_spec.rb +500 -0
  40. data/spec/sessions/session_spec.rb +61 -0
  41. data/spec/sessions/shell_session_spec.rb +482 -0
  42. data/spec/spec_helper.rb +9 -0
  43. data/spec/system_spec.rb +66 -0
  44. metadata +155 -0
@@ -0,0 +1,482 @@
1
+ require 'spec_helper'
2
+ require 'ronin/post_ex/sessions/shell_session'
3
+
4
+ require 'socket'
5
+
6
+ describe Ronin::PostEx::Sessions::ShellSession do
7
+ let(:pipe) { UNIXSocket.pair }
8
+ let(:io) { pipe[0] }
9
+ let(:shell) { pipe[1] }
10
+
11
+ subject { described_class.new(io) }
12
+
13
+ describe "#initialize" do
14
+ it "must set #io" do
15
+ expect(subject.io).to be(io)
16
+ end
17
+ end
18
+
19
+ describe "#shell_gets" do
20
+ it "must read a line of text from #io" do
21
+ thread = Thread.new do
22
+ sleep 0.1
23
+ shell.write("foo bar\n")
24
+ end
25
+
26
+ expect(subject.shell_gets).to eq("foo bar\n")
27
+ end
28
+ end
29
+
30
+ describe "#shell_puts" do
31
+ let(:line) { "foo bar" }
32
+
33
+ it "must write a line of text to #io" do
34
+ subject.shell_puts(line)
35
+
36
+ expect(shell.gets).to eq("#{line}\n")
37
+ end
38
+ end
39
+
40
+ describe "#shell_exec" do
41
+ let(:command) { 'ls' }
42
+ let(:output) do
43
+ [
44
+ "API_SPEC.md",
45
+ "ChangeLog.md",
46
+ "COPYING.txt",
47
+ "Gemfile",
48
+ "Gemfile.lock",
49
+ "gemspec.yml",
50
+ "lib",
51
+ "Rakefile",
52
+ "README.md",
53
+ "ronin-post_ex.gemspec",
54
+ "spec",
55
+ "vendor"
56
+ ].map { |line| "#{line}\n" }.join
57
+ end
58
+
59
+ it "must print a beginning deliminator, pipe the command into base64, and print an ending deliminator" do
60
+ thread = Thread.new do
61
+ sleep 0.1
62
+ subject.shell_exec(command)
63
+ end
64
+
65
+ expect(shell.gets).to eq("echo #{described_class::DELIMINATOR}; #{command} 2>/dev/null | base64; echo #{described_class::DELIMINATOR}\n")
66
+ shell.puts(described_class::DELIMINATOR)
67
+ shell.write(Base64.encode64(output))
68
+ shell.puts(described_class::DELIMINATOR)
69
+ end
70
+
71
+ it "must return the output of the command" do
72
+ thread = Thread.new do
73
+ sleep 0.1
74
+
75
+ shell.gets
76
+ shell.puts(described_class::DELIMINATOR)
77
+ shell.write(Base64.encode64(output))
78
+ shell.puts(described_class::DELIMINATOR)
79
+ end
80
+
81
+ expect(subject.shell_exec(command)).to eq(output)
82
+ end
83
+ end
84
+
85
+ describe "#sys_time" do
86
+ let(:timestamp) { 1668692783 }
87
+ let(:output) { "#{timestamp}\n" }
88
+
89
+ it "must run the 'date +%s' and parse the output as an Integer" do
90
+ expect(subject).to receive(:shell_exec).with('date +%s').and_return(output)
91
+
92
+ expect(subject.sys_time).to eq(timestamp)
93
+ end
94
+ end
95
+
96
+ describe "#sys_hostname" do
97
+ let(:hostname) { 'computer' }
98
+ let(:output) { "#{hostname}\n" }
99
+
100
+ it "must run the 'echo $HOSTNAME' and parse the output as an Integer" do
101
+ expect(subject).to receive(:shell_exec).with('echo $HOSTNAME').and_return(output)
102
+
103
+ expect(subject.sys_hostname).to eq(hostname)
104
+ end
105
+ end
106
+
107
+ describe "#fs_getcwd" do
108
+ let(:pwd) { '/current/directory' }
109
+ let(:output) { "#{pwd}\n" }
110
+
111
+ it "must run the 'pwd' command and return the path" do
112
+ expect(subject).to receive(:shell_exec).with('pwd').and_return(output)
113
+
114
+ expect(subject.fs_getcwd).to eq(pwd)
115
+ end
116
+ end
117
+
118
+ describe "#fs_chdir" do
119
+ let(:new_dir) { '/path/to/directory' }
120
+ let(:output) { "\n" }
121
+
122
+ it "must run the 'cd <path> 2>/dev/null' command" do
123
+ expect(subject).to receive(:shell_puts).with("cd #{new_dir} 2>/dev/null")
124
+
125
+ subject.fs_chdir(new_dir)
126
+ end
127
+ end
128
+
129
+ describe "#fs_readfile" do
130
+ let(:path) { '/path/to/file' }
131
+ let(:contents) { "foo bar\nbaz qux\n" }
132
+
133
+ it "must run the 'cat <path>' command and return the file contents" do
134
+ expect(subject).to receive(:command_exec).with('cat',path).and_return(contents)
135
+
136
+ expect(subject.fs_readfile(path)).to eq(contents)
137
+ end
138
+ end
139
+
140
+ describe "#fs_readlink" do
141
+ let(:path) { '/path/to/link' }
142
+ let(:dest_path) { 'path/to/file' }
143
+ let(:output) { "#{dest_path}\n" }
144
+
145
+ it "must run the 'readlink -f <path>' command and return the link's path" do
146
+ expect(subject).to receive(:command_exec).with('readlink','-f',path).and_return(output)
147
+
148
+ expect(subject.fs_readlink(path)).to eq(dest_path)
149
+ end
150
+ end
151
+
152
+ describe "#fs_readdir" do
153
+ let(:path) { '/path/to/dir' }
154
+ let(:entries) do
155
+ %w[
156
+ API_SPEC.md
157
+ ChangeLog.md
158
+ COPYING.txt
159
+ examples
160
+ Gemfile
161
+ Gemfile.lock
162
+ gemspec.yml
163
+ lib
164
+ Rakefile
165
+ README.md
166
+ ronin-post_ex.gemspec
167
+ spec
168
+ vendor
169
+ ]
170
+ end
171
+ let(:output) { "#{entries.join("\n")}\n" }
172
+
173
+ it "must run the 'ls <path>' command and return the directories entries" do
174
+ expect(subject).to receive(:command_exec).with('ls',path).and_return(output)
175
+
176
+ expect(subject.fs_readdir(path)).to eq(entries)
177
+ end
178
+ end
179
+
180
+ describe "#fs_glob" do
181
+ let(:pattern) { '*.md' }
182
+ let(:entries) do
183
+ %w[
184
+ API_SPEC.md
185
+ ChangeLog.md
186
+ README.md
187
+ ]
188
+ end
189
+ let(:output) { "#{entries.join("\n")}\n" }
190
+
191
+ it "must run the 'ls <pattern>' command and return the matching paths" do
192
+ expect(subject).to receive(:shell_exec).with("ls #{pattern}").and_return(output)
193
+
194
+ expect(subject.fs_glob(pattern)).to eq(entries)
195
+ end
196
+ end
197
+
198
+ describe "#fs_mktemp" do
199
+ let(:basename) { 'ronin-XXXX.txt' }
200
+ let(:tempfile) { 'ronin-LtFK.txt' }
201
+ let(:output) { "#{tempfile}\n" }
202
+
203
+ it "must run the 'mktemp <basename>' command and return the tempfile name" do
204
+ expect(subject).to receive(:command_exec).with('mktemp',basename).and_return(output)
205
+
206
+ expect(subject.fs_mktemp(basename)).to eq(tempfile)
207
+ end
208
+ end
209
+
210
+ describe "#fs_mkdir" do
211
+ let(:path) { '/path/to/new_dir' }
212
+
213
+ it "must run the 'mkdir <pattern>' command" do
214
+ expect(subject).to receive(:command_exec).with('mkdir',path)
215
+
216
+ subject.fs_mkdir(path)
217
+ end
218
+ end
219
+
220
+ describe "#fs_copy" do
221
+ let(:src) { '/path/to/src' }
222
+ let(:dest) { '/path/to/dest' }
223
+
224
+ it "must run the 'cp -r <src> <dest>' command" do
225
+ expect(subject).to receive(:command_exec).with('cp','-r',src,dest)
226
+
227
+ subject.fs_copy(src,dest)
228
+ end
229
+ end
230
+
231
+ describe "#fs_unlink" do
232
+ let(:path) { '/path/to/file' }
233
+
234
+ it "must run the 'rm <path>' command" do
235
+ expect(subject).to receive(:command_exec).with('rm',path)
236
+
237
+ subject.fs_unlink(path)
238
+ end
239
+ end
240
+
241
+ describe "#fs_rmdir" do
242
+ let(:path) { '/path/to/dir' }
243
+
244
+ it "must run the 'rmdir <path>' command" do
245
+ expect(subject).to receive(:command_exec).with('rmdir',path)
246
+
247
+ subject.fs_rmdir(path)
248
+ end
249
+ end
250
+
251
+ describe "#fs_move" do
252
+ let(:src) { '/path/to/src' }
253
+ let(:dest) { '/path/to/dest' }
254
+
255
+ it "must run the 'mv <src> <dest>' command" do
256
+ expect(subject).to receive(:command_exec).with('mv',src,dest)
257
+
258
+ subject.fs_move(src,dest)
259
+ end
260
+ end
261
+
262
+ describe "#fs_link" do
263
+ let(:src) { '/path/to/src' }
264
+ let(:dest) { '/path/to/dest' }
265
+
266
+ it "must run the 'ln -s <src> <dest>' command" do
267
+ expect(subject).to receive(:command_exec).with('ln','-s',src,dest)
268
+
269
+ subject.fs_link(src,dest)
270
+ end
271
+ end
272
+
273
+ describe "#fs_chgrp" do
274
+ let(:group) { 'wheel' }
275
+ let(:path) { '/path/to/file' }
276
+
277
+ it "must run the 'chgrp <group> <path>' command" do
278
+ expect(subject).to receive(:command_exec).with('chgrp',group,path)
279
+
280
+ subject.fs_chgrp(group,path)
281
+ end
282
+ end
283
+
284
+ describe "#fs_chown" do
285
+ let(:user) { 'root' }
286
+ let(:path) { '/path/to/file' }
287
+
288
+ it "must run the 'chown <user> <path>' command" do
289
+ expect(subject).to receive(:command_exec).with('chown',user,path)
290
+
291
+ subject.fs_chown(user,path)
292
+ end
293
+ end
294
+
295
+ describe "#fs_chmod" do
296
+ let(:mode) { 0777 }
297
+ let(:umask) { "%.4o" % mode }
298
+ let(:path) { '/path/to/file' }
299
+
300
+ it "must run the 'chown <user> <path>' command" do
301
+ expect(subject).to receive(:command_exec).with('chmod',umask,path)
302
+
303
+ subject.fs_chmod(mode,path)
304
+ end
305
+ end
306
+
307
+ describe "#fs_stat" do
308
+ let(:path) { '/path/to/file' }
309
+ let(:size) { 420 }
310
+ let(:blocks) { 16 }
311
+ let(:uid) { 1000 }
312
+ let(:gid) { 1000 }
313
+ let(:inode) { 12345 }
314
+ let(:links) { 1 }
315
+ let(:atime) { Time.at(1668608914) }
316
+ let(:mtime) { Time.at(1668427627) }
317
+ let(:ctime) { Time.at(1668427627) }
318
+ let(:blocksize) { 1668427627 }
319
+
320
+ let(:output) do
321
+ "#{path} #{size} #{blocks} 81a4 #{uid} #{gid} fd01 #{inode} #{links} 0 0 #{atime.to_i} #{mtime.to_i} #{ctime.to_i} #{blocksize} 4096 unconfined_u:object_r:unlabeled_t:s0\n"
322
+ end
323
+
324
+ it "must run the 'stat -t <path>' command and return a Hash of parsed stat information" do
325
+ expect(subject).to receive(:command_exec).with('stat','-t',path).and_return(output)
326
+
327
+ expect(subject.fs_stat(path)).to eq(
328
+ {
329
+ path: path,
330
+ size: size,
331
+ blocks: blocks,
332
+ uid: uid,
333
+ gid: gid,
334
+ inode: inode,
335
+ links: links,
336
+ atime: atime,
337
+ mtime: mtime,
338
+ ctime: ctime,
339
+ blocksize: blocksize
340
+ }
341
+ )
342
+ end
343
+ end
344
+
345
+ describe "#process_getpid" do
346
+ let(:pid) { 1234 }
347
+ let(:output) { "#{pid}\n" }
348
+
349
+ it "must run the 'echo $$' command and return the parsed PID" do
350
+ expect(subject).to receive(:shell_exec).with('echo $$').and_return(output)
351
+
352
+ expect(subject.process_getpid).to eq(pid)
353
+ end
354
+ end
355
+
356
+ describe "#process_getppid" do
357
+ let(:ppid) { 1234 }
358
+ let(:output) { "#{ppid}\n" }
359
+
360
+ it "must run the 'echo $PPID' command and return the parsed PPID" do
361
+ expect(subject).to receive(:shell_exec).with('echo $PPID').and_return(output)
362
+
363
+ expect(subject.process_getppid).to eq(ppid)
364
+ end
365
+ end
366
+
367
+ describe "#process_getuid" do
368
+ let(:uid) { 1000 }
369
+ let(:output) { "#{uid}\n" }
370
+
371
+ it "must run the 'id -u' command and return the parsed UID" do
372
+ expect(subject).to receive(:command_exec).with('id','-u').and_return(output)
373
+
374
+ expect(subject.process_getuid).to eq(uid)
375
+ end
376
+ end
377
+
378
+ describe "#process_getgid" do
379
+ let(:gid) { 1000 }
380
+ let(:output) { "#{gid}\n" }
381
+
382
+ it "must run the 'id -g' command and return the parsed GID" do
383
+ expect(subject).to receive(:command_exec).with('id','-g').and_return(output)
384
+
385
+ expect(subject.process_getgid).to eq(gid)
386
+ end
387
+ end
388
+
389
+ describe "#process_getgid" do
390
+ let(:env) do
391
+ {
392
+ 'FOO' => 'foo',
393
+ 'BAR' => 'bar'
394
+ }
395
+ end
396
+ let(:output) do
397
+ "#{env.keys[0]}=#{env.values[0]}\n#{env.keys[1]}=#{env.values[1]}\n"
398
+ end
399
+
400
+ it "must run the 'env' command and return the parsed env Hash" do
401
+ expect(subject).to receive(:command_exec).with('env').and_return(output)
402
+
403
+ expect(subject.process_environ).to eq(env)
404
+ end
405
+ end
406
+
407
+ describe "#process_getenv" do
408
+ let(:name) { 'FOO' }
409
+ let(:value) { 'foo bar baz' }
410
+ let(:output) { "#{value}\n" }
411
+
412
+ it "must run the 'echo $<name>' command and return the parsed value" do
413
+ expect(subject).to receive(:shell_exec).with("echo $#{name}").and_return(output)
414
+
415
+ expect(subject.process_getenv(name)).to eq(value)
416
+ end
417
+ end
418
+
419
+ describe "#process_setenv" do
420
+ let(:name) { 'FOO' }
421
+ let(:value) { 'foo bar baz' }
422
+
423
+ it "must run the 'export <name>=<value>' command and return the parsed value" do
424
+ expect(subject).to receive(:shell_puts).with("export #{name}=#{value}")
425
+
426
+ subject.process_setenv(name,value)
427
+ end
428
+ end
429
+
430
+ describe "#process_unsetenv" do
431
+ let(:name) { 'FOO' }
432
+
433
+ it "must run the 'unset <name>' command" do
434
+ expect(subject).to receive(:shell_puts).with("unset #{name}")
435
+
436
+ subject.process_unsetenv(name)
437
+ end
438
+ end
439
+
440
+ describe "#process_kill" do
441
+ let(:pid) { 1234 }
442
+ let(:signal) { 'TERM' }
443
+
444
+ it "must run the 'kill -s <signal> <pid>' command" do
445
+ expect(subject).to receive(:command_exec).with('kill','-s',signal,pid)
446
+
447
+ subject.process_kill(pid,signal)
448
+ end
449
+ end
450
+
451
+ describe "#process_spawn" do
452
+ let(:command_name) { 'cmd' }
453
+ let(:arguments) { ['foo', 'bar baz'] }
454
+
455
+ let(:pid) { 1234 }
456
+ let(:output) { "#{pid}\n" }
457
+
458
+ it "must run the command with arguments and return the parsed PID" do
459
+ command = Shellwords.join([command_name, *arguments])
460
+
461
+ expect(subject).to receive(:shell_exec).with("#{command} 2>&1 >/dev/null &; echo $!").and_return(output)
462
+
463
+ expect(subject.process_spawn(command_name,*arguments)).to eq(pid)
464
+ end
465
+ end
466
+
467
+ describe "#process_exit" do
468
+ it "must run the 'exit' command" do
469
+ expect(subject).to receive(:shell_puts).with('exit')
470
+
471
+ subject.process_exit
472
+ end
473
+ end
474
+
475
+ describe "#close" do
476
+ it "must call #close on #io" do
477
+ expect(io).to receive(:close)
478
+
479
+ subject.close
480
+ end
481
+ end
482
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+ require 'simplecov'
3
+ require 'ronin/post_ex/version'
4
+
5
+ SimpleCov.start
6
+
7
+ RSpec.configure do |c|
8
+ c.include Ronin::PostEx
9
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'ronin/post_ex/system'
3
+ require 'ronin/post_ex/sessions/session'
4
+
5
+ describe Ronin::PostEx::System do
6
+ let(:session) { Ronin::PostEx::Sessions::Session.new }
7
+
8
+ subject { described_class.new(session) }
9
+
10
+ describe "#initialize" do
11
+ it "must set #session" do
12
+ expect(subject.session).to be(session)
13
+ end
14
+
15
+ it "must initialize #fs" do
16
+ expect(subject.fs).to be_kind_of(described_class::FS)
17
+ end
18
+
19
+ it "must initialize #process" do
20
+ expect(subject.process).to be_kind_of(described_class::Process)
21
+ end
22
+
23
+ it "must initialize #shell" do
24
+ expect(subject.shell).to be_kind_of(described_class::Shell)
25
+ end
26
+ end
27
+
28
+ describe "#fs" do
29
+ it "must return a System::FS object" do
30
+ expect(subject.fs).to be_kind_of(described_class::FS)
31
+ end
32
+ end
33
+
34
+ describe "#process" do
35
+ it "must return a System::Process object" do
36
+ expect(subject.process).to be_kind_of(described_class::Process)
37
+ end
38
+ end
39
+
40
+ describe "#shell" do
41
+ it "must return a System::Shell object" do
42
+ expect(subject.shell).to be_kind_of(described_class::Shell)
43
+ end
44
+ end
45
+
46
+ describe "#time" do
47
+ let(:unix_timestamp) { 1642775495 }
48
+ let(:time) { Time.at(unix_timestamp) }
49
+
50
+ it "must call the 'sys_time' API function and return a Time object" do
51
+ expect(session).to receive(:sys_time).and_return(unix_timestamp)
52
+
53
+ expect(subject.time).to eq(time)
54
+ end
55
+ end
56
+
57
+ describe "#hostname" do
58
+ let(:hostname) { 'computer' }
59
+
60
+ it "must call the 'sys_hostname' API function and return the hostname" do
61
+ expect(session).to receive(:sys_hostname).and_return(hostname)
62
+
63
+ expect(subject.hostname).to eq(hostname)
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ronin-post_ex
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.beta1
5
+ platform: ruby
6
+ authors:
7
+ - Postmodern
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fake_io
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hexdump
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ronin-core
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0.beta1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0.beta1
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ description: ronin-post_ex is a Ruby API for Post-Exploitation.
70
+ email: postmodern.mod3@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files:
74
+ - API_SPEC.md
75
+ - COPYING.txt
76
+ - ChangeLog.md
77
+ - README.md
78
+ files:
79
+ - ".document"
80
+ - ".github/workflows/ruby.yml"
81
+ - ".gitignore"
82
+ - ".rspec"
83
+ - ".ruby-version"
84
+ - ".yardopts"
85
+ - API_SPEC.md
86
+ - COPYING.txt
87
+ - ChangeLog.md
88
+ - Gemfile
89
+ - README.md
90
+ - Rakefile
91
+ - examples/bind_shell.rb
92
+ - gemspec.yml
93
+ - lib/ronin/post_ex.rb
94
+ - lib/ronin/post_ex/cli/shell_shell.rb
95
+ - lib/ronin/post_ex/cli/system_shell.rb
96
+ - lib/ronin/post_ex/remote_dir.rb
97
+ - lib/ronin/post_ex/remote_file.rb
98
+ - lib/ronin/post_ex/remote_file/stat.rb
99
+ - lib/ronin/post_ex/remote_process.rb
100
+ - lib/ronin/post_ex/resource.rb
101
+ - lib/ronin/post_ex/sessions/bind_shell.rb
102
+ - lib/ronin/post_ex/sessions/remote_shell_session.rb
103
+ - lib/ronin/post_ex/sessions/reverse_shell.rb
104
+ - lib/ronin/post_ex/sessions/rpc_session.rb
105
+ - lib/ronin/post_ex/sessions/session.rb
106
+ - lib/ronin/post_ex/sessions/shell_session.rb
107
+ - lib/ronin/post_ex/system.rb
108
+ - lib/ronin/post_ex/system/fs.rb
109
+ - lib/ronin/post_ex/system/process.rb
110
+ - lib/ronin/post_ex/system/shell.rb
111
+ - lib/ronin/post_ex/version.rb
112
+ - ronin-post_ex.gemspec
113
+ - spec/sessions/bind_shell_spec.rb
114
+ - spec/sessions/remote_shell_session_spec.rb
115
+ - spec/sessions/reverse_shell_spec.rb
116
+ - spec/sessions/rpc_session_spec.rb
117
+ - spec/sessions/session_spec.rb
118
+ - spec/sessions/shell_session_spec.rb
119
+ - spec/spec_helper.rb
120
+ - spec/system_spec.rb
121
+ homepage: https://ronin-rb.dev/
122
+ licenses:
123
+ - LGPL-3.0
124
+ metadata:
125
+ documentation_uri: https://rubydoc.info/gems/ronin-post_ex
126
+ source_code_uri: https://github.com/ronin-rb/ronin-post_ex
127
+ bug_tracker_uri: https://github.com/ronin-rb/ronin-post_ex/issues
128
+ changelog_uri: https://github.com/ronin-rb/ronin-post_ex/blob/master/ChangeLog.md
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 3.0.0
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubygems_version: 3.3.26
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Ruby API for Post-Exploitation
148
+ test_files:
149
+ - spec/sessions/bind_shell_spec.rb
150
+ - spec/sessions/remote_shell_session_spec.rb
151
+ - spec/sessions/reverse_shell_spec.rb
152
+ - spec/sessions/rpc_session_spec.rb
153
+ - spec/sessions/session_spec.rb
154
+ - spec/sessions/shell_session_spec.rb
155
+ - spec/system_spec.rb