Ignore:
Timestamp:
Jan 24, 2007, 4:06:17 PM (13 years ago)
Author:
Sam Hocevar
Message:
  • Added DLL injection to the Win32 port attempt.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/zzuf.c

    r1701 r1702  
    3838#if defined HAVE_WINSOCK2_H
    3939#   include <winsock2.h>
     40#endif
     41#if defined HAVE_IO_H
    4042#   include <io.h>
    4143#endif
    4244#include <string.h>
     45#include <fcntl.h>
    4346#include <errno.h>
    4447#include <signal.h>
     
    6366#endif
    6467
    65 static void loop_stdin(struct opts *opts);
    66 
    67 static void spawn_children(struct opts *opts);
    68 static void clean_children(struct opts *opts);
    69 static void read_children(struct opts *opts);
    70 
     68static void loop_stdin(struct opts *);
     69static int run_process(char const *[]);
     70
     71static void spawn_children(struct opts *);
     72static void clean_children(struct opts *);
     73static void read_children(struct opts *);
     74
     75#if !defined HAVE_GETENV
     76static void setenv(char const *, char const *, int);
     77#endif
     78#if defined HAVE_WAITPID
    7179static char const *sig2str(int);
     80#endif
     81#if defined HAVE_WINDOWS_H
     82static int dll_inject(void *, void *);
     83static void *get_entry(char const *);
     84#endif
    7285#if defined HAVE_REGEX_H
    7386static char *merge_regex(char *, char *);
    7487static char *merge_file(char *, char *);
    7588#endif
    76 static void set_environment(char const *);
    7789static void version(void);
    7890#if defined HAVE_GETOPT_H
     
    8092#endif
    8193
     94#if defined HAVE_WINDOWS_H
     95static inline void addcpy(void *buf, void *x)
     96{
     97    memcpy(buf, &x, 4);
     98}
     99#endif
     100
    82101#define ZZUF_FD_SET(fd, p_fdset, maxfd) \
    83102    if(fd >= 0) \
    84103    { \
    85         FD_SET(fd, p_fdset); \
     104        FD_SET((unsigned int)fd, p_fdset); \
    86105        if(fd > maxfd) \
    87106            maxfd = fd; \
     
    212231            opts->md5 = 1;
    213232            break;
     233#if defined HAVE_SETRLIMIT
    214234        case 'M': /* --max-memory */
    215235            setenv("ZZUF_MEMORY", "1", 1);
    216236            opts->maxmem = atoi(optarg);
    217237            break;
     238#endif
    218239        case 'n': /* --network */
    219240            setenv("ZZUF_NETWORK", "1", 1);
     
    325346    opts->nchild = 0;
    326347
    327     /* Preload libzzuf.so */
    328     set_environment(argv[0]);
    329 
    330348    /* Create new argv */
    331349    opts->newargv = malloc((argc - optind + 1) * sizeof(char *));
     
    489507    /* Prepare communication pipe */
    490508    for(j = 0; j < 3; j++)
    491         if(pipe(fd[j]) == -1)
     509    {
     510        int ret;
     511#if defined HAVE_PIPE
     512        ret = pipe(fd[j]);
     513#elif defined HAVE__PIPE
     514        ret = _pipe(fd[j], 256, _O_BINARY);
     515#endif
     516        if(ret < 0)
    492517        {
    493518            perror("pipe");
    494519            return;
    495520        }
    496 
     521    }
     522
     523#if defined HAVE_FORK
    497524    /* Fork and launch child */
    498525    pid = fork();
    499     switch(pid)
    500     {
    501         case -1:
    502             perror("fork");
     526    if(pid < -1)
     527    {
     528        perror("fork");
     529        return;
     530    }
     531#else
     532    pid = 0;
     533#endif
     534
     535    if(pid == 0)
     536    {
     537#if defined HAVE_SETRLIMIT
     538        if(opts->maxmem >= 0)
     539        {
     540            struct rlimit rlim;
     541            rlim.rlim_cur = opts->maxmem * 1000000;
     542            rlim.rlim_max = opts->maxmem * 1000000;
     543            setrlimit(RLIMIT_AS, &rlim);
     544        }
     545#endif
     546
     547#if defined HAVE_FORK
     548        /* We loop in reverse order so that files[0] is done last,
     549         * just in case one of the other dup2()ed fds had the value */
     550        for(j = 3; j--; )
     551        {
     552            close(fd[j][0]);
     553            if(fd[j][1] != files[j])
     554            {
     555                dup2(fd[j][1], files[j]);
     556                close(fd[j][1]);
     557            }
     558        }
     559#endif
     560
     561        /* Set environment variables */
     562        sprintf(buf, "%i", opts->seed);
     563        setenv("ZZUF_SEED", buf, 1);
     564        sprintf(buf, "%g", opts->minratio);
     565        setenv("ZZUF_MINRATIO", buf, 1);
     566        sprintf(buf, "%g", opts->maxratio);
     567        setenv("ZZUF_MAXRATIO", buf, 1);
     568
     569#if defined HAVE_FORK
     570        if(run_process(opts->newargv) < 0)
     571            exit(EXIT_FAILURE);
     572        exit(EXIT_SUCCESS);
     573#else
     574        if(run_process(opts->newargv) < 0)
    503575            return;
    504         case 0:
    505             /* We’re the child */
    506             if(opts->maxmem >= 0)
    507             {
    508                 struct rlimit rlim;
    509                 rlim.rlim_cur = opts->maxmem * 1000000;
    510                 rlim.rlim_max = opts->maxmem * 1000000;
    511                 setrlimit(RLIMIT_AS, &rlim);
    512             }
    513 
    514             /* We loop in reverse order so that files[0] is done last,
    515              * just in case one of the other dup2()ed fds had the value */
    516             for(j = 3; j--; )
    517             {
    518                 close(fd[j][0]);
    519                 if(fd[j][1] != files[j])
    520                 {
    521                     dup2(fd[j][1], files[j]);
    522                     close(fd[j][1]);
    523                 }
    524             }
    525 
    526             /* Set environment variables */
    527             sprintf(buf, "%i", opts->seed);
    528             setenv("ZZUF_SEED", buf, 1);
    529             sprintf(buf, "%g", opts->minratio);
    530             setenv("ZZUF_MINRATIO", buf, 1);
    531             sprintf(buf, "%g", opts->maxratio);
    532             setenv("ZZUF_MAXRATIO", buf, 1);
    533 
    534             /* Run our process */
    535             if(execvp(opts->newargv[0], opts->newargv))
    536             {
    537                 perror(opts->newargv[0]);
    538                 exit(EXIT_FAILURE);
    539             }
    540             return;
     576#endif
    541577    }
    542578
     
    570606static void clean_children(struct opts *opts)
    571607{
     608#if defined HAVE_KILL
    572609    int64_t now = _zz_time();
     610#endif
    573611    int i, j;
    574612
     613#if defined HAVE_KILL
    575614    /* Terminate children if necessary */
    576615    for(i = 0; i < opts->maxchild; i++)
     
    617656        }
    618657    }
     658#endif
    619659
    620660    /* Collect dead children */
     
    622662    {
    623663        uint8_t md5sum[16];
     664#if defined HAVE_WAITPID
    624665        int status;
    625666        pid_t pid;
     667#endif
    626668
    627669        if(opts->child[i].status != STATUS_SIGKILL
     
    630672            continue;
    631673
     674#if defined HAVE_WAITPID
    632675        pid = waitpid(opts->child[i].pid, &status, WNOHANG);
    633676        if(pid <= 0)
     
    652695            opts->crashes++;
    653696        }
     697#endif
    654698
    655699        for(j = 0; j < 3; j++)
     
    694738
    695739    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
    696     if(ret < 0)
     740    if(ret < 0 && errno)
    697741        perror("select");
    698742    if(ret <= 0)
     
    736780}
    737781
     782#if !defined HAVE_GETENV
     783static void setenv(char const *name, char const *value, int overwrite)
     784{
     785    char *str;
     786
     787    if(!overwrite && getenv(name))
     788        return;
     789
     790    str = malloc(strlen(name) + 1 + strlen(value) + 1);
     791    sprintf(str, "%s=%s", name, value);
     792    putenv(str);
     793}
     794#endif
     795
     796#if defined HAVE_WAITPID
    738797static char const *sig2str(int signum)
    739798{
     
    743802        case SIGFPE:   return " (SIGFPE)";
    744803        case SIGILL:   return " (SIGILL)";
     804#ifdef SIGQUIT
    745805        case SIGQUIT:  return " (SIGQUIT)";
     806#endif
    746807        case SIGSEGV:  return " (SIGSEGV)";
     808#ifdef SIGTRAP
    747809        case SIGTRAP:  return " (SIGTRAP)";
     810#endif
    748811#ifdef SIGSYS
    749812        case SIGSYS:   return " (SIGSYS)";
     
    765828    return "";
    766829}
    767 
    768 static void set_environment(char const *progpath)
    769 {
     830#endif
     831
     832static int run_process(char const *argv[])
     833{
     834#if defined HAVE_FORK
    770835    char *libpath, *tmp;
    771     int ret, len = strlen(progpath);
    772 #if defined __APPLE__
    773 #   define FILENAME "libzzuf.dylib"
    774 #   define EXTRAINFO ""
    775 #   define PRELOAD "DYLD_INSERT_LIBRARIES"
     836    int ret, len = strlen(argv[0]);
     837#   if defined __APPLE__
     838#       define FILENAME "libzzuf.dylib"
     839#       define EXTRAINFO ""
     840#       define PRELOAD "DYLD_INSERT_LIBRARIES"
    776841    setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1);
    777 #elif defined __osf__
    778 #   define FILENAME "libzzuf.so"
    779 #   define EXTRAINFO ":DEFAULT"
    780 #   define PRELOAD "_RLD_LIST"
    781 #else
    782 #   define FILENAME "libzzuf.so"
    783 #   define EXTRAINFO ""
    784 #   define PRELOAD "LD_PRELOAD"
    785 #endif
     842#   elif defined __osf__
     843#       define FILENAME "libzzuf.so"
     844#       define EXTRAINFO ":DEFAULT"
     845#       define PRELOAD "_RLD_LIST"
     846#   else
     847#       define FILENAME "libzzuf.so"
     848#       define EXTRAINFO ""
     849#       define PRELOAD "LD_PRELOAD"
     850#   endif
    786851
    787852    libpath = malloc(len + strlen("/.libs/" FILENAME EXTRAINFO) + 1);
    788     strcpy(libpath, progpath);
     853    strcpy(libpath, argv[0]);
    789854
    790855    tmp = strrchr(libpath, '/');
     
    798863        setenv(PRELOAD, LIBDIR "/" FILENAME EXTRAINFO, 1);
    799864    free(libpath);
    800 }
     865
     866    if(execvp(argv[0], argv))
     867    {
     868        perror(argv[0]);
     869        return -1;
     870    }
     871
     872    return 0;
     873#elif HAVE_WINDOWS_H
     874    PROCESS_INFORMATION pinfo;
     875    STARTUPINFO sinfo;
     876    void *epaddr;
     877    int ret;
     878
     879    /* Get entry point */
     880    epaddr = get_entry(argv[0]);
     881    if(!epaddr)
     882        return -1;
     883   
     884    memset(&sinfo, 0, sizeof(sinfo));
     885    sinfo.cb = sizeof(sinfo);
     886    ret = CreateProcess(NULL, argv[0], NULL, NULL, FALSE,
     887                        CREATE_SUSPENDED, NULL, NULL, &sinfo, &pinfo);
     888    if(!ret)
     889        return -1;
     890
     891    /* Insert the replacement code */
     892    ret = dll_inject(pinfo.hProcess, epaddr);
     893    if(ret < 0)
     894    {
     895        TerminateProcess(pinfo.hProcess, -1);
     896        return -1;
     897    }
     898
     899    ret = ResumeThread(pinfo.hThread);
     900    if(ret < 0)
     901    {
     902        TerminateProcess(pinfo.hProcess, -1);
     903        return -1;
     904    }
     905
     906    return 0;
     907#else
     908    return -1;
     909#endif
     910}
     911
     912#if defined HAVE_WINDOWS_H
     913static int dll_inject(void *process, void *epaddr)
     914{
     915    uint8_t old_ep[7];
     916    uint8_t new_ep[] = "\xb8<01>\xff\xe0";
     917    uint8_t loader[] = "libzzuf.dll\0<0000c>\xb8<14>\x50\xb8<1a>\xff\xd0"
     918                       "\xb8\0\0\0\0\x50\xb8\x07\x00\x00\x00\x50\xb8<2d>"
     919                       "\x50\xb8<33>\x50\xb8<39>\xff\xd0\x50\xb8<41>\xff"
     920                       "\xd0\xb8<48>\xff\xe0";
     921    void *lib;
     922    uint8_t *loaderaddr;
     923    DWORD tmp;
     924
     925    /* Save the old entry-point code */
     926    ReadProcessMemory(process, epaddr, old_ep, 7, &tmp);
     927    if(tmp != 7)
     928        return -1;
     929
     930    loaderaddr = VirtualAllocEx(process, NULL, 78, MEM_COMMIT,
     931                                PAGE_EXECUTE_READWRITE);
     932    if(!loaderaddr)
     933        return -1;
     934
     935    addcpy(new_ep + 0x01, loaderaddr + 0x0c + 7);
     936    WriteProcessMemory(process, epaddr, new_ep, 7, &tmp);
     937    if(tmp != 7)
     938        return -1;
     939
     940    lib = LoadLibrary("kernel32.dll");
     941    if(!lib)
     942        return -1;
     943
     944    memcpy(loader + 0x0c, old_ep, 7);
     945    addcpy(loader + 0x14, loaderaddr + 0x00); /* offset for dll string */
     946    addcpy(loader + 0x1a, GetProcAddress(lib, "LoadLibraryA"));
     947    addcpy(loader + 0x2d, loaderaddr + 0x0c);
     948    addcpy(loader + 0x33, epaddr);
     949    addcpy(loader + 0x39, GetProcAddress(lib, "GetCurrentProcess"));
     950    addcpy(loader + 0x41, GetProcAddress(lib, "WriteProcessMemory"));
     951    addcpy(loader + 0x48, epaddr);
     952    FreeLibrary(lib);
     953
     954    WriteProcessMemory(process, loaderaddr, loader, 78, &tmp);
     955    if(tmp != 78)
     956        return -1;
     957
     958    return 0;
     959}
     960
     961static void *get_entry(char const *name)
     962{
     963    PIMAGE_DOS_HEADER dos;
     964    PIMAGE_NT_HEADERS nt;
     965    void *file, *map, *base;
     966
     967    file = CreateFile(name, GENERIC_READ, FILE_SHARE_READ,
     968                      NULL, OPEN_EXISTING, 0, NULL);
     969    if(file == INVALID_HANDLE_VALUE)
     970        return NULL;
     971
     972    map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
     973    if(!map)
     974    {
     975        CloseHandle(file);
     976        return NULL;
     977    }
     978
     979    base = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
     980    if(!base)
     981    {
     982        CloseHandle(map);
     983        CloseHandle(file);
     984        return NULL;
     985    }
     986
     987    /* Sanity checks */
     988    dos = (PIMAGE_DOS_HEADER)base;
     989    nt = (PIMAGE_NT_HEADERS)((char *)base + dos->e_lfanew);
     990    if(dos->e_magic != IMAGE_DOS_SIGNATURE
     991      || nt->Signature != IMAGE_NT_SIGNATURE
     992      || nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386
     993      || nt->OptionalHeader.Magic != 0x10b /* IMAGE_NT_OPTIONAL_HDR32_MAGIC */)
     994    {
     995        UnmapViewOfFile(base);
     996        CloseHandle(map);
     997        CloseHandle(file);
     998        return NULL;
     999    }
     1000
     1001    return (char *)nt->OptionalHeader.ImageBase +
     1002                           nt->OptionalHeader.AddressOfEntryPoint;
     1003}
     1004#endif
    8011005
    8021006static void version(void)
     
    8541058#endif
    8551059    printf("  -m, --md5                 compute the output's MD5 hash\n");
     1060#if defined HAVE_SETRLIMIT
    8561061    printf("  -M, --max-memory <n>      maximum child virtual memory size in MB\n");
     1062#endif
    8571063    printf("  -n, --network             fuzz network input\n");
    8581064    printf("  -P, --protect <list>      protect bytes and characters in <list>\n");
     
    8871093#endif
    8881094    printf("  -m               compute the output's MD5 hash\n");
     1095#if defined HAVE_SETRLIMIT
    8891096    printf("  -M               maximum child virtual memory size in MB\n");
     1097#endif
    8901098    printf("  -n               fuzz network input\n");
    8911099    printf("  -P <list>        protect bytes and characters in <list>\n");
Note: See TracChangeset for help on using the changeset viewer.