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.
- checksums.yaml +7 -0
- data/.document +6 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/API_SPEC.md +235 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +23 -0
- data/Gemfile +36 -0
- data/README.md +245 -0
- data/Rakefile +34 -0
- data/examples/bind_shell.rb +19 -0
- data/gemspec.yml +25 -0
- data/lib/ronin/post_ex/cli/shell_shell.rb +66 -0
- data/lib/ronin/post_ex/cli/system_shell.rb +811 -0
- data/lib/ronin/post_ex/remote_dir.rb +190 -0
- data/lib/ronin/post_ex/remote_file/stat.rb +174 -0
- data/lib/ronin/post_ex/remote_file.rb +417 -0
- data/lib/ronin/post_ex/remote_process.rb +170 -0
- data/lib/ronin/post_ex/resource.rb +144 -0
- data/lib/ronin/post_ex/sessions/bind_shell.rb +60 -0
- data/lib/ronin/post_ex/sessions/remote_shell_session.rb +48 -0
- data/lib/ronin/post_ex/sessions/reverse_shell.rb +67 -0
- data/lib/ronin/post_ex/sessions/rpc_session.rb +779 -0
- data/lib/ronin/post_ex/sessions/session.rb +73 -0
- data/lib/ronin/post_ex/sessions/shell_session.rb +618 -0
- data/lib/ronin/post_ex/system/fs.rb +650 -0
- data/lib/ronin/post_ex/system/process.rb +422 -0
- data/lib/ronin/post_ex/system/shell.rb +1037 -0
- data/lib/ronin/post_ex/system.rb +191 -0
- data/lib/ronin/post_ex/version.rb +26 -0
- data/lib/ronin/post_ex.rb +22 -0
- data/ronin-post_ex.gemspec +61 -0
- data/spec/sessions/bind_shell_spec.rb +31 -0
- data/spec/sessions/remote_shell_session_spec.rb +28 -0
- data/spec/sessions/reverse_shell_spec.rb +49 -0
- data/spec/sessions/rpc_session_spec.rb +500 -0
- data/spec/sessions/session_spec.rb +61 -0
- data/spec/sessions/shell_session_spec.rb +482 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/system_spec.rb +66 -0
- metadata +155 -0
data/README.md
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
# ronin-post_ex
|
2
|
+
|
3
|
+
[](https://github.com/ronin-rb/ronin-post_ex/actions/workflows/ruby.yml)
|
4
|
+
[](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
|