#!/bin/bash
# (C) Janis Jansons, Kirils Solovjovs, 2017-2018

if [ "$(ps -o comm= $PPID)" == "ssh" ]; then
	cat /tmp/.pass
	exit 0
fi


function cleanup {
  rm /tmp/.pass 2> /dev/null
  rm -- jb_*.backup 2> /dev/null
}

trap cleanup EXIT

vercomp () {
    #(C) Dennis Williamson, 2010, https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

cd "$(dirname "$(echo $0)")"

rm /tmp/PASSOUT 2> /dev/null
echo "* Not affiliated with Mikrotikls or Oracle *"
echo
echo "Welcome to jailbreak tool v1.92 for MikroTik devices"
echo "                                    by PossibleSecurity.com"
echo 
echo "WARNING! THIS TOOL IS LIKELY TO BRICK YOUR DEVICE. USE AT YOUR OWN RISK."
echo "AUTHORS OF THIS TOOL MAY NOT BE HOLD LIABLE FOR ANY DIRECT OR"
echo "INDIRECT DAMAGES CAUSED AS A RESULT OF USING THIS TOOL."
echo 
echo "If <<brick>> happens, go for netinstall to recover."
echo 
echo " * * * * * * * * "

JBID="jb_$$_$RANDOM.backup" #.backup is important

echo "We'll need the IP address of the device, user and password."
while true; do
	echo -n "IP [192.168.88.1]: "
	read IP
	echo -n "USER [admin]: "
	read USER
	echo -n "PASS []: "
	read PASS
	[ "$IP" == "" ] && IP="192.168.88.1"
	[ "$USER" == "" ] && USER="admin"
	echo 
	echo "We got $USER@$IP with password '$PASS'."
	while true; do
		echo -n "Is this correct? (y/N) "
		read confirm
		[ -z "$confirm" ] && echo "Please enter 'yes' or 'no'!" || break
	done

	[ "${confirm:0:1}" == "y" -o "${confirm:0:1}" == "Y" ] && break
	echo "Try again, please."
done


echo -n "$PASS" > /tmp/.pass


echo 
echo "Let's begin."

ping -c1 $IP &> /dev/null
[ $? -ne 0 ] && echo ERROR: IP address must respond to ICMP echo requests. && exit 1

echo "Verifying version..."
res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/system resource print" 2>/dev/null )"
[ "$?" -ne "0" ] && echo ERROR: Unable to connect to $IP:22 with user $USER. && exit 1

arch="$(echo $res |tr $'\r' $'\n'| grep architecture-name |cut -d : -f 2|tr -dc [a-zA-Z0-9]_ )"
version="$(echo $res |tr $'\r' $'\n'| grep version |cut -d : -f 2|cut -d \( -f 1|tr -dc [a-zA-Z0-9]._ )"

version_cmp="$(echo $version | sed s/rc.*$//)"

version_rc="$(echo $version |grep rc | sed s/^.*rc//)"

vercomp "$version_cmp" "2.9.8"
[ $? -eq 2 ] && echo "Software $version is not supported by this tool. The first supported version is 2.9.8." && exit 9
vercomp "$version_cmp" "6.42"
[ ! $? -eq 2 ] && echo "Software $version is not supported by this tool. The last supported versoin is 6.41rc56." && exit 9
vercomp "$version_cmp" "6.41"
if [ $? -eq 0 ]; then
	[ -z "$version_rc" ] && version_rc="99"
	vercomp "$version_rc" "61"
	[ ! $? -eq 2 ] && echo "Software $version is not supported by this tool. The last supported versoin is 6.41rc56." && exit 9
fi

res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/system backup save name=\"$JBID\" dont-encrypt=yes" 2> /dev/null)"
[ "$?" -ne "0" ] && echo ERROR: Unable to connect to $IP:22 with user $USER. && exit 1

if ! [[ "$res" =~ "backup saved" ]]; then
	#try an older version approach
	res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/system backup save name=\"$JBID\"" 2> /dev/null)"
	[ "$?" -ne "0" ] && echo ERROR: Unable to connect to $IP:22 with user $USER. && exit 1
	! [[ "$res" =~ "backup saved" ]] && echo ERROR: Unable to export current configuration. && exit 1
fi


