/* * search an offset and fill the filter_op structure * return ESUCCESS on error. */ int encode_offset(char *string, struct filter_op *fop) { char *str, *p, *q, *tok; int ret; memset(fop, 0, sizeof(struct filter_op)); /* make the modifications on a copy */ str = strdup(string); /* * the offset contains at least one '.' * we are sure because the syntax parser * will not have passed it here if it is not * in the right form. */ p = ec_strtok(str, ".", &tok); q = ec_strtok(NULL, ".", &tok); /* * the assumption above is not always true, e.g.: * log(DATA,d "x.log"); * results in q == NULL. */ if (q == NULL) return -ENOTFOUND; /* the the virtual pointer from the table */ ret = get_virtualpointer(p, q, &fop->op.test.level, &fop->op.test.offset, &fop->op.test.size); SAFE_FREE(str); return ret; }
/* * update a single file. * parse the "tokens" and check the version * if the version is newer, update it from the website */ static void update_file(char *tokens) { char *file = NULL; char *rev = NULL; char *curr = NULL; char *url = NULL; size_t i, n = 0; char *tok; char errbuf[ERR_MAX_LEN]; DEBUG_MSG("update_file"); /* count the number of tokens delimited by ' ' */ for (i = 0; i < strlen(tokens); i++) if (tokens[i] == ' ') n++; /* the token is invalid */ if (n != 2) return; /* split the tokens */ file = strdup(ec_strtok(tokens, " ", &tok)); rev = strdup(ec_strtok(NULL, " ", &tok)); url = strdup(ec_strtok(NULL, " ", &tok)); /* get the current revision */ if (get_current_rev(file, &curr, errbuf) == 0) { fprintf(stdout, " + %-18s -> "EC_COLOR_RED"ERROR"EC_COLOR_END" %s\n", file, errbuf); } else { fprintf(stdout, " + %-18s -> revision "EC_COLOR_BLUE"%-4s"EC_COLOR_END" updating to "EC_COLOR_CYAN"%-4s"EC_COLOR_END"... ", file, curr, rev ); fflush(stdout); /* update it if the current rev is different (newer) */ if (!strcmp(curr, rev)) fprintf(stdout, EC_COLOR_GREEN"OK"EC_COLOR_END"\n"); else if (strcmp(curr, rev) < 0) { if (GBL_OPTIONS->silent) fprintf(stdout, EC_COLOR_YELLOW"NEED UPDATE"EC_COLOR_END"\n"); else { if (do_update(file, url, errbuf)) fprintf(stdout, EC_COLOR_YELLOW"UPDATED"EC_COLOR_END"\n"); else fprintf(stdout, EC_COLOR_RED"ERROR"EC_COLOR_END" %s\n", errbuf); } } else fprintf(stdout, EC_COLOR_RED"NEWER"EC_COLOR_END" %s\n", errbuf); } SAFE_FREE(curr); SAFE_FREE(file); SAFE_FREE(rev); SAFE_FREE(url); }
/* * parse a function and its arguments and fill the structure */ int encode_function(char *string, struct filter_op *fop) { char *str = strdup(string); int ret = -ENOTFOUND; char *name, *args; int nargs = 0, i; char **dec_args = NULL; char *tok; memset(fop, 0, sizeof(struct filter_op)); /* get the name of the function */ name = ec_strtok(string, "(", &tok); /* get all the args */ args = name + strlen(name) + 1; /* analyze the arguments */ dec_args = decode_args(args, &nargs); /* this fop is a function */ fop->opcode = FOP_FUNC; /* check if it is a known function */ if (!strcmp(name, "search")) { if (nargs == 2) { /* get the level (DATA or DECODED) */ if (encode_offset(dec_args[0], fop) == ESUCCESS) { /* encode offset wipe the fop !! */ fop->opcode = FOP_FUNC; fop->op.func.op = FFUNC_SEARCH; fop->op.func.string = (u_char*)strdup(dec_args[1]); fop->op.func.slen = strescape((char*)fop->op.func.string, (char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Unknown offset %s ", dec_args[0]); } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "regex")) { if (nargs == 2) { int err; regex_t regex; char errbuf[100]; /* get the level (DATA or DECODED) */ if (encode_offset(dec_args[0], fop) == ESUCCESS) { /* encode offset wipe the fop !! */ fop->opcode = FOP_FUNC; fop->op.func.op = FFUNC_REGEX; fop->op.func.string = (u_char*)strdup(dec_args[1]); fop->op.func.slen = strescape((char*)fop->op.func.string, (char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Unknown offset %s ", dec_args[0]); /* check if the regex is valid */ err = regcomp(®ex, (const char*)fop->op.func.string, REG_EXTENDED | REG_NOSUB | REG_ICASE ); if (err) { regerror(err, ®ex, errbuf, sizeof(errbuf)); SCRIPT_ERROR("%s", errbuf); } regfree(®ex); } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "pcre_regex")) { #ifndef HAVE_PCRE WARNING("The script contains pcre_regex, but you don't have support for it."); #else pcre *pregex; const char *errbuf = NULL; int erroff; if (nargs == 2) { /* get the level (DATA or DECODED) */ if (encode_offset(dec_args[0], fop) == ESUCCESS) { /* encode offset wipe the fop !! */ fop->opcode = FOP_FUNC; fop->op.func.op = FFUNC_PCRE; fop->op.func.string = strdup(dec_args[1]); fop->op.func.slen = strlen(fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Unknown offset %s ", dec_args[0]); /* check if the pcre is valid */ pregex = pcre_compile(fop->op.func.string, 0, &errbuf, &erroff, NULL ); if (pregex == NULL) SCRIPT_ERROR("%s\n", errbuf); pcre_free(pregex); } else if (nargs == 3) { fop->opcode = FOP_FUNC; fop->op.func.op = FFUNC_PCRE; /* substitution always at layer DATA */ fop->op.func.level = 5; fop->op.func.string = strdup(dec_args[1]); fop->op.func.slen = strlen(fop->op.func.string); fop->op.func.replace = strdup(dec_args[2]); fop->op.func.rlen = strlen(fop->op.func.replace); ret = ESUCCESS; /* check if the pcre is valid */ pregex = pcre_compile(fop->op.func.string, 0, &errbuf, &erroff, NULL ); if (pregex == NULL) SCRIPT_ERROR("%s\n", errbuf); pcre_free(pregex); } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); #endif } else if (!strcmp(name, "replace")) { if (nargs == 2) { fop->op.func.op = FFUNC_REPLACE; /* replace always operate at DATA level */ fop->op.func.level = 5; fop->op.func.string = (u_char*)strdup(dec_args[0]); fop->op.func.slen = strescape((char*)fop->op.func.string, (char*)fop->op.func.string); fop->op.func.replace = (u_char*)strdup(dec_args[1]); fop->op.func.rlen = strescape((char*)fop->op.func.replace, (char*)fop->op.func.replace); ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "inject")) { if (nargs == 1) { fop->op.func.op = FFUNC_INJECT; /* inject always operate at DATA level */ fop->op.func.level = 5; fop->op.func.string = (u_char*)strdup(dec_args[0]); fop->op.func.slen = strlen((const char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "execinject")) { if (nargs == 1) { fop->op.func.op = FFUNC_EXECINJECT; /* execinject always operate at DATA level */ fop->op.func.level = 5; fop->op.func.string = (u_char*)strdup(dec_args[0]); fop->op.func.slen = strlen((const char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "log")) { if (nargs == 2) { /* get the level (DATA or DECODED) */ if (encode_offset(dec_args[0], fop) == ESUCCESS) { /* encode offset wipe the fop !! */ fop->opcode = FOP_FUNC; fop->op.func.op = FFUNC_LOG; fop->op.func.string = (u_char*)strdup(dec_args[1]); fop->op.func.slen = strlen((const char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Unknown offset %s ", dec_args[0]); } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "drop")) { if (nargs == 0) { fop->op.func.op = FFUNC_DROP; ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "kill")) { if (nargs == 0) { fop->op.func.op = FFUNC_KILL; ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "msg")) { if (nargs == 1) { fop->op.func.op = FFUNC_MSG; fop->op.func.string = (u_char*)strdup(dec_args[0]); fop->op.func.slen = strescape((char*)fop->op.func.string, (char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "exec")) { if (nargs == 1) { fop->op.func.op = FFUNC_EXEC; fop->op.func.string = (u_char*)strdup(dec_args[0]); fop->op.func.slen = strlen((const char*)fop->op.func.string); ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } else if (!strcmp(name, "exit")) { if (nargs == 0) { fop->opcode = FOP_EXIT; ret = ESUCCESS; } else SCRIPT_ERROR("Wrong number of arguments for function \"%s\" ", name); } /* free the array */ for (i = 0; i < nargs; i++) SAFE_FREE(dec_args[i]); SAFE_FREE(dec_args); SAFE_FREE(str); return ret; }
/* * parse the packet and send the fake reply */ static void remote_browser(struct packet_object *po) { char *tmp, *p, *q; char *url, *host; char *command; char **param = NULL; int i = 0, k = 0; /* the client is making a request */ if (po->DATA.disp_len != 0 && strstr((const char*)po->DATA.disp_data, "GET")) { /* I'm the sender, opening a browser with a request coming by me will trigger a loop in this function! */ if(ip_addr_is_ours(&po->L3.src) == E_FOUND || ip_addr_is_ours(&po->L3.src) == E_BRIDGE) return; /* I'm not the sender, I can safely open the browser, the GET triggered by it shouldn't cause bad effects */ tmp = strdup((const char*)po->DATA.disp_data); /* get the Host: directive */ host = strstr(tmp, "Host: "); if (host != NULL) { host = host + 6; // 6 is like strlen("Host: "); if ((p = strstr(host, "\r\n")) != NULL) *p = 0; } else goto bad; /* null terminate the request before the HTTP/x.x */ p = strstr(tmp, " HTTP"); if (p != NULL) *p = 0; else goto bad; /* get the requested url */ url = tmp + 4; // 4 is like strlen("GET "); /* parse only pages, not images or other amenities */ if (!good_page(url)) goto bad; /* fill the command */ command = strdup(GBL_CONF->remote_browser); str_replace(&command, "%host", host); str_replace(&command, "%url", url); USER_MSG("REMOTE COMMAND: %s\n", command); /* split the string in the parameter array */ for (p = ec_strtok(command, " ", &q); p != NULL; p = ec_strtok(NULL, " ", &q)) { /* allocate the array */ SAFE_REALLOC(param, (i + 1) * sizeof(char *)); /* copy the tokens in the array */ param[i++] = strdup(p); } /* NULL terminate the array */ SAFE_REALLOC(param, (i + 1) * sizeof(char *)); param[i] = NULL; /* execute the script */ if (fork() == 0) { /* chrome won't start as root, changing UID in order to prevent this and for more security in the browser context */ /* the following line has been commented since some Penetration Testing distros can run only as root */ /*setuid(1000);*/ u_int uid, gid; DEBUG_MSG("drop_privs: getuid(%d) \n", getuid()); /* are we root ? */ if (getuid() == 0) { gid = uid = 1000; DEBUG_MSG("drop_privs: setuid(%d) setgid(%d)\n", uid, gid); /* drop to a good uid/gid ;) */ if ( setgid(gid) < 0 ) DEBUG_MSG("setgid() FAILED\n"); if ( setuid(uid) < 0 ) DEBUG_MSG("setuid() FAILED\n"); DEBUG_MSG("privs: UID: %d %d GID: %d %d\n", (int)getuid(), (int)geteuid(), (int)getgid(), (int)getegid() ); DEBUG_MSG("Privileges dropped to UID %d GID %d...\n\n", (int)getuid(), (int)getgid() ); /* "nobody" cannot open a browser */ } else if(getuid() == 65535) WARN_MSG("your ec_gid and ec_uid in etter.conf file are set to nobody (65535), you probably cannot open a new browser\n"); execvp(param[0], param); WARN_MSG("Cannot launch the default browser (command: %s), please edit your etter.conf file and put a valid value in remote_browser field\n", GBL_CONF->remote_browser); _exit(-E_INVALID); } //to free the char **param for(k= 0; k < i; ++k) SAFE_FREE(param[k]); SAFE_FREE(param); SAFE_FREE(command); bad: SAFE_FREE(tmp); } }
/* * perform the update */ void global_update(void) { int sock; char *ptr; char *latest; char getmsg[512]; char buffer[8192]; int len; char *tok; char host[] = "ettercap.sourceforge.net"; // char host[] = "local.alor.org"; char page[] = "/updateNG.php"; DEBUG_MSG("global_update"); memset(buffer, 0, sizeof(buffer)); fprintf(stdout, "Connecting to http://%s\n", host); /* open the socket with the server */ if ((sock = open_socket(host, 80)) < 0) clean_exit(-1); fprintf(stdout, "Requesting %s\n\n", page); /* prepare the HTTP request */ snprintf(getmsg, sizeof(getmsg), "GET %s HTTP/1.0\r\n" "Host: %s\r\n" "User-Agent: %s (%s)\r\n" "\r\n", page, host, GBL_PROGRAM, GBL_VERSION ); /* send the request to the server */ socket_send(sock, getmsg, strlen(getmsg)); DEBUG_MSG("global_update - SEND \n\n%s\n\n", getmsg); /* get the server response */ len = socket_recv(sock, buffer, sizeof(buffer) - 1); if (len == 0) FATAL_ERROR(EC_COLOR_RED"ERROR"EC_COLOR_END" The server does not respond"); DEBUG_MSG("global_update - RECEIVE \n\n%s\n\n", buffer); close_socket(sock); /* skip the HTTP headers */ ptr = strstr(buffer, "\r\n\r\n"); if (ptr == NULL) FATAL_ERROR(EC_COLOR_RED"ERROR"EC_COLOR_END" Bad response from server"); ptr += 4; /* the first word MUST be "ettercap" */ if (strncmp(ptr, GBL_PROGRAM, strlen(GBL_PROGRAM))) FATAL_ERROR(EC_COLOR_RED"ERROR"EC_COLOR_END" Bad response from server"); ptr += strlen(GBL_PROGRAM) + 1; /* the first line in the response is the latest version */ latest = strdup(ec_strtok(ptr, "\n", &tok)); /* move the ptr after the first token */ ptr += strlen(latest) + 1; fprintf(stdout, " + %-18s -> version "EC_COLOR_BLUE"%-4s"EC_COLOR_END" latest is ", GBL_PROGRAM, GBL_VERSION); if (!strcmp(GBL_VERSION, latest)) fprintf(stdout, EC_COLOR_GREEN"%-4s"EC_COLOR_END"\n\n", latest ); else fprintf(stdout, EC_COLOR_YELLOW"%-4s"EC_COLOR_END"\n\n", latest ); SAFE_FREE(latest); /* update every entry in the response */ for(latest = strsep(&ptr, "\n"); latest != NULL; latest = strsep(&ptr, "\n")) { update_file(latest); } fprintf(stdout, "\n\n"); clean_exit(0); }