librex 0.0.51 → 0.0.52

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.
@@ -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: 13694
6
+ SVN Revision: 13798
7
7
 
8
8
  # Credits
9
9
  The Metasploit development team <http://www.metasploit.com>
@@ -1,8 +1,7 @@
1
1
  ##
2
- # $Id: jsobfu.rb 12843 2011-06-03 17:52:34Z egypt $
2
+ # $Id: jsobfu.rb 13761 2011-09-19 23:01:26Z jduck $
3
3
  ##
4
4
 
5
- $:.unshift("lib")
6
5
  require 'rex/text'
7
6
  require 'rkelly'
8
7
 
@@ -190,7 +190,7 @@ module Rex
190
190
  return unless @state[:fullurl].kind_of? URI
191
191
  return unless @state[:form_variables].kind_of? Array
192
192
  return if @state[:form_variables].empty?
193
- method = @state[:form_variables].first[1]
193
+ method = parse_method(@state[:form_variables].first[1])
194
194
  vars = @state[:form_variables].map {|x| x[0]}
195
195
  form_info = {}
196
196
  form_info[:web_site] = @state[:web_site]
@@ -276,6 +276,17 @@ module Rex
276
276
  parsed
277
277
  end
278
278
 
279
+ # Don't cause the web report to die just because we can't tell
280
+ # what method was used -- default to GET. Sometimes it's just "POST," and
281
+ # sometimes it's "URL encoded POST," and sometimes it might be something
282
+ # else.
283
+ def parse_method(meth)
284
+ verbs = "(GET|POST|PATH)"
285
+ real_method = meth.match(/^\s*#{verbs}/)
286
+ real_method ||= meth.match(/\s*#{verbs}\s*$/)
287
+ ( real_method && real_method[1] ) ? real_method[1] : "GET"
288
+ end
289
+
279
290
  def report_host(&block)
280
291
  return unless @report_data[:host]
281
292
  return unless in_tag("Scan")
@@ -134,9 +134,50 @@ module Analyze
134
134
  LoaderFlags
135
135
  NumberOfRvaAndSizes
136
136
  })
137
+
137
138
  $stdout.puts tbl.to_s
138
139
  $stdout.puts "\n\n"
139
140
 
141
+ # Get DllCharacteristics (in Integer)
142
+ dllcharacteristics = pe.hdr.opt.struct[23].value
143
+
144
+ if (dllcharacteristics > 0)
145
+ tbl = table("DllCharacteristics", ['Flag', 'Value'])
146
+
147
+ # http://msdn.microsoft.com/en-us/library/ms680339(v=vs.85).aspx
148
+ traits = {
149
+ :ASLR => 'False', #IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
150
+ :Integrity => 'False', #IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
151
+ :NX => 'False', #IMAGE_DLLCHARACTERISTICS_NX_COMPAT
152
+ :Isolation => 'False', #IMAGE_DLLCHARACTERISTICS_NO_ISOLATION
153
+ :SEH => 'False', #IMAGE_DLLCHARACTERISTICS_NO_SEH
154
+ :Bind => 'False', #IMAGE_DLLCHARACTERISTICS_NO_BIND
155
+ :WDM => 'False', #IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
156
+ :Terminal => 'False' #IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
157
+ }
158
+
159
+ # Convert integer to an bit array
160
+ c_bits = ("%32d" %dllcharacteristics.to_s(2)).split('').map { |e| e.to_i }.reverse
161
+
162
+ # Check characteristics
163
+ traits[:ASLR] = 'True' if c_bits[6] == 1 #0x0040
164
+ traits[:Integrity] = 'True' if c_bits[7] == 1 #0x0080
165
+ traits[:NX] = 'True' if c_bits[8] == 1 #0x0100
166
+ traits[:Isolation] = 'True' if c_bits[9] == 1 #0x0200
167
+ traits[:SEH] = 'True' if c_bits[10] == 1 #0x0400
168
+ traits[:Bind] = 'True' if c_bits[11] == 1 #0x0800
169
+ traits[:WDM] = 'True' if c_bits[13] == 1 #2000
170
+ traits[:Terminal] = 'True' if c_bits[15] == 1 #0x8000
171
+
172
+ # Putting results to table
173
+ traits.each do |trait_name, trait_value|
174
+ tbl << [trait_name, trait_value]
175
+ end
176
+
177
+ $stdout.puts tbl.to_s
178
+ $stdout.puts "\n\n"
179
+ end
180
+
140
181
  if (pe.exports)
141
182
  tbl = table("Exported Functions", ['Ordinal', 'Name', 'Address'])
142
183
  pe.exports.entries.each do |ent|