echo "Downloading current configuration..."
! [[ "$res" =~ "backup saved" ]] && echo ERROR: Unable to export current configuration. && exit 1
DISPLAY="none" SSH_ASKPASS="$0" setsid scp -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$USER@$IP:/$JBID" "./$JBID" 2> /dev/null
[ "$?" -ne "0" ] && echo ERROR: Unable to download current configuration from $IP:22 with user $USER. && exit 1
[ ! -f "$JBID" ] && echo ERROR: Download failed. This should never happen. && exit 1

echo "Patching..."

#cp $JBID orig_$JBID
[ -z "$(./exploit_b.py $JBID |grep "^Done\.")" ] && echo ERROR: Unable to patch current configuration. && exit 1

echo "Uploading exploit..."
DISPLAY="none" SSH_ASKPASS="$0" setsid scp -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "./$JBID" "$USER@$IP:/$JBID" 2> /dev/null
[ "$?" -ne "0" ] && echo ERROR: Unable to upload configuration with payload to $IP:22 with user $USER. && exit 1

res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/system backup load name=\"$JBID\" password=\"\"" 2> /dev/null)"
[ "$?" -ne "0" ] && echo ERROR: Unable to connect to $IP:22 with user $USER. && exit 1

if ! [[ "$res" =~ "configuration restored" ]]; then
	#try an older version approach
	res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/system backup load name=\"$JBID\"" 2> /dev/null)"
	[ "$?" -ne "0" ] && echo ERROR: Unable to connect to $IP:22 with user $USER. && exit 1
	! [[ "$res" =~ "configuration restored" ]] && echo ERROR: Unable to apply patched configuration. && exit 1
fi

echo
echo " * * * * * * * * "
echo "Congrats! Jailbreak was (likely) successfull. Device will now reboot."
echo " * * * * * * * * "
echo "Linux mode can be accessed via telnet using user 'devel' with admin's password."
echo 

echo "Device is now rebooting..."

[ ! -f "busybox-$arch" ] && echo "As we do not have binaries for your architecture ($arch) you are all set." && exit 0

echo "You may opt to install additional utilities to make using the shell easier."
echo "Please note that this will enable telnet service on port 23/tcp, "
echo "send YOUR PASSWORD AND USERNAME UNENCRYPTED over the network, and"
echo "   may REMOVE YOUR ABILITY TO UPDATE software on smaller devices."
echo

while true; do
	echo -n "Would you like some additional utilities with your jailbreak? (y/N) "
	read confirm
	[ -z "$confirm" ] && echo "Please enter 'yes' or 'no'!" || break
done

! [ "${confirm:0:1}" == "y" -o "${confirm:0:1}" == "Y" ] && echo You are on your own. Good luck. && exit 0

echo "Waiting for device to reboot..."
sleep 10

echo "Waiting for device to become available..."
until ping -c1 $IP &>/dev/null; do :; done

c=0
while true; do #just making sure that we're all up
	echo "Connecting..."
	res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/" 2> /dev/null)"
	[ "$?" -eq "0" ] && break
	sleep 2
	c=$(( $c + 1 ))
	[ $c -gt 10 ] && echo ERROR: Connection failed. && exit 2
done

echo "Uploading binaries..."
DISPLAY="none" SSH_ASKPASS="$0" setsid scp -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "./busybox-$arch" "$USER@$IP:/busybox_p" 2> /dev/null #this is separate because of rename
[ "$?" -ne "0" ] && echo ERROR: Unable to upload binaries. && exit 2
DISPLAY="none" SSH_ASKPASS="$0" setsid scp -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "./slave.sh" "$USER@$IP:" 2> /dev/null
[ "$?" -ne "0" ] && echo ERROR: Unable to upload binaries. && exit 2

echo "Enabling telnet..."
res="$(DISPLAY="none" SSH_ASKPASS="$0" setsid ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l "$USER" "$IP" "/ip service set disabled=no port=23 telnet" 2> /dev/null)"
[ ! -z "$res" ] && echo ERROR: Failed to enable telnet. && exit 2

echo -n "Setting up..."
status="$(
(sleep 1; echo "devel"; sleep 0.5; echo "$PASS"; sleep 0.5
echo "chmod a+x slave.sh"; sleep 0.5; echo "./slave.sh"; sleep 5; echo "reboot &"; sleep 3
) | telnet "$IP" 2>&1 )"


echo "$status" |grep 888|tr -d 8

sleep 1

echo
echo "Please be aware that telnet will stay enabled on 23/tcp!"
echo
echo "Enjoy your new shell via telnet using user 'devel' with admin's password."
echo 

exit 0




