#!/bin/bash

bashacks_config="$HOME/.config/bashacks"
bashacks_cachedir="$bashacks_config/cache"
bashacks_os=$(uname -s)
bashacks_wget_user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"

if [[ $bashacks_os = 'Darwin' ]]; then
	alias bh_cmd_md5='md5 -r'
	alias bh_cmd_sha1='shasum'
	alias bh_cmd_sha256='shasum -a256'
	alias bh_cmd_sha512='shasum -a512'
	alias bh_cmd_disasm='objdump -d --x86-asm-syntax=intel'
	alias bh_cmd_sed_ext='sed -E'
else # assume Linux
	alias bh_cmd_md5='md5sum'
	alias bh_cmd_sha1='sha1sum'
	alias bh_cmd_sha256='sha256sum'
	alias bh_cmd_sha512='sha512sum'
	alias bh_cmd_disasm='objdump -dM intel'
	alias bh_cmd_sed_ext='sed -r'
fi

alias bh_rot13='bh_rot 13'

bh_rot() {
	(( $# < 2 )) && return 1

	local n
	local N

	# n gets the alphabet letter
	n=$(echo -e \\x$(bh_dec2hex $(( 97 + $1 )) ) )

	# N gets uppercase n
	N="${n^^}"

	# rot with tr command
	echo $2 | tr a-z $n-za-z | tr A-Z $N-ZA-Z
}

bh_rotall() {
	(( $# < 1 )) && return 1

	local i

	for i in {1..25}; do
		echo "ROT$i $(bh_rot $i "$1")"
	done
}

bh_strxor() {
    (( $# < 2 )) && return 1
    
    local str
    local xored
    local i

    # $2 is the string and $1 is the xor key
    str=$(bh_str2dec "$2")

    for i in $str; do
        xored=$(( $i ^ $1 ))
        echo -n "$(bh_dec2asc $xored)"
   	done
   	echo
}

bh_bkp() {
	(( $# < 1 )) && return 1
	cp -vi "$1"{,.$(date +%Y%m%d)}
}

bh_findmime() {
	(( $# < 2 )) && return 1

	local dir=.
	local filetype
	local opt
	local matches

	[[ -d "$2" ]] && dir="$2"

	case $1 in
		# documents
		-txt)
			opt='text/';;
		-pdf)
			opt='pdf' ;;
		-office)
			opt='vnd\.openxmlformats\-officedocument' ;;

		# compressed
		-zip)
			opt='zip';;
		-rar)
			opt='x\-rar' ;;

		# executables
		-pe)
			opt='(x\-dosexec|vnd\.microsoft\.portable\-executable)' ;;
		-msi)
			opt='vnd\.ms\-office' ;;
		-macho)
			opt='x\-mach\-binary' ;;
		-elf)
			opt='x\-(executable|pie\-executable|sharedlib)' ;;
		*)
			return
	esac

	# buffering results
	matches=$(for i in "$dir"/*; do
		filetype=$(file -Nb --mime-type "$i")
		[[ "$filetype" =~ application/$opt ]] && echo "${i#./*}"
	done)

	[[ -n "$matches" ]] && echo "$matches" | tr -s / /
}

bh_hashes() {
	(( $# < 1 )) && return 1

	local i

	for i in $*; do
		echo $(bh_cmd_md5 "$i")
		echo $(bh_cmd_sha1 "$i")
		echo $(bh_cmd_sha256 "$i")
	done | tr -s ' ' ' '
}

bh_md5rename() {
	(( $# < 1 )) && return 1

	local md5_hash
	local i

	for i in $*; do
		md5_hash=$(bh_cmd_md5 "$i" | cut -d" " -f1)
		[[ $md5_hash ]] && mv -v "$i" $(dirname "$i")/$md5_hash
	done
}

bh_secretfile(){
	(( $# < 1 )) && return 1
	
	local pw=$(tr -dc "a-zA-Z0-9_#@.-" < /dev/urandom | head -c 20)
	local filename=$RANDOM.zip
	zip -P "$pw" "$filename" "$1"
	echo "password: $pw"
	rm -f "$filename"
}

bh_sharefile() {
	(( $# < 1 )) && return 1
	
	curl -sF "file=@$1" https://file.io | grep -o 'https://file\.io/[a-zA-Z0-9]*'
}

bh_zipmal() {
	(( $# < 1 )) && return 1
	
	local name=${1%\.*}.zip
	zip --encrypt -P infected "$name" $@
	ls -lh "$name"
    echo "password: infected"
}

bh_bin2dec() {
    (( $# < 1 )) && return 1
    
    echo $((2#$1))
}

bh_charcalc() {
    (( $# < 3 )) && return 1

    local char
    local chars
    local res
    local i

    case $2 in
    +|-)
        for i in $(echo "$1" | sed 's/./& /g'); do
            char=$(bh_str2dec $i)
            res=$(($char $2 $3))
            echo -n $(bh_dec2asc $res)
        done
        echo
        ;;
    '*')
        for (( i=0; i<$3; i++ )); do
            res="$res$1"
        done
        echo $res
        ;;
    esac
}

bh_dec2bin() {
    (( $# < 1 )) && return 1
    
    echo "obase=2;$1" | bc
}

bh_dec2hex() {
    (( $# < 1 )) && return 1

    printf "%x\n" "$1"
}

bh_hex2bin() {
    (( $# < 1 )) && return 1

	local bin
	local i

	for i in $*; do
		bin=$(echo "obase=2;ibase=16;$(echo $i | tr a-f A-F)" | bc)
		echo -n "$bin "
    done
	echo
}

bh_hex2dec() {
    (( $# < 1 )) && return 1

    echo $(( 0x${1#0x} ))
}

bh_hexcalc() {
	(( $# < 3 )) && return 1

	echo -n 0x
	bh_dec2hex $((0x${1#0x} $2 0x${3#0x}))
}

bh_epoch() {
	(( $# == 0 )) && ( date +%s; return; )

	if [[ $1 =~ ^[0-9]+$ ]]; then
		[[ $bashacks_os == Darwin ]] && date -ur $1 || date -d @$1
	fi
}

bh_bin2ip() {
	(( $# < 1 )) && return 1

	local a=b=c=d=
	
	IFS=. read a b c d <<< "$1"								
	echo $((2#$a)).$((2#$b)).$((2#$c)).$((2#$d))
}

bh_hostcalc() {
        (( $# < 1 )) && return 1

        local prefix=${1##*/}
        echo $((2**(32-prefix) - 2))
}