@@ -146,13 +187,28 @@ module Analyze
146
187
  $stdout.puts "\n\n"
147
188
  end
148
189
 
190
+ # Rex::PeParsey::Pe doesn't seem to give us any offset information for each function,
191
+ # which makes it difficult to calculate the actual addresses for them. So instead we
192
+ # are using Metasm::COFF::ImportDirectory to do this task. The ability to see
193
+ # addresses is mainly for ROP.
149
194
  if (pe.imports)
150
- tbl = table("Imported Functions", ['Library', 'Ordinal', 'Name'])
151
- pe.imports.each do |lib|
152
- lib.entries.each do |ent|
153
- tbl << [lib.name, ent.ordinal, ent.name]
195
+ tbl = table("Imported Functions", ['Library', 'Address', 'Ordinal', 'Name'])
196
+ exefmt = Metasm::AutoExe.orshellcode{ Metasm.const_get('x86_64').new }
197
+ exe = exefmt.decode_file(pe._isource.file.path)
198
+ ibase = pe.image_base
199
+ exe_imports = exe.imports
200
+ exe_imports.each do |lib|
201
+ lib_name = lib.libname
202
+ ini_offset = lib.iat_p
203
+ func_table = lib.imports
204
+ offset = 0
205
+ func_table.each do |func|
206
+ func_addr = "0x%08x" %(ibase + ini_offset + offset)
207
+ tbl << [lib_name, func_addr, func.hint, func.name]
208
+ offset += 4
154
209
  end
155
210
  end
211
+
156
212
  $stdout.puts tbl.to_s
157
213
  $stdout.puts "\n\n"
158
214
  end
@@ -73,7 +73,7 @@ class Console::CommandDispatcher::Priv::Timestomp
73
73
  when "-e"
74
74
  emodified = str_to_time(val)
75
75
  when "-z"
76
- puts "#{val}"
76
+ print_line("#{val}")
77
77
  modified = str_to_time(val)
78
78
  accessed = str_to_time(val)
79
79
  creation = str_to_time(val)
@@ -129,4 +129,4 @@ end
129
129
  end
130
130
  end
131
131
  end
132
- end
132
+ end
@@ -91,7 +91,7 @@ class Console::CommandDispatcher::Sniffer
91
91
  stats = client.sniffer.capture_stats(intf)
92
92
  print_status("Capture statistics for interface #{intf}")
93
93
  stats.each_key do |k|
94
- puts "\t#{k}: #{stats[k]}"
94
+ print_line("\t#{k}: #{stats[k]}")
95
95
  end
96
96
 
97
97
  return true
@@ -1,4 +1,4 @@
1
- # $Id: server.rb 13639 2011-08-25 22:48:33Z scriptjunkie $
1
+ # $Id: server.rb 13779 2011-09-23 15:12:19Z scriptjunkie $
2
2
 
3
3
  require 'rex/socket'
4
4
  require 'rex/proto/dhcp'
@@ -275,7 +275,6 @@ protected
275
275
  return
276
276
  end
277
277
  elsif messageType == DHCPRequest #DHCP Request - send DHCP ACK
278
- self.served[buf[28..43]][1] = true # mark as requested
279
278
  pkt << [DHCPAck].pack('C')
280
279
  # now we ignore their discovers (but we'll respond to requests in case a packet was lost)
281
280
  if ( self.served_over != 0 )
@@ -322,6 +321,9 @@ protected
322
321
 
323
322
  pkt << ("\x00" * 32) #padding
324
323
 
324
+ # And now we mark as requested
325
+ self.served[buf[28..43]][1] = true if messageType == DHCPRequest
326
+
325
327
  send_packet(nil, pkt)
326
328
  end
327
329
 
@@ -15,7 +15,7 @@ class RopBase
15
15
 
16
16
  def to_csv(gadgets = [])
17
17
  if gadgets.empty? and @gadgets.nil? or @gadgets.empty?
18
- print_error("No gadgets collected to convert to CSV format.")
18
+ @stdio.print_error("No gadgets collected to convert to CSV format.")
19
19
  return
20
20
  end
21
21
 
@@ -45,14 +45,25 @@ class RopBase
45
45
  begin
46
46
  data = File.new(file, 'r').read
47
47
  rescue
48
- print_error("Error reading #{file}")
48
+ @stdio.print_error("Error reading #{file}")
49
+ return []
50
+ end
51
+
52
+ if data.empty? or data.nil?
53
+ return []
49
54
  end
50
55
 
