static void init_user_stack(elf_prog_t *prog, int prot) { long argc = strings_count(prog->argv), envc = strings_count(prog->envp), auxc = auxv_count(prog->auxv); char *tmp_argv[argc+1], *tmp_envp[envc+1], *platform = (char *)get_aux(prog->auxv, AT_PLATFORM), *base_platform = (char *)get_aux(prog->auxv, AT_BASE_PLATFORM), *rand_bytes = (char *)get_aux(prog->auxv, AT_RANDOM); char *sp = (char *)(prog->task_size-get_stack_random_shift(prog->auxv)); sp -= sizeof(long); sp = prog->filename = stack_push_string(sp, prog->filename); char *untrusted_data_end=sp; sp = stack_push_strings(sp, tmp_envp, prog->envp); sp = stack_push_strings(sp, tmp_argv, prog->argv); taint_mem(sp, untrusted_data_end-sp, TAINT_ENV); sp = (char *)(((long)sp-0x100)&~0xf); if (platform) sp = platform = stack_push_string(sp, platform); if (base_platform) sp = base_platform = stack_push_string(sp, base_platform); if (rand_bytes) sp = rand_bytes = stack_push_data(sp, rand_bytes, 16); sp = (char *)((long)sp&~0xf); sp = stack_push_data(sp, prog->auxv, (auxc+1)*2*sizeof(long)); prog->auxv = (long *)sp; sp = stack_push_data(sp, tmp_envp, (envc+1)*sizeof(char *)); prog->envp = (char **)sp; sp = stack_push_data(sp, tmp_argv, (argc+1)*sizeof(char *)); prog->argv = (char **)sp; sp = stack_push_data(sp, &argc, sizeof(long)); set_aux(prog->auxv, AT_EXECFN, (long)prog->filename); set_aux(prog->auxv, AT_PLATFORM, (long)platform); set_aux(prog->auxv, AT_BASE_PLATFORM, (long)base_platform); set_aux(prog->auxv, AT_RANDOM, (long)rand_bytes); set_aux(prog->auxv, AT_PHDR, (long)prog->bin.phdr); set_aux(prog->auxv, AT_PHNUM, prog->bin.hdr.e_phnum); set_aux(prog->auxv, AT_BASE, prog->bin.base); set_aux(prog->auxv, AT_ENTRY, prog->bin.base + prog->bin.hdr.e_entry); prog->sp = (long *)sp; }
/* Return hook (executed after the return instruction) */ static int getsockname_ret(void *opaque) { static int offset = 0; int read_err = 0; uint32_t bufRealLen = 0; getsockname_t *s = (getsockname_t *)opaque; struct sockaddr_in addrData; char addrStr[INET_ADDRSTRLEN]; /* Remove return hook */ hookapi_remove_hook(s->hook_handle); /* Check return value -> status */ uint32_t eax = 0; read_reg(eax_reg, &eax); if (eax != 0) return 0; /* Read size of address structure */ read_err = read_mem(s->bufLenPtr, 4, (unsigned char*)&bufRealLen); if (!read_err) { WRITE ("tracenetlog","\tNumBytesWritten: %u\n",bufRealLen); } else { WRITE ("tracenetlog","\tCould not get number of bytes written\n"); return 0; } /* Read the address structure */ read_err = read_mem(s->bufStart, 16, (unsigned char*)&addrData); if (read_err) return 0; /* Print the address structure */ inet_ntop(AF_INET, &addrData.sin_addr, addrStr, sizeof(addrStr)); WRITE ("tracenetlog","\tFamily: %d Port: %u Address: %s\n", addrData.sin_family,ntohs(addrData.sin_port),addrStr); /* Taint address structure */ if (bufRealLen > 0) { hook_taint_record_t tr; tr.source = TAINT_SOURCE_API_SOCK_INFO_IN; tr.origin = GETSOCKNAME_ORIGIN; tr.offset = offset; taint_mem(s->bufStart+2, 6, (void *)&tr); } /* Increment the taint offset */ offset += 6; /* Free structure used to pass info between call and return hooks */ if (s) free(s); return 0; }
static void taint_iov(struct iovec *iov, int iocnt, unsigned long size, int type) { unsigned long v_size; while (size > 0) { v_size = iov->iov_len; if (v_size > size) v_size = size; size -= v_size; taint_mem(iov->iov_base, v_size, type); iov++; } }
void do_taint(long ret, long call, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { if (ret < 0) return; switch (call) { case __NR_read: taint_mem((char *)arg2, ret, taint_val(arg1)); return; case __NR_readv: taint_iov( (struct iovec *)arg2, arg3, ret, taint_val(arg1)); return; case __NR_open: case __NR_creat: case __NR_openat: set_fd(ret, FD_FILE); if (strcmp((char *)(call == __NR_openat ? arg2 : arg1), "/proc/self/stat") == 0) { taint_val(ret); fake_proc_self_stat(ret); } return; case __NR_dup: case __NR_dup2: set_fd( ret, get_thread_ctx()->files->fd_type[arg1]); return; case __NR_pipe: set_fd( ((long *)arg1)[0], FD_SOCKET); set_fd( ((long *)arg1)[1], FD_SOCKET); return; case __NR_socketcall: { long *sockargs = (long *)arg2; switch (arg1) { case SYS_GETPEERNAME: if ( (ret >= 0) && sockargs[1] && sockargs[2]) taint_mem((char *)sockargs[1], *(long *)sockargs[2], TAINT_SOCKADDR); return; case SYS_ACCEPT: if ( (ret >= 0) && sockargs[1] && sockargs[2]) taint_mem((char *)sockargs[1], *(long *)sockargs[2], TAINT_SOCKADDR); case SYS_SOCKET: set_fd(ret, FD_SOCKET); return; case SYS_RECV: case SYS_RECVFROM: taint_mem((char *)sockargs[1], ret, TAINT_SOCKET); return; case SYS_RECVMSG: { struct msghdr *msg = (struct msghdr *)sockargs[1]; taint_iov( msg->msg_iov, msg->msg_iovlen, ret, TAINT_SOCKET ); return; } default: return; } } default: return; } }