这篇来分析一下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
测试
确实是崩了,OOB
pwndbg> p h->cubeStackDepth
$1 = 69
pwndbg> p h->cube[h->cubeStackDepth]
Cannot access memory at address 0x800000000160
再来查看一下调用栈
记住这里出问题的函数,对fuzz
很有用
具体为什么,先不考虑,主要是我们写fuz
z代码,看看能不能找到这个crash
首先可以发现,是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
效果
afl
效果
目前使用个人办公机器的一半cpu
来跑afl
,自己的单核小机场来跑honggfuzz
,就目前来看都出了很多的crashes
,等跑一段时间再来看看哪个效果比较好吧,没准能够发现PJ0
没有提交的洞:)