ronin-post_ex 0.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
data/README.md ADDED
@@ -0,0 +1,245 @@
1
+ # ronin-post_ex
2
+
3
+ [![CI](https://github.com/ronin-rb/ronin-post_ex/actions/workflows/ruby.yml/badge.svg)](https://github.com/ronin-rb/ronin-post_ex/actions/workflows/ruby.yml)
4
+ [![Code Climate](https://codeclimate.com/github/ronin-rb/ronin-post_ex.svg)](https://codeclimate.com/github/ronin-rb/ronin-post_ex)
5
+
6
+ * [Website](https://ronin-rb.dev/)
7
+ * [Source](https://github.com/ronin-rb/ronin-post_ex)
8
+ * [Issues](https://github.com/ronin-rb/ronin-post_ex/issues)
9
+ * [Documentation](https://ronin-rb.dev/docs/ronin-post_ex/frames)
10
+ * [Discord](https://discord.gg/6WAb3PsVX9) |
11
+ [Twitter](https://twitter.com/ronin_rb) |
12
+ [Mastodon](https://infosec.exchange/@ronin_rb)
13
+
14
+ ## Description
15
+
16
+ ronin-post_ex is a Ruby API for Post-Exploitation.
17
+
18
+ This library is used by [ronin-payloads], [ronin-c2], and [ronin-exploits]
19
+ to provide a Post-Exploitation API around payloads, C2 sessions, or even
20
+ exploits.
21
+
22
+ ronin-post_ex is part of the [ronin-rb] project, a [Ruby] toolkit for security
23
+ research and development.
24
+
25
+ ## Features
26
+
27
+ * Defines a syscall-like [API for Post-Exploitation][API Spec].
28
+ * Provides classes for interacting with the Post-Exploitation API.
29
+ * {Ronin::PostEx::System} - allows interacting with a remote system.
30
+ * {Ronin::PostEx::System::FS} - allows interacting with the file-system.
31
+ * {Ronin::PostEx::System::Process} - allows manipulating the current process
32
+ or child processes.
33
+ * {Ronin::PostEx::System::Shell} - allows interacting with an interactive
34
+ shell..
35
+ * {Ronin::PostEx::RemoteFile} - allows reading/writing files.
36
+ * {Ronin::PostEx::RemoteDir} - allows reading the contents of directories.
37
+ * {Ronin::PostEx::RemoteProcess} - allows reading/writing to an running
38
+ command.
39
+ * Supports interacting with interactive shell commands.
40
+ * Provides interactive command shells for interacting with systems.
41
+ * Supports Linux/BSD/UNIX systems.
42
+ * Provides common post-exploitation session classes for interacting with shells,
43
+ bind shells, and reverse shells.
44
+ * Supports defining custom post-exploitation session classes.
45
+
46
+ ## Limitations
47
+
48
+ * Does not currently support Windows systems.
49
+ * Does not fully support bidirectional fully interactive shell commands.
50
+
51
+ ## Examples
52
+
53
+ ### Bind Shell
54
+
55
+ ```ruby
56
+ session = Ronin::PostEx::Sessions::BindShell.connect(host,port)
57
+ system = session.system
58
+
59
+ system.shell.ls('/')
60
+ # => "..."
61
+ ```
62
+
63
+ ### Reverse Shell
64
+
65
+ ```ruby
66
+ session = Ronin::PostEx::Sessions::ReverseShell.listen(host,port)
67
+ system = session.system
68
+
69
+ system.shell.ls('/')
70
+ # => "..."
71
+ ```
72
+
73
+ ### Custom Session Class
74
+
75
+ Define a custom session class which defines the
76
+ [Post-Exploitation API methods][API Spec]:
77
+
78
+ ```ruby
79
+ class RATSession < Ronin::PostEx::Sessions::Session
80
+
81
+ def initialize(host,port)
82
+ # ...
83
+ end
84
+
85
+ def rpc_call(method,*arguments)
86
+ # ...
87
+ end
88
+
89
+ def fs_read(path)
90
+ rpc_call("fs_read",path)
91
+ end
92
+
93
+ def shell_exec(command)
94
+ rpc_call("shell_exec",command)
95
+ end
96
+
97
+ # ...
98
+
99
+ end
100
+
101
+ session = RATSession.new
102
+ system = session.system
103
+ ```
104
+
105
+ ### System
106
+
107
+ Interact with the system's remote files as if they were local files:
108
+
109
+ ```ruby
110
+ file = system.fs.open('/etc/passwd')
111
+
112
+ file.each_line do |line|
113
+ user, x, uid, gid, name, home_dir, shell = line.split(':')
114
+
115
+ puts "User Detected: #{user} (id=#{uid})"
116
+ end
117
+ ```
118
+
119
+ Get information about the current process:
120
+
121
+ ```ruby
122
+ system.process.pid
123
+ # => 1234
124
+
125
+ system.process.getuid
126
+ # => 1001
127
+
128
+ system.process.environ
129
+ # => {"HOME"=>"...", "PATH"=>"...", ...}
130
+ ```
131
+
132
+ Execute commands on the remote system:
133
+
134
+ ```ruby
135
+ system.shell.ls('/')
136
+ # => "bin\nboot\ndev\netc\nhome\nlib\nlib64\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsnap\nsrv\nsys\ntmp\nusr\nvar\n"
137
+
138
+ system.shell.exec("find -type f -name '*.xls' /srv") do |path|
139
+ puts "Found XLS file: #{path}"
140
+ end
141
+ ```
142
+
143
+ Spawn an interactive command shell:
144
+
145
+ ```ruby
146
+ system.shell.interact
147
+ $
148
+ ```
149
+
150
+ Spawn an interactive post-exploitation system shell:
151
+
152
+ ```ruby
153
+ system.interact
154
+ ```
155
+ ```
156
+ ronin-post_ex> help
157
+ help [COMMAND] Prints the list of commands or additional help
158
+ fs.chdir DIR Changes the current working directory
159
+ fs.pwd Prints the current working directory
160
+ fs.readfile FILE Reads the contents of a given FILE
161
+ fs.readlink SYMLINK Reads the destination path of a symlink
162
+ fs.readdir DIR Reads the contents of a given directory
163
+ fs.hexdump FILE Hexdumps a given file
164
+ fs.copy SRC DEST Copies the SRC file to the DEST path
165
+ fs.unlink FILE Deletes a given file
166
+ fs.rmdir DIR Removes a given directory
167
+ fs.mv SRC DEST Moves or renames a given file or directory
168
+ fs.link SRC DEST Creates a link from the source to the destination
169
+ fs.chown USER PATH Changes the owner of a given file or directory
170
+ fs.chgrp GROUP PATH Changes the group of a given file or directory
171
+ fs.chmod MODE PATH Changes the permission mode of a given file or directory
172
+ fs.stat PATH Prints file system information about a given file or directory
173
+ fs.open PATH [MODE] Opens a file for reading or writing
174
+ files Lists opened files
175
+ file.seek FILE_ID POS [WHENCE] Seeks to a position within the file
176
+ file.read FILE_ID LENGTH Reads LENGTH of data from an opened file
177
+ file.write FILE_ID DATA Writes data to an opened file
178
+ file.close FILE_ID Closes an open file
179
+ ronin-post_ex>
180
+ ```
181
+
182
+ ## Requirements
183
+
184
+ * [Ruby] >= 3.0.0
185
+ * [fake_io] ~> 0.1
186
+ * [hexdump] ~> 1.0
187
+ * [ronin-core] ~> 0.1
188
+
189
+ ## Install
190
+
191
+ ```shell
192
+ $ gem install ronin-post_ex
193
+ ```
194
+
195
+ ### Gemfile
196
+
197
+ ```ruby
198
+ gem 'ronin-post_ex', '~> 0.1'
199
+ ```
200
+
201
+ ### gemspec
202
+
203
+ ```ruby
204
+ gem.add_dependency 'ronin-post_ex', '~> 0.1'
205
+ ```
206
+
207
+ ## Development
208
+
209
+ 1. [Fork It!](https://github.com/ronin-rb/ronin-post_ex/fork)
210
+ 2. Clone It!
211
+ 3. `cd ronin-post_ex/`
212
+ 4. `bundle install`
213
+ 5. `git checkout -b my_feature`
214
+ 6. Code It!
215
+ 7. `bundle exec rake spec`
216
+ 8. `git push origin my_feature`
217
+
218
+ ## License
219
+
220
+ Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
221
+
222
+ ronin-post_ex is free software: you can redistribute it and/or modify
223
+ it under the terms of the GNU Lesser General Public License as published
224
+ by the Free Software Foundation, either version 3 of the License, or
225
+ (at your option) any later version.
226
+
227
+ ronin-post_ex is distributed in the hope that it will be useful,
228
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
229
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
230
+ GNU Lesser General Public License for more details.
231
+
232
+ You should have received a copy of the GNU Lesser General Public License
233
+ along with ronin-post_ex. If not, see <https://www.gnu.org/licenses/>.
234
+
235
+ [Ruby]: https://www.ruby-lang.org
236
+ [ronin-rb]: https://ronin-rb.dev
237
+
238
+ [fake_io]: https://github.com/postmodern/fake_io.rb#readme
239
+ [hexdump]: https://github.com/postmodern/hexdump.rb#readme
240
+ [ronin-core]: https://github.com/ronin-rb/ronin-core#readme
241
+ [ronin-payloads]: https://github.com/ronin-rb/ronin-payloads#readme
242
+ [ronin-c2]: https://github.com/ronin-rb/ronin-c2#readme
243
+ [ronin-exploits]: https://github.com/ronin-rb/ronin-exploits#readme
244
+
245
+ [API Spec]: https://github.com/ronin-rb/ronin-post_ex/blob/main/API_SPEC.md
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+
3
+ begin
4
+ require 'bundler'
5
+ rescue LoadError => e
6
+ warn e.message
7
+ warn "Run `gem install bundler` to install Bundler"
8
+ exit -1
9
+ end
10
+
11
+ begin
12
+ Bundler.setup(:development)
13
+ rescue Bundler::BundlerError => e
14
+ warn e.message
15
+ warn "Run `bundle install` to install missing gems"
16
+ exit e.status_code
17
+ end
18
+
19
+ require 'rake'
20
+
21
+ require 'rubygems/tasks'
22
+ Gem::Tasks.new(sign: {checksum: true, pgp: true})
23
+
24
+ require 'rspec/core/rake_task'
25
+ RSpec::Core::RakeTask.new
26
+ task :test => :spec
27
+ task :default => :spec
28
+
29
+ require 'yard'
30
+ YARD::Rake::YardocTask.new
31
+ task :docs => :yard
32
+
33
+ require 'kramdown/man/task'
34
+ Kramdown::Man::Task.new
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'ronin/post_ex/sessions/shell_session'
5
+ require 'ronin/post_ex/system'
6
+ require 'socket'
7
+
8
+ # run `nc -l -p 1337 -e /bin/sh` in another terminal
9
+ socket = begin
10
+ TCPSocket.new('localhost',1337)
11
+ rescue
12
+ warn "Please run 'nc -l -p 1337 -e /bin/sh' in another terminal"
13
+ exit(-1)
14
+ end
15
+
16
+ session = Ronin::PostEx::Sessions::ShellSession.new(socket)
17
+ system = Ronin::PostEx::System.new(session)
18
+
19
+ system.interact
data/gemspec.yml ADDED
@@ -0,0 +1,25 @@
1
+ name: ronin-post_ex
2
+ summary: Ruby API for Post-Exploitation
3
+ description: ronin-post_ex is a Ruby API for Post-Exploitation.
4
+ license: LGPL-3.0
5
+ authors: Postmodern
6
+ email: postmodern.mod3@gmail.com
7
+ homepage: https://ronin-rb.dev/
8
+ has_yard: true
9
+
10
+ metadata:
11
+ documentation_uri: https://rubydoc.info/gems/ronin-post_ex
12
+ source_code_uri: https://github.com/ronin-rb/ronin-post_ex
13
+ bug_tracker_uri: https://github.com/ronin-rb/ronin-post_ex/issues
14
+ changelog_uri: https://github.com/ronin-rb/ronin-post_ex/blob/master/ChangeLog.md
15
+
16
+ required_ruby_version: ">= 3.0.0"
17
+
18
+ dependencies:
19
+ fake_io: ~> 0.1
20
+ hexdump: ~> 1.0
21
+ # Ronin dependencies:
22
+ ronin-core: ~> 0.1.0.beta1
23
+
24
+ development_dependencies:
25
+ bundler: ~> 2.0
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-post_ex - a Ruby API for Post-Exploitation.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-post_ex is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-post_ex is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-post_ex. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/core/cli/shell'
22
+
23
+ module Ronin
24
+ module PostEx
25
+ module CLI
26
+ #
27
+ # A shell for {System::Shell}.
28
+ #
29
+ class ShellShell < Core::CLI::Shell
30
+
31
+ prompt_sigil '$'
32
+
33
+ #
34
+ # Initializes the shell.
35
+ #
36
+ # @param [System::Shell] shell
37
+ # The shell resource.
38
+ #
39
+ # @param [Hash{Symbol => Object}] kwargs
40
+ # Additional keyword arguments for
41
+ # `Ronin::Core::CLI::Shell#initialize`.
42
+ #
43
+ def initialize(shell, **kwargs)
44
+ super(**kwargs)
45
+
46
+ @shell = shell
47
+ end
48
+
49
+ #
50
+ # Executes a command and prints it's output.
51
+ #
52
+ # @param [String] command
53
+ # The command string.
54
+ #
55
+ def exec(command)
56
+ if command == 'exit'
57
+ exit
58
+ else
59
+ puts @shell.run(command)
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end