bh_ip2bin() {
    [[ "$1" =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]] || return 1

    local i
	for i in $(echo "$1" | tr . ' '); do
	    printf "%.8d." $(bh_dec2bin $i)
    done | sed "s/.$//"
    echo
}

bh_ipinfo()
{
    local ipaddress="${1:-`bh_myip`}"
    local url="http://ipinfo.io"

    wget -qO - "$url/$ipaddress"
}

bh_ipisblocked() {
    (( $# < 1 )) && return 1

    local ipaddress="${1:-`bh_myip`}"
    local url_projects='TALOS;https://www.talosintelligence.com/documents/ip-blacklist
    Malc0de;http://malc0de.com/bl/IP_Blacklist.txt
    Projecthoneypot.org;https://www.projecthoneypot.org/list_of_ips.php
    blocklist.de;http://lists.blocklist.de/lists/all.txt
    Alienvault;https://reputation.alienvault.com/reputation.generic
    SANS-TOPSOURCE;https://isc.sans.edu/api/topsources?json'

    echo "== $ipaddress =="
    for project in $url_projects; do
        pjname="$(echo $project \
            | cut -d ';' -f1)"
        pjlink="$(echo $project \
            | cut -d ';' -f2)"

        if wget -T10 $pjlink -q -O - \
            | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" \
            | grep -E ^$ipaddress$ > /dev/null 2>&1
        then
            echo -e "[T]\t$pjname" 
        else
            echo -e "[F]\t$pjname"
        fi
    done
}

bh_myip() {
	local ip=$(wget -q https://api.ipify.org -O -)
	[[ $ip =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]] && echo $ip
}
bh_unshort() {
    (( $# < 1 )) && return 1
    
    wget -T10 --max-redirect 0 --spider "$1" 2>&1 | grep -E '^Loca(tion|liza..o):' | cut -d' ' -f2
}

bh_wgetr() {
	(( $# < 1 )) && return 1
	
	wget -crw 2 --random-wait -U "$bashacks_wget_user_agent" "$1"
}
bh_skel_c() {
	echo -e "#include <stdio.h>\n\nint main(int argc, char *argv[]) {\n\n\n\treturn 0;\n}"
}

bh_skel_go(){
    echo -e "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\n\tfmt.Println(\"test\")\n\n}"
}

bh_skel_latex(){
	echo -e \
'\\documentclass{article}

\\usepackage[english]{babel}
\\usepackage[utf8]{inputenc}
\\usepackage[margin=1in]{geometry}

\\author{}
\\title{}

\\begin{document}
\\maketitle

\\end{document}'
}

bh_skel_python() {
	echo -e "#!/usr/bin/env python\n# *-* coding: utf-8 *-*\n\nif __name__ == "__main__":\n\t"
}
bh_skel_yara() {
    echo -e \
"rule test {
    meta:
        author = \"$(whoami)\"
        description = \"\"
        date = \"$(date +%Y-%m-%d)\"
        ref = \"\"
        hash = \"\"

    strings:
        \$a = \"test\" ascii wide

    condition:
        all of them
}"
}

bh_asmgrep() {
    (( $# < 2 )) && return 1

    bh_cmd_disasm "$2" | grep --color -EC4 "$1"
}

bh_asminfo() {
    (( $# < 1 )) && return 1

    local ins=$1

    [[ -d $bashacks_cachedir ]] || mkdir -p $bashacks_cachedir

    if [[ -s $bashacks_cachedir/$ins.txt ]]; then
        cat $bashacks_cachedir/$ins.txt
    else
        wget -T10 -U "${bashacks_wget_user_agent}" \
         -q https://faydoc.tripod.com/cpu/$ins.htm -O - \
         | html2text \
         | sed -n '/^===.*/,$p' \
         | sed 's/^===.*/'${ins}'/;s/_/ /g' \
         | tee -a $bashacks_cachedir/$ins.txt
    fi
}

bh_replacestring() {
    [[ -f "$1" && -n "$2" && -n "$3" && "${#2}" == "${#3}" ]] || return 1

    local fil="$1"
    local src="$2"
    local dst="$3"

    local srchex=$(echo "$src" | xxd -pu)
    local dsthex=$(echo "$dst" | xxd -pu)

    local tmpfile=$(mktemp)

    # xxd -r -p works, while xxd -rp or xxd -pr doesn't O.o
    xxd -p $fil | tr -d \\n | sed "s/${srchex::-2}/${dsthex::-2}/g" | xxd -r -p >  $tmpfile
    
    [[ -s $tmpfile ]] && mv $tmpfile $fil
}

bh_zerostring() {
	[[ -f "$1" && -n "$2" ]] || return 1

	local fil="$1"
	local search="$2"

	# 'tr' is needed here because the strings command
    # might output lines starting with two spaces
	local pos=$(strings -t d "$fil" | grep -F "$search" | tr -s ' ' ' ' | cut -d' ' -f1)

	local siz=${#search}
	for i in $pos; do
		dd conv=notrunc bs=1 count=$siz seek=$i if=/dev/zero of="$fil"
	done
}

bh_asciitable() {
	echo -en \
	"Dec Hex    Dec Hex    Dec Hex  Dec Hex  Dec Hex  Dec Hex   Dec Hex   Dec Hex\n\
  0 00 NUL  16 10 DLE  32 20    48 30 0  64 40 @  80 50 P   96 60 \`  112 70 p\n\
  1 01 SOH  17 11 DC1  33 21 !  49 31 1  65 41 A  81 51 Q   97 61 a  113 71 q\n\
  2 02 STX  18 12 DC2  34 22 \"  50 32 2  66 42 B  82 52 R   98 62 b  114 72 r\n\
  3 03 ETX  19 13 DC3  35 23 #  51 33 3  67 43 C  83 53 S   99 63 c  115 73 s\n\
  4 04 EOT  20 14 DC4  36 24 $  52 34 4  68 44 D  84 54 T  100 64 d  116 74 t\n\
  5 05 ENQ  21 15 NAK  37 25 %  53 35 5  69 45 E  85 55 U  101 65 e  117 75 u\n\
  6 06 ACK  22 16 SYN  38 26 &  54 36 6  70 46 F  86 56 V  102 66 f  118 76 v\n\
  7 07 BEL  23 17 ETB  39 27 '  55 37 7  71 47 G  87 57 W  103 67 g  119 77 w\n\
  8 08 BS   24 18 CAN  40 28 (  56 38 8  72 48 H  88 58 X  104 68 h  120 78 x\n\
  9 09 HT   25 19 EM   41 29 )  57 39 9  73 49 I  89 59 Y  105 69 i  121 79 y\n\
 10 0A LF   26 1A SUB  42 2A *  58 3A :  74 4A J  90 5A Z  106 6A j  122 7A z\n\
 11 0B VT   27 1B ESC  43 2B +  59 3B ;  75 4B K  91 5B [  107 6B k  123 7B {\n\
 12 0C FF   28 1C FS   44 2C ,  60 3C <  76 4C L  92 5C \\  108 6C l  124 7C |\n\
 13 0D CR   29 1D GS   45 2D -  61 3D =  77 4D M  93 5D ]  109 6D m  125 7D }\n\
 14 0E SO   30 1E RS   46 2E .  62 3E >  78 4E N  94 5E ^  110 6E n  126 7E ~\n\
 15 0F SI   31 1F US   47 2F /  63 3F ?  79 4F O  95 5F _  111 6F o  127 7F DEL\n"
}

bh_dec2asc() {
    (( $# < 1 )) && return 1

    echo -e $(printf "\\\x%x" $1)
}

bh_hex2str() {
	(( $# < 1 )) && return 1
	
	local hex
	local i
	
	# remove non-hexa characters
	hex=$(echo "$1" | bh_cmd_sed_ext 's/(0x|\\x| |\{|\||\}|,)//g')

	# insert space every two characters
	hex=$(echo "$hex" | bh_cmd_sed_ext 's/../& /g')
	
	for i in $hex; do
		echo -ne "\\x$i"
	done
	echo
}

bh_str2dec() {
	(( $# < 1 )) && return 1

	# count the number of digits of the param ($1)
	# and print each one with printf in the decimal format
	#
	local param_length=${#1}
	for (( i=0; i<$param_length; i++ )); do

		# avoid the last space in the last char, if this last space exists
		# other modules can fail
		(( (i + 1) < param_length )) && { printf "%d " "'${1:$i:1}'"; continue; }

		printf "%d" "'${1:$i:1}'"
	done

	echo
}

bh_asc2dec() {
    echo "WARNING: bh_asc2dec() is depcreated and will be removed in the next release. Use bh_str2dec() instead."
	(( $# < 1 )) && return 1

	bh_str2dec "$1"
}

bh_str2hex() {
	(( $# < 1 )) && return 1

	case "$1" in
		"-x")
			echo -n "$2" | hexdump -ve '/1 "%02x"' | sed 's/../\\x&/g'
			echo
			;;
		"-0x")
			echo -n "$2" | hexdump -ve '/1 "0x%02x "' | sed 's/\(.*\) /\1/'
			echo
			;;
		"-c")
			echo -n '{ '
			echo -n "$2" | hexdump -ve '/1 "0x%02x, "' | sed 's/\(.*\), /\1/'
			echo ' }'
			;;
        *)
			echo -n "$1" | hexdump -ve '/1 "%02x "' | sed 's/\(.*\) /\1/'
			echo
			;;
	esac
}


bh_str2hexr() {
    (( $# < 1 )) && return 1

    case "$1" in
	    "-x" | "-0x" | "-c")
	        bh_str2hex $1 "$(echo "$2" | rev)"
		;;
        *)
		    bh_str2hex "$(echo "$1" | rev)"
	    ;;
	esac
}

bh_urldecode() {
	(( $# < 1 )) && return 1
	echo "$1" | perl -pe 's/%([0-9a-f]{2})/pack "H*", $1/gie'
}
bh_urlencode() {
	(( $# < 1 )) && return 1
	echo -ne "$1" | perl -pe 's/\W/"%".unpack "H*",$&/gei'
	echo
}
bh_utf8table() {
	echo -ne \
"Hex      Hex      Hex      Hex      Hex      Hex      Hex      Hex\n\
c2 a0    c2 ac ¬  c2 b8 ¸  c3 84 Ä  c3 90 Ð  c3 9c Ü  c3 a8 è  c3 b4 ô\n\
c2 a1 ¡  c2 ad ­  c2 b9 ¹  c3 85 Å  c3 91 Ñ  c3 9d Ý  c3 a9 é  c3 b5 õ\n\
c2 a2 ¢  c2 ae ®  c2 ba º  c3 86 Æ  c3 92 Ò  c3 9e Þ  c3 aa ê  c3 b6 ö\n\
c2 a3 £  c2 af ¯  c2 bb »  c3 87 Ç  c3 93 Ó  c3 9f ß  c3 ab ë  c3 b7 ÷\n\
c2 a4 ¤  c2 b0 °  c2 bc ¼  c3 88 È  c3 94 Ô  c3 a0 à  c3 ac ì  c3 b8 ø\n\
c2 a5 ¥  c2 b1 ±  c2 bd ½  c3 89 É  c3 95 Õ  c3 a1 á  c3 ad í  c3 b9 ù\n\
c2 a6 ¦  c2 b2 ²  c2 be ¾  c3 8a Ê  c3 96 Ö  c3 a2 â  c3 ae î  c3 ba ú\n\
c2 a7 §  c2 b3 ³  c2 bf ¿  c3 8b Ë  c3 97 ×  c3 a3 ã  c3 af ï  c3 bb û\n\
c2 a8 ¨  c2 b4 ´  c3 80 À  c3 8c Ì  c3 98 Ø  c3 a4 ä  c3 b0 ð  c3 bc ü\n\
c2 a9 ©  c2 b5 µ  c3 81 Á  c3 8d Í  c3 99 Ù  c3 a5 å  c3 b1 ñ  c3 bd ý\n\
c2 aa ª  c2 b6 ¶  c3 82 Â  c3 8e Î  c3 9a Ú  c3 a6 æ  c3 b2 ò  c3 be þ\n\
c2 ab «  c2 b7 ·  c3 83 Ã  c3 8f Ï  c3 9b Û  c3 a7 ç  c3 b3 ó  c3 bf ÿ\n"
}
