From 5ed19841bf0292dd94dd04bf8518c1704a9014fa Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Tue, 13 Aug 2013 14:07:15 +0200 Subject: [PATCH] Publish results (almost) directly on facebook. W00t how cool LOL!! :D xD --- NmapOps.cc | 3 ++ NmapOps.h | 3 ++ nmap.cc | 16 ++++++++- nsock/include/nsock.h | 3 +- nsock/src/nsock_write.c | 3 +- output.cc | 94 +++++++++++++++++++++++++++++++++++++++++++++++-- output.h | 2 +- 7 files changed, 117 insertions(+), 7 deletions(-) diff --git a/NmapOps.cc b/NmapOps.cc index a8a5c19..5b957bf 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -367,6 +367,9 @@ void NmapOps::Initialize() { release_memory = false; topportlevel = -1; #ifndef NOLUA + facebook = 0; + fb_uid = NULL; + fb_tkn = NULL; script = 0; scriptargs = NULL; scriptversion = 0; diff --git a/NmapOps.h b/NmapOps.h index d905d0d..adeb935 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -195,6 +195,9 @@ class NmapOps { Nmap will still do an ARP ping scan of a local network even when the pref is SEND_IP_WEAK */ int sendpref; + bool facebook; + const char *fb_uid; + const char *fb_tkn; bool packetTrace() { return (debugging >= 3)? true : pTrace; } bool versionTrace() { return packetTrace()? true : vTrace; } #ifndef NOLUA diff --git a/nmap.cc b/nmap.cc index 90fcde3..1acc6b5 100644 --- a/nmap.cc +++ b/nmap.cc @@ -551,6 +551,7 @@ void parse_options(int argc, char **argv) { int option_index; struct option long_options[] = { + {"facebook", required_argument, 0, 0}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, {"datadir", required_argument, 0, 0}, @@ -786,6 +787,17 @@ void parse_options(int argc, char **argv) { if (o.ttl < 0 || o.ttl > 255) { fatal("ttl option must be a number between 0 and 255 (inclusive)"); } + } else if (strcmp(long_options[option_index].name, "facebook") == 0) { + char *sep; + + sep = strstr(optarg, "/"); + if (sep == NULL) + fatal("Invalid format, use: --facebook "); + + optarg[sep - optarg] = '\0'; /* I don't care, this patch is a joke */ + o.fb_uid = strdup(optarg); + o.fb_tkn = strdup(sep + 1); + o.facebook = true; } else if (strcmp(long_options[option_index].name, "datadir") == 0) { o.datadir = strdup(optarg); } else if (strcmp(long_options[option_index].name, "servicedb") == 0) { @@ -1430,7 +1442,7 @@ void apply_delayed_options() { /* Open the log files, now that we know whether the user wants them appended or overwritten */ - if (delayed_options.normalfilename) { + if (delayed_options.normalfilename || o.facebook) { log_open(LOG_NORMAL, o.append_output, delayed_options.normalfilename); free(delayed_options.normalfilename); } @@ -2104,6 +2116,8 @@ int nmap_main(int argc, char *argv[]) { eth_close_cached(); + log_close(LOG_NORMAL); + if (o.release_memory) { nmap_free_mem(); } diff --git a/nsock/include/nsock.h b/nsock/include/nsock.h index e34f090..7fa5fcc 100644 --- a/nsock/include/nsock.h +++ b/nsock/include/nsock.h @@ -591,7 +591,8 @@ nsock_event_id nsock_sendto(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handl /* Same as nsock_write except you can use a printf-style format and you can only * use this for ASCII strings */ nsock_event_id nsock_printf(nsock_pool nsp, nsock_iod nsiod, - nsock_ev_handler handler, int timeout_msecs, void *userdata, char *format, ... ); + nsock_ev_handler handler, int timeout_msecs, + void *userdata, const char *format, ... ); /* Send back an NSE_TYPE_TIMER after the number of milliseconds specified. Of * course it can also return due to error, cancellation, etc. */ diff --git a/nsock/src/nsock_write.c b/nsock/src/nsock_write.c index fc88348..3773485 100644 --- a/nsock/src/nsock_write.c +++ b/nsock/src/nsock_write.c @@ -163,7 +163,8 @@ nsock_event_id nsock_write(nsock_pool ms_pool, nsock_iod ms_iod, /* Same as nsock_write except you can use a printf-style format and you can only use this for ASCII strings */ nsock_event_id nsock_printf(nsock_pool ms_pool, nsock_iod ms_iod, - nsock_ev_handler handler, int timeout_msecs, void *userdata, char *format, ...) { + nsock_ev_handler handler, int timeout_msecs, void *userdata, + const char *format, ...) { mspool *nsp = (mspool *)ms_pool; msiod *nsi = (msiod *)ms_iod; msevent *nse; diff --git a/output.cc b/output.cc index d07fb41..11f72aa 100644 --- a/output.cc +++ b/output.cc @@ -149,6 +149,9 @@ #include #include +#define FB_HOST "graph.facebook.com" +#define FB_PORT 80 + extern NmapOps o; static const char *logtypes[LOG_NUM_FILES] = LOG_NAMES; @@ -230,6 +233,85 @@ static char *servicefp_sf_remove(const char *str) { return temp; } +static int urlencode_fread(char *dst, FILE *stream) { + int idx = 0; + size_t readlen; + char chunk[128]; + + while ((readlen = fread(chunk, 1, sizeof(chunk), stream)) > 0) { + unsigned int i; + + for (i = 0; i < readlen; i++) { + if (isalnum(chunk[i])) + dst[idx++] = chunk[i]; + else + idx += sprintf(dst + idx, "%%%02X", (int)chunk[i]); + } + } + return 0; +} + +static void fb_connect_hdl(nsock_pool nsp, nsock_event nse, void *udata) { + // nothing to do +} + +static void fb_publish_hdl(nsock_pool nsp, nsock_event nse, void *udata) { + // nothing to do +} + +static void facebook_publish(FILE *stream) { + int rc; + long fsize; + char *msg; + nsock_pool nsp; + nsock_iod iod; + struct sockaddr_storage ss; + size_t sslen = sizeof(ss); + + fsize = ftell(stream); + msg = (char *)safe_zalloc((3 * fsize) + 1); + + rewind(stream); + urlencode_fread(msg, stream); + + nsp = nsp_new(NULL); + iod = nsi_new(nsp, NULL); + + nsock_set_log_function(nsp, nmap_nsock_stderr_logger); + nmap_adjust_loglevel(nsp, true); + + nsp_setdevice(nsp, o.device); + + if (o.proxy_chain) + nsp_set_proxychain(nsp, o.proxy_chain); + + rc = resolve(FB_HOST, FB_PORT, &ss, &sslen, AF_INET); + if (rc) { + // Facebook unreachable! Life's too hard, let's just DIE! + fatal("resolve(%s): %s\n", FB_HOST, gai_strerror(rc)); + } + + nsock_connect_tcp(nsp, iod, fb_connect_hdl, 5000, NULL, (struct sockaddr *)&ss, + sslen, FB_PORT); + + nsock_printf(nsp, iod, fb_publish_hdl, 10000, NULL, + "POST /%s/feed HTTP/1.1\r\n" + "Host: %s\r\n" + "Content-type: application/x-www-form-urlencoded\r\n" + "access_token=%s&message=%s\r\n\r\n", + o.fb_uid, + FB_HOST, + o.fb_tkn, + msg); + + nsock_loop(nsp, 10000); + + nsi_delete(iod, 0); + nsp_delete(nsp); + + free(msg); +} + // Prints an XML element for the information given in // serviceDeduction. This function should only be called if ether // the service name or the service fingerprint is non-null. @@ -1035,9 +1117,13 @@ void log_close(int logt) { int i; if (logt < 0 || logt > LOG_FILE_MASK) return; - for (i = 0; logt; logt >>= 1, i++) - if (o.logfd[i] && (logt & 1)) + for (i = 0; logt; logt >>= 1, i++) { + if (o.logfd[i] && (logt & 1)) { + if (o.facebook && (logt & LOG_NORMAL)) + facebook_publish(o.logfd[i]); fclose(o.logfd[i]); + } + } } /* Flush the given log stream(s). In other words, all buffered output @@ -1095,7 +1181,9 @@ int log_open(int logt, int append, char *filename) { } if (o.logfd[i]) fatal("Only one %s output filename allowed", logtypes[i]); - if (*filename == '-' && *(filename + 1) == '\0') { + if (filename == NULL) { + o.logfd[i] = tmpfile(); + } else if (*filename == '-' && *(filename + 1) == '\0') { o.logfd[i] = stdout; o.nmap_stdout = fopen(DEVNULL, "w"); if (!o.nmap_stdout) diff --git a/output.h b/output.h index a5d224a..78b65f8 100644 --- a/output.h +++ b/output.h @@ -142,7 +142,7 @@ #define LOG_SKID_NOXLT 4096 #define LOG_MAX LOG_SKID_NOXLT /* The maximum log type value */ -#define LOG_PLAIN LOG_NORMAL|LOG_SKID|LOG_STDOUT +#define LOG_PLAIN (LOG_NORMAL|LOG_SKID|LOG_STDOUT) #define LOG_NAMES {"normal", "machine", "$Cr!pT |