mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-10-29 18:07:27 +01:00
Use rex-arch gem
MS-1703
This commit is contained in:
parent
8bd6db8bd7
commit
01f08da345
@ -31,6 +31,7 @@ PATH
|
||||
rb-readline-r7
|
||||
recog
|
||||
redcarpet
|
||||
rex-arch
|
||||
rex-java
|
||||
rex-powershell
|
||||
rex-random_identifier
|
||||
@ -220,8 +221,10 @@ GEM
|
||||
recog (2.0.21)
|
||||
nokogiri
|
||||
redcarpet (3.3.4)
|
||||
rex-arch (0.1.0)
|
||||
rex-text
|
||||
rex-java (0.1.2)
|
||||
rex-powershell (0.1.0)
|
||||
rex-powershell (0.1.1)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.0)
|
||||
|
109
lib/rex/arch.rb
109
lib/rex/arch.rb
@ -1,109 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'rex/constants'
|
||||
|
||||
module Rex
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides generalized methods for performing operations that are
|
||||
# architecture specific. Furthermore, the modules contained within this
|
||||
# module provide features that are specific to a given architecture.
|
||||
#
|
||||
###
|
||||
module Arch
|
||||
|
||||
#
|
||||
# Architecture classes
|
||||
#
|
||||
require 'rex/arch/x86'
|
||||
require 'rex/arch/sparc'
|
||||
require 'rex/arch/zarch'
|
||||
|
||||
#
|
||||
# This routine adjusts the stack pointer for a given architecture.
|
||||
#
|
||||
def self.adjust_stack_pointer(arch, adjustment)
|
||||
|
||||
if ( arch.is_a?(::Array))
|
||||
arch = arch[0]
|
||||
end
|
||||
|
||||
case arch
|
||||
when /x86/
|
||||
Rex::Arch::X86.adjust_reg(Rex::Arch::X86::ESP, adjustment)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This route provides address packing for the specified arch
|
||||
#
|
||||
def self.pack_addr(arch, addr)
|
||||
|
||||
if ( arch.is_a?(::Array))
|
||||
arch = arch[0]
|
||||
end
|
||||
|
||||
case arch
|
||||
when ARCH_X86
|
||||
[addr].pack('V')
|
||||
when ARCH_X86_64, ARCH_X64
|
||||
[addr].pack('Q<')
|
||||
when ARCH_MIPS # ambiguous
|
||||
[addr].pack('N')
|
||||
when ARCH_MIPSBE
|
||||
[addr].pack('N')
|
||||
when ARCH_MIPSLE
|
||||
[addr].pack('V')
|
||||
when ARCH_PPC # ambiguous
|
||||
[addr].pack('N')
|
||||
when ARCH_SPARC
|
||||
[addr].pack('N')
|
||||
when ARCH_ARMLE
|
||||
[addr].pack('V')
|
||||
when ARCH_ARMBE
|
||||
[addr].pack('N')
|
||||
when ARCH_ZARCH
|
||||
[addr].pack('Q>')
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This routine reports the endianess of a given architecture
|
||||
#
|
||||
def self.endian(arch)
|
||||
|
||||
if ( arch.is_a?(::Array))
|
||||
arch = arch[0]
|
||||
end
|
||||
|
||||
case arch
|
||||
when ARCH_X86
|
||||
return ENDIAN_LITTLE
|
||||
when ARCH_X86_64
|
||||
return ENDIAN_LITTLE
|
||||
when ARCH_MIPS # ambiguous
|
||||
return ENDIAN_BIG
|
||||
when ARCH_MIPSLE
|
||||
return ENDIAN_LITTLE
|
||||
when ARCH_MIPSBE
|
||||
return ENDIAN_BIG
|
||||
when ARCH_PPC # ambiguous
|
||||
return ENDIAN_BIG
|
||||
when ARCH_SPARC
|
||||
return ENDIAN_BIG
|
||||
when ARCH_ARMLE
|
||||
return ENDIAN_LITTLE
|
||||
when ARCH_ARMBE
|
||||
return ENDIAN_BIG
|
||||
when ARCH_ZARCH
|
||||
return ENDIAN_BIG
|
||||
end
|
||||
|
||||
return ENDIAN_LITTLE
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,75 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Arch
|
||||
|
||||
#
|
||||
# Everything here is mostly stolen from vlad's perl sparc stuff
|
||||
#
|
||||
module Sparc
|
||||
|
||||
#
|
||||
# Register number constants
|
||||
#
|
||||
RegisterNumber =
|
||||
{
|
||||
'g0' => 0, 'g1' => 1, 'g2' => 2, 'g3' => 3,
|
||||
'g4' => 4, 'g5' => 5, 'g6' => 6, 'g7' => 7,
|
||||
'o0' => 8, 'o1' => 9, 'o2' => 10, 'o3' => 11,
|
||||
'o4' => 12, 'o5' => 13, 'o6' => 14, 'o7' => 15,
|
||||
'l0' => 16, 'l1' => 17, 'l2' => 18, 'l3' => 19,
|
||||
'l4' => 20, 'l5' => 21, 'l6' => 22, 'l7' => 23,
|
||||
'i0' => 24, 'i1' => 25, 'i2' => 26, 'i3' => 27,
|
||||
'i4' => 28, 'i5' => 29, 'i6' => 30, 'i7' => 31,
|
||||
'sp' => 14, 'fp' => 30,
|
||||
} # :nodoc:
|
||||
|
||||
#
|
||||
# Encodes a SETHI instruction with the value 'constant' being put into 'dst' register
|
||||
#
|
||||
def self.sethi(constant, dst)
|
||||
[
|
||||
(RegisterNumber[dst] << 25) |
|
||||
(4 << 22) |
|
||||
(constant >> 10)
|
||||
].pack('N')
|
||||
end
|
||||
|
||||
#
|
||||
# Encodes an OR instruction with the value 'constant' being OR'ed with the 'src' register into the 'dst' register
|
||||
#
|
||||
def self.ori(src, constant, dst)
|
||||
[
|
||||
(2 << 30) |
|
||||
(RegisterNumber[dst] << 25) |
|
||||
(2 << 19) |
|
||||
(RegisterNumber[src] << 14) |
|
||||
(1 << 13) |
|
||||
(constant & 0x1fff)
|
||||
].pack('N')
|
||||
end
|
||||
|
||||
#
|
||||
# Puts 'constant' into the 'dst' register using as few instructions as possible by checking the size of the value.
|
||||
# XXX: signedness support
|
||||
#
|
||||
def self.set(constant, dst)
|
||||
if (constant <= 4095 and constant >= 0)
|
||||
ori('g0', constant, dst)
|
||||
elsif (constant & 0x3ff != 0)
|
||||
set_dword(constant, dst)
|
||||
else
|
||||
sethi(constant, dst)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Puts 'constant' into the 'dst' register using both sethi and ori (necessary to use both uncessarily in some cases with encoders)
|
||||
#
|
||||
def self.set_dword(constant, dst)
|
||||
sethi(constant, dst) + ori(dst, constant & 0x3ff, dst)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end
|
@ -1,556 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Arch
|
||||
|
||||
#
|
||||
# everything here is mostly stole from vlad's perl x86 stuff
|
||||
#
|
||||
|
||||
module X86
|
||||
|
||||
#
|
||||
# Register number constants
|
||||
#
|
||||
EAX = AL = AX = ES = 0
|
||||
ECX = CL = CX = CS = 1
|
||||
EDX = DL = DX = SS = 2
|
||||
EBX = BL = BX = DS = 3
|
||||
ESP = AH = SP = FS = 4
|
||||
EBP = CH = BP = GS = 5
|
||||
ESI = DH = SI = 6
|
||||
EDI = BH = DI = 7
|
||||
|
||||
REG_NAMES32 = [ 'eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi' ]
|
||||
|
||||
REG_NAMES16 = [ 'ax', 'cx', 'dx', 'bx', 'sp', 'bp', 'si', 'di' ]
|
||||
|
||||
REG_NAMES8L = [ 'al', 'cl', 'dl', 'bl', nil, nil, nil, nil ]
|
||||
|
||||
# Jump tp a specific register
|
||||
def self.jmp_reg(str)
|
||||
reg = reg_number(str)
|
||||
_check_reg(reg)
|
||||
"\xFF" + [224 + reg].pack('C')
|
||||
end
|
||||
|
||||
#
|
||||
# Generate a LOOP instruction (Decrement ECX and jump short if ECX == 0)
|
||||
#
|
||||
def self.loop(offset)
|
||||
"\xE2" + pack_lsb(rel_number(offset, -2))
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the opcodes that compose a jump instruction to the
|
||||
# supplied relative offset.
|
||||
def self.jmp(addr)
|
||||
"\xe9" + pack_dword(rel_number(addr))
|
||||
end
|
||||
|
||||
#
|
||||
# This method adds/subs a packed long integer
|
||||
#
|
||||
def self.dword_adjust(dword, amount=0)
|
||||
pack_dword(dword.unpack('V')[0] + amount)
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the opcodes that compose a tag-based search routine
|
||||
#
|
||||
def self.searcher(tag)
|
||||
"\xbe" + dword_adjust(tag,-1)+ # mov esi, Tag - 1
|
||||
"\x46" + # inc esi
|
||||
"\x47" + # inc edi (end_search:)
|
||||
"\x39\x37" + # cmp [edi],esi
|
||||
"\x75\xfb" + # jnz 0xa (end_search)
|
||||
"\x46" + # inc esi
|
||||
"\x4f" + # dec edi (start_search:)
|
||||
"\x39\x77\xfc" + # cmp [edi-0x4],esi
|
||||
"\x75\xfa" + # jnz 0x10 (start_search)
|
||||
jmp_reg('edi') # jmp edi
|
||||
end
|
||||
|
||||
#
|
||||
# Generates a buffer that will copy memory immediately following the stub
|
||||
# that is generated to be copied to the stack
|
||||
#
|
||||
def self.copy_to_stack(len)
|
||||
# four byte align
|
||||
len = (len + 3) & ~0x3
|
||||
|
||||
stub =
|
||||
"\xeb\x0f"+ # jmp _end
|
||||
push_dword(len)+ # push n
|
||||
"\x59"+ # pop ecx
|
||||
"\x5e"+ # pop esi
|
||||
"\x29\xcc"+ # sub esp, ecx
|
||||
"\x89\xe7"+ # mov edi, esp
|
||||
"\xf3\xa4"+ # rep movsb
|
||||
"\xff\xe4"+ # jmp esp
|
||||
"\xe8\xec\xff\xff\xff" # call _start
|
||||
|
||||
stub
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the opcodes that compose a short jump instruction to
|
||||
# the supplied relative offset.
|
||||
#
|
||||
def self.jmp_short(addr)
|
||||
"\xeb" + pack_lsb(rel_number(addr, -2))
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the opcodes that compose a relative call instruction
|
||||
# to the address specified.
|
||||
#
|
||||
def self.call(addr)
|
||||
"\xe8" + pack_dword(rel_number(addr, -5))
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns a number offset to the supplied string.
|
||||
#
|
||||
def self.rel_number(num, delta = 0)
|
||||
s = num.to_s
|
||||
|
||||
case s[0, 2]
|
||||
when '$+'
|
||||
num = s[2 .. -1].to_i
|
||||
when '$-'
|
||||
num = -1 * s[2 .. -1].to_i
|
||||
when '0x'
|
||||
num = s.hex
|
||||
else
|
||||
delta = 0
|
||||
end
|
||||
|
||||
return num + delta
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the number associated with a named register.
|
||||
#
|
||||
def self.reg_number(str)
|
||||
return self.const_get(str.upcase)
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the register named associated with a given register
|
||||
# number.
|
||||
#
|
||||
def self.reg_name32(num)
|
||||
_check_reg(num)
|
||||
return REG_NAMES32[num].dup
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the encoded effective value for a register.
|
||||
#
|
||||
def self.encode_effective(shift, dst)
|
||||
return (0xc0 | (shift << 3) | dst)
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the mod r/m character for a source and destination
|
||||
# register.
|
||||
#
|
||||
def self.encode_modrm(dst, src)
|
||||
_check_reg(dst, src)
|
||||
return (0xc0 | src | dst << 3).chr
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates a push byte instruction.
|
||||
#
|
||||
def self.push_byte(byte)
|
||||
# push byte will sign extend...
|
||||
if byte < 128 && byte >= -128
|
||||
return "\x6a" + (byte & 0xff).chr
|
||||
end
|
||||
raise ::ArgumentError, "Can only take signed byte values!", caller()
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates a push word instruction.
|
||||
#
|
||||
def self.push_word(val)
|
||||
return "\x66\x68" + pack_word(val)
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates a push dword instruction.
|
||||
#
|
||||
def self.push_dword(val)
|
||||
return "\x68" + pack_dword(val)
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates a pop dword instruction into a register.
|
||||
#
|
||||
def self.pop_dword(dst)
|
||||
_check_reg(dst)
|
||||
return (0x58 | dst).chr
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates an instruction that clears the supplied register in
|
||||
# a manner that attempts to avoid bad characters, if supplied.
|
||||
#
|
||||
def self.clear(reg, badchars = '')
|
||||
_check_reg(reg)
|
||||
return set(reg, 0, badchars)
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the opcodes that set the low byte of a given
|
||||
# register to the supplied value.
|
||||
#
|
||||
def self.mov_byte(reg, val)
|
||||
_check_reg(reg)
|
||||
# chr will raise RangeError if val not between 0 .. 255
|
||||
return (0xb0 | reg).chr + val.chr
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the opcodes that set the low word of a given
|
||||
# register to the supplied value.
|
||||
#
|
||||
def self.mov_word(reg, val)
|
||||
_check_reg(reg)
|
||||
if val < 0 || val > 0xffff
|
||||
raise RangeError, "Can only take unsigned word values!", caller()
|
||||
end
|
||||
return "\x66" + (0xb8 | reg).chr + pack_word(val)
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the opcodes that set the a register to the
|
||||
# supplied value.
|
||||
#
|
||||
def self.mov_dword(reg, val)
|
||||
_check_reg(reg)
|
||||
return (0xb8 | reg).chr + pack_dword(val)
|
||||
end
|
||||
|
||||
#
|
||||
# This method is a general way of setting a register to a value. Depending
|
||||
# on the value supplied, different sets of instructions may be used.
|
||||
#
|
||||
# TODO: Make this moderatly intelligent so it chain instructions by itself
|
||||
# (ie. xor eax, eax + mov al, 4 + xchg ah, al)
|
||||
def self.set(dst, val, badchars = '')
|
||||
_check_reg(dst)
|
||||
|
||||
# If the value is 0 try xor/sub dst, dst (2 bytes)
|
||||
if val == 0
|
||||
opcodes = Rex::Text.remove_badchars("\x29\x2b\x31\x33", badchars)
|
||||
if !opcodes.empty?
|
||||
return opcodes[rand(opcodes.length)].chr + encode_modrm(dst, dst)
|
||||
end
|
||||
# TODO: SHL/SHR
|
||||
# TODO: AND
|
||||
end
|
||||
|
||||
# try push BYTE val; pop dst (3 bytes)
|
||||
begin
|
||||
return _check_badchars(push_byte(val) + pop_dword(dst), badchars)
|
||||
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
||||
end
|
||||
|
||||
# try clear dst, mov BYTE dst (4 bytes)
|
||||
begin
|
||||
unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion
|
||||
return _check_badchars(clear(dst, badchars) + mov_byte(dst, val), badchars)
|
||||
end
|
||||
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
||||
end
|
||||
|
||||
# try mov DWORD dst (5 bytes)
|
||||
begin
|
||||
return _check_badchars(mov_dword(dst, val), badchars)
|
||||
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
||||
end
|
||||
|
||||
# try push DWORD, pop dst (6 bytes)
|
||||
begin
|
||||
return _check_badchars(push_dword(val) + pop_dword(dst), badchars)
|
||||
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
||||
end
|
||||
|
||||
# try clear dst, mov WORD dst (6 bytes)
|
||||
begin
|
||||
unless val == 0 # clear tries to set(dst, 0, badchars), entering an infinite recursion
|
||||
return _check_badchars(clear(dst, badchars) + mov_word(dst, val), badchars)
|
||||
end
|
||||
rescue ::ArgumentError, ::RuntimeError, ::RangeError
|
||||
end
|
||||
|
||||
raise RuntimeError, "No valid set instruction could be created!", caller()
|
||||
end
|
||||
|
||||
#
|
||||
# Builds a subtraction instruction using the supplied operand
|
||||
# and register.
|
||||
#
|
||||
def self.sub(val, reg, badchars = '', add = false, adjust = false, bits = 0)
|
||||
opcodes = []
|
||||
shift = (add == true) ? 0 : 5
|
||||
|
||||
if (bits <= 8 and val >= -0x7f and val <= 0x7f)
|
||||
opcodes <<
|
||||
((adjust) ? '' : clear(reg, badchars)) +
|
||||
"\x83" +
|
||||
[ encode_effective(shift, reg) ].pack('C') +
|
||||
[ val.to_i ].pack('C')
|
||||
end
|
||||
|
||||
if (bits <= 16 and val >= -0xffff and val <= 0)
|
||||
opcodes <<
|
||||
((adjust) ? '' : clear(reg, badchars)) +
|
||||
"\x66\x81" +
|
||||
[ encode_effective(shift, reg) ].pack('C') +
|
||||
[ val.to_i ].pack('v')
|
||||
end
|
||||
|
||||
opcodes <<
|
||||
((adjust) ? '' : clear(reg, badchars)) +
|
||||
"\x81" +
|
||||
[ encode_effective(shift, reg) ].pack('C') +
|
||||
[ val.to_i ].pack('V')
|
||||
|
||||
# Search for a compatible opcode
|
||||
opcodes.each { |op|
|
||||
begin
|
||||
_check_badchars(op, badchars)
|
||||
rescue
|
||||
next
|
||||
end
|
||||
|
||||
return op
|
||||
}
|
||||
|
||||
if opcodes.empty?
|
||||
raise RuntimeError, "Could not find a usable opcode", caller()
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This method generates the opcodes equivalent to subtracting with a
|
||||
# negative value from a given register.
|
||||
#
|
||||
def self.add(val, reg, badchars = '', adjust = false, bits = 0)
|
||||
sub(val, reg, badchars, true, adjust, bits)
|
||||
end
|
||||
|
||||
#
|
||||
# This method wrappers packing a short integer as a little-endian buffer.
|
||||
#
|
||||
def self.pack_word(num)
|
||||
[num].pack('v')
|
||||
end
|
||||
|
||||
#
|
||||
# This method wrappers packing an integer as a little-endian buffer.
|
||||
#
|
||||
def self.pack_dword(num)
|
||||
[num].pack('V')
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the least significant byte of a packed dword.
|
||||
#
|
||||
def self.pack_lsb(num)
|
||||
pack_dword(num)[0,1]
|
||||
end
|
||||
|
||||
#
|
||||
# This method adjusts the value of the ESP register by a given amount.
|
||||
#
|
||||
def self.adjust_reg(reg, adjustment)
|
||||
if (adjustment > 0)
|
||||
sub(adjustment, reg, '', false, false, 32)
|
||||
else
|
||||
add(adjustment, reg, '', true, 32)
|
||||
end
|
||||
end
|
||||
|
||||
def self._check_reg(*regs) # :nodoc:
|
||||
regs.each { |reg|
|
||||
if reg > 7 || reg < 0
|
||||
raise ArgumentError, "Invalid register #{reg}", caller()
|
||||
end
|
||||
}
|
||||
return nil
|
||||
end
|
||||
|
||||
def self._check_badchars(data, badchars) # :nodoc:
|
||||
idx = Rex::Text.badchar_index(data, badchars)
|
||||
if idx
|
||||
raise RuntimeError, "Bad character at #{idx}", caller()
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns an array of 'safe' FPU instructions
|
||||
#
|
||||
def self.fpu_instructions
|
||||
fpus = []
|
||||
|
||||
0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
|
||||
0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
|
||||
0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
|
||||
0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
|
||||
0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
|
||||
|
||||
fpus << "\xd9\xd0"
|
||||
fpus << "\xd9\xe1"
|
||||
fpus << "\xd9\xf6"
|
||||
fpus << "\xd9\xf7"
|
||||
fpus << "\xd9\xe5"
|
||||
|
||||
# This FPU instruction seems to fail consistently on Linux
|
||||
#fpus << "\xdb\xe1"
|
||||
|
||||
fpus
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns an array containing a geteip stub, a register, and an offset
|
||||
# This method will return nil if the getip generation fails
|
||||
#
|
||||
def self.geteip_fpu(badchars, modified_registers = [])
|
||||
#
|
||||
# Default badchars to an empty string
|
||||
#
|
||||
badchars ||= ''
|
||||
|
||||
#
|
||||
# Bail out early if D9 is restricted
|
||||
#
|
||||
return nil if badchars.index("\xd9")
|
||||
|
||||
#
|
||||
# Create a list of FPU instructions
|
||||
#
|
||||
fpus = *self.fpu_instructions
|
||||
bads = []
|
||||
badchars.each_byte do |c|
|
||||
fpus.each do |str|
|
||||
bads << str if (str.index(c.chr))
|
||||
end
|
||||
end
|
||||
bads.each { |str| fpus.delete(str) }
|
||||
return nil if fpus.length == 0
|
||||
|
||||
#
|
||||
# Create a list of registers to use for fnstenv
|
||||
#
|
||||
dsts = []
|
||||
0.upto(7) do |c|
|
||||
dsts << c if (not badchars.index( (0x70+c).chr ))
|
||||
end
|
||||
|
||||
if (dsts.include?(ESP) and badchars.index("\x24"))
|
||||
dsts.delete(ESP)
|
||||
end
|
||||
|
||||
return nil if dsts.length == 0
|
||||
|
||||
#
|
||||
# Grab a random FPU instruction
|
||||
#
|
||||
fpu = fpus[ rand(fpus.length) ]
|
||||
|
||||
#
|
||||
# Grab a random register from dst
|
||||
#
|
||||
while(dsts.length > 0)
|
||||
buf = ''
|
||||
mod_registers = [ESP]
|
||||
dst = dsts[ rand(dsts.length) ]
|
||||
dsts.delete(dst)
|
||||
|
||||
# If the register is not ESP, copy ESP
|
||||
if (dst != ESP)
|
||||
mod_registers.push(dst)
|
||||
if badchars.index( (0x70 + dst).chr )
|
||||
mod_registers.pop(dst)
|
||||
next
|
||||
end
|
||||
|
||||
if !(badchars.index("\x89") or badchars.index( (0xE0+dst).chr ))
|
||||
buf << "\x89" + (0xE0 + dst).chr
|
||||
else
|
||||
if badchars.index("\x54")
|
||||
mod_registers.pop(dst)
|
||||
next
|
||||
end
|
||||
if badchars.index( (0x58+dst).chr )
|
||||
mod_registers.pop(dst)
|
||||
next
|
||||
end
|
||||
buf << "\x54" + (0x58 + dst).chr
|
||||
end
|
||||
end
|
||||
|
||||
pad = 0
|
||||
while (pad < (128-12) and badchars.index( (256-12-pad).chr))
|
||||
pad += 4
|
||||
end
|
||||
|
||||
# Give up on finding a value to use here
|
||||
if (pad == (128-12))
|
||||
return nil
|
||||
end
|
||||
|
||||
out = buf + fpu + "\xd9" + (0x70 + dst).chr
|
||||
out << "\x24" if dst == ESP
|
||||
out << (256-12-pad).chr
|
||||
|
||||
regs = [*(0..7)]
|
||||
while (regs.length > 0)
|
||||
reg = regs[ rand(regs.length) ]
|
||||
regs.delete(reg)
|
||||
next if reg == ESP
|
||||
next if badchars.index( (0x58 + reg).chr )
|
||||
mod_registers.push(reg)
|
||||
|
||||
# Pop the value back out
|
||||
0.upto(pad / 4) { |c| out << (0x58 + reg).chr }
|
||||
|
||||
# Fix the value to point to self
|
||||
gap = out.length - buf.length
|
||||
|
||||
mod_registers.uniq!
|
||||
modified_registers.concat(mod_registers)
|
||||
return [out, REG_NAMES32[reg].upcase, gap]
|
||||
end
|
||||
mod_registers.pop(dst)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a list of registers as a space or command delimited
|
||||
# string and return the internal register IDs as an array
|
||||
#
|
||||
def self.register_names_to_ids(str)
|
||||
register_ids = []
|
||||
str.to_s.strip.split(/[,\s]/).
|
||||
map {|reg| reg.to_s.strip.upcase }.
|
||||
select {|reg| reg.length > 0 }.
|
||||
uniq.each do |reg|
|
||||
next unless self.const_defined?(reg.intern)
|
||||
register_ids << self.const_get(reg.intern)
|
||||
end
|
||||
register_ids
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end end
|
||||
|
@ -1,17 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Arch
|
||||
|
||||
#
|
||||
# base module for ZARCH creation 8/13/15
|
||||
# Author: BeS Bigendian Smalls
|
||||
#
|
||||
|
||||
module ZARCH
|
||||
|
||||
|
||||
end
|
||||
|
||||
end end
|
||||
|
@ -125,6 +125,9 @@ Gem::Specification.new do |spec|
|
||||
spec.add_runtime_dependency 'rex-java'
|
||||
# Library for C-style structs
|
||||
spec.add_runtime_dependency 'rex-struct2'
|
||||
# Library which contains architecture specific information such as registers, opcodes,
|
||||
# and stack manipulation routines.
|
||||
spec.add_runtime_dependency 'rex-arch'
|
||||
|
||||
# rb-readline doesn't work with Ruby Installer due to error with Fiddle:
|
||||
# NoMethodError undefined method `dlopen' for Fiddle:Module
|
||||
|
Loading…
Reference in New Issue
Block a user