-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathoutput.c
More file actions
128 lines (113 loc) · 4.77 KB
/
output.c
File metadata and controls
128 lines (113 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "output.h"
/* ── internal state ───────────────────────────────────────────── */
static FILE *g_txt_fp = NULL;
static FILE *g_json_fp = NULL;
static pthread_mutex_t g_txt_mu = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_json_mu = PTHREAD_MUTEX_INITIALIZER;
static int g_first_json = 1;
/* ── timestamp helper ─────────────────────────────────────────── */
static void get_ts(char *buf, size_t sz) {
time_t now = time(NULL);
struct tm *t = localtime(&now);
strftime(buf, sz, "%Y-%m-%d %H:%M:%S", t);
}
/* ── JSON escape (minimal) ────────────────────────────────────── */
static void json_escape(const char *src, char *dst, size_t dsz) {
size_t j = 0;
for (size_t i = 0; src[i] && j + 6 < dsz; i++) {
unsigned char c = (unsigned char)src[i];
if (c == '"') { dst[j++]='\\'; dst[j++]='"'; }
else if (c == '\\') { dst[j++]='\\'; dst[j++]='\\'; }
else if (c == '\n') { dst[j++]='\\'; dst[j++]='n'; }
else if (c == '\r') { dst[j++]='\\'; dst[j++]='r'; }
else if (c == '\t') { dst[j++]='\\'; dst[j++]='t'; }
else if (c < 0x20) { j += snprintf(dst+j, dsz-j, "\\u%04x", c); }
else { dst[j++] = (char)c; }
}
dst[j] = '\0';
}
/* ══════════════════════════════════════════════════════════════ */
int output_init(const char *txt_path, const char *json_path) {
g_txt_fp = fopen(txt_path, "a");
if (!g_txt_fp) { perror(txt_path); return -1; }
g_json_fp = fopen(json_path, "w");
if (!g_json_fp) { perror(json_path); fclose(g_txt_fp); return -1; }
fprintf(g_json_fp, "[\n");
fflush(g_json_fp);
return 0;
}
void output_write(const exploit_result_t *r) {
char ts[32];
get_ts(ts, sizeof(ts));
/* ── TXT ────────────────────────────────────────────────── */
pthread_mutex_lock(&g_txt_mu);
if (g_txt_fp) {
fprintf(g_txt_fp,
"%s | %s:%s | %-12s | %-20s | %s | %s | HTTP %d | %ldms\n",
ts,
r->ip_str, r->port_str,
r->device, r->cve,
r->method,
r->verified ? "VERIFIED" : "UNVERIFIED",
r->status_code,
r->time_ms);
fflush(g_txt_fp);
}
pthread_mutex_unlock(&g_txt_mu);
/* ── JSON ───────────────────────────────────────────────── */
char e_ip[64], e_dev[64], e_cve[64],
e_meth[128], e_pld[1024], e_resp[512];
json_escape(r->ip_str, e_ip, sizeof(e_ip));
json_escape(r->device, e_dev, sizeof(e_dev));
json_escape(r->cve, e_cve, sizeof(e_cve));
json_escape(r->method, e_meth, sizeof(e_meth));
json_escape(r->payload, e_pld, sizeof(e_pld));
json_escape(r->response_preview, e_resp, sizeof(e_resp));
pthread_mutex_lock(&g_json_mu);
if (g_json_fp) {
if (!g_first_json) fprintf(g_json_fp, ",\n");
g_first_json = 0;
fprintf(g_json_fp,
" {\n"
" \"timestamp\": \"%s\",\n"
" \"ip\": \"%s\",\n"
" \"port\": \"%s\",\n"
" \"device\": \"%s\",\n"
" \"cve\": \"%s\",\n"
" \"method\": \"%s\",\n"
" \"payload\": \"%s\",\n"
" \"status_code\": %d,\n"
" \"success\": %s,\n"
" \"verified\": %s,\n"
" \"is_honeypot\": %s,\n"
" \"time_ms\": %ld,\n"
" \"response_preview\": \"%s\"\n"
" }",
ts,
e_ip, r->port_str,
e_dev, e_cve, e_meth, e_pld,
r->status_code,
r->success ? "true" : "false",
r->verified ? "true" : "false",
r->is_honeypot? "true" : "false",
r->time_ms,
e_resp);
fflush(g_json_fp);
}
pthread_mutex_unlock(&g_json_mu);
}
void output_finish(void) {
pthread_mutex_lock(&g_json_mu);
if (g_json_fp) {
fprintf(g_json_fp, "\n]\n");
fclose(g_json_fp);
g_json_fp = NULL;
}
pthread_mutex_unlock(&g_json_mu);
pthread_mutex_lock(&g_txt_mu);
if (g_txt_fp) {
fclose(g_txt_fp);
g_txt_fp = NULL;
}
pthread_mutex_unlock(&g_txt_mu);
}