Changeset 4115 for zzuf/trunk


Ignore:
Timestamp:
Dec 12, 2009, 11:20:11 PM (11 years ago)
Author:
Sam Hocevar
Message:

Move process creation stuff to a separate myfork.c file.

Location:
zzuf/trunk/src
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/Makefile.am

    r4112 r4115  
    55
    66ZZUF = \
    7     zzuf.c opts.c opts.h md5.c md5.h timer.c timer.h
     7    zzuf.c opts.c opts.h md5.c md5.h timer.c timer.h myfork.c myfork.h
    88
    99LIBZZUF = \
     
    2626
    2727zzuf_SOURCES = $(ZZUF) $(COMMON) $(GETOPT)
    28 zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\" -Icommon/
     28zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\" -I$(srcdir)/common
    2929zzuf_LDFLAGS = $(MATH_LIBS) $(WINSOCK2_LIBS)
    3030zzuf_DEPENDENCIES = libzzuf.la
    3131
    3232libzzuf_la_SOURCES = $(LIBZZUF) $(COMMON)
    33 libzzuf_la_CFLAGS = -DLIBZZUF -Ilibzzuf/ -Icommon/
     33libzzuf_la_CFLAGS = -DLIBZZUF -I$(srcdir)/libzzuf -I$(srcdir)/common
    3434libzzuf_la_LDFLAGS = -avoid-version -no-undefined $(DLL_LDFLAGS)
    3535libzzuf_la_LIBADD = $(GETOPT_LIBS) $(DL_LIBS) $(MATH_LIBS) $(WINSOCK2_LIBS)
  • zzuf/trunk/src/common/common.h

    r4112 r4115  
    3636#define DEFAULT_MEM 1024
    3737
     38/* We use file descriptor 17 as the debug channel */
     39#define DEBUG_FILENO 17
     40#define DEBUG_FILENO_STR "17"
     41
    3842struct fuzz
    3943{
  • zzuf/trunk/src/zzuf.c

    r4112 r4115  
    1919#include "config.h"
    2020
    21 /* Needed for STDERR_FILENO on HP-UX */
    22 #define _INCLUDE_POSIX_SOURCE
     21#define _INCLUDE_POSIX_SOURCE /* for STDERR_FILENO on HP-UX */
    2322
    2423#if defined HAVE_STDINT_H
     
    3534#include <stdlib.h>
    3635#if defined HAVE_UNISTD_H
    37 #   include <unistd.h>
     36#   include <unistd.h> /* for read(), write(), close() */
    3837#endif
    3938#if defined HAVE_REGEX_H
     
    4140#endif
    4241#if defined HAVE_WINSOCK2_H
    43 #   include <winsock2.h>
    44 #endif
    45 #if defined HAVE_WINDOWS_H
    46 #   include <windows.h>
    47 #   include <imagehlp.h>
    48 #   include <tlhelp32.h>
     42#   include <winsock2.h> /* for fd_set */
    4943#endif
    5044#if defined HAVE_IO_H
     
    5246#endif
    5347#include <string.h>
    54 #include <fcntl.h>
    5548#include <errno.h>
    5649#include <signal.h>
     
    7063#include "fd.h"
    7164#include "fuzz.h"
     65#include "myfork.h"
    7266#include "md5.h"
    7367#include "timer.h"
     
    10599#endif
    106100
    107 /* We use file descriptor 17 as the debug channel */
    108 #define DEBUG_FILENO 17
    109 #define DEBUG_FILENO_STR "17"
    110 
    111101static void loop_stdin(struct opts *);
    112 static int run_process(struct opts *, int[][2]);
    113102
    114103static void spawn_children(struct opts *);
     
    122111static char const *sig2name(int);
    123112#endif
    124 #if defined HAVE_WINDOWS_H
    125 static int dll_inject(void *, void *);
    126 static intptr_t get_base_address(DWORD);
    127 static intptr_t get_entry_point_offset(char const *);
    128 #endif
    129113static void finfo(FILE *, struct opts *, uint32_t);
    130114#if defined HAVE_REGEX_H
     
    134118static void version(void);
    135119static void usage(void);
    136 
    137 #if defined HAVE_WINDOWS_H
    138 static inline void addcpy(void *buf, void *x)
    139 {
    140     memcpy(buf, &x, 4);
    141 }
    142 #endif
    143120
    144121#define ZZUF_FD_SET(fd, p_fdset, maxfd) \
     
    659636static void spawn_children(struct opts *opts)
    660637{
    661     int pipes[3][2];
    662638    int64_t now = _zz_time();
    663     pid_t pid;
    664     int i, j;
     639    int i;
    665640
    666641    if(opts->nchild == opts->maxchild)
     
    681656            break;
    682657
    683     /* Prepare communication pipe */
    684     for(j = 0; j < 3; j++)
    685     {
    686         int ret;
    687 #if defined HAVE_PIPE
    688         ret = pipe(pipes[j]);
    689 #elif defined HAVE__PIPE
    690         ret = _pipe(pipes[j], 512, _O_BINARY | O_NOINHERIT);
    691 #endif
    692         if(ret < 0)
    693         {
    694             perror("pipe");
    695             opts->seed++;
    696             return;
    697         }
    698     }
    699 
    700     pid = run_process(opts, pipes);
    701     if(pid < 0)
     658    if (myfork(&opts->child[i], opts) < 0)
    702659    {
    703660        fprintf(stderr, "error launching `%s'\n", opts->newargv[0]);
     
    708665    /* We’re the parent, acknowledge spawn */
    709666    opts->child[i].date = now;
    710     opts->child[i].pid = pid;
    711     for(j = 0; j < 3; j++)
    712     {
    713         close(pipes[j][1]);
    714         opts->child[i].fd[j] = pipes[j][0];
    715     }
    716667    opts->child[i].bytes = 0;
    717668    opts->child[i].seed = opts->seed;
     
    968919
    969920    return "";
    970 }
    971 #endif
    972 
    973 static int run_process(struct opts *opts, int pipes[][2])
    974 {
    975     char buf[64];
    976 #if defined HAVE_FORK
    977     static int const files[] = { DEBUG_FILENO, STDERR_FILENO, STDOUT_FILENO };
    978     char *libpath, *tmp;
    979     int pid, j, len = strlen(opts->oldargv[0]);
    980 #   if defined __APPLE__
    981 #       define EXTRAINFO ""
    982 #       define PRELOAD "DYLD_INSERT_LIBRARIES"
    983     setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1);
    984 #   elif defined __osf__
    985 #       define EXTRAINFO ":DEFAULT"
    986 #       define PRELOAD "_RLD_LIST"
    987 #   else
    988 #       define EXTRAINFO ""
    989 #       define PRELOAD "LD_PRELOAD"
    990 #   endif
    991 #elif HAVE_WINDOWS_H
    992     PROCESS_INFORMATION pinfo;
    993     STARTUPINFO sinfo;
    994     HANDLE pid;
    995     void *epaddr;
    996     int ret;
    997 #endif
    998 
    999 #if defined HAVE_FORK
    1000     /* Fork and launch child */
    1001     pid = fork();
    1002     if(pid < -1)
    1003         perror("fork");
    1004     if(pid != 0)
    1005         return pid;
    1006 
    1007     /* We loop in reverse order so that files[0] is done last,
    1008      * just in case one of the other dup2()ed fds had the value */
    1009     for(j = 3; j--; )
    1010     {
    1011         close(pipes[j][0]);
    1012         if(pipes[j][1] != files[j])
    1013         {
    1014             dup2(pipes[j][1], files[j]);
    1015             close(pipes[j][1]);
    1016         }
    1017     }
    1018 #endif
    1019 
    1020 #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
    1021     if(opts->maxmem >= 0)
    1022     {
    1023         struct rlimit rlim;
    1024         rlim.rlim_cur = opts->maxmem * 1000000;
    1025         rlim.rlim_max = opts->maxmem * 1000000;
    1026         setrlimit(ZZUF_RLIMIT_MEM, &rlim);
    1027     }
    1028 #endif
    1029 
    1030 #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_CPU
    1031     if(opts->maxcpu >= 0)
    1032     {
    1033         struct rlimit rlim;
    1034         rlim.rlim_cur = opts->maxcpu;
    1035         rlim.rlim_max = opts->maxcpu + 5;
    1036         setrlimit(ZZUF_RLIMIT_CPU, &rlim);
    1037     }
    1038 #endif
    1039 
    1040     /* Set environment variables */
    1041     sprintf(buf, "%i", opts->seed);
    1042     setenv("ZZUF_SEED", buf, 1);
    1043     sprintf(buf, "%g", opts->minratio);
    1044     setenv("ZZUF_MINRATIO", buf, 1);
    1045     sprintf(buf, "%g", opts->maxratio);
    1046     setenv("ZZUF_MAXRATIO", buf, 1);
    1047 
    1048 #if defined HAVE_FORK
    1049     /* Make sure there is space for everything we might do. */
    1050     libpath = malloc(len + strlen(LIBDIR "/" LT_OBJDIR SONAME EXTRAINFO) + 1);
    1051     strcpy(libpath, opts->oldargv[0]);
    1052 
    1053     /* If the binary name contains a '/', we look for a libzzuf in the
    1054      * same directory. Otherwise, we only look into the system directory
    1055      * to avoid shared library attacks. Write the result in libpath. */
    1056     tmp = strrchr(libpath, '/');
    1057     if(tmp)
    1058     {
    1059         strcpy(tmp + 1, LT_OBJDIR SONAME);
    1060         if(access(libpath, R_OK) < 0)
    1061             strcpy(libpath, LIBDIR "/" SONAME);
    1062     }
    1063     else
    1064         strcpy(libpath, LIBDIR "/" SONAME);
    1065 
    1066     /* OSF1 only */
    1067     strcat(libpath, EXTRAINFO);
    1068 
    1069     /* Do not clobber previous LD_PRELOAD values */
    1070     tmp = getenv(PRELOAD);
    1071     if(tmp && *tmp)
    1072     {
    1073         char *bigbuf = malloc(strlen(tmp) + strlen(libpath) + 2);
    1074         sprintf(bigbuf, "%s:%s", tmp, libpath);
    1075         free(libpath);
    1076         libpath = bigbuf;
    1077     }
    1078 
    1079     setenv(PRELOAD, libpath, 1);
    1080     free(libpath);
    1081 
    1082     if(execvp(opts->newargv[0], opts->newargv))
    1083     {
    1084         perror(opts->newargv[0]);
    1085         exit(EXIT_FAILURE);
    1086     }
    1087 
    1088     exit(EXIT_SUCCESS);
    1089     /* no return */
    1090     return 0;
    1091 #elif HAVE_WINDOWS_H
    1092     pid = GetCurrentProcess();
    1093 
    1094     memset(&sinfo, 0, sizeof(sinfo));
    1095     sinfo.cb = sizeof(sinfo);
    1096     DuplicateHandle(pid, (HANDLE)_get_osfhandle(pipes[0][1]), pid,
    1097         /* FIXME */ &sinfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
    1098     DuplicateHandle(pid, (HANDLE)_get_osfhandle(pipes[1][1]), pid,
    1099                     &sinfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);
    1100     DuplicateHandle(pid, (HANDLE)_get_osfhandle(pipes[2][1]), pid,
    1101                     &sinfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
    1102     sinfo.dwFlags = STARTF_USESTDHANDLES;
    1103     ret = CreateProcess(NULL, opts->newargv[0], NULL, NULL, FALSE,
    1104                         CREATE_SUSPENDED, NULL, NULL, &sinfo, &pinfo);
    1105     if(!ret)
    1106         return -1;
    1107 
    1108     /* Get the child process's entry point address */
    1109     epaddr = (void *)(get_base_address(pinfo.dwProcessId)
    1110                        + get_entry_point_offset(opts->newargv[0]));
    1111     if(!epaddr)
    1112         return -1;
    1113 
    1114     /* Insert the replacement code */
    1115     ret = dll_inject(pinfo.hProcess, epaddr);
    1116     if(ret < 0)
    1117     {
    1118         TerminateProcess(pinfo.hProcess, -1);
    1119         return -1;
    1120     }
    1121 
    1122     ret = ResumeThread(pinfo.hThread);
    1123     if(ret < 0)
    1124     {
    1125         TerminateProcess(pinfo.hProcess, -1);
    1126         return -1;
    1127     }
    1128 
    1129     return (long int)pinfo.hProcess;
    1130 #endif
    1131 }
    1132 
    1133 #if defined HAVE_WINDOWS_H
    1134 static int dll_inject(void *process, void *epaddr)
    1135 {
    1136     uint8_t code1[] =                  /* LIBZZUF: */
    1137                       "libzzuf.dll\0"
    1138                                        /* OLDEP: */
    1139                       "_______"
    1140                                        /* START: */
    1141                       "\xb8____"       /* mov eax,<libzzuf.dll> */
    1142                       "\x50"           /* push eax */
    1143                       "\xb8____"       /* mov eax,<LoadLibraryA> */
    1144                       "\xff\xd0"       /* call eax */
    1145                       "\xb8\0\0\0\0"   /* mov eax,0 */
    1146                       "\x50"           /* push eax */
    1147                       "\xb8\x07\0\0\0" /* mov eax,7 */
    1148                       "\x50"           /* push eax */
    1149                       "\xb8____"       /* mov eax,<OLDEP> */
    1150                       "\x50"           /* push eax */
    1151                       "\xb8____"       /* mov eax,<NEWEP> */
    1152                       "\x50"           /* push eax */
    1153                       "\xb8____"       /* mov eax,<GetCurrentProcess> */
    1154                       "\xff\xd0"       /* call eax */
    1155                       "\x50"           /* push eax */
    1156                       "\xb8____"       /* mov eax,<WriteProcessMemory> */
    1157                       "\xff\xd0"       /* call eax */
    1158                       "\xb8____"       /* mov eax,<NEWEP> */
    1159                       "\xff\xe0";      /* jmp eax */
    1160     uint8_t code2[] =                  /* NEWEP: */
    1161                       "\xb8____"       /* mov eax,<START> */
    1162                       "\xff\xe0";      /* jmp eax */
    1163     void *lib;
    1164     uint8_t *loaderaddr;
    1165     DWORD tmp;
    1166 
    1167     /* Backup the old entry-point code */
    1168     ReadProcessMemory(process, epaddr, code1 + 0x0c, 7, &tmp);
    1169     if(tmp != 7)
    1170         return -1;
    1171 
    1172     /* Copy the first shell code to a freshly allocated memory area. */
    1173     loaderaddr = VirtualAllocEx(process, NULL, sizeof(code1), MEM_COMMIT,
    1174                                 PAGE_EXECUTE_READWRITE);
    1175     if(!loaderaddr)
    1176         return -1;
    1177 
    1178     lib = LoadLibrary("kernel32.dll");
    1179     if(!lib)
    1180         return -1;
    1181 
    1182     addcpy(code1 + 0x14, loaderaddr + 0x00); /* offset for dll string */
    1183     addcpy(code1 + 0x1a, GetProcAddress(lib, "LoadLibraryA"));
    1184     addcpy(code1 + 0x2d, loaderaddr + 0x0c);
    1185     addcpy(code1 + 0x33, epaddr);
    1186     addcpy(code1 + 0x39, GetProcAddress(lib, "GetCurrentProcess"));
    1187     addcpy(code1 + 0x41, GetProcAddress(lib, "WriteProcessMemory"));
    1188     addcpy(code1 + 0x48, epaddr);
    1189     FreeLibrary(lib);
    1190 
    1191     WriteProcessMemory(process, loaderaddr, code1, sizeof(code1), &tmp);
    1192     if(tmp != sizeof(code1))
    1193         return -1;
    1194 
    1195     /* Copy the second shell code where the old entry point was. */
    1196     addcpy(code2 + 0x01, loaderaddr + 12 + 7);
    1197     WriteProcessMemory(process, epaddr, code2, 7, &tmp);
    1198     if(tmp != 7)
    1199         return -1;
    1200 
    1201     return 0;
    1202 }
    1203 
    1204 /* Find the process's base address once it is loaded in memory (the header
    1205  * information is unreliable because of Vista's ASLR). */
    1206 static intptr_t get_base_address(DWORD pid)
    1207 {
    1208     MODULEENTRY32 entry;
    1209     intptr_t ret = 0;
    1210     void *list;
    1211     int k;
    1212 
    1213     list = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    1214     entry.dwSize = sizeof(entry);
    1215     for(k = Module32First(list, &entry); k; k = Module32Next(list, &entry))
    1216     {
    1217         /* FIXME: how do we select the correct module? */
    1218         ret = (intptr_t)entry.modBaseAddr;
    1219     }
    1220     CloseHandle(list);
    1221 
    1222     return ret;
    1223 }
    1224 
    1225 /* Find the process's entry point address offset. The information is in
    1226  * the file's PE header. */
    1227 static intptr_t get_entry_point_offset(char const *name)
    1228 {
    1229     PIMAGE_DOS_HEADER dos;
    1230     PIMAGE_NT_HEADERS nt;
    1231     intptr_t ret = 0;
    1232     void *file, *map, *base;
    1233 
    1234     file = CreateFile(name, GENERIC_READ, FILE_SHARE_READ,
    1235                       NULL, OPEN_EXISTING, 0, NULL);
    1236     if(file == INVALID_HANDLE_VALUE)
    1237         return ret;
    1238 
    1239     map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
    1240     if(!map)
    1241     {
    1242         CloseHandle(file);
    1243         return ret;
    1244     }
    1245 
    1246     base = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
    1247     if(!base)
    1248     {
    1249         CloseHandle(map);
    1250         CloseHandle(file);
    1251         return ret;
    1252     }
    1253 
    1254     /* Sanity checks */
    1255     dos = (PIMAGE_DOS_HEADER)base;
    1256     nt = (PIMAGE_NT_HEADERS)((char *)base + dos->e_lfanew);
    1257     if(dos->e_magic == IMAGE_DOS_SIGNATURE /* 0x5A4D */
    1258       && nt->Signature == IMAGE_NT_SIGNATURE /* 0x00004550 */
    1259       && nt->FileHeader.Machine == IMAGE_FILE_MACHINE_I386
    1260       && nt->OptionalHeader.Magic == 0x10b /* IMAGE_NT_OPTIONAL_HDR32_MAGIC */)
    1261     {
    1262         ret = (intptr_t)nt->OptionalHeader.AddressOfEntryPoint;
    1263     }
    1264 
    1265     UnmapViewOfFile(base);
    1266     CloseHandle(map);
    1267     CloseHandle(file);
    1268 
    1269     return ret;
    1270921}
    1271922#endif
Note: See TracChangeset for help on using the changeset viewer.