c获取当前程序的路径_漏洞挖掘|使用AFL Fuzzing网络程序
AFL基于代码插桩来生成测试用例,这样生成的样本就比较的好,而且针对 linux
做了许多性能优化使得速度也非常快。
AFL(American Fuzzy Lop)是由安全研究员Michał Zalewski开发的一款基于覆盖引导(Coverage-guided)的模糊测试工具,它通过记录输入样本的代码覆盖率,从而调整输入样本以提高覆盖率,增加发现漏洞的概率。其工作流程大致如下:
①从源码编译程序时进行插桩,以记录代码覆盖率(Code Coverage);
②选择一些输入文件,作为初始测试集加入输入队列(queue);
③将队列中的文件按一定的策略进行“突变”;
④如果经过变异文件更新了覆盖范围,则将其保留添加到队列中;
⑤上述过程会一直循环进行,期间触发了crash的文件会被记录下来。
目录
AFL状态窗口代表意义Fuzz网络程序 构建Modbus TCP Server 利用 preeny库 编译 modbus server 获取样本数据 使用获取的样本再次fuzz 总结AFL Persistent Mode总结
使用 afl
的常规步骤
如果有源码,用
afl-gcc
或者afl-clang-fast
编译源码,afl
会利用这些工具在编译期间对代码进行插桩,为后面的测试提供代码覆盖率,测试样本的变异则会基于代码覆盖率进行。无源码的话可以使用qemu
进行插桩搜集好 初始样本集,如果必要的话使用
afl-cmin
把样本集进行精简。然后用
afl-fuzz
开始fuzz
afl-cmin -i in/ -o out/ /path/to/program
in/
是初始样本集目录
out/
是 精简后的样本集存放的目录
afl-fuzz -i in/ -o out/ /path/to/program
in/
是初始样本集目录
out/
用于保存fuzz
过程中的一些文件
afl-fuzz
默认是往 stdin
中写测试数据,它同时支持从文件喂 测试数据给目标程序,只要把设置文件的参数修改为 @@
, fuzz
过程中 afl-fuzz
会把它替换成 文件名。
比如 ./a
这个程序的 第二个参数是要处理的文件的名称, 那么相应的 afl-fuzz 的命令就是
afl-fuzz -i in/ -o out/ ./a arg1 @@
AFL状态窗口代表意义
① Process timing:Fuzzer运行时长、以及距离最近发现的路径、崩溃和挂起经过了多长时间。
② Overall results:Fuzzer当前状态的概述。
③ Cycle progress:我们输入队列的距离。
④ Map coverage:目标二进制文件中的插桩代码所观察到覆盖范围的细节。
⑤ Stage progress:Fuzzer现在正在执行的文件变异策略、执行次数和执行速度。
⑥ Findings in depth:有关我们找到的执行路径,异常和挂起数量的信息。
⑦ Fuzzing strategy yields:关于突变策略产生的最新行为和结果的详细信息。
⑧ Path geometry:有关Fuzzer找到的执行路径的信息。
⑨ CPU load:CPU利用率
因为afl-fuzz永远不会停止,所以何时停止测试很多时候就是依靠afl-fuzz提供的状态来决定的。
Fuzz 网络程序
这里以 libmodbus
这个库为目标进行 fuzz 。
构建 Modbus TCP Server
库的官网地址如下
http://libmodbus.org/documentation/
这是一个用于 modbus
通讯的库, 通过这个库可以很方便的实现 modbus
服务器 和 客户端。这里以 modbus tcp
的服务端作为 fuzz
的对象。
首先在官网下载好源码
http://libmodbus.org/releases/libmodbus-3.1.4.tar.gz
源码目录下的 tests
目录里面有一些示例程序, 其中 tests/bandwidth-server-one.c
就实现了一个 modbus tcp server
精简得到
#include #include #include #include #include
int main(int argc, char *argv[]){ int s = -1; modbus_t *ctx = NULL; modbus_mapping_t *mb_mapping = NULL; int rc; int use_backend; ctx = modbus_new_tcp("127.0.0.1", 1502); s = modbus_tcp_listen(ctx, 1); modbus_tcp_accept(ctx, &s); mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0, MODBUS_MAX_READ_REGISTERS, 0); if (mb_mapping == NULL) { modbus_free(ctx); return -1; } uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH]; memset(query, 0, MODBUS_TCP_MAX_ADU_LENGTH); rc = modbus_receive(ctx, query); // 获取客户端的请求数据 if (rc > 0) { modbus_reply(ctx, query, rc, mb_mapping); // 处理并响应之 } modbus_mapping_free(mb_mapping); if (s != -1) { close(s); } /* For RTU, skipped by TCP (no TCP connect) */ modbus_close(ctx); modbus_free(ctx); return 0;}
代码逻辑简单理一下
modbus_new_tcp
初始化modbus_t
结构体modbus_tcp_accept
和modbus_tcp_listen
就是调用socket
监听端口modbus_mapping_new
初始化一个缓冲区,用于模拟寄存器信息然后
modbus_receive
接收客户端的请求和输入获取输入后就 通过
modbus_reply
处理 请求,以及构造响应数据包, 同时返回响应然后就是释放掉分配的一些内存
利用 preeny 库辅助
afl
默认只能 fuzz
通过 stdin
和 文件 获取输入的程序, 要 fuzz
网络相关的程序,需要使用一个库
https://github.com/zardus/preeny
这个库利用 LD_PRELOAD
机制,重写了 很多库函数, 其中 desock.c 这个文件负责重写 socket
相关的函数,其实现的功能就是当应用从 socket
获取输入时,其实是从 stdin
获取输入。
首先下载编译下
git clone https://github.com/zardus/preeny.gitcd preeny/sudo apt-get install libseccomp-devmake
然后会在 x86_64-linux-gnu
目录下生成编译好的 lib
。
写个测试脚本,测试一下 (根据 tests
目录里面的 sock.c
改造)
#include #include #include #include
int main(){ int s = socket(AF_INET, SOCK_STREAM, 0); char buf[1024]={0}; char send_msg[] = "hello, send by send() :\n"; send(s, send_msg, strlen(send_msg), 0); recv(s, buf, 1024, 0); printf("recv from recv() : %s\n", buf);}编译运行
编译运行
gcc sock_test.c -o sock_testLD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" ./sock_test
╭─birdpwn@ubuntu ~/vuln╰─$ LD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" ./sock_testhello, send by send() :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArecv from recv() : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
往 socket
调用 send
, 成功往 stdout
输出了 字符串。
从 stdin
输入 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
,可以看到成功写入 buf
里面
所以我们就可以利用 preeny
来 fuzz modbus tcp server
了
编译 modbus server
首先使用 afl-gcc
编译 libmodbus
,对 libmodbus
插桩。
cd libmodbus-master/CC=afl-gcc CXX=afl-g++ ./configure --enable-staticmake -j4
--enable-static:用于生成静态库
然后在 src/.libs
下就可以看到编译好的库
─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4╰─$ ls src/.libs/libmodbus.a libmodbus.la libmodbus.lai libmodbus.so libmodbus.so.5 libmodbus.so.5.1.0 modbus-data.o modbus.o modbus-rtu.o modbus-tcp.o
libmodbus.a 就是编译好的静态库
然后使用我们修改过的 bandwidth-server-one.c
编译 和 fuzz
cd tests/vim bandwidth-server-one.cafl-gcc bandwidth-server-one.c -I../src ../src/.libs/libmodbus.a -o servermkdir inecho 11111 > in/1LD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" afl-fuzz -i in -o out ./server
这里 直接用 echo
生成了一个 测试文件,如果直接用这个去测的话会发现速度非常的慢。
─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ afl-gcc bandwidth-server-one.c -I../src ../src/.libs/libmodbus.a -o serverafl-cc 2.52b by afl-as 2.52b by [+] Instrumented 24 locations (64-bit, non-hardened mode, ratio 100%).╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ mkdir in╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ echo 11111 > in/1╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ LD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" afl-fuzz -i in -o out ./serverafl-fuzz 2.52b by [+] You have 1 CPU core and 7 runnable tasks (utilization: 700%).[*] Checking core_pattern...[*] Setting up output directories...[*] Scanning 'in'...[+] No auto-generated dictionary tokens to reuse.[*] Creating hard links for all input files...[*] Validating target binary...[*] Attempting dry run with 'id:000000,orig:1'...[*] Spinning up the fork server...[+] All right - fork server is up. len = 6, map size = 108, exec speed = 501074 us[+] All test cases processed.[!] WARNING: The target binary is pretty slow! See /usr/local/share/doc/afl/perf_tips.txt.[+] Here are some useful stats: Test case count : 1 favored, 0 variable, 1 total Bitmap range : 108 to 108 bits (average: 108.00 bits) Exec timing : 501k to 501k us (average: 501k us)[*] No -t option specified, so I'll use exec timeout of 1000 ms.[+] All set and ready to roll!
这里 直接用 echo
生成了一个 测试文件,如果直接用这个去测的话会发现速度非常的慢。
获取样本数据
一组好的样本数据对 fuzzer
的影响还是非常大的,一般我们可以去网上搜索样本,比如图片,视频文件等。对于我们这次的目标 libmodbus
, 它自带了很多的测试程序,我们可以利用这些测试程序测试,然后用 tcpdump
抓包, 最后在把其中的请求数据保存下来,作为测试样本集。
首先使用 random-test-server 在 127.0.0.1:1502 起一个 modbus tcp 服务
╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ ./random-test-server
然后开启 tcpdump , 保存数据包到 ~/modbus.pcap
─birdpwn@ubuntu ~╰─$sudo tcpdump -i lo -w ~/modbus.pcap[sudo] password for birdpwn:tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
最后使用 random-test-client
随机发送各种 modbus
请求到 127.0.0.1:1502
╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ ./random-test-clientConnecting to 127.0.0.1:1502[00][01][00][00][00][06][FF][05][00][00][FF][00]Waiting for a confirmation...<00><01><00><00><00><06><FF><05><00><00><FF><00>[00][02][00][00][00][06][FF][01][00][00][00][01]Waiting for a confirmation...
然后写一个脚本把 ~/modbus.pcap
中 由客户端发送的数据包 (也就是目的地为 127.0.0.1:1502
的数据包) 的内容提取出来,每个数据包内容保存为一个单独的文件。
sudo apt-get install python-scapy
from scapy.all import *save_path = "/tmp/seeds/"uuid = 0
if not os.path.exists(save_path): os.system("mkdir %s" %(save_path))
def save_to_file(data): global uuid with open("{}{}".format(save_path, uuid), "w") as fp: fp.write(str(data)) uuid += 1 print "write test file: {}".format(uuid)
modbus_session = ''pg = rdpcap("modbus.pcap")session = pg.sessions()for k in session.keys(): if k.endswith("127.0.0.1:1502"): modbus_session = session[k]
for s in modbus_session: payload = s[TCP].payload if len(payload) > 4: save_to_file(payload)
print "Total: %d tests" %(uuid)
生成测试用例:
─birdpwn@ubuntu /tmp/seeds╰─$ ls0 120 143 166 189 210 233 256 279 300 323 346 369 391 413 436 459 481 503 526 549 571 594 616 639 661 684 706 729 751 774 797 819 841 864 887 909 931 954 9771 121 144 167 19 211 234 257 28 301 324 347 37 392 414 437 46 482 504 527 55 572 595 617 64 662 685 707 73 752 775 798 82 842 865 888 91 932 955 97810 122 145 168 190 212 235 258 280 302 325 348 370 393 415 438 460 483 505 528 550 573 596 618 640 663 686 708 730 753 776 799 820 843 866 889 910 933 956 979100 123 146 169 191 213 236 259 281 303 326 349 371 394 416 439 461 484 506 529 551 574 597 619 641 664 687 709 731 754 777 8 821 844 867 89 911 934 957 98101 124 147 17 192 214 237 26 282 304 327 35 372 395 417 44 462 485 507 53 552 575 598 62 642 665 688 71 732 755 778 80 822 845 868 890 912 935 958 980102 125 148 170 193 215 238 260 283 305 328 350 373 396 418 440 463 486 508 530 553 576 599 620 643 666 689 710 733 756 779 800 823 846 869 891 913 936 959 981103 126 149 171 194 216 239 261 284 306 329 351 374 397 419 441 464 487 509 531 554 577 6 621 644 667 69 711 734 757 78 801 824 847 87 892 914 937 96 982104 127 15 172 195 217 24 262 285 307 33 352 375 398 42 442 465 488 51 532 555 578 60 622 645 668 690 712 735 758 780 802 825 848 870 893 915 938 960 983105 128 150 173 196 218 240 263 286 308 330 353 376 399 420 443 466 489 510 533 556 579 600 623 646 669 691 713 736 759 781 803 826 849 871 894 916 939 961 984106 129 151 174 197 219 241 264 287 309 331 354 377 4 421 444 467 49 511 534 557 58 601 624 647 67 692 714 737 76 782 804 827 85 872 895 917 94 962 985107 13 152 175 198 22 242 265 288 31 332 355 378 40 422 445 468 490 512 535 558 580 602 625 648 670 693 715 738 760 783 805 828 850 873 896 918 940 963 986108 130 153 176 199 220 243 266 289 310 333 356 379 400 423 446 469 491 513 536 559 581 603 626 649 671 694 716 739 761 784 806 829 851 874 897 919 941 964 987109 131 154 177 2 221 244 267 29 311 334 357 38 401 424 447 47 492 514 537 56 582 604 627 65 672 695 717 74 762 785 807 83 852 875 898 92 942 965 98811 132 155 178 20 222 245 268 290 312 335 358 380 402 425 448 470 493 515 538 560 583 605 628 650 673 696 718 740 763 786 808 830 853 876 899 920 943 966 989110 133 156 179 200 223 246 269 291 313 336 359 381 403 426 449 471 494 516 539 561 584 606 629 651 674 697 719 741 764 787 809 831 854 877 9 921 944 967 99111 134 157 18 201 224 247 27 292 314 337 36 382 404 427 45 472 495 517 54 562 585 607 63 652 675 698 72 742 765 788 81 832 855 878 90 922 945 968112 135 158 180 202 225 248 270 293 315 338 360 383 405 428 450 473 496 518 540 563 586 608 630 653 676 699 720 743 766 789 810 833 856 879 900 923 946 969113 136 159 181 203 226 249 271 294 316 339 361 384 406 429 451 474 497 519 541 564 587 609 631 654 677 7 721 744 767 79 811 834 857 88 901 924 947 97114 137 16 182 204 227 25 272 295 317 34 362 385 407 43 452 475 498 52 542 565 588 61 632 655 678 70 722 745 768 790 812 835 858 880 902 925 948 970115 138 160 183 205 228 250 273 296 318 340 363 386 408 430 453 476 499 520 543 566 589 610 633 656 679 700 723 746 769 791 813 836 859 881 903 926 949 971116 139 161 184 206 229 251 274 297 319 341 364 387 409 431 454 477 5 521 544 567 59 611 634 657 68 701 724 747 77 792 814 837 86 882 904 927 95 972117 14 162 185 207 23 252 275 298 32 342 365 388 41 432 455 478 50 522 545 568 590 612 635 658 680 702 725 748 770 793 815 838 860 883 905 928 950 973118 140 163 186 208 230 253 276 299 320 343 366 389 410 433 456 479 500 523 546 569 591 613 636 659 681 703 726 749 771 794 816 839 861 884 906 929 951 974119 141 164 187 209 231 254 277 3 321 344 367 39 411 434 457 48 501 524 547 57 592 614 637 66 682 704 727 75 772 795 817 84 862 885 907 93 952 97512 142 165 188 21 232 255 278 30 322 345 368 390 412 435 458 480 502 525 548 570 593 615 638 660 683 705 728 750 773 796 818 840 863 886 908 930 953 976
使用获取的样本再次 fuzz
然后以生成的样本集作为初始样本集进行 fuzz
LD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" afl-fuzz -i /tmp/seeds -o out ./server
刚开始一直报错
在一顿查找原因后,是配置有问题
╭─birdpwn@ubuntu ~/vuln/libmodbus-3.1.4/tests╰─$ LD_PRELOAD="/home/giantbranch/afl-2.52b/preeny/x86_64-linux-gnu/desock.so" afl-fuzz -t 100+ -i seeds -o out ./server export AFL_NO_FORKSRV=1 1 ↵afl-fuzz 2.52b by [+] You have 1 CPU core and 7 runnable tasks (utilization: 700%).[*] Checking core_pattern...
总结
afl + preeny
来 fuzz
网络应用 速度还行, 关键的还是要找到好的样本,从程序自带的测试用例中抓取也是一个不错的思路。
AFL Persistent Mode
在介绍一个 在 fuzz
一些网络程序时可能用到的特性, AFL
的 persistent
模式。
persistent
模式就是在程序的某个代码位置不断喂生成的变异数据进行 fuzz
, 而不用每次喂数据都得重新 fork
一个程序。
要使用这个特性,首先得编译 llvm_mode
cd afl-2.52b/cd llvm_mode/makecd ..sudo make install
此时就会有 afl-clang-fast
和 afl-clang-fast++
两个命令, 要使用这个模式,就要用这两个命令来编译目标应用。
面还是用 afl
自带的 测试文件 experimental/persistent_demo/persistent_demo.c
来看看。
#include #include #include #include #include int main(int argc, char** argv) {char buf[100];while (__AFL_LOOP(1000)) { memset(buf, 0, 100); read(0, buf, 100); if (buf[0] == 'f') { printf("one\n"); if (buf[1] == 'o') { printf("two\n"); if (buf[2] == 'o') { printf("three\n"); if (buf[3] == '!') { printf("four\n"); abort(); } } } }} // end of while (__AFL_LOOP(1000))return 0;}
最关键的 就是 AFL_LOOP(1000)
这个宏, 其中的参数指定循环的次数。
每一次循环 afl 都会生成 测试数据,然后喂到 stdin
, 这样 fuzzer
就可以在 AFL_LOOP
宏 包围的内部,通过 read(0,buf, size)
来获取测试数据,然后喂给目标程序的数据处理的代码,这样可以减少 fork
等操作的开销。
对应到上面的程序,就是 afl
会在
while (__AFL_LOOP(1000)) {................}
里面 fuzz 1000
次,即生成 1000
次测试数据, 然后会 return 0
. 程序结束,然后 afl
会重新起一个程序。继续这样的 fuzz
.
被 while (__AFL_LOOP(1000))
包围的代码,就是不断的 从 stdin
获取测试数据,然后进入下面的 if
判断逻辑。
编译 然后用 afl-fuzz
它
afl-clang-fast persistent_demo.c -o persistent_demoafl-fuzz -i in/ -o out/ ./persistent_demo
总结
如果使用 afl
来 fuzz
网络应用,有两种方式
利用
preeny
把从socket
获取数据,转变为 从stdin
获取数据利用
afl
的persistent
模式
此外 , afl 还有各种扩展模式,比如 利用 qemu 可以无源码 fuzz。
c获取当前程序的路径_漏洞挖掘|使用AFL Fuzzing网络程序相关推荐
- js 获取上下文后面的路径_通过在数据后面显示上下文来可视化公众意见
js 获取上下文后面的路径 In 1824, The Harrisburg Pennsylvanian, a newspaper from a town in Pennsylvania conduct ...
- 二进制漏洞挖掘_漏洞挖掘的艺术-面向二进制的静态漏洞挖掘
本文首发于"合天智汇"公众号 作者: 萌新 0 本文是本系列的第二篇,将对面向二进制程序的静态漏洞挖掘技术进行介绍与分析. 面向二进制程序的静态漏洞的挖掘技术由于缺少源代码中的结构 ...
- 漏洞挖掘 符号执行_漏洞挖掘新思路:fuzz+符号执行——driller
driller 符号执行+fuzz漏洞挖掘思路 先看一段程序 int main() { config_t* config=read_config(); if (config==null){ puts( ...
- 小程序项目实施_实施对关键业务IT应用程序的持续分析和管理
在当今竞争激烈的商业环境中,组织必须能够快速有效地响应推动业务目标,优先级和要求发生变化的市场需求. 为了建立竞争优势,IT投资必须与这些目标和优先事项直接挂钩. 灵活,协作并集成到整个业务中的软件交 ...
- 漏洞 立即留言_漏洞挖掘小白入坑指南
文章出处:FreeBuf 文章链接:http://www.freebuf.com/articles/neopoints/144967.html 写在前面的话在此之前,很多朋友都曾通过电子邮件在我直播的 ...
- 小程序 input自动换行_直播 | 最实用的微信小程序自动化测试技术独家揭秘
随着微信小程序的功能和生态日益完善,很多企业级小程序项目的页面越来越多,业务逻辑也越来越复杂.如何做好微信小程序的自动化测试成为测试同学面临的一大难题. 如何合理构建多端架构和自动化测试体系? 如何深 ...
- 拼团小程序源码_带你了解拼团小程序
随着智能手机的普及,移动互联网的快读发展,很多创业者抓住了社交电商的商机,2018年许多人通过微信公众号,微博,抖音等自媒体.流媒体迅速建立了流量入口.那么现在的社区团购系统又是怎样的呢? 一.拼团社 ...
- 超市微信小程序怎么做_新手如何制作一个超市小程序?能发挥什么作用?
对于线下超市实体店来说,开发一个自己的社区超市小程序,能获得不少好处: (1)提升线下店铺曝光度 微信"附近的小程序"功能,会向用户展示其5公里内的开发了小程序的商家,也就是说,实 ...
- 根据id获取多维数组路径_程序员的进阶课-架构师之路(2)-数组
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/ ...
最新文章
- c# 基于layui的通用后台管理系统_【SpringBoot】三十三、SpringBoot+LayUI后台管理系统开发脚手架...
- PHP-RSA加密跨域通讯实战
- @JsonProperty注解解析
- 从服务器请求文件流工具类,SpringBoot我想获取图片流,然后将图片流的数据传到服务器上...
- OpenCV基础篇之Mat数据结构
- 手把手教你用SPSS做出二元logistic回归分析
- “无线射频识别”可节省1/3物流成本
- 固态硬盘是什么接口_固态硬盘的各种接口
- 那些高中时曾经背得烂熟的古文(滕王阁序,阿房宫赋, 兰亭集序 , 师说,蜀道难 ...)再一次读读吧,慢慢的读,突然很想哭...有些岁月果真不曾忘怀
- html文本显示不完整,css 内容显示不全怎么办
- Nature Communications:使用连接组的嵌入向量表征映射大脑结构与功能之间的高阶关系
- 【论文笔记】Camera Style Adaption for Person Re-identification
- Lambda与Stream流
- 代理arp 无故arp 反向arp
- ASP.NET:母版页与内容页
- 【回忆】【Xposed】【Magisk】小米4c的ROOT,XP框架,Magisk,Viper4Android音效之路
- html星星坠落效果,抖音星球坠落特效怎么弄 摘下星星送给你
- 用Javascript开发《三国志曹操传》-开源讲座(三)-情景对话中,仿打字机输出文字
- 【论文详解】—AlphaGo中用到的3个关键技术
- 记事本中TAB键替换为空格键的方法