Skip to content

Latest commit

 

History

History
250 lines (184 loc) · 6.59 KB

README.md

File metadata and controls

250 lines (184 loc) · 6.59 KB

fuzz CVE-2019-1117

这篇来分析一下CVE-2019-1117,问题为stack corruption in OpenType font handling due to out-of-bounds cubeStackDepth

漏洞复现

搭建环境,简单复现一下

git clone https://github.com/adobe-type-tools/afdko
cd afdko
git checkout 2.8.8
cd c
bash buildalllinux.sh debug

根据给出的poc测试

1563456773112

确实是崩了,OOB

pwndbg> p h->cubeStackDepth
$1 = 69
pwndbg> p  h->cube[h->cubeStackDepth]
Cannot access memory at address 0x800000000160

再来查看一下调用栈

1563457266808

记住这里出问题的函数,对fuzz很有用

具体为什么,先不考虑,主要是我们写fuzz代码,看看能不能找到这个crash

编写fuzz代码

首先可以发现,是tx在处理otf文件发生的错误,直接看tx.c源码,整体代码特别长,直接看main函数

/* Main program. */
int CTL_CDECL main(int argc, char *argv[]) {
    txCtx h;
    char *progname;
#if PLAT_MAC
    argc = ccommand(&argv);
    (void)__reopen(stdin); /* Change stdin to binary mode */
#endif                     /* PLAT_MAC */

#if PLAT_WIN
    /* The Microsoft standard C-Library opens stderr in buffered mode in
       contravention of the C standard. The following code establishes the
       correct unbuffered mode */
    (void)setvbuf(stderr, NULL, _IONBF, 0);
#endif /* PLAT_WIN */

    /* Get program name */
    progname = tail(argv[0]);
    --argc;
    ++argv;

    /* Allocate program context */
    h = malloc(sizeof(struct txCtx_));
    if (h == NULL) {
        fprintf(stderr, "%s: out of memory\n", progname);
        return EXIT_FAILURE;
    }
    memset(h, 0, sizeof(struct txCtx_));

    h->app = APP_TX;
    h->appSpecificInfo = NULL; /* unused in tx.c, used in rotateFont.c & mergeFonts.c */
    h->appSpecificFree = txFree;

    txNew(h, progname);

    if (argc > 1 && getOptionIndex(argv[argc - 2]) == opt_s) {
        /* Option list ends with script option */
        int i;

        /* Copy args preceeding -s */
        for (i = 0; i < argc - 2; i++)
            *dnaNEXT(h->script.args) = argv[i];

        /* Add args from script file */
        addArgs(h, argv[argc - 1]);

        parseArgs(h, (int)h->script.args.cnt, h->script.args.array);
    } else
        parseArgs(h, argc, argv);

    if (h->failmem.iFail == FAIL_REPORT) {
        fflush(stdout);
        fprintf(stderr, "mem_manage() called %ld times in this run.\n",
                h->failmem.iCall);
    }
    txFree(h);

    return 0;
}

看到这个代码其实就很开心了,这种可以直接fuzz了,基本都不用改啥了。

但是为了提高我们的fuzz效率,并且重现1117的这个漏洞,更改一下代码,让我们的代码只分析otf文件

/* Main program. */
int CTL_CDECL main(int argc, char *argv[]) {
    txCtx h;
    char *progname;

    /* Get program name */
    progname = tail(argv[0]);
    --argc;
    ++argv;

    /* Allocate program context */
    h = malloc(sizeof(struct txCtx_));
    if (h == NULL) {
        fprintf(stderr, "%s: out of memory\n", progname);
        return EXIT_FAILURE;
    }
    memset(h, 0, sizeof(struct txCtx_));

    h->app = APP_TX;
    h->appSpecificInfo = NULL; /* unused in tx.c, used in rotateFont.c & mergeFonts.c */
    h->appSpecificFree = txFree;

    txNew(h, progname);

    h->t1r.flags = 0; /* I initialize these here,as I need to set the std Encoding flags before calling setMode. */
    h->cfr.flags = 0;
    h->cfw.flags = 0;
    h->dcf.flags = DCF_AllTables | DCF_BreakFlowed;
    h->dcf.level = 5;
    h->svr.flags = 0;
    h->ufr.flags = 0;
    h->ufow.flags = 0;
    h->t1w.options = 0;

    // 设置cff模式
    setMode(h, mode_cff);

    // argv[1] 文件名,对应上面argv--
    doSingleFileSet(h, argv[0]);

    if (h->failmem.iFail == FAIL_REPORT) {
        fflush(stdout);
        fprintf(stderr, "mem_manage() called %ld times in this run.\n",
                h->failmem.iCall);
    }
    txFree(h);

    return 0;
}

建立一个patch文件,方便以后直接patch

diff ./afdko/c/tx/source/tx.c target.cc > target.patch

之后具体的操作build.sh

#!/bin/bash

# clean up
if [ -e ./tx_fuzzer ]; then
    rm -f ./tx_fuzzer
fi

# install requirements
apt install -y git make clang

install afl
if [ -d ./afl/ ]; then
    git clone https://github.com/mirrorer/afl && cd afl && make && make install && cd ..
fi

# install honggfuzz
if [ ! -e /usr/local/bin/hfuzz-cc ]; then 
    git clone https://github.com/google/honggfuzz
    cd honggfuzz && apt install gcc git make pkg-config libipt-dev libunwind8-dev binutils-dev && \
        make install && cd ..
fi

# create output_corps directory
if [ ! -d ./output_corpus/ ]; then
    mkdir ./output_corpus
fi

# afdko exists or not
if [ ! -d ./afdko/c/ ]; then
    git clone https://github.com/adobe-type-tools/afdko && cd afdko && git checkout 2.8.8 && cd ..
fi


# patch files
if [ -e ./target.patch ]; then
    patch afdko/c/tx/source/tx.c target.patch
fi

# make tx file
if [ -d ./afdko/c/tx/build/linux/gcc/debug ]; then
    cd ./afdko/c/tx/build/linux/gcc/debug && CC=hfuzz-clang make 
    cd ../../../../../../../
    cp ./afdko/c/tx/exe/linux/debug/tx ./tx_fuzzer
fi


if [ -e ./tx_fuzzer ]; then
    echo "[+] build tx_fuzzer success!"
else
    echo "[-] build tx_fuzzer failed!"
fi

如果利用honggfuzz

honggfuzz -f input_corps -W output_corpus -- ./tx_fuzzer ___FILE___

如果是afl

screen -S txfuzz1 afl-fuzz -i input_corps/ -o output_corps/ -M tx_fuzz1 -- ./tx_fuzzer @@
screen -S txfuzz2 afl-fuzz -i input_corps/ -o output_corps/ -S tx_fuzz2 -- ./tx_fuzzer @@

最后来看一下效果

honggfuzz效果

1563457952168

afl效果

1563458019611

目前使用个人办公机器的一半cpu来跑afl,自己的单核小机场来跑honggfuzz,就目前来看都出了很多的crashes,等跑一段时间再来看看哪个效果比较好吧,没准能够发现PJ0没有提交的洞:)

参考

Microsoft DirectWrite / AFDKOstack corruption in OpenType font handling due to out-of-bounds cubeStackDepth