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,190 @@
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
+ module Ronin
22
+ module PostEx
23
+ #
24
+ # The {RemoteDir} class represents directories on a remote system.
25
+ #
26
+ class RemoteDir
27
+
28
+ include Enumerable
29
+
30
+ # The path of the directory
31
+ attr_reader :path
32
+
33
+ # The current position in the open directory.
34
+ #
35
+ # @return [Integer]
36
+ attr_reader :pos
37
+
38
+ #
39
+ # Creates a new Dir object.
40
+ #
41
+ # @param [String] path
42
+ # The path to the directory.
43
+ #
44
+ # @param [Array<String>] entries
45
+ # The entries of the directory.
46
+ #
47
+ def initialize(path,entries=[])
48
+ @path = path
49
+ @entries = entries
50
+ @pos = 0
51
+ @closed = false
52
+ end
53
+
54
+ #
55
+ # Returns the position in the opened directory.
56
+ #
57
+ # @return [Integer]
58
+ # The position of the opened directory.
59
+ #
60
+ # @raise [IOError]
61
+ # The directory is closed.
62
+ #
63
+ def tell
64
+ if @closed
65
+ raise(IOError,"closed directory")
66
+ end
67
+
68
+ return @pos
69
+ end
70
+
71
+ #
72
+ # Rewinds the opened directory.
73
+ #
74
+ # @return [Dir]
75
+ #
76
+ # @raise [IOError]
77
+ # The directory is closed.
78
+ #
79
+ def rewind
80
+ if @closed
81
+ raise(IOError,"closed directory")
82
+ end
83
+
84
+ @pos = 0
85
+ return self
86
+ end
87
+
88
+ #
89
+ # Sets the position within the open directory.
90
+ #
91
+ # @param [Integer] new_pos
92
+ # The new position within the open directory.
93
+ #
94
+ # @return [Dir]
95
+ #
96
+ # @raise [Errno::EINVAL]
97
+ # The new position was out of bounds.
98
+ #
99
+ # @raise [IOError]
100
+ # The directory is closed.
101
+ #
102
+ def seek(new_pos)
103
+ if @closed
104
+ raise(IOError,"closed directory")
105
+ end
106
+
107
+ if (new_pos < 0) || (new_pos >= @entries.length)
108
+ raise(Errno::EINVAL,"invalid seek position")
109
+ end
110
+
111
+ @pos = new_pos
112
+ return self
113
+ end
114
+
115
+ #
116
+ # Iterates through the entries within the directory.
117
+ #
118
+ # @yield [entry]
119
+ # The given block will be passed each entry.
120
+ #
121
+ # @yieldparam [String] entry
122
+ # An entry from the directory.
123
+ #
124
+ # @return [Enumerator]
125
+ # An enumerator will be returned if no block is given.
126
+ #
127
+ # @raise [IOError]
128
+ # The directory is closed.
129
+ #
130
+ def each
131
+ return enum_for(__method__) unless block_given?
132
+
133
+ if @closed
134
+ raise(IOError,"closed directory")
135
+ end
136
+
137
+ @pos = 0
138
+
139
+ @entries.each do |entry|
140
+ yield entry
141
+ @pos += 1
142
+ end
143
+
144
+ return self
145
+ end
146
+
147
+ #
148
+ # Reads the next entry from the directory.
149
+ #
150
+ # @return [String, nil]
151
+ # The next entry from the opened directory.
152
+ # If all entries have been read, `nil` is returned.
153
+ #
154
+ # @raise [IOError]
155
+ # The directory is closed.
156
+ #
157
+ def read
158
+ if @closed
159
+ raise(IOError,"closed directory")
160
+ end
161
+
162
+ if @pos < @entries.length
163
+ next_entry = @entries[@pos]
164
+
165
+ @pos += 1
166
+ return next_entry
167
+ end
168
+ end
169
+
170
+ #
171
+ # Closes the opened directory.
172
+ #
173
+ def close
174
+ @closed = true
175
+ return nil
176
+ end
177
+
178
+ #
179
+ # Inspects the directory.
180
+ #
181
+ # @return [String]
182
+ # The inspected directory.
183
+ #
184
+ def inspect
185
+ "<#{self.class}:#{@path}>"
186
+ end
187
+
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,174 @@
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/post_ex/resource'
22
+
23
+ module Ronin
24
+ module PostEx
25
+ class RemoteFile < Resource
26
+ #
27
+ # Represents the status information of a remote file. The {Stat} class
28
+ # using the `fs_stat` or `file_stat` method defined by the API object to
29
+ # request the remote status information.
30
+ #
31
+ # ## Supported API Methods
32
+ #
33
+ # * `file_stat(fd : Integer) -> Hash[Symbol, Object] | nil`
34
+ # * `fs_stat(path : String) -> Hash[Symbol, Object] | nil`
35
+ #
36
+ class Stat
37
+
38
+ # The path of the file
39
+ #
40
+ # @return [String]
41
+ attr_reader :path
42
+
43
+ # The size of the file (in bytes)
44
+ #
45
+ # @return [Integer]
46
+ attr_reader :size
47
+
48
+ # The number of native file-system blocks
49
+ #
50
+ # @return [Integer]
51
+ attr_reader :blocks
52
+
53
+ # The native file-system block size.
54
+ #
55
+ # @return [Integer]
56
+ attr_reader :blocksize
57
+
58
+ # The Inode number
59
+ #
60
+ # @return [Integer]
61
+ attr_reader :inode
62
+
63
+ # The number of hard links to the file
64
+ #
65
+ # @return [Integer]
66
+ attr_reader :nlinks
67
+
68
+ # The mode of the file
69
+ #
70
+ # @return [Integer]
71
+ attr_reader :mode
72
+
73
+ # The owner's UID of the file.
74
+ #
75
+ # @return [Integer]
76
+ attr_reader :uid
77
+
78
+ # The owner's GID of the file.
79
+ #
80
+ # @return [Integer]
81
+ attr_reader :gid
82
+
83
+ # The access time of the file.
84
+ #
85
+ # @return [Time, nil]
86
+ attr_reader :atime
87
+
88
+ # The creation time of the file.
89
+ #
90
+ # @return [Time]
91
+ attr_reader :ctime
92
+
93
+ # The modification time of the file.
94
+ #
95
+ # @return [Time]
96
+ attr_reader :mtime
97
+
98
+ #
99
+ # Creates a new File Stat object.
100
+ #
101
+ # @param [Sessions::Session##fs_stat] session
102
+ # The object controlling file-system stat.
103
+ #
104
+ # @param [String] path
105
+ # The path to stat.
106
+ #
107
+ # @param [Integer] fd
108
+ # The file description to stat.
109
+ #
110
+ # @raise [ArgumentError]
111
+ # Neither the `path:` or `fd:` keyword arguments were given.
112
+ #
113
+ # @raise [NotImplementedError]
114
+ # The leveraging object does not define `fs_stat` or `file_stat`
115
+ # needed by {Stat}.
116
+ #
117
+ # @raise [Errno::ENOENT]
118
+ # The remote file does not exist.
119
+ #
120
+ # @note
121
+ # This method requires `session` define the `fs_stat` API method.
122
+ #
123
+ def initialize(session, path: nil, fd: nil)
124
+ if path
125
+ unless session.respond_to?(:fs_stat)
126
+ raise(NotImplementedError,"#{session.inspect} does not define #fs_stat")
127
+ end
128
+ elsif fd
129
+ unless session.respond_to?(:file_stat)
130
+ raise(NotImplementedError,"#{session.inspect} does not define #file_stat")
131
+ end
132
+ else
133
+ raise(ArgumentError,"#{self.class}#initialize must be given either the path: or fd: keyword argument")
134
+ end
135
+
136
+ @session = session
137
+ @path = path.to_s
138
+
139
+ unless (stat = @session.fs_stat(@path))
140
+ raise(Errno::ENOENT,"No such file or directory #{@path.dump}")
141
+ end
142
+
143
+ @size = stat[:size]
144
+ @blocks = stat[:blocks]
145
+ @blocksize = stat[:blocksize]
146
+ @inode = stat[:inode]
147
+ @nlinks = stat[:nlinks]
148
+
149
+ @mode = stat[:mode]
150
+ @uid = stat[:uid]
151
+ @gid = stat[:gid]
152
+
153
+ @atime = stat[:atime]
154
+ @ctime = stat[:ctime]
155
+ @mtime = stat[:mtime]
156
+ end
157
+
158
+ alias ino inode
159
+ alias blksize blocksize
160
+
161
+ #
162
+ # Determines whether the file has zero size.
163
+ #
164
+ # @return [Boolean]
165
+ # Specifies whether the file has zero size.
166
+ #
167
+ def zero?
168
+ @size == 0
169
+ end
170
+
171
+ end
172
+ end
173
+ end
174
+ end