ïŒ*ïŒå®éã«ã¯ãããã§ã¯ãããŸããã
ãããããValgrind-ãã€ãã£ãããã°ã©ã ã®ã©ãã§ã¡ã¢ãªãªãŒã¯ãçºçããŠããããåæåãããŠããªã倿°ã«ãã£ãŠåå²ãã©ãã«ããããªã©ãç¥ãããšãã§ãããããã¬ãŒïŒããã³memcheckã®ä»ã«ãä»ã®æäœã¢ãŒãããããŸãïŒã«ã€ããŠå€ãã®äººãèããããšãããã§ãããã å
éšçã«ã¯ããã®ãã°ãããããã°ã©ã ã¯ãã€ãã£ãã³ãŒããäžéãã€ãã³ãŒãã«ç²ç ãããããæç€ºããæ°ãããã·ã³ã³ãŒããçæããŸã-ãã§ã«ã©ã³ã¿ã€ã ãã§ãã¯ããããŸãã ããããåé¡ããããŸããValgrindã¯Windowsã§ã®äœæ¥æ¹æ³ãç¥ããŸããã å¿
èŠãªãšãã«ãæ€çŽ¢ã«ãã£ãŠDrMemoryãšåŒã°ããåæ§ã®ãŠãŒãã£ãªãã£ãèŠã€ãããŸãã ããããã¢ããã°strace
ã§ããã ããããããã¯ãããã«ã€ããŠã§ã¯ãªããããããæ§ç¯ãããŠããããšã«åºã¥ããåçèšè£
ã©ã€ãã©ãªã DynamoRIOã«ã€ããŠã§ãã ããæç¹ã§ãç§ã¯èªåã®ã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã®äœæãšããç¹ã§ãã®ã©ã€ãã©ãªã«èå³ãæã¡ãããã¥ã¡ã³ããæ¢ãå§ãã 倿°ã®äŸã«åºäŒãã åŒã³åºãåœä»€ã®ã«ãŠã³ãã®ãããªå®å
šãªã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã237è¡ã®ã³ãŒãã§èšè¿°ã§ããããšã«é©ãã32ãã®ãã¡ã®-ã©ã€ã»ã³ã¹ãããã³8-説æã ãããããã¡ãããããã¯ã30è¡ã®JavaScriptã³ãŒãã§Valgrindãã©ãŒãäœæãããã®ã§ã¯ãªãããã®ãããªã¿ã¹ã¯ã§æ³åã§ãããããã¯ããã«ç°¡åã§ãã
äŸãšããŠãæè¿HabrÃ©ã§æžãããFuzzer American Fuzzy Lopã®èšè£
ã®4çªç®ã®å®è£
ãæžããŸãããã
AFLãšã¯äœã§ããïŒ
AFLã¯ãéçã³ã³ã¯ãªãŒãããçµã¿ç«ãŠãããããã°ãè匱æ§ãæ€çŽ¢ããããã®ã¬ã€ãä»ããã¡ãžã³ã°ããŒã«ã§ãã æŸèæ æãèªæã§å¹ççãªæ¹æ³ã§å®è£
ããããã¥ãŒãªã¹ãã£ãã¯ã ãããã£ãŠãlibjpegã®åäœã芳å¯ããŠæå¹ãªãžãŒããåæã§ããããŒã«ãèŠããšããã®ãã¹ãŠãããã»ã©è€éã§ã¯ãªãã¡ã«ããºã ã«åºã¥ããŠè¡ãããŠããããšã«é©ããããŸãã èŠããã«ãæ¬æ ŒçãªAFLæäœã§ã¯ãå®è¡äžã«ãšããžã«ããŒãåéããããã«ã¿ãŒã²ãããã€ããªãã€ã³ã¹ãã«ã¡ã³ãåããå¿
èŠããããŸããååºæ¬ãããã¯ïŒ åºæ¬ããã㯠ãã©ãã«ããæãè¿ãé·ç§»åœä»€ãŸã§ã®äžé£ã®åœä»€ã®ãããªãã®ïŒãã°ã©ãã®é ç¹ãšããŠæ³åããŠãã ããã BBã¯ãBBéã§å¶åŸ¡ãç§»ãå¯èœãªæ¹æ³ã§ãã ãããã£ãŠãAFLã¯ãããã°ã©ã ã®åºæ¬ãããã¯éã§ã©ã®ãããªé·ç§»ãçºçãããããäœåçºçããã®ãã«é¢å¿ããããŸãã
AFLã§ã€ã³ã¹ãã«ã¡ã³ãããäž»ãªæ¹æ³ã¯ãã³ã³ãã€ã«æ®µéã§afl-gcc
/ afl-g++
ã©ãããŒãŸãã¯clang
é¡äŒŒç©ã䜿çšããŠéçã§ãã afl-gcc
ããšã«ã afl-gcc
ã¯ãåŒã³åºãas
ã³ãã³ãããã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããã¢ã»ã³ãã©ãŒã®ãªã¹ããäžæžãããã©ãããŒã«çœ®ãæããŸãã llvm mode
ãšåŒã°ãããããé«åºŠãªãªãã·ã§ã³ãããllvm mode
ãããã¯ã³ã³ãã€ã«ããã»ã¹ïŒãã¡ããLLVMã䜿çšããŠçæããllvm mode
ïŒã«æ£çŽã«çµ±åããããããçè«çã«ã¯çæã³ãŒãã®ããã©ãŒãã³ã¹ãåäžããŸãã æåŸã«ããã§ã«ã³ã³ãã€ã«ããããã€ããªããã¡ãžã³ã°ããããã®qemu mode
ãããqemu mode
-å¿
èŠãªã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã远å ãã1ã€ã®ããã»ã¹ã®ãšãã¥ã¬ãŒã·ã§ã³ã¢ãŒãã§ã®QEMUã®ãããïŒæåã¯ããã®QEMUã¢ãŒãã®åäœã¯ããã¹ãã«ãŒãã«ã䜿çšããŠå¥ã®ã¢ãŒããã¯ãã£çšã«ã¢ã»ã³ãã«ãããåå¥ã®ããã»ã¹ãéå§ããããšãç®çãšããŠããŸããïŒ
DynamoRIOãšã¯
DynamoRIOã¯åçã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã·ã¹ãã ã§ãïŒã€ãŸããå®è¡æã«æ¢ã«ã³ã³ãã€ã«æžã¿ã®ãã€ããªãçŽæ¥æç€ºããŸãïŒãx86ããã³x86_64ã¢ãŒããã¯ãã£ã®WindowsãLinuxãAndroidãããã³ARMïŒãªãªãŒã¹åè£ããŒãžã§ã³7.0ã¯AArch64ããµããŒãããŸãïŒã§å®è¡ãããŸãã QEMUãšã¯ç°ãªããä»ã®èª°ãã®ã¢ãŒããã¯ãã£ã§ãããã¹ãã«è¿ããããã°ã©ã ãå®è¡ããããšãæå³ããŠããŸãããããã€ãã£ãã¢ãŒããã¯ãã£ã§ããã°ã©ã ã®åäœã倿Žããç¬èªã®ããŒã«ãç°¡åã«äœæããããšãç®çãšããŠããŸãã åæã«ãå¯èœãªå Žåãç®æšã¯æé©åãããã³ãŒããç Žæããªãããšã§ãã æ®å¿µãªããã倿ãè¡ãããªãããã ã¯ã©ã€ã¢ã³ã ïŒããããã«ã¹ã¿ã ã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã©ã€ãã©ãªïŒãã¿ãŒã²ããåœä»€ã»ããã«ã€ããŠç¥ããªãæ¹æ³ãèŠã€ããããšããããŸããïŒåºæ¬çãªåœä»€ã«ååãªã¯ãã¹ãã©ãããã©ãŒã ã©ãããŒãååšããå Žåãé€ããŸãïŒããã·ã³ã³ãŒã->ãã€ãã³ãŒã-[instrumentation]->æ°ãããã€ãã³ãŒã->ã€ã³ã¹ãã«ã¡ã³ãããããã·ã³ã³ãŒã "ã 代ããã«ãåãããŒããã£ã¹ãããŒã¹ãŠãããã«å¯ŸããŠãã¯ã©ã€ã¢ã³ãã¯ãã³ãŒããããåœä»€ã®ãªã¹ããåä¿¡ããŸããããã¯ã䟿å©ãªæ©èœãšãã¯ãã§ä¿®æ£ããã³è£è¶³ã§ããŸãã ã€ãŸãããã·ã³ã³ãŒãã§ããã°ã©ãã³ã°ããå¿
èŠã¯ãããŸããããã»ãšãã©ã®å Žåãx86åœä»€ïŒãŸãã¯å¥ã®ãã©ãããã©ãŒã ïŒã®ã»ãããç¥ã£ãŠããå¿
èŠããããŸãã
ã¡ãã£ãšããããŒãã¹ãšããŠã Githubã¢ã«ãŠã³ãã§ä»ã«äœãé¢çœããã調ã¹ãŠã¿ãŠãè峿·±ããªããžããªDRKã«åºäŒããŸããã ãªããžããªã¯æŸæ£ãããŠãããå€å°å€ããªã£ãŠããããã§ããã説æã¯å°è±¡çã§ãã
DRKã¯ãããŒãå¯èœãªLinuxã«ãŒãã«ã¢ãžã¥ãŒã«ãšããŠã®DynamoRIOã§ãã DRKãããŒãããããšããã¹ãŠã®ã«ãŒãã«ã¢ãŒãå®è¡ïŒã·ã¹ãã ã³ãŒã«ãå²ã蟌ã¿ããã³äŸå€ãã³ãã©ãŒãã«ãŒãã«ã¹ã¬ãããªã©ïŒã¯DynamoRIOã®ç¯å²å
ã§è¡ãããŸããããŠãŒã¶ãŒã¢ãŒãå®è¡ã¯å€æŽãããŸãã-ãŠãŒã¶ãŒãã€ã³ã¹ãã«ã¡ã³ãããéåžžã®DynamoRIOã®éã§ããã¢ãŒãããã»ã¹ã§ãããã«ãŒãã«ã¢ãŒãã®å®è¡ã«ã¯åœ±é¿ããŸããã
ãã¹ãããã°ã©ã
ãŸããAFLã®æ©èœãèŠãŠã¿ãŸãããã ããããè匱ãªããŒãžã§ã³ã®ã©ã€ãã©ãªã䜿çšããŠæ°æéãŸãã¯æ°æ¥åŸ
ã€ããšã¯ãããŸããã ãã¹ãã®ããã«ãæåNULL
å§ãŸãè¡ãstdinã«æž¡ããšãnullãã€ã³ã¿ãŒãéåç
§ããæãæããªããã°ã©ã ãäœæãNULL
ã ããã¯ããã¡ãããã©ããããšããªããžãŒããåæãããã®ã§ã¯ãããŸããããåŸ
ã€å¿
èŠã¯ã»ãšãã©ãããŸããã
ãããã£ãŠã ãããã AFL ãããŠã³ããŒãããŠåéããŠãã ããã ããããæ¢ã«ãæ³åã®ãšãããGNU / Linuxã§ã¢ã»ã³ãã«ããŸãã ãã ããä»ã®Unixã©ã€ã¯ãªã·ã¹ãã ãMac OS Xã®ãããªUnixãåäœããã¯ãã§ãã å°ããªããã°ã©ã ãåããŸãïŒ
#include <stdio.h> #include <string.h> volatile int *ptr = NULL; const char cmd[] = "NULL"; int main(int argc, char *argv[]) { char buf[16]; fgets(buf, sizeof buf, stdin); if (strncmp(buf, cmd, 4)) { return 0; } *ptr = 1; return 0; }
ã³ã³ãã€ã«ããŠãã¡ãžã³ã°ãå®è¡ããŸãã
$ export AFL_PATH=~/tmp/build/afl-2.42b/ $ # , $ $AFL_PATH/afl-gcc example-bug-libc.c -o example-bug-libc $ # - ( ) $ mkdir input $ echo test > input/1 $ # $ $AFL_PATH/afl-fuzz -i input -o output -- ./example-bug-libc
ãããŠãç§ãã¡ã¯äœãèŠãŸãïŒ
ã©ããããããæ©èœããŸãã...æåŸã®æ°ãããã¹ã«æ³šæããŠãã ãããAFLã¯ã9äž1ååã®çºå£²åŸãæ°ãããã¹ãèŠã€ããããªãã£ãããšãèªããŸãã å®éãããã¯éåžžã«è«ççã§ããã¢ã»ã³ãã©ãŒãåŒã³åºã段éã§éçã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã䜿çšããããšãæãåºããŸãã äž»ãªæ¯èŒã¯libcã®é¢æ°ã«ãã£ãŠè¡ãããŸãããããã¯è£
åãããŠããªããããäžèŽããæåã®æ°ãèšç®ããããšã¯ã§ããŸããã ããã§ãç§ã¯ããããã§ãã¯ããããšã決ãããŸã§èããŸããããç§ãã¡ã®ãã€ããªã¯strncmp
颿°ãã€ã³ããŒãããªãããšã倿ããŸããã objdump -d
ã®åºåãã倿ãããšãã³ã³ãã€ã©ãŒã¯ã strncmp
代ããã«ãã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ãstrncmp
ã«ãŒãã§ã¯ãªããæ¥é éšãstrncmp
åœä»€ãåã«çæããŸããã
strncmpã§ã€ã³ã¹ãã¥ã«ã¡ã³ããããã¡ã€ã³é¢æ° 00000000000007f0 <.plt.got>: 7f0: ff 25 82 17 20 00 jmpq *0x201782(%rip) # 201f78 <getenv@GLIBC_2.2.5> 7f6: 66 90 xchg %ax,%ax 7f8: ff 25 8a 17 20 00 jmpq *0x20178a(%rip) # 201f88 <_exit@GLIBC_2.2.5> 7fe: 66 90 xchg %ax,%ax 800: ff 25 8a 17 20 00 jmpq *0x20178a(%rip) # 201f90 <write@GLIBC_2.2.5> 806: 66 90 xchg %ax,%ax 808: ff 25 8a 17 20 00 jmpq *0x20178a(%rip) # 201f98 <__stack_chk_fail@GLIBC_2.4> 80e: 66 90 xchg %ax,%ax 810: ff 25 8a 17 20 00 jmpq *0x20178a(%rip) # 201fa0 <close@GLIBC_2.2.5> 816: 66 90 xchg %ax,%ax 818: ff 25 8a 17 20 00 jmpq *0x20178a(%rip) # 201fa8 <read@GLIBC_2.2.5> 81e: 66 90 xchg %ax,%ax 820: ff 25 92 17 20 00 jmpq *0x201792(%rip) # 201fb8 <fgets@GLIBC_2.2.5> 826: 66 90 xchg %ax,%ax 828: ff 25 9a 17 20 00 jmpq *0x20179a(%rip) # 201fc8 <waitpid@GLIBC_2.2.5> 82e: 66 90 xchg %ax,%ax 830: ff 25 a2 17 20 00 jmpq *0x2017a2(%rip) # 201fd8 <shmat@GLIBC_2.2.5> 836: 66 90 xchg %ax,%ax 838: ff 25 a2 17 20 00 jmpq *0x2017a2(%rip) # 201fe0 <atoi@GLIBC_2.2.5> 83e: 66 90 xchg %ax,%ax 840: ff 25 aa 17 20 00 jmpq *0x2017aa(%rip) # 201ff0 <__cxa_finalize@GLIBC_2.2.5> 846: 66 90 xchg %ax,%ax 848: ff 25 aa 17 20 00 jmpq *0x2017aa(%rip) # 201ff8 <fork@GLIBC_2.2.5> 84e: 66 90 xchg %ax,%ax ... 0000000000000850 <main>: 850: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp 857: ff 858: 48 89 14 24 mov %rdx,(%rsp) 85c: 48 89 4c 24 08 mov %rcx,0x8(%rsp) 861: 48 89 44 24 10 mov %rax,0x10(%rsp) 866: 48 c7 c1 04 6a 00 00 mov $0x6a04,%rcx 86d: e8 9e 02 00 00 callq b10 <__afl_maybe_log> 872: 48 8b 44 24 10 mov 0x10(%rsp),%rax 877: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx 87c: 48 8b 14 24 mov (%rsp),%rdx 880: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp 887: 00 888: 53 push %rbx 889: be 10 00 00 00 mov $0x10,%esi 88e: 48 83 ec 20 sub $0x20,%rsp 892: 48 8b 15 77 17 20 00 mov 0x201777(%rip),%rdx # 202010 <stdin@@GLIBC_2.2.5> 899: 48 89 e7 mov %rsp,%rdi 89c: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 8a3: 00 00 8a5: 48 89 44 24 18 mov %rax,0x18(%rsp) 8aa: 31 c0 xor %eax,%eax 8ac: e8 6f ff ff ff callq 820 <.plt.got+0x30> 8b1: 48 8d 3d dc 06 00 00 lea 0x6dc(%rip),%rdi # f94 <cmd> 8b8: b9 04 00 00 00 mov $0x4,%ecx 8bd: 48 89 e6 mov %rsp,%rsi 8c0: f3 a6 repz cmpsb %es:(%rdi),%ds:(%rsi) 8c2: 75 45 jne 909 <main+0xb9> 8c4: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp 8cb: ff 8cc: 48 89 14 24 mov %rdx,(%rsp) 8d0: 48 89 4c 24 08 mov %rcx,0x8(%rsp) 8d5: 48 89 44 24 10 mov %rax,0x10(%rsp) 8da: 48 c7 c1 2d 5b 00 00 mov $0x5b2d,%rcx 8e1: e8 2a 02 00 00 callq b10 <__afl_maybe_log> 8e6: 48 8b 44 24 10 mov 0x10(%rsp),%rax 8eb: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx 8f0: 48 8b 14 24 mov (%rsp),%rdx 8f4: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp 8fb: 00 8fc: 48 8b 05 1d 17 20 00 mov 0x20171d(%rip),%rax # 202020 <ptr> 903: c7 00 01 00 00 00 movl $0x1,(%rax) 909: 0f 1f 00 nopl (%rax) 90c: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp 913: ff 914: 48 89 14 24 mov %rdx,(%rsp) 918: 48 89 4c 24 08 mov %rcx,0x8(%rsp) 91d: 48 89 44 24 10 mov %rax,0x10(%rsp) 922: 48 c7 c1 8f 33 00 00 mov $0x338f,%rcx 929: e8 e2 01 00 00 callq b10 <__afl_maybe_log> 92e: 48 8b 44 24 10 mov 0x10(%rsp),%rax 933: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx 938: 48 8b 14 24 mov (%rsp),%rdx 93c: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp 943: 00 944: 31 c0 xor %eax,%eax 946: 48 8b 54 24 18 mov 0x18(%rsp),%rdx 94b: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx 952: 00 00 954: 75 40 jne 996 <main+0x146> 956: 66 90 xchg %ax,%ax 958: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp 95f: ff 960: 48 89 14 24 mov %rdx,(%rsp) 964: 48 89 4c 24 08 mov %rcx,0x8(%rsp) 969: 48 89 44 24 10 mov %rax,0x10(%rsp) 96e: 48 c7 c1 0a 7d 00 00 mov $0x7d0a,%rcx 975: e8 96 01 00 00 callq b10 <__afl_maybe_log> 97a: 48 8b 44 24 10 mov 0x10(%rsp),%rax 97f: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx 984: 48 8b 14 24 mov (%rsp),%rdx 988: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp 98f: 00 990: 48 83 c4 20 add $0x20,%rsp 994: 5b pop %rbx 995: c3 retq 996: 66 90 xchg %ax,%ax 998: 48 8d a4 24 68 ff ff lea -0x98(%rsp),%rsp 99f: ff 9a0: 48 89 14 24 mov %rdx,(%rsp) 9a4: 48 89 4c 24 08 mov %rcx,0x8(%rsp) 9a9: 48 89 44 24 10 mov %rax,0x10(%rsp) 9ae: 48 c7 c1 a8 dc 00 00 mov $0xdca8,%rcx 9b5: e8 56 01 00 00 callq b10 <__afl_maybe_log> 9ba: 48 8b 44 24 10 mov 0x10(%rsp),%rax 9bf: 48 8b 4c 24 08 mov 0x8(%rsp),%rcx 9c4: 48 8b 14 24 mov (%rsp),%rdx 9c8: 48 8d a4 24 98 00 00 lea 0x98(%rsp),%rsp 9cf: 00 9d0: e8 33 fe ff ff callq 808 <.plt.got+0x18> 9d5: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 9dc: 00 00 00 9df: 90 nop
åãããã ãèšè£
ãªã 0000000000000630 <.plt.got>: 630: ff 25 82 09 20 00 jmpq *0x200982(%rip) # 200fb8 <strncmp@GLIBC_2.2.5> 636: 66 90 xchg %ax,%ax 638: ff 25 8a 09 20 00 jmpq *0x20098a(%rip) # 200fc8 <__stack_chk_fail@GLIBC_2.4> 63e: 66 90 xchg %ax,%ax 640: ff 25 92 09 20 00 jmpq *0x200992(%rip) # 200fd8 <fgets@GLIBC_2.2.5> 646: 66 90 xchg %ax,%ax 648: ff 25 aa 09 20 00 jmpq *0x2009aa(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 64e: 66 90 xchg %ax,%ax ... 0000000000000780 <main>: 780: 55 push %rbp 781: 48 89 e5 mov %rsp,%rbp 784: 48 83 ec 30 sub $0x30,%rsp 788: 89 7d dc mov %edi,-0x24(%rbp) 78b: 48 89 75 d0 mov %rsi,-0x30(%rbp) 78f: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 796: 00 00 798: 48 89 45 f8 mov %rax,-0x8(%rbp) 79c: 31 c0 xor %eax,%eax 79e: 48 8b 15 6b 08 20 00 mov 0x20086b(%rip),%rdx # 201010 <stdin@@GLIBC_2.2.5> 7a5: 48 8d 45 e0 lea -0x20(%rbp),%rax 7a9: be 10 00 00 00 mov $0x10,%esi 7ae: 48 89 c7 mov %rax,%rdi 7b1: e8 8a fe ff ff callq 640 <.plt.got+0x10> 7b6: 48 8d 45 e0 lea -0x20(%rbp),%rax 7ba: ba 04 00 00 00 mov $0x4,%edx 7bf: 48 8d 35 ce 00 00 00 lea 0xce(%rip),%rsi # 894 <cmd> 7c6: 48 89 c7 mov %rax,%rdi 7c9: e8 62 fe ff ff callq 630 <.plt.got> 7ce: 85 c0 test %eax,%eax 7d0: 74 07 je 7d9 <main+0x59> 7d2: b8 00 00 00 00 mov $0x0,%eax 7d7: eb 12 jmp 7eb <main+0x6b> 7d9: 48 8b 05 40 08 20 00 mov 0x200840(%rip),%rax # 201020 <ptr> 7e0: c7 00 01 00 00 00 movl $0x1,(%rax) 7e6: b8 00 00 00 00 mov $0x0,%eax 7eb: 48 8b 4d f8 mov -0x8(%rbp),%rcx 7ef: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx 7f6: 00 00 7f8: 74 05 je 7ff <main+0x7f> 7fa: e8 39 fe ff ff callq 638 <.plt.got+0x8> 7ff: c9 leaveq 800: c3 retq 801: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 808: 00 00 00 80b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
è峿·±ãããšã«ã strncmp
ã¯strncmp
ããŠãstrncmp
æ£çŽã«åŒã³åºããããããAFLèªäœãæé©åããªã³ã«ããstrncmp
ã afl-gcc
ã«ãã£ãŠã³ã³ãã€ã«ãããã³ãŒãå
ã®èšæœ€ããPLTã«ã€ããŠã¯ãæããã«ãforkserverã«ãã£ãŠåŒã³åºããã颿°ã衚瀺ãããŸãããããèšè¿°ããŸãããæåã«æåã«èšè¿°ããŸãã ããŠããããèŠãªãã£ããµããããŠãã©ã€ãã©ãªé¢æ°ãªãã§åçŽã«äŸãæžãæããŠã¿ãŸãããïŒ
#include <stdio.h> volatile int *ptr = NULL; const char cmd[] = "NULL"; int main(int argc, char *argv[]) { char buf[16]; fgets(buf, sizeof buf, stdin); for (int i = 0; i < sizeof cmd - 1; ++i) { if (buf[i] != cmd[i]) return 0; } *ptr = 1; return 0; }
ã³ã³ãã€ã«ãå®è¡ã... tadamïŒ
ãã©ãŒã¯ãµãŒããŒãæžã
ãã§ã«è¿°ã¹ãããã«ãAFLã¯ã調æ»äžã®ããã°ã©ã ã®åºæ¬ãããã¯éã®é·ç§»ã«é¢ããæ
å ±ãåéããèšè£
ã®å¯çšæ§ãæ³å®ããŠããŸãã ãã ãã afl-gcc
ã«ãã£ãŠè¿œå ãããæé©åïŒ forkserverããããŸãã ãã®æå³ã¯ã fork
- execve
ãã³ãã«ã䜿çšããŠããã°ã©ã ãåèµ·åããããšã§ã¯ãªããæ¯ååçãªã³ã¯ãªã©ãå®è¡ããfuzzerããã»ã¹å
ã§fork
ãäœæããŠãããã€ã³ã¹ãã«ã¡ã³ãæžã¿ããã°ã©ã ã«å®è¡ããŸãã 調æ»ããããã°ã©ã ãã©ã®ããã«åèµ·åããŸããïŒ ãã€ã³ãã¯ããã®å®è¡äžã®ããã»ã¹ããã¹ãããªãããšã§ãã 代ããã«ãç¡éã«ãŒãã§ãã¡ã¶ãŒããã®ã³ãã³ããåŸ
æ©ãã fork
äœæããåããã»ã¹ãå®äºãããŸã§åŸ
æ©ããçµæã«ã€ããŠã³ãŒã«ããã¯ããã³ãŒããå®è¡ããŸãã ããããåºèœããã»ã¹ã¯ãã§ã«å
¥åããŒã¿ãå®éã«åŠçãããšããžã«ãã¬ããžã«é¢ããæ
å ±ãåéããŸãã afl-gcc
å Žåããã®ããžãã¯ãæ£ããçè§£ããŠããã°ãforkserverã¯ã€ã³ã¹ãã«ã¡ã³ãæžã¿ã³ãŒãã«åããŠã¢ã¯ã»ã¹ãããšãã«èµ·åããŸãã llvm mode
ã®å Žåã é
å»¶forkserver llvm mode
ããµããŒããããŸã-ãã®æ¹æ³ã§ã¯ãåçãªã³ã¯ã ãã§ãªããæ€èšäžã®ããã»ã¹ã®æšæºã§ããåæåãã¹ãããã§ããŸããããã«ãããããã»ã¹å
šäœãæ¡éãã«ã¹ããŒãã¢ããã§ããŸãããèæ
®ãã¹ãããã€ãã®ãã¥ã¢ã³ã¹ããããŸãïŒ
- forkserverãéå§ããåã®ããã»ã¹ã®å®è¡ã¯ãå
¥åã«æ±ºããŠäŸåããŠã¯ãªããŸããã
- çæãããããã»ã¹ã¯ãforkserverã®èµ·åæã«éãããã¡ã€ã«èšè¿°åã®çŸåšã®äœçœ®ãžã®ãã€ã³ã¿ãªã©ãå
±éã®ç¶æ
ãå
±æããªãã§ãã ããã
fork
ãåŒã³åºããšããã»ã¹ã®ã³ããŒãäœæãããŸããããã®ã³ããŒã«ã¯fork
äœæããã¹ã¬ããã®ã¿ãååšããŸã- ...
Llvmã¢ãŒãã¯æ°žç¶ã¢ãŒãããµããŒãããŸã ããã®ã¢ãŒãã§ã¯ãè€æ°ã®ãã¹ãã±ãŒã¹ãåãçºèœããã»ã¹å
ã§é£ç¶ããŠå®è¡ãããŸãã ãããããããã«ãããªãŒããŒãããã³ã¹ãã¯ããã«åæžãããŸãããæ¬¡ã®ãã¹ãäŸã§ã®ããã°ã©ã å®è¡ã®çµæã¯ãçŸåšã®äŸã ãã§ãªãèµ·åå±¥æŽã«ãäŸåããå±éºæ§ããããŸãã ãšããã§ãèšäºã®å·çãéå§ããåŸã Windowsã®AFLããŒããã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã«DynamoRIOã䜿çšããæ°žç¶ã¢ãŒãã®ã¿ã䜿çšãããšããæ
å ±ã«åºäŒããŸããã ããŠã fork
ãµããŒããªãã§ä»ã«äœãæ®ã£ãŠããŸããïŒ
ãã®ããããã©ãŒã¯ãµãŒããŒãDynamoRIOã§äœæããå¿
èŠããããŸããããŸãããã¡ã¶ãŒããã»ã¹ãšã®çžäºäœçšã«å¿
èŠãªãããã³ã«ãçè§£ããå¿
èŠããããŸãã äžèšã®AFLäœè
ã®ããã°ãžã®ãªã³ã¯ããäœããåéã§ããŸããã llvm_mode/afl-llvm-rt.oc
ã§llvm_mode/afl-llvm-rt.oc
ãã¡ã€ã«ãèŠã€ããæ¹ãç°¡åã§ãã ããããã®è峿·±ããã®ããããŸãããæåã«__afl_start_forkserver
颿°ãèŠãŠã¿ãŸããã-ã³ã¡ã³ãã__afl_start_forkserver
ãŠããã¹ãŠãããã§è©³çްã«èª¬æãããŠããŸãã æ°žç¶ã¢ãŒãã«ã¯èå³ããããŸãããããã§ãªããã°ããã¹ãŠãæç¢ºã§ããæ¢ç¥ã®çªå·ãæã€2ã€ã®ãã¡ã€ã«èšè¿°åãäžããããŸããäžæ¹ããèªã¿åãã仿¹ã«æžã蟌ã¿ãŸãã å¿
èŠãªãã®ïŒ
- ãœãŒã¹ããã®åŒçšïŒ é»è©±ãããã芪ã«å€§äžå€«ã ãšäŒããŸã ã ä»»æã®4ãã€ããæžã蟌ã¿ãŸãã
- 4ãã€ããèªã¿åããŸãã ç§ãã¡ã®å ŽåïŒæ°žç¶ã¢ãŒããªãïŒã«ã¯äžå€ãª
child_stopped == 0
ãããããã«èŠãããããæ£ç¢ºã«èªã¿åã£ããã®ã¯éèŠã§ã¯ãããŸããã - ãã¡ã¶ãŒãšã®éä¿¡ã®ããã«ãåããã»ã¹ãäœæãããã®äžã®ãã¡ã€ã«èšè¿°åãéããŸãã
- åããã»ã¹ã®PIDã§4ãã€ãããã¡ã€ã«èšè¿°åã«æžã蟌ã¿ãããïŒããã»ã¹ïŒãå®äºããã®ãåŸ
ã¡ãŸãã
- åŸ
æ©ããåŸãæ»ãã³ãŒãã§ããã«4ãã€ããæžã蟌ã¿ãã¹ããã2ã«é²ã¿ãŸãã
ãããŠãå®éã«ã¯ã©ã€ã¢ã³ããæžãããšã«ãªããŸããã ããã§ã¯ãããã¥ã¡ã³ããŒã·ã§ã³ã®äŸã¯æ°çŸè¡ããåããªãããããã¥ã¡ã³ããŒã·ã§ã³ãèªã䟡å€ããããšããäœè«ãããå¿
èŠããããŸãã ããšãã°ã ããããå§ããããšãã§ããŸããç¹ã«ããã§ã¯ããã¹ãã§ãªãããšã«ã€ããŠæžãããŠããŸãã ããšãã°ãããç¥ãããŠããæåŠçãªãã£ã©ã¯ã¿ãŒãèšãæãããšããèšè£
ã¯ã©ã€ã¢ã³ãã¯éåžžã«å¥åŠãªãã®ã§ãïŒããã«ããããã«èŠããŸããããªããªã£ãŠããããã§ãããããã¯ããã¥ã¡ã³ãã§ã¯ã¯ã©ã€ã¢ã³ãã®éææ§ãšåŒã°ããŸã ïŒç¹ã«ãã·ã¹ãã ã©ã€ãã©ãªã®ã³ããŒã䜿çšããå¿
èŠããããŸãïŒãã©ã€ããŒãããŒããŒã圹ç«ã€ãã®ïŒããŸãã¯DynamoRIO APIã䜿çšããŸãïŒã¡ã¢ãªã®å²ãåœãŠãã³ãã³ãã©ã€ã³ãªãã·ã§ã³ã®è§£æãªã©ïŒã API颿°ã®ããã¥ã¡ã³ãã«ãéèŠãªæ
å ±ããããŸããããšãã°ã dr_register_bb_event颿°ã®èª¬æã«ã¯ã11é
ç®ã®çããªã¹ãã瀺ãããŠãããã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³åŸã«çµæãšããŠçããåœä»€ã®ã·ãŒã±ã³ã¹ãæºããå¿
èŠããããŸãã
DynamoRIOã®ã¯ã©ã€ã¢ã³ãã®ãã«ãã管çããã«ã¯ãCMakeã䜿çšããããšããå§ãããŸã-CMakeã䜿çšããŸãã ããã¥ã¡ã³ãã§ãããè¡ãæ¹æ³ã«ã€ããŠèªãããšãã§ããŸãããããã«è峿·±ã質åã«é²ã¿ãŸãã ããšãã°ãé
å»¶ãã©ãŒã¯ãµãŒããŒãäœæããã«ã¯ã調æ»äžã®ããã°ã©ã ã§ãã®èµ·åå Žæãäœããã®æ¹æ³ã§ããŒã¯ããDynamoRIOã§ãã®ããŒã¯ãèŠã€ããå¿
èŠããããŸãïŒãã ãã調æ»äžã®ããã°ã©ã å
ã®éåžžã®é¢æ°ã®åŒã³åºããšããŠãã©ãŒã¯ãµãŒããŒãäœæããããšã劚ãããã®ã¯ãªãããã§ãããããããã¯é¢çœããããŸãããïŒïŒã幞ããªããšã«ããã®ãããªæ©èœã¯DynamoRIOã«çµã¿èŸŒãŸããŠããã æ³šéãšåŒã°ããŸãã ã¯ã©ã€ã¢ã³ãã®éçºè
ã¯ã調æ»äžã®ããã°ã©ã ã«ãªã³ã¯ããå¿
èŠã®ããç¹å¥ãªéçã©ã€ãã©ãªãåéããå¿
èŠãªå Žæã§ãã®ã©ã€ãã©ãªãã颿°ãåŒã³åºãå¿
èŠããããŸããéåžžã®å®è¡äžã¯äœãå®è¡ããŸããããDynamoRIOã§å®è¡ããããšãç¹å®ã®å®æ°ã«çœ®ãæãããããã颿°åŒã³åºãã
ç§ã¯å
¬åŒã®æç§æžãç¹°ãè¿ãããããããŒãã¡ã€ã«ãDynamoRIOé
ä¿¡ããã³ããŒããæ³šéã®ååãšçœ²åã®äžã«2ã€ã®ãã¯ãã®ãåŒã³åºãããäœãçŽãïŒãã®ãã¡ã€ã«ã¯ãã¹ãäžã®ããã°ã©ã ã«æ¥ç¶ããå¿
èŠããããŸãïŒããŸããœãŒã¹ã³ãŒããäœæããããšãææ¡ããŸããã¯ããžã®1åã®åŒã³åºããããã«ãããæ³šéçšã®ã¹ã¿ãã®å®è£
ãçæãããŸãïŒãã¹ã察象ã®ããã°ã©ã ã«ãªã³ã¯ããå¿
èŠãããéçã©ã€ãã©ãªãããããæ§ç¯ãããŸãïŒã
forkserverã®å®è£
ã«ã€ããŠã¯ã libc
ã³ããŒããfork
ãåŒã³åºãã®ãããããããŸãæ£ãããªãããšãé€ããŠããã¹ãŠãéåžžã«ç°¡åã§ãïŒããšãã°ãforkserverå®è£
ã®æ©èœã«é¢ããäžèšã®èšäºã®AFLã®èè
ã¯ã libc
PIDããã£ãã·ã¥ãããšè¿°ã¹ãŠããŸãã 調æ»äžã®ã¢ããªã±ãŒã·ã§ã³ã®libc
ã³ããŒããfork
åŒã³åºããšãçºçããfork
åŒã³åºãã«ã€ããŠç¥ãããšãã§ããDynamoRIOã¯ç§ãããã«æ°ã¥ãã§ãããã ã ããç§ã¯æ¬¡ã®ãããªãã®ãæžããªããã°ãªããªãã£ã
module_data_t *module = dr_lookup_module_by_name("libc.so.6"); EXIT_IF_FAILED(module != NULL, "Cannot lookup libc.\n", 1) fork_fun_t fork_ptr = (fork_fun_t)dr_get_proc_address(module->handle, "fork"); EXIT_IF_FAILED(fork_ptr != NULL, "Cannot get fork function from libc.\n", 1) dr_free_module_data(module);
ãããã£ãŠãããã°ã©ã ã®èµ·åæã«åŸæ¥ã®forkserverèµ·åã¢ãŒãããµããŒãããã«ã¯ããã®æç¹ã§libcããã§ã«å©çšå¯èœã§ããããšã確èªããå¿
èŠããããŸãã
ããããã¹ãããããšãããšãå¥åŠãªåäœã«ééããŸããããã¹ãäžã®ããã°ã©ã ã¯èµ·åããŸããããforkserverã¯èµ·åããŸããã§ããã dr_client_main
å°å·ã远å ãdr_client_main
-衚瀺ãããŸããã§ããã ãã©ããã³ãŒãã®ã¢ã»ã³ããªãã£ã¬ã¯ããªã«åãæ¿ããŸãã ããŒã...ããã¯åäœããŸãã nm -D
ã®åºåããåäœäžããã³åäœããªãã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã©ã€ãã©ãªãšæ¯èŒããŸããdr_client_main
颿°ããããŸãã ããäžåºŠæ¯èŒããŸã-æ¬åœã«ãããŸã... drrunãªãã·ã§ã³-verbose -debug
æå®ãããŠã-verbose -debug
ã , , , . QtCreator .../build-afl-dr-Desktop_3fb6e5-
, "" â .../build-afl-dr-Desktop-
. , . , , , , , , , ⊠(, - .)
:
$ ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so -- ./example-bug Running forkserver... Cannot connect to fuzzer. 1 $ ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so -- ./example-bug 198<&0 199>/dev/null Running forkserver... xxxx 1 Incorrect spawn command from fuzzer.
, - . , AFL. dumb mode ( ), - forkserver:
$ AFL_DUMB_FORKSRV=1 $AFL_PATH/afl-fuzz -i input -o output -n -- ./example-bug ... - Fork server handshake failed -- , ... $ AFL_DUMB_FORKSRV=1 $AFL_PATH/afl-fuzz -i input -o output -n -- ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so -- ./example-bug ... - Timeout while initializing fork server (adjusting -t may help) $
, . .
: forkserver , SIGSEGV. , , , , fork
libc
, , . , extension droption
. , dr_option_t<T>
, , , dr_client_main
droption_parser_t::parse_argv(...)
(, C++). , 7.0 RC1, 6.2.0-2 , CMake droption
- . . , , , , drutil
.
:
afl-annotations.h // Based on dr_annotations.h from DynamoRIO sources #ifndef _AFL_DR_ANNOTATIONS_H_ #define _AFL_DR_ANNOTATIONS_H_ 1 #include /* To simplify project configuration, this pragma excludes the file from GCC warnings. */ #ifdef __GNUC__ # pragma GCC system_header #endif #define RUN_FORKSERVER() \ DR_ANNOTATION(run_forkserver) #ifdef __cplusplus extern { #endif DR_DECLARE_ANNOTATION(void, run_forkserver, ()); #ifdef __cplusplus } #endif #endif
afl-annotations.c #include "afl-annotations.h" DR_DEFINE_ANNOTATION(void, run_forkserver, (), )
afl-dr.c #include <dr_api.h> #include <droption.h> #include <stdint.h> #include <unistd.h> #include <sys/wait.h> #include "afl-annotations.h" static const int FROM_FUZZER_FD = 198; static const int TO_FUZZER_FD = 199; typedef int (*fork_fun_t)(); #define EXIT_IF_FAILED(isOk, msg, code) \ if (!(isOk)) { \ dr_fprintf(STDERR, (msg)); \ dr_exit_process((code)); \ } static droption_t<bool> opt_private_fork(DROPTION_SCOPE_CLIENT, "private-fork", false, "Use fork function from the private libc", "Use fork function from the private libc"); static void parse_options(int argc, const char *argv[]) { std::string parse_err; if (!droption_parser_t::parse_argv(DROPTION_SCOPE_CLIENT, argc, argv, &parse_err, NULL)) { dr_fprintf(STDERR, "Incorrect client options: %s\n", parse_err.c_str()); dr_exit_process(1); } } static void start_forkserver() { // For references, see https://lcamtuf.blogspot.ru/2014/10/fuzzing-binaries-without-execve.html // and __afl_start_forkserver in llvm_mode/afl-llvm-rt.oc from AFL sources static bool forkserver_is_running = false; uint32_t unused_four_bytes = 0; uint32_t was_killed; if (!forkserver_is_running) { dr_printf("Running forkserver...\n"); forkserver_is_running = true; } else { dr_printf("Warning: Attempt to re-run forkserver ignored.\n"); return; } if (write(TO_FUZZER_FD, &unused_four_bytes, 4) != 4) { dr_printf("Cannot connect to fuzzer.\n"); return; } fork_fun_t fork_ptr; // Lookup the fork function from target application, so both DynamoRIO // and application's copy of libc know about fork // Currently causes crashes sometimes, in that case use the private libc's fork. if (!opt_private_fork.get_value()) { module_data_t *module = dr_lookup_module_by_name("libc.so.6"); EXIT_IF_FAILED(module != NULL, "Cannot lookup libc.\n", 1) fork_ptr = (fork_fun_t)dr_get_proc_address(module->handle, "fork"); EXIT_IF_FAILED(fork_ptr != NULL, "Cannot get fork function from libc.\n", 1) dr_free_module_data(module); } else { fork_ptr = fork; } while (true) { EXIT_IF_FAILED(read(FROM_FUZZER_FD, &was_killed, 4) == 4, "Incorrect spawn command from fuzzer.\n", 1) int child_pid = fork_ptr(); EXIT_IF_FAILED(child_pid >= 0, "Cannot fork.\n", 1) if (child_pid == 0) { close(TO_FUZZER_FD); close(FROM_FUZZER_FD); return; } else { int status; EXIT_IF_FAILED(write(TO_FUZZER_FD, &child_pid, 4) == 4, "Cannot write child PID.\n", 1) EXIT_IF_FAILED(waitpid(child_pid, &status, 0) >= 0, "Wait for child failed.\n", 1) EXIT_IF_FAILED(write(TO_FUZZER_FD, &status, 4) == 4, "Cannot write child exit status.\n", 1) } } } DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { parse_options(argc, argv); EXIT_IF_FAILED( dr_annotation_register_call("run_forkserver", (void *)start_forkserver, false, 0, DR_ANNOTATION_CALL_TYPE_FASTCALL), "Cannot register forkserver annotation.\n", 1); }
, , . , , AFL, . , afl-gcc
afl-as.c
, afl-as.h
. AFL , , , technical details . ,
cur_location = <COMPILE_TIME_RANDOM>; shared_mem[cur_location ^ prev_location]++; prev_location = cur_location >> 1;
( AFL). , , , 1 â . 64- shared memory, llvm_mode/afl-llvm-rt.oc
.
, DynamoRIO, . , ( , , / ) DynamoRIO . , dr_register_bb_event
. , , thread-local , , . , -, , :
// dr_client_main: lock = dr_mutex_create(); dr_register_thread_init_event(event_thread_init); dr_register_thread_exit_event(event_thread_exit); dr_register_bb_event(event_basic_block); dr_register_exit_event(event_exit);
:
typedef struct { uint64_t scratch; uint8_t map[MAP_SIZE]; } thread_data; static void event_thread_init(void *drcontext) { void *data = dr_thread_alloc(drcontext, sizeof(thread_data)); memset(data, 0, sizeof(thread_data)); dr_set_tls_field(drcontext, data); } static void event_thread_exit(void *drcontext) { thread_data *data = (thread_data *) dr_get_tls_field(drcontext); dr_mutex_lock(lock); for (int i = 0; i < MAP_SIZE; ++i) { shmem[i] += data->map[i]; } dr_mutex_unlock(lock); dr_thread_free(drcontext, data, sizeof(thread_data)); }
⊠. , -, , DynamoRIO , , thread-specific memory pool. -, --- thread_data
, tls field.
, : event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating)
, . , â instrlist_t *bb
. ( ) , , , amd64 aka x86_64. DynamoRIO , dr_register_bb_event
. , basic block:
DR constructs dynamic basic blocks, which are distinct from a compiler's classic basic blocks. DR does not know all entry points ahead of time, and will end up duplicating the tail of a basic block if a later entry point is discovered that targets the middle of a block created earlier, or if a later entry point targets straight-line code that falls through into code already present in a block.
, , â !
. , , :
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { instr_t *where = instrlist_first(bb); reg_id_t tls_reg = DR_REG_XDI, offset_reg = DR_REG_XDX; dr_save_arith_flags(drcontext, bb, where, SPILL_SLOT_1); dr_save_reg(drcontext, bb, where, tls_reg, SPILL_SLOT_2); dr_save_reg(drcontext, bb, where, offset_reg, SPILL_SLOT_3); dr_insert_read_tls_field(drcontext, bb, where, tls_reg); // dr_restore_reg(drcontext, bb, where, offset_reg, SPILL_SLOT_3); dr_restore_reg(drcontext, bb, where, tls_reg, SPILL_SLOT_2); dr_restore_arith_flags(drcontext, bb, where, SPILL_SLOT_1); return DR_EMIT_DEFAULT; }
tls_reg
. COMPILE_TIME_RANDOM. , event_basic_block
: for_trace
translating
. , , , DynamoRIO . , , , for_trace = true
, . , , , translating = true
â , , , translating = false
. , DR_EMIT_STORE_TRANSLATIONS
DR_EMIT_DEFAULT
, , . , by design, , . , basic block.
void *app_pc = dr_fragment_app_pc(tag); uint32_t cur_location = ((uint32_t)(uintptr_t)app_pc * (uint32_t)33533) & 0xFFFF;
, ASLR , . , " ", sysctl -w kernel.randomize_va_space=0
.
, . . API , . .:
instrlist_meta_preinsert(bb, where, XINST_CREATE_load(drcontext, opnd_create_reg(offset_reg), OPND_CREATE_MEM64(tls_reg, offsetof(thread_data, scratch))))
, , , -- , Segmentation fault. , XINST_CREATE_load
XINST_CREATE_store
:
$ ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so --private-fork -- ./example-bug Cannot get SHM id from environment. Creating dummy map. Running forkserver... Cannot connect to fuzzer. ^C $ # load store $ ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so --private-fork -- ./example-bug Cannot get SHM id from environment. Creating dummy map. <Application /path/to/example-bug (5058). Tool internal crash at PC 0x00005605e72bbeaa. Please report this at your tool's issue tracker. Program aborted. Received SIGSEGV at pc 0x00005605e72bbeaa in thread 5058 Base: 0x00005605e71c5000 Registers:eax=0x0000000000000001 ebx=0x00007ff6dfa12038 ecx=0x0000000000000048 edx=0x0000000000000000 esi=0x0000000000000049 edi=0x0000000000000005 esp=0x00007ff6dfa0ebb0 ebp=0x00007ff6dfa0ebc0 r8 =0x0000000000000003 r9 =0x0000000000000005 r10=0x0000000000000000 r11=0x00005605e72b70ef r12=0x0000000000000000 r13=0x0000000000000000 r14=0x000000000000000c r15=0x00005605e7368c50 eflags=0x0000000000010202 version 6.2.0, build 2 -no_dynamic_options -client_lib '/path/to/libafl-dr.so;0;"--private-fork"' -code_api -stack_size 56K -max_elide_jmp 0 -max_elide_call 0 -early_inject -emulate_brk -no_inline_ignored_syscalls -native_exec_default_list '' -no_native_exec_managed_code -no_indcall2direct 0x00007ff6dfa0ebc0 0x0000020803000000>
ã©ããã , . -debug -loglevel 1 -logdir /tmp/dynamorio/
, - :
ERROR: Could not find encoding for: mov (%rdi)[8byte] -> %rdx SYSLOG_ERROR: Application /path/to/example-bug (5192) DynamoRIO usage error : instr_encode error: no encoding found (see log) SYSLOG_ERROR: Usage error: instr_encode error: no encoding found (see log) (/dynamorio_package/core/arch/x86/encode.c, line 2417)
, : , â .
, , :
$ $AFL_PATH/afl-fuzz -i input -o output -m 2048 -- ~/soft/DynamoRIO-Linux-6.2.0-2/bin64/drrun -c libafl-dr.so -- ./example-bug afl-fuzz 2.42b by <lcamtuf@google.com> [+] You have 4 CPU cores and 1 runnable tasks (utilization: 25%). [+] Try parallel jobs - see docs/parallel_fuzzing.txt. [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern... [*] Checking CPU scaling governor... [*] Setting up output directories... [+] Output directory exists but deemed OK to reuse. [*] Deleting old session data... [+] Output dir cleanup successful. [*] Scanning 'input'... [+] No auto-generated dictionary tokens to reuse. [*] Creating hard links for all input files... [*] Validating target binary... [-] Looks like the target binary is not instrumented! The fuzzer depends on compile-time instrumentation to isolate interesting test cases while mutating the input data. For more information, and for tips on how to instrument binaries, please see docs/README. When source code is not available, you may be able to leverage QEMU mode support. Consult the README for tips on how to enable this. (It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer. For that, you can use the -n option - but expect much worse results.) [-] PROGRAM ABORT : No instrumentation detected Location : check_binary(), afl-fuzz.c:6894
⊠⊠? : strace
, , drrun
. , afl-fuzz
, ? , , AFL â ? , , , , afl-fuzz.c:6894
, :
f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); // ... if (!qemu_mode && !dumb_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { // ... FATAL("No instrumentation detected"); }
-, : AFL __AFL_SHM_ID
â , . - , echo -ne "__AFL_SHM_ID\0" >> /path/to/drrun
, , : , , AFL_SKIP_BIN_CHECK
:
$ # -d $ AFL_SKIP_BIN_CHECK=1 $AFL_PATH/afl-fuzz -i input -o output -m 2048 -d
, AFL , , , total paths: 12
, 4-5. , , libc. example-bug
, , (, DynamoRIO, ). âŠ
æé©å
⊠, . , , " ". module_data_t *
, dr_client_main
, event_basic_block
, " ":
module_data_t *main_module; // dr_client_main: main_module = dr_get_main_module(); // event_basic_block: if (!opt_instrument_everything.get_value() && !dr_module_contains_addr(main_module, pc)) { return DR_EMIT_DEFAULT; }
80 ( 2 ), output/queue
test
NU
â , .
, DynamoRIO -thread_private
, . tls field , , , immediate-:
if (dr_using_all_private_caches()) { instrlist_meta_preinsert(bb, where, INSTR_CREATE_mov_imm(drcontext, opnd_create_reg(tls_reg), OPND_CREATE_INTPTR(dr_get_tls_field(drcontext)))); } else { dr_insert_read_tls_field(drcontext, bb, where, tls_reg); }
-thread_private
( -c libafl-dr.so
, DynamoRIO, ), 5 . , if (0 && dr_using_all_private_caches())
, â , DynamoRIO . :)
, : -disable_traces
â , , , , , , . ⊠10-15 . , , , , , test case-.
, , "" forkserver-: example-bug.c
ungetc('1', stdin); char ch; fscanf(stdin, "%c", &ch); RUN_FORKSERVER();
⊠15 . , , : , - libc forkserver, , - .
. :
- ,
afl-as
- ( , , )
- QEMU forkserver , (, , DynamoRIO. , : feature request, issues, ... )
⊠. , : " API / ?" , ", , !" â , . , , , , â , .
åç
§ïŒ
UPD: , ( qemu_mode
). API , 5. , , .