Utility for working with pointers. Test coverage is incomplete
This commit is contained in:
parent
b9b5b1e66f
commit
3d7d5d5f3d
|
@ -0,0 +1,108 @@
|
|||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Type
|
||||
module PointerUtil
|
||||
|
||||
X86_64 = :x86_64
|
||||
X86_32 = :x86_32
|
||||
|
||||
ARCH_POINTER_SIZE = {
|
||||
X86_64 => 8,
|
||||
X86_32 => 4
|
||||
}.freeze
|
||||
|
||||
# Returns the pointer size for this architecture. Should accept client or platform or arch
|
||||
def self.pointer_size(platform)
|
||||
ARCH_POINTER_SIZE[platform]
|
||||
end
|
||||
|
||||
def self.pack_pointer(pointer, platform)
|
||||
|
||||
# TODO: Ensure the correct size
|
||||
unless pointer.kind_of?(Fixnum)
|
||||
return nil
|
||||
end
|
||||
|
||||
case platform
|
||||
when X86_64
|
||||
# XXX: Only works if attacker and victim are like-endianed
|
||||
[pointer].pack('Q')
|
||||
when X86_32
|
||||
[pointer].pack('V')
|
||||
else
|
||||
raise "platform symbol #{platform.to_s} not supported"
|
||||
end
|
||||
end
|
||||
|
||||
# Given a packed pointer, unpack it according to architecture
|
||||
def self.unpack_pointer(packed_pointer, platform)
|
||||
case platform
|
||||
when X86_64
|
||||
# XXX: Only works if attacker and victim are like-endianed
|
||||
packed_pointer.unpack('Q').first
|
||||
when X86_32
|
||||
packed_pointer.unpack('V').first
|
||||
else
|
||||
raise "platform symbol #{platform.to_s} not supported"
|
||||
end
|
||||
end
|
||||
|
||||
def self.null_pointer(pointer, platform)
|
||||
pack_pointer(0, platform)
|
||||
end
|
||||
|
||||
###
|
||||
# Summary: Returns true if pointer will be considered a 'null' pointer
|
||||
#
|
||||
# If given nil, returns true
|
||||
# If given 0, returns true
|
||||
# If given a string, if 0 after unpacking, returns true
|
||||
# false otherwise
|
||||
##
|
||||
def self.is_null_pointer?(pointer, platform)
|
||||
if pointer.kind_of?(String)
|
||||
pointer = unpack_pointer(pointer, platform)
|
||||
end
|
||||
|
||||
return pointer.nil? || pointer == 0
|
||||
end
|
||||
|
||||
def self.is_unpacked_pointer?(pointer, platform)
|
||||
# TODO also check that the integer size is appropriate for the platform
|
||||
unless pointer.kind_of?(Fixnum) and pointer > 0 # and pointer <
|
||||
return false
|
||||
end
|
||||
|
||||
packed_pointer = pack_pointer(pointer, platform)
|
||||
if !packed_pointer.nil? and packed_pointer.length == pointer_size(platform)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns true if the data type is a pointer, false otherwise
|
||||
def self.is_pointer_type?(type)
|
||||
if type == :pointer
|
||||
return true
|
||||
end
|
||||
|
||||
if type.kind_of?(String) && type =~ /^P/
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
end # PointerUtil
|
||||
end # Type
|
||||
end # Railgun
|
||||
end # Stdapi
|
||||
end # Extensions
|
||||
end # Meterpreter
|
||||
end # Post
|
||||
end # Rex
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..','..','..','..','..', '..', '..', 'lib'))
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/mock_magic'
|
||||
require 'test/unit'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Type
|
||||
class PointerUtil::UnitTest < Test::Unit::TestCase
|
||||
|
||||
include Rex::Post::Meterpreter::Extensions::Stdapi::Railgun::MockMagic
|
||||
|
||||
# memread value of win x86 pointer mapped to target unpack value
|
||||
X86_32_POINTERS = {
|
||||
"8D\x15\x00" => 1393720,
|
||||
"\x1C\x84\x15\x00" => 1410076,
|
||||
"\x0E\x84\x15\x00" => 1410062,
|
||||
"\x02\x84\x15\x00" => 1410050,
|
||||
"\xE6\x83\x15\x00" => 1410022,
|
||||
"\xC4\x83\x15\x00" => 1409988,
|
||||
"\x00\x00\x00\x00" => 0,
|
||||
}
|
||||
X86_64_POINTERS = {
|
||||
"\x10^ \x00\x00\x00\x00\x00" => 2121232,
|
||||
"\xCA\x9D \x00\x00\x00\x00\x00" => 2137546,
|
||||
"\xC8\x9D \x00\x00\x00\x00\x00" => 2137544,
|
||||
"Z\x9D \x00\x00\x00\x00\x00" => 2137434,
|
||||
"X\x9D \x00\x00\x00\x00\x00" => 2137432,
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00" => 0,
|
||||
}
|
||||
|
||||
X86_64_NULL_POINTER = "\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
X86_32_NULL_POINTER = "\x00\x00\x00\x00"
|
||||
|
||||
X86_64 = :x86_64
|
||||
X86_32 = :x86_32
|
||||
|
||||
def test_unpack_pointer
|
||||
X86_64_POINTERS.each_pair do |packed, unpacked|
|
||||
assert_equal(unpacked, PointerUtil.unpack_pointer(packed, X86_64),
|
||||
"unpack_pointer should unpack 64-bit pointers")
|
||||
end
|
||||
|
||||
X86_32_POINTERS.each_pair do |packed, unpacked|
|
||||
assert_equal(unpacked, PointerUtil.unpack_pointer(packed, X86_32),
|
||||
"unpack_pointer should unpack 32-bit pointers")
|
||||
end
|
||||
end
|
||||
|
||||
def test_is_null_pointer
|
||||
[X86_32, X86_64].each do |platform|
|
||||
assert(PointerUtil.is_null_pointer?(nil, platform), 'nil should be a null pointer')
|
||||
assert(PointerUtil.is_null_pointer?(0, platform), 'numeric 0 should be a null pointer')
|
||||
end
|
||||
|
||||
assert_equal(true, PointerUtil.is_null_pointer?(X86_32_NULL_POINTER, X86_32),
|
||||
'is_null_pointer? should return true for packed 32-bit null pointers')
|
||||
|
||||
assert_equal(true, PointerUtil.is_null_pointer?(X86_64_NULL_POINTER, X86_64),
|
||||
'is_null_pointer? should return true for packed 64-bit null pointers')
|
||||
|
||||
end
|
||||
|
||||
def test_pointer_size
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue