librex 0.0.12 → 0.0.13
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.
- data/README.markdown +1 -1
- data/Rakefile +1 -1
- data/lib/rex/io/stream.rb +1 -1
- data/lib/rex/parser/nmap_xml.rb +4 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +6 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +31 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +47 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +36 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/{model.rb → dll.rb} +4 -226
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +100 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +42 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +148 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +127 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +2 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +3 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +75 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +103 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +44 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +2 -2
- data/lib/rex/proto/dhcp/server.rb +7 -6
- data/lib/rex/proto/ntlm/utils.rb +505 -100
- data/lib/rex/proto/rfb/cipher.rb +6 -0
- data/lib/rex/proto/smb/client.rb +40 -332
- data/lib/rex/proto/smb/simpleclient.rb +3 -1
- data/lib/rex/proto/smb/utils.rb +0 -4
- metadata +14 -4
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
A non-official re-packaging of the Rex library as a gem for easy of usage of the Metasploit REX framework in a non Metasploit application. I received permission from HDM to create this package.
|
4
4
|
|
5
5
|
Currently based on:
|
6
|
-
SVN Revision:
|
6
|
+
SVN Revision: 12182
|
7
7
|
|
8
8
|
# Credits
|
9
9
|
The Metasploit development team <http://www.metasploit.com>
|
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ task :update do
|
|
17
17
|
system "git rm lib/rex.rb"
|
18
18
|
system "git rm lib/rex.rb.ts.rb"
|
19
19
|
system "git rm -rf lib/rex/"
|
20
|
-
system "git commit -a -m \"Removed old code.\""
|
20
|
+
# system "git commit -a -m \"Removed old code.\""
|
21
21
|
system "mkdir lib"
|
22
22
|
|
23
23
|
puts "[*] Checking out Metasploit trunk"
|
data/lib/rex/io/stream.rb
CHANGED
@@ -95,7 +95,7 @@ module Stream
|
|
95
95
|
false
|
96
96
|
end
|
97
97
|
rescue ::Errno::EBADF, ::Errno::ENOTSOCK
|
98
|
-
|
98
|
+
raise ::EOFError
|
99
99
|
rescue StreamClosedError, ::IOError, ::EOFError, ::Errno::EPIPE
|
100
100
|
# If the thing that lead to the closure was an abortive close, then
|
101
101
|
# don't raise the stream closed error.
|
data/lib/rex/parser/nmap_xml.rb
CHANGED
@@ -84,9 +84,12 @@ class NmapXMLStreamParser
|
|
84
84
|
# <state> refers to the state of a port; values are "open", "closed", or "filtered"
|
85
85
|
@host["ports"].last["state"] = attributes["state"]
|
86
86
|
when "service"
|
87
|
-
# Store any service info with the associated port. There shouldn't
|
87
|
+
# Store any service and script info with the associated port. There shouldn't
|
88
88
|
# be any collisions on attribute names here, so just merge them.
|
89
89
|
@host["ports"].last.merge!(attributes)
|
90
|
+
when "script"
|
91
|
+
@host["ports"].last["scripts"] ||= {}
|
92
|
+
@host["ports"].last["scripts"][attributes["id"]] = attributes["output"]
|
90
93
|
when "trace"
|
91
94
|
@host["trace"] = {"port" => attributes["port"], "proto" => attributes["proto"], "hops" => [] }
|
92
95
|
when "hop"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..','..','..','..','..', 'lib'))
|
4
|
+
|
5
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/api_constants'
|
6
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager'
|
7
|
+
require 'rex/text'
|
8
|
+
require 'test/unit'
|
9
|
+
|
10
|
+
module Rex
|
11
|
+
module Post
|
12
|
+
module Meterpreter
|
13
|
+
module Extensions
|
14
|
+
module Stdapi
|
15
|
+
module Railgun
|
16
|
+
class ApiConstants::UnitTest < Test::Unit::TestCase
|
17
|
+
def test_add_constants
|
18
|
+
const_manager = WinConstManager.new
|
19
|
+
|
20
|
+
ApiConstants.add_constants(const_manager)
|
21
|
+
|
22
|
+
assert_equal(0, const_manager.parse('SUCCESS'),
|
23
|
+
"ApiConstants.add_constants should have added WinAPI constants to given constant manager")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright (c) 2010, patrickHVE@googlemail.com
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
# * Redistributions of source code must retain the above copyright
|
7
|
+
# notice, this list of conditions and the following disclaimer.
|
8
|
+
# * Redistributions in binary form must reproduce the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer in the
|
10
|
+
# documentation and/or other materials provided with the distribution.
|
11
|
+
# * The names of the author may not be used to endorse or promote products
|
12
|
+
# derived from this software without specific prior written permission.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
# DISCLAIMED. IN NO EVENT SHALL patrickHVE@googlemail.com BE LIABLE FOR ANY
|
18
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
19
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
20
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
21
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
22
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
|
25
|
+
module Rex
|
26
|
+
module Post
|
27
|
+
module Meterpreter
|
28
|
+
module Extensions
|
29
|
+
module Stdapi
|
30
|
+
module Railgun
|
31
|
+
|
32
|
+
#
|
33
|
+
#
|
34
|
+
#
|
35
|
+
class BufferItem
|
36
|
+
|
37
|
+
attr_reader :belongs_to_param_n, :addr, :length_in_bytes, :datatype
|
38
|
+
|
39
|
+
def initialize(belongs_to_param_n, addr, length_in_bytes, datatype)
|
40
|
+
@belongs_to_param_n = belongs_to_param_n
|
41
|
+
@addr = addr
|
42
|
+
@length_in_bytes = length_in_bytes
|
43
|
+
@datatype = datatype
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end; end; end; end; end; end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..','..','..','..','..', 'lib'))
|
4
|
+
|
5
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/buffer_item'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
module Rex
|
9
|
+
module Post
|
10
|
+
module Meterpreter
|
11
|
+
module Extensions
|
12
|
+
module Stdapi
|
13
|
+
module Railgun
|
14
|
+
class BufferItem::UnitTest < Test::Unit::TestCase
|
15
|
+
|
16
|
+
def test_initialization
|
17
|
+
target_belongs_to_param_n = 1
|
18
|
+
target_addr = 232323
|
19
|
+
target_length_in_bytes = 4
|
20
|
+
target_datatype = "DWORD"
|
21
|
+
|
22
|
+
item = BufferItem.new(target_belongs_to_param_n, target_addr,
|
23
|
+
target_length_in_bytes, target_datatype)
|
24
|
+
|
25
|
+
assert_equal(target_belongs_to_param_n, item.belongs_to_param_n)
|
26
|
+
assert_equal(target_addr, item.addr)
|
27
|
+
assert_equal(target_length_in_bytes, item.length_in_bytes)
|
28
|
+
assert_equal(target_datatype, item.datatype)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -22,8 +22,9 @@
|
|
22
22
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
23
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
24
|
|
25
|
-
require '
|
26
|
-
require '
|
25
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_helper'
|
26
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_function'
|
27
|
+
require 'rex/post/meterpreter/extensions/stdapi/railgun/buffer_item'
|
27
28
|
|
28
29
|
module Rex
|
29
30
|
module Post
|
@@ -32,229 +33,6 @@ module Extensions
|
|
32
33
|
module Stdapi
|
33
34
|
module Railgun
|
34
35
|
|
35
|
-
#
|
36
|
-
# Manages our library of windows constants
|
37
|
-
#
|
38
|
-
class WinConstManager
|
39
|
-
|
40
|
-
def initialize()
|
41
|
-
@consts = {}
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_const(name, value)
|
45
|
-
@consts[name] = value
|
46
|
-
end
|
47
|
-
|
48
|
-
# parses a string constaining constants and returns an integer
|
49
|
-
# the string can be either "CONST" or "CONST1 | CONST2"
|
50
|
-
#
|
51
|
-
# this function will NOT throw an exception but return "nil" if it can't parse a string
|
52
|
-
def parse(s)
|
53
|
-
if s.class != String
|
54
|
-
return nil # it's not even a string'
|
55
|
-
end
|
56
|
-
return_value = 0
|
57
|
-
for one_const in s.split('|')
|
58
|
-
one_const = one_const.strip()
|
59
|
-
if not @consts.has_key? one_const
|
60
|
-
return nil # at least one "Constant" is unknown to us
|
61
|
-
end
|
62
|
-
return_value |= @consts[one_const]
|
63
|
-
end
|
64
|
-
return return_value
|
65
|
-
end
|
66
|
-
|
67
|
-
def is_parseable(s)
|
68
|
-
return parse(s) != nil
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# represents one function, e.g. MessageBoxW
|
74
|
-
#
|
75
|
-
class DLLFunction
|
76
|
-
attr_reader :return_type, :params, :windows_name
|
77
|
-
|
78
|
-
def initialize(return_type, params, windows_name)
|
79
|
-
check_return_type(return_type) # we do error checking as early as possible so the library is easier to use
|
80
|
-
check_params(params)
|
81
|
-
@return_type = return_type
|
82
|
-
@params = params
|
83
|
-
@windows_name = windows_name
|
84
|
-
end
|
85
|
-
|
86
|
-
@@directions = ["in", "out", "inout", "return"]
|
87
|
-
|
88
|
-
@@allowed_datatypes = {
|
89
|
-
"VOID" => ["return"],
|
90
|
-
"BOOL" => ["in", "return"],
|
91
|
-
"DWORD" => ["in", "return"],
|
92
|
-
"WORD" => ["in", "return"],
|
93
|
-
"BYTE" => ["in", "return"],
|
94
|
-
"LPVOID" => ["in", "return"], # sf: for specifying a memory address (e.g. VirtualAlloc/HeapAlloc/...) where we dont want ot back it up with actuall mem ala PBLOB
|
95
|
-
"HANDLE" => ["in", "return"],
|
96
|
-
"PDWORD" => ["in", "out", "inout"], # todo: support for functions that return pointers to strings
|
97
|
-
"PWCHAR" => ["in", "out", "inout"],
|
98
|
-
"PCHAR" => ["in", "out", "inout"],
|
99
|
-
"PBLOB" => ["in", "out", "inout"],
|
100
|
-
}
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def check_type_exists (type)
|
105
|
-
if not @@allowed_datatypes.has_key?(type)
|
106
|
-
raise "Type unknown: #{type}. Allowed types: #{PP.pp(@@allowed_datatypes.keys, "")}"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def check_return_type (type)
|
111
|
-
check_type_exists(type)
|
112
|
-
if not @@allowed_datatypes[type].include?("return")
|
113
|
-
raise "#{type} is not allowed as a return type"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def check_params (params)
|
118
|
-
params.each do |param|
|
119
|
-
throw "each param must be descriped by a three-tuple [type,name,direction]" unless param.length == 3
|
120
|
-
type = param[0]
|
121
|
-
direction = param[2]
|
122
|
-
check_type_exists(type)
|
123
|
-
throw "invalid direction: #{direction}" unless @@directions.include?(direction)
|
124
|
-
throw "direction 'return' is only for the return value of the function." unless direction != "return"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
class BufferItem
|
134
|
-
|
135
|
-
attr_reader :belongs_to_param_n, :addr, :length_in_bytes, :datatype
|
136
|
-
|
137
|
-
def initialize(belongs_to_param_n, addr, length_in_bytes, datatype)
|
138
|
-
@belongs_to_param_n = belongs_to_param_n
|
139
|
-
@addr = addr
|
140
|
-
@length_in_bytes = length_in_bytes
|
141
|
-
@datatype = datatype
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
#
|
146
|
-
# shared functions
|
147
|
-
#
|
148
|
-
module DLLHelper
|
149
|
-
|
150
|
-
# converts ruby string to zero-terminated ASCII string
|
151
|
-
def str_to_ascii_z(str)
|
152
|
-
return str+"\x00"
|
153
|
-
end
|
154
|
-
|
155
|
-
# converts 0-terminated ASCII string to ruby string
|
156
|
-
def asciiz_to_str(asciiz)
|
157
|
-
zero_byte_idx = asciiz.index("\x00")
|
158
|
-
if zero_byte_idx != nil
|
159
|
-
return asciiz[0, zero_byte_idx]
|
160
|
-
else
|
161
|
-
return asciiz
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# converts ruby string to zero-terminated WCHAR string
|
166
|
-
def str_to_uni_z(str)
|
167
|
-
enc = str.unpack("C*").pack("v*")
|
168
|
-
enc += "\x00\x00"
|
169
|
-
return enc
|
170
|
-
end
|
171
|
-
|
172
|
-
# converts 0-terminated UTF16 to ruby string
|
173
|
-
def uniz_to_str(uniz)
|
174
|
-
uniz.unpack("v*").pack("C*").unpack("A*")[0]
|
175
|
-
end
|
176
|
-
|
177
|
-
# parses a number param and returns the value
|
178
|
-
# raises an exception if the param cannot be converted to a number
|
179
|
-
# examples:
|
180
|
-
# nil => 0
|
181
|
-
# 3 => 3
|
182
|
-
# "MB_OK" => 0
|
183
|
-
# "SOME_CONSTANT | OTHER_CONSTANT" => 17
|
184
|
-
# "tuna" => !!!!!!!!!!Exception
|
185
|
-
def param_to_number(v)
|
186
|
-
if v.class == NilClass then
|
187
|
-
return 0
|
188
|
-
elsif v.class == Fixnum then
|
189
|
-
return v # ok, it's already a number
|
190
|
-
elsif v.class == Bignum then
|
191
|
-
return v # ok, it's already a number
|
192
|
-
elsif v.class == String then
|
193
|
-
dw = @win_consts.parse(v) # might raise an exception
|
194
|
-
if dw != nil
|
195
|
-
return dw
|
196
|
-
else
|
197
|
-
raise "Param #{v} (class #{v.class}) cannot be converted to a number. It's a string but matches no constants I know."
|
198
|
-
end
|
199
|
-
else
|
200
|
-
raise "Param #{v} (class #{v.class}) should be a number but isn't"
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# assembles the buffers "in" and "inout"
|
205
|
-
def assemble_buffer(direction, function, args)
|
206
|
-
layout = {} # paramName => BufferItem
|
207
|
-
blob = ""
|
208
|
-
#puts " building buffer: #{direction}"
|
209
|
-
function.params.each_with_index do |param_desc, param_idx|
|
210
|
-
#puts " processing #{param_desc[0]} #{param_desc[1]} #{param_desc[2]}"
|
211
|
-
# we care only about inout buffers
|
212
|
-
if param_desc[2] == direction
|
213
|
-
buffer = nil
|
214
|
-
# Special case:
|
215
|
-
# The user can choose to supply a Null pointer instead of a buffer
|
216
|
-
# in this case we don't need space in any heap buffer
|
217
|
-
if param_desc[0][0,1] == 'P' # type is a pointer
|
218
|
-
if args[param_idx] == nil
|
219
|
-
next
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
case param_desc[0] # required argument type
|
224
|
-
when "PDWORD"
|
225
|
-
dw = param_to_number(args[param_idx])
|
226
|
-
buffer = [dw].pack('V')
|
227
|
-
when "PWCHAR"
|
228
|
-
raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
|
229
|
-
buffer = str_to_uni_z(args[param_idx])
|
230
|
-
when "PCHAR"
|
231
|
-
raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
|
232
|
-
buffer = str_to_ascii_z(args[param_idx])
|
233
|
-
when "PBLOB"
|
234
|
-
raise "param #{param_desc[1]}: please supply your BLOB as string!" unless args[param_idx].class == String
|
235
|
-
buffer = args[param_idx]
|
236
|
-
# other types (non-pointers) don't reference buffers
|
237
|
-
# and don't need any treatment here
|
238
|
-
end
|
239
|
-
|
240
|
-
if buffer != nil
|
241
|
-
#puts " adding #{buffer.length} bytes to heap blob"
|
242
|
-
layout[param_desc[1]] = BufferItem.new(param_idx, blob.length, buffer.length, param_desc[0])
|
243
|
-
blob += buffer
|
244
|
-
# sf: force 8 byte alignment to satisfy x64, wont matter on x86.
|
245
|
-
while( blob.length % 8 != 0 )
|
246
|
-
blob += "\x00"
|
247
|
-
end
|
248
|
-
#puts " heap blob size now #{blob.length}"
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
#puts " built buffer: #{direction}"
|
253
|
-
return [layout, blob]
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
36
|
#
|
259
37
|
# represents a DLL, e.g. kernel32.dll
|
260
38
|
#
|
@@ -537,4 +315,4 @@ class DLL
|
|
537
315
|
end
|
538
316
|
end
|
539
317
|
|
540
|
-
end; end; end; end; end; end
|
318
|
+
end; end; end; end; end; end;
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Copyright (c) 2010, patrickHVE@googlemail.com
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
# * Redistributions of source code must retain the above copyright
|
7
|
+
# notice, this list of conditions and the following disclaimer.
|
8
|
+
# * Redistributions in binary form must reproduce the above copyright
|
9
|
+
# notice, this list of conditions and the following disclaimer in the
|
10
|
+
# documentation and/or other materials provided with the distribution.
|
11
|
+
# * The names of the author may not be used to endorse or promote products
|
12
|
+
# derived from this software without specific prior written permission.
|
13
|
+
#
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
# DISCLAIMED. IN NO EVENT SHALL patrickHVE@googlemail.com BE LIABLE FOR ANY
|
18
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
19
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
20
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
21
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
22
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
|
25
|
+
module Rex
|
26
|
+
module Post
|
27
|
+
module Meterpreter
|
28
|
+
module Extensions
|
29
|
+
module Stdapi
|
30
|
+
module Railgun
|
31
|
+
|
32
|
+
#
|
33
|
+
# represents one function, e.g. MessageBoxW
|
34
|
+
#
|
35
|
+
class DLLFunction
|
36
|
+
@@allowed_datatypes = {
|
37
|
+
"VOID" => ["return"],
|
38
|
+
"BOOL" => ["in", "return"],
|
39
|
+
"DWORD" => ["in", "return"],
|
40
|
+
"WORD" => ["in", "return"],
|
41
|
+
"BYTE" => ["in", "return"],
|
42
|
+
"LPVOID" => ["in", "return"], # sf: for specifying a memory address (e.g. VirtualAlloc/HeapAlloc/...) where we dont want ot back it up with actuall mem ala PBLOB
|
43
|
+
"HANDLE" => ["in", "return"],
|
44
|
+
"PDWORD" => ["in", "out", "inout"], # todo: support for functions that return pointers to strings
|
45
|
+
"PWCHAR" => ["in", "out", "inout"],
|
46
|
+
"PCHAR" => ["in", "out", "inout"],
|
47
|
+
"PBLOB" => ["in", "out", "inout"],
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
@@directions = ["in", "out", "inout", "return"].freeze
|
51
|
+
|
52
|
+
attr_reader :return_type, :params, :windows_name
|
53
|
+
|
54
|
+
def initialize(return_type, params, windows_name)
|
55
|
+
check_return_type(return_type) # we do error checking as early as possible so the library is easier to use
|
56
|
+
check_params(params)
|
57
|
+
@return_type = return_type
|
58
|
+
@params = params
|
59
|
+
@windows_name = windows_name
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def check_type_exists (type)
|
65
|
+
if not @@allowed_datatypes.has_key?(type)
|
66
|
+
raise ArgumentError, "Type unknown: #{type}. Allowed types: #{PP.pp(@@allowed_datatypes.keys, "")}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_return_type (type)
|
71
|
+
check_type_exists(type)
|
72
|
+
if not @@allowed_datatypes[type].include?("return")
|
73
|
+
raise ArgumentError, "#{type} is not allowed as a return type"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def check_params (params)
|
78
|
+
params.each do |param|
|
79
|
+
raise ArgumentError, "each param must be descriped by a three-tuple [type,name,direction]" unless param.length == 3
|
80
|
+
type = param[0]
|
81
|
+
direction = param[2]
|
82
|
+
|
83
|
+
# Assert a valid type
|
84
|
+
check_type_exists(type)
|
85
|
+
|
86
|
+
# Only our set of predefined directions are valid
|
87
|
+
unless @@directions.include?(direction)
|
88
|
+
raise ArgumentError, "invalid direction: #{direction}"
|
89
|
+
end
|
90
|
+
|
91
|
+
# 'return' is not a valid direction in this context
|
92
|
+
unless direction != "return"
|
93
|
+
raise "direction 'return' is only for the return value of the function."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end; end; end; end; end; end
|