51
56
  data.gsub!(/\"/, '')
52
57
  data.gsub!("Address,Raw,Disassembly\n", '')
58
+
53
59
  @gadgets = []
60
+
54
61
  data.each_line do |line|
55
62
  addr, raw, disasm = line.split(',', 3)
63
+ if addr.nil? or raw.nil? or disasm.nil?
64
+ @stdio.print_error("Import file format corrupted")
65
+ return []
66
+ end
56
67
  disasm.gsub!(/: /, ":\t")
57
68
  disasm.gsub!(' | ', "\n")
58
69
  raw = [raw].pack('H*')
@@ -77,6 +88,7 @@ end
77
88
 
78
89
  class RopCollect < RopBase
79
90
  def initialize(file="")
91
+ @stdio = Rex::Ui::Text::Output::Stdio.new
80
92
  @file = file if not file.empty?
81
93
  @bin = Metasm::AutoExe.decode_file(file) if not file.empty?
82
94
  @disassembler = @bin.disassembler if not @bin.nil?
@@ -254,4 +266,4 @@ class RopCollect < RopBase
254
266
  end
255
267
  end
256
268
  end
257
- end
269
+ end
@@ -152,27 +152,26 @@ module Socket
152
152
  #
153
153
  def self.getaddress(addr, accept_ipv6 = true)
154
154
  begin
155
-
156
155
  if dotted_ip?(addr)
157
156
  return addr
158
157
  end
159
-
158
+
160
159
  res = ::Socket.gethostbyname(addr)
161
160
  return nil if not res
162
-
161
+
163
162
  # Shift the first three elements out
164
163
  rname = res.shift
165
164
  ralias = res.shift
166
165
  rtype = res.shift
167
-
168
- # Reject IPv6 addresses if we don't accept them
166
+
167
+ # Reject IPv6 addresses if we don't accept them
169
168
  if not accept_ipv6
170
169
  res.reject!{|nbo| nbo.length != 4}
171
170
  end
172
-
171
+
173
172
  # Make sure we have at least one name
174
- return nil if res.length == 0
175
-
173
+ return nil if res.length == 0
174
+
176
175
  # Return the first address of the result
177
176
  self.addr_ntoa( res[0] )
178
177
  rescue ::ArgumentError # Win32 bug
@@ -236,10 +235,10 @@ module Socket
236
235
  addr_ntoi(resolv_nbo(host))
237
236
  end
238
237
 
239
- #
238
+ #
240
239
  # Converts an ASCII IP address to a CIDR mask. Returns
241
240
  # nil if it's not convertable.
242
- #
241
+ #
243
242
  def self.addr_atoc(mask)
244
243
  mask_i = resolv_nbo_i(mask)
245
244
  cidr = nil
@@ -476,7 +475,7 @@ module Socket
476
475
  ##
477
476
 
478
477
  #
479
- # This method does NOT send any traffic to the destination, instead, it uses a
478
+ # This method does NOT send any traffic to the destination, instead, it uses a
480
479
  # "bound" UDP socket to determine what source address we would use to
481
480
  # communicate with the specified destination. The destination defaults to
482
481
  # Google's DNS server to make the standard behavior determine which IP
@@ -491,14 +490,14 @@ module Socket
491
490
  )
492
491
  r = s.getsockname[1]
493
492
  s.close
494
-
493
+
495
494
  # Trim off the trailing interface ID for link-local IPv6
496
495
  return r.split('%').first
497
496
  rescue ::Exception
498
497
  return '127.0.0.1'
499
498
  end
500
499
  end
501
-
500
+
502
501
  #
503
502
  # Identifies the link-local address of a given interface (if IPv6 is enabled)
504
503
  #
@@ -507,10 +506,10 @@ module Socket
507
506
  return if not (r and r =~ /^fe80/i)
508
507
  r
509
508
  end
510
-
509
+
511
510
  #
512
511
  # Identifies the mac address of a given interface (if IPv6 is enabled)
513
- #
512
+ #
514
513
  def self.ipv6_mac(intf)
515
514
  r = ipv6_link_address(intf)
516
515
  return if not r
@@ -862,7 +862,7 @@ module Text
862
862
  0.upto(len-1) do |i|
863
863
  setnum = i % sets.size
864
864
 
865
- puts counter.inspect
865
+ #puts counter.inspect
866
866
  end
867
867
 
868
868
  return buf
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: librex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.51
4
+ version: 0.0.52
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,10 +10,10 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-09-05 00:00:00.000000000Z
13
+ date: 2011-09-27 00:00:00.000000000Z
14
14
  dependencies: []
15
15
  description: Rex provides a variety of classes useful for security testing and exploit
16
- development. Based on SVN Revision 13694
16
+ development. Based on SVN Revision 13798
17
17
  email:
18
18
  - hdm@metasploit.com
19
19
  - jacob.hammack@hammackj.com