Changeset 4393 for zzuf


Ignore:
Timestamp:
Apr 19, 2010, 10:51:58 PM (10 years ago)
Author:
Sam Hocevar
Message:

New operating mode "copy". It uses temporary files instead of preloading
libzzuf into the process.

Location:
zzuf/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/doc/zzuf.1.in

    r4388 r4393  
    1111[\fB\-b\fR \fIranges\fR] [\fB\-p\fR \fIports\fR] [\fB\-P\fR \fIprotect\fR]
    1212[\fB\-R\fR \fIrefuse\fR] [\fB\-l\fR \fIlist\fR] [\fB\-I\fR \fIinclude\fR]
    13 [\fB\-E\fR \fIexclude\fR] [\fIPROGRAM\fR [\fIARGS\fR]...]
     13[\fB\-E\fR \fIexclude\fR] [\fB\-O\fR \fIopmode\fR]
     14[\fIPROGRAM\fR [\fIARGS\fR]...]
    1415.br
    1516\fBzzuf \-h\fR | \fB\-\-help\fR
     
    194195Only INET (IPv4) and INET6 (IPv6) connections are fuzzed. Other protocol
    195196families are not yet supported.
     197.TP
     198\fB\-O\fR, \fB\-\-opmode\fR=\fImode\fR
     199Use operating mode \fImode\fR. Valid values for \fImode\fR are:
     200.RS
     201.TP
     202\fBpreload\fR
     203override functions by preloading libzzuf into the executable using the
     204system's dynamic linker
     205.TP
     206\fBcopy\fR
     207temporarily copy files that need to be fuzzed
     208.RE
     209.IP
     210The default value for \fImode\fR is \fBpreload\fR. \fBcopy\fR is useful on
     211platforms that do not support dynamic linker injection, for instance when
     212fuzzing a Cocoa application on Mac OS X.
    196213.TP
    197214\fB\-p\fR, \fB\-\-ports\fR=\fIranges\fR
  • zzuf/trunk/src/myfork.c

    r4291 r4393  
    7070#endif
    7171
    72 static int run_process(struct opts *, int[][2]);
     72static int run_process(struct child *child, struct opts *, int[][2]);
    7373
    7474#if defined HAVE_WINDOWS_H
     
    101101    }
    102102
    103     pid = run_process(opts, pipes);
     103    pid = run_process(child, opts, pipes);
    104104    if(pid < 0)
    105105    {
    106106        /* FIXME: close pipes */
    107         fprintf(stderr, "error launching `%s'\n", opts->newargv[0]);
     107        fprintf(stderr, "error launching `%s'\n", child->newargv[0]);
    108108        return -1;
    109109    }
     
    133133#endif
    134134
    135 static int run_process(struct opts *opts, int pipes[][2])
     135static int run_process(struct child *child, struct opts *opts, int pipes[][2])
    136136{
    137137    char buf[64];
     
    242242    }
    243243
    244     setenv(PRELOAD, libpath, 1);
     244    /* Only preload the library in preload mode */
     245    if (opts->opmode == OPMODE_PRELOAD)
     246        setenv(PRELOAD, libpath, 1);
    245247    free(libpath);
    246248
    247     if(execvp(opts->newargv[0], opts->newargv))
    248     {
    249         perror(opts->newargv[0]);
     249    if(execvp(child->newargv[0], child->newargv))
     250    {
     251        perror(child->newargv[0]);
    250252        exit(EXIT_FAILURE);
    251253    }
     
    266268                    &sinfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
    267269    sinfo.dwFlags = STARTF_USESTDHANDLES;
    268     ret = CreateProcess(NULL, opts->newargv[0], NULL, NULL, FALSE,
     270    ret = CreateProcess(NULL, child->newargv[0], NULL, NULL, FALSE,
    269271                        CREATE_SUSPENDED, NULL, NULL, &sinfo, &pinfo);
    270272    if(!ret)
     
    272274
    273275    /* Get the child process's entry point address */
    274     epaddr = (void *)get_entry_point(opts->newargv[0],
     276    epaddr = (void *)get_entry_point(child->newargv[0],
    275277                                     pinfo.dwProcessId);
    276278    if(!epaddr)
  • zzuf/trunk/src/opts.c

    r4264 r4393  
    3333void _zz_opts_init(struct opts *opts)
    3434{
     35    opts->opmode = OPMODE_PRELOAD;
    3536    opts->fuzzing = opts->bytes = opts->list = opts->ports = NULL;
    3637    opts->allow = NULL;
     
    5253    opts->lastlaunch = 0;
    5354
    54     opts->newargv = NULL;
    5555    opts->maxchild = 1;
    5656    opts->nchild = 0;
     
    6262void _zz_opts_fini(struct opts *opts)
    6363{
     64    int i;
     65
    6466    if(opts->child)
     67    {
     68        for(i = 0; i < opts->maxchild; i++)
     69            if (opts->child[i].newargv)
     70                free(opts->child[i].newargv);
    6571        free(opts->child);
    66     if(opts->newargv)
    67         free(opts->newargv);
     72    }
    6873}
    6974
  • zzuf/trunk/src/opts.h

    r4264 r4393  
    1717struct opts
    1818{
     19    enum opmode
     20    {
     21        OPMODE_PRELOAD,
     22        OPMODE_COPY,
     23    } opmode;
    1924    char **oldargv;
    20     char **newargv;
     25    int oldargc;
    2126    char *fuzzing, *bytes, *list, *ports, *protect, *refuse, *allow;
    2227    uint32_t seed;
     
    5560        int64_t date;
    5661        struct md5 *ctx;
     62        char **newargv;
    5763    } *child;
    5864};
  • zzuf/trunk/src/zzuf.c

    r4308 r4393  
    154154#endif
    155155#define OPTSTR "+" OPTSTR_REGEX OPTSTR_RLIMIT_MEM OPTSTR_RLIMIT_CPU \
    156                 "a:Ab:B:C:dD:e:f:F:ij:l:mnp:P:qr:R:s:St:U:vxhV"
     156                "a:Ab:B:C:dD:e:f:F:ij:l:mnO:p:P:qr:R:s:St:U:vxhV"
    157157#define MOREINFO "Try `%s --help' for more information.\n"
    158158        int option_index = 0;
     
    183183            { "max-memory",   1, NULL, 'M' },
    184184            { "network",      0, NULL, 'n' },
     185            { "opmode",       1, NULL, 'O' },
    185186            { "ports",        1, NULL, 'p' },
    186187            { "protect",      1, NULL, 'P' },
     
    257258        case 'F':
    258259            fprintf(stderr, "%s: `-F' is deprecated, use `-j'\n", argv[0]);
     260            _zz_opts_fini(opts);
    259261            return EXIT_FAILURE;
    260262        case 'i': /* --stdin */
     
    294296            setenv("ZZUF_NETWORK", "1", 1);
    295297            network = 1;
     298            break;
     299        case 'O': /* --opmode */
     300            if(myoptarg[0] == '=')
     301                myoptarg++;
     302            if (!strcmp(myoptarg, "preload"))
     303                opts->opmode = OPMODE_PRELOAD;
     304            else if (!strcmp(myoptarg, "copy"))
     305                opts->opmode = OPMODE_COPY;
     306            else
     307            {
     308                fprintf(stderr, "%s: invalid operating mode -- `%s'\n",
     309                        argv[0], myoptarg);
     310                _zz_opts_fini(opts);
     311                return EXIT_FAILURE;
     312            }
    296313            break;
    297314        case 'p': /* --ports */
     
    386403    _zz_setseed(opts->seed);
    387404
    388     /* If asked to read from the standard input */
    389     if(myoptind >= argc)
    390     {
    391         if(opts->verbose)
    392         {
    393             finfo(stderr, opts, opts->seed);
    394             fprintf(stderr, "reading from stdin\n");
    395         }
    396 
    397         if(opts->endseed != opts->seed + 1)
    398         {
    399             fprintf(stderr, "%s: seed ranges are incompatible with "
    400                             "stdin fuzzing\n", argv[0]);
    401             printf(MOREINFO, argv[0]);
    402             _zz_opts_fini(opts);
    403             return EXIT_FAILURE;
    404         }
    405 
    406         loop_stdin(opts);
    407 
    408         _zz_opts_fini(opts);
    409         return EXIT_SUCCESS;
    410     }
    411 
    412     /* If asked to launch programs */
    413 #if defined HAVE_REGEX_H
    414     if(cmdline)
    415     {
    416         int dashdash = 0;
    417 
    418         for(i = myoptind + 1; i < argc; i++)
    419         {
    420             if(dashdash)
    421                 include = merge_file(include, argv[i]);
    422             else if(!strcmp("--", argv[i]))
    423                 dashdash = 1;
    424             else if(argv[i][0] != '-')
    425                 include = merge_file(include, argv[i]);
    426         }
    427     }
    428 
    429     if(include)
    430         setenv("ZZUF_INCLUDE", include, 1);
    431     if(exclude)
    432         setenv("ZZUF_EXCLUDE", exclude, 1);
    433 #endif
    434 
    435     setenv("ZZUF_DEBUG", debug ? debug > 1 ? "2" : "1" : "0", 1);
    436     setenv("ZZUF_DEBUGFD", DEBUG_FILENO_STR, 1);
    437 
    438     if(opts->fuzzing)
    439         setenv("ZZUF_FUZZING", opts->fuzzing, 1);
    440     if(opts->bytes)
    441         setenv("ZZUF_BYTES", opts->bytes, 1);
    442     if(opts->list)
    443         setenv("ZZUF_LIST", opts->list, 1);
    444     if(opts->ports)
    445         setenv("ZZUF_PORTS", opts->ports, 1);
    446     if(opts->allow && opts->allow[0] == '!')
    447         setenv("ZZUF_DENY", opts->allow, 1);
    448     else if(opts->allow)
    449         setenv("ZZUF_ALLOW", opts->allow, 1);
    450     if(opts->protect)
    451         setenv("ZZUF_PROTECT", opts->protect, 1);
    452     if(opts->refuse)
    453         setenv("ZZUF_REFUSE", opts->refuse, 1);
    454 #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
    455     if(opts->maxmem >= 0)
    456     {
    457         char buf[32];
    458         snprintf(buf, 32, "%i", opts->maxmem);
    459         setenv("ZZUF_MEMORY", buf, 1);
    460     }
    461 #endif
    462 
    463     /* Allocate memory for children handling */
    464     opts->child = malloc(opts->maxchild * sizeof(struct child));
    465     for(i = 0; i < opts->maxchild; i++)
    466         opts->child[i].status = STATUS_FREE;
    467     opts->nchild = 0;
    468 
    469     /* Create new argv */
    470     opts->oldargv = argv;
    471     opts->newargv = malloc((argc - myoptind + 1) * sizeof(char *));
    472     memcpy(opts->newargv, argv + myoptind, (argc - myoptind) * sizeof(char *));
    473     opts->newargv[argc - myoptind] = (char *)NULL;
    474 
    475     /* Main loop */
    476     while(opts->nchild || opts->seed < opts->endseed)
    477     {
    478         /* Spawn new children, if necessary */
    479         spawn_children(opts);
    480 
    481         /* Cleanup dead or dying children */
    482         clean_children(opts);
    483 
    484         /* Read data from children */
    485         read_children(opts);
    486 
    487         if(opts->maxcrashes && opts->crashes >= opts->maxcrashes
    488             && opts->nchild == 0)
    489         {
    490             if(opts->verbose)
    491                 fprintf(stderr,
    492                         "zzuf: maximum crash count reached, exiting\n");
    493             break;
    494         }
    495 
    496         if(opts->maxtime && _zz_time() - opts->starttime >= opts->maxtime
    497             && opts->nchild == 0)
    498         {
    499             if(opts->verbose)
    500                 fprintf(stderr,
    501                         "zzuf: maximum running time reached, exiting\n");
    502             break;
    503         }
    504     }
    505 
    506     /* Clean up */
    507     _zz_opts_fini(opts);
    508 
    509     return opts->crashes ? EXIT_FAILURE : EXIT_SUCCESS;
    510 }
    511 
    512 static void loop_stdin(struct opts *opts)
    513 {
    514     uint8_t md5sum[16];
    515     struct md5 *ctx = NULL;
    516     int total = 0;
    517 
    518     if(opts->md5)
    519         ctx = _zz_md5_init();
    520 
    521405    if(opts->fuzzing)
    522406        _zz_fuzzing(opts->fuzzing);
     
    530414        _zz_refuse(opts->refuse);
    531415
     416    /* Needed for stdin mode and for copy opmode. */
    532417    _zz_fd_init();
     418
     419    /*
     420     * Mode 1: asked to read from the standard input
     421     */
     422    if(myoptind >= argc)
     423    {
     424        if(opts->verbose)
     425        {
     426            finfo(stderr, opts, opts->seed);
     427            fprintf(stderr, "reading from stdin\n");
     428        }
     429
     430        if(opts->endseed != opts->seed + 1)
     431        {
     432            fprintf(stderr, "%s: seed ranges are incompatible with "
     433                            "stdin fuzzing\n", argv[0]);
     434            printf(MOREINFO, argv[0]);
     435            _zz_opts_fini(opts);
     436            return EXIT_FAILURE;
     437        }
     438
     439        loop_stdin(opts);
     440    }
     441    /*
     442     * Mode 2: asked to launch programs
     443     */
     444    else
     445    {
     446#if defined HAVE_REGEX_H
     447        if(cmdline)
     448        {
     449            int dashdash = 0;
     450
     451            for(i = myoptind + 1; i < argc; i++)
     452            {
     453                if(dashdash)
     454                    include = merge_file(include, argv[i]);
     455                else if(!strcmp("--", argv[i]))
     456                    dashdash = 1;
     457                else if(argv[i][0] != '-')
     458                    include = merge_file(include, argv[i]);
     459            }
     460        }
     461
     462        if(include)
     463            setenv("ZZUF_INCLUDE", include, 1);
     464        if(exclude)
     465            setenv("ZZUF_EXCLUDE", exclude, 1);
     466#endif
     467
     468        setenv("ZZUF_DEBUG", debug ? debug > 1 ? "2" : "1" : "0", 1);
     469        setenv("ZZUF_DEBUGFD", DEBUG_FILENO_STR, 1);
     470
     471        if(opts->fuzzing)
     472            setenv("ZZUF_FUZZING", opts->fuzzing, 1);
     473        if(opts->bytes)
     474            setenv("ZZUF_BYTES", opts->bytes, 1);
     475        if(opts->list)
     476            setenv("ZZUF_LIST", opts->list, 1);
     477        if(opts->ports)
     478            setenv("ZZUF_PORTS", opts->ports, 1);
     479        if(opts->allow && opts->allow[0] == '!')
     480            setenv("ZZUF_DENY", opts->allow, 1);
     481        else if(opts->allow)
     482            setenv("ZZUF_ALLOW", opts->allow, 1);
     483        if(opts->protect)
     484            setenv("ZZUF_PROTECT", opts->protect, 1);
     485        if(opts->refuse)
     486            setenv("ZZUF_REFUSE", opts->refuse, 1);
     487#if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
     488        if(opts->maxmem >= 0)
     489        {
     490            char buf[32];
     491            snprintf(buf, 32, "%i", opts->maxmem);
     492            setenv("ZZUF_MEMORY", buf, 1);
     493        }
     494#endif
     495
     496        /* Allocate memory for children handling */
     497        opts->child = malloc(opts->maxchild * sizeof(struct child));
     498        for(i = 0; i < opts->maxchild; i++)
     499            opts->child[i].status = STATUS_FREE;
     500        opts->nchild = 0;
     501
     502        /* Create new argv */
     503        opts->oldargc = argc;
     504        opts->oldargv = argv;
     505        for(i = 0; i < opts->maxchild; i++)
     506        {
     507            int len = argc - myoptind;
     508            opts->child[i].newargv = malloc((len + 1) * sizeof(char *));
     509            memcpy(opts->child[i].newargv, argv + myoptind,
     510                   len * sizeof(char *));
     511            opts->child[i].newargv[len] = (char *)NULL;
     512        }
     513
     514        /* Main loop */
     515        while(opts->nchild || opts->seed < opts->endseed)
     516        {
     517            /* Spawn new children, if necessary */
     518            spawn_children(opts);
     519
     520            /* Cleanup dead or dying children */
     521            clean_children(opts);
     522
     523            /* Read data from children */
     524            read_children(opts);
     525
     526            if(opts->maxcrashes && opts->crashes >= opts->maxcrashes
     527                && opts->nchild == 0)
     528            {
     529                if(opts->verbose)
     530                    fprintf(stderr,
     531                            "zzuf: maximum crash count reached, exiting\n");
     532                break;
     533            }
     534
     535            if(opts->maxtime && _zz_time() - opts->starttime >= opts->maxtime
     536                && opts->nchild == 0)
     537            {
     538                if(opts->verbose)
     539                    fprintf(stderr,
     540                            "zzuf: maximum running time reached, exiting\n");
     541                break;
     542            }
     543        }
     544    }
     545
     546    /* Clean up */
     547    _zz_fd_fini();
     548    _zz_opts_fini(opts);
     549
     550    return opts->crashes ? EXIT_FAILURE : EXIT_SUCCESS;
     551}
     552
     553static void loop_stdin(struct opts *opts)
     554{
     555    uint8_t md5sum[16];
     556    struct md5 *ctx = NULL;
     557    int total = 0;
     558
     559    if(opts->md5)
     560        ctx = _zz_md5_init();
     561
    533562    _zz_register(0);
    534563
     
    579608
    580609    _zz_unregister(0);
    581     _zz_fd_fini();
    582610}
    583611
     
    666694            break;
    667695
     696    /* Prepare required files, if necessary */
     697    if (opts->opmode == OPMODE_COPY)
     698    {
     699        char tmpname[4096];
     700        char *tmpdir;
     701        FILE *fpin;
     702        int j, k = 0, fdout;
     703
     704        tmpdir = getenv("TEMP");
     705        if (!tmpdir || !*tmpdir)
     706            tmpdir = "/tmp";
     707
     708        for (j = optind + 1; j < opts->oldargc; j++)
     709        {
     710            fpin = fopen(opts->oldargv[j], "r");
     711            if (!fpin)
     712                continue;
     713
     714            sprintf(tmpname, "%s/zzuf.%i.XXXXXX", tmpdir, (int)getpid());
     715            fdout = mkstemp(tmpname);
     716            if (fdout < 0)
     717            {
     718                fclose(fpin);
     719                continue;
     720            }
     721
     722            opts->child[i].newargv[j - optind] = strdup(tmpname);
     723
     724            _zz_register(k);
     725            while(!feof(fpin))
     726            {
     727                uint8_t buf[BUFSIZ];
     728                size_t n = fread(buf, 1, BUFSIZ, fpin);
     729                if (n <= 0)
     730                    break;
     731                _zz_fuzz(k, buf, n);
     732                _zz_addpos(k, n);
     733                write(fdout, buf, n);
     734            }
     735            _zz_unregister(k);
     736
     737            fclose(fpin);
     738            close(fdout);
     739
     740            k++;
     741        }
     742    }
     743
     744    /* Launch process */
    668745    if (myfork(&opts->child[i], opts) < 0)
    669746    {
    670         fprintf(stderr, "error launching `%s'\n", opts->newargv[0]);
     747        fprintf(stderr, "error launching `%s'\n", opts->child[i].newargv[0]);
    671748        opts->seed++;
     749        /* FIXME: clean up OPMODE_COPY files here */
    672750        return;
    673751    }
     
    685763    {
    686764        finfo(stderr, opts, opts->child[i].seed);
    687         fprintf(stderr, "launched `%s'\n", opts->newargv[0]);
     765        fprintf(stderr, "launched `%s'\n", opts->child[i].newargv[0]);
    688766    }
    689767
     
    814892            if(opts->child[i].fd[j] >= 0)
    815893                close(opts->child[i].fd[j]);
     894
     895        if (opts->opmode == OPMODE_COPY)
     896        {
     897            for (j = optind + 1; j < opts->oldargc; j++)
     898            {
     899                if (opts->child[i].newargv[j - optind] != opts->oldargv[j])
     900                {
     901                    unlink(opts->child[i].newargv[j - optind]);
     902                    free(opts->child[i].newargv[j - optind]);
     903                    opts->child[i].newargv[j - optind] = opts->oldargv[j];
     904                }
     905            }
     906        }
    816907
    817908        if(opts->md5)
     
    9761067    printf(                                                " [-I include] [-E exclude]");
    9771068#endif
     1069    printf("              [-O mode]\n");
    9781070    printf("\n");
    9791071    printf("              [PROGRAM [--] [ARGS]...]\n");
     
    10091101#endif
    10101102    printf("  -n, --network             fuzz network input\n");
     1103    printf("  -O, --opmode <mode>       use operating mode <mode> ([preload] copy)\n");
    10111104    printf("  -p, --ports <list>        only fuzz network destination ports in <list>\n");
    10121105    printf("  -P, --protect <list>      protect bytes and characters in <list>\n");
Note: See TracChangeset for help on using the changeset viewer.