[Nexus 6P Android Development] digiuseppefederico:
#!/bin/bash

VERSION=3.0
red='\033[1;31m'
green='\033[1;32m'
yellow='\033[1;33m'
blue='\033[1;34m'
light_cyan='\033[1;96m'
reset='\033[0m'

ARCH=$(uname -m)
SLTIMEOUT=100
WINKEXDIR="/usr/lib/win-kex"
XSTARTUP="${WINKEXDIR}/xstartup"
XRDPINI="/etc/xrdp/xrdp.ini"
WINKEX="${WINKEXDIR}/win-kex"
XSERV="${WINKEXDIR}/VcXsrv/vcxsrv.exe"
WSLGSOCK="${WINKEXDIR}/wslg-sock/wslg-sock"
XRDPSERVICE="${WINKEXDIR}/xrdp/xrdpservice"
VNCSRV=$(which tigervncserver)
SESSION_CACHE="$HOME/.cache/sessions/xfce4-session-"
HOST="localhost"
HOSTIP=$(grep -m 1 nameserver /etc/resolv.conf | awk '{print $2}')
RECONN_ON_ERR=1
unset IP USR SOUND MULTISCREEN

function print_help() {
printf "\n\tWin-Kex ${VERSION} provides a GUI desktop experience for Kali Linux" printf "\n\tin Windows Subsystem for Linux 2 (WSL 2)"
printf "\n\n\tUsage:"
printf "\n\t\tkex <mode> <command> <parameters>"
printf "\n"
printf "\n\t\t${blue}Mode:${reset}"
printf '\n\t\t--esm\t\t : Launch KeX desktop in a dedicated window using Windows native RDP'
printf '\n\t\t--sl\t\t : Seemlessly integrate KeX into the Windows desktop'
printf '\n\t\t--win\t\t : Launch KeX desktop in a dedicated window'
printf "\n"
printf "\n\t\t${blue}Command:${reset}"
printf "\n\t\t[none]\t\t : start KeX server and launch KeX client"
printf "\n\t\t--start\t\t : start kex server"
printf "\n\t\t--start-client\t : start kex client"
printf "\n\t\t--stop\t\t : stop kex server"
printf "\n\t\t--status\t : show kex server status"
printf "\n\t\t--kill\t\t : stop kex server and kill all related processes"
printf "\n\t\t--passwd\t : set kex server password"
printf "\n\t\t--wtstart\t : start kex server and launch win-kex client"
printf "\n\t\t\t\t in Windows Terminal session"
printf "\n\t\t--start-sound\t : start Windows sound server"
printf "\n\t\t--stop-sound\t : stop Windows sound server"
printf "\n\t\t--help\t\t : display help"
printf "\n\t\t--wslg-remove\t : Move WSLg unix socket"
printf "\n\t\t--wslg-restore\t : Restore WSLg unix socket"
printf "\n\t\t--wslg-status\t : Display status of WSLg unix socket"
printf "\n\t\t--version\t : display version"
printf "\n"
printf "\n\t\t${blue}Parameters:${reset}"
printf "\n\t\t-i\t\t : Use container IP address instead of \"localhost\""
printf "\n\t\t-m\t\t : Optimized for Multiscreen"
printf "\n\t\t-s\t\t : Sound support"
printf "\n"
printf "\n\n\tExamples:"
printf "\n\t\tkex -s\t\t : Start KeX server in window mode and launch KeX client with sound support"
printf "\n\t\tkex --sl -s\t : Start KeX in seemless mode and launch KeX client with sound support"
printf "\n\t\tkex --esm -i -s\t : Start KeX in ESM mode with arm workaround and launch KeX client with sound support"
printf "\n\t\tsudo kex\t : Start KeX server as root in window mode and launch KeX client"
printf "\n"
}

function print_version() {
printf "${VERSION}\n"
}

function print_wrong_arch() {
printf "\n\t${light_cyan}The function is not supported on this architecture${SESSION_FILE}${reset}\n"
}

function ask() {
# [URL]http://djm.me/ask[/URL]
while true; do

if [ "${2:-}" = "Y" ]; then
prompt="Y/n"
default=Y
elif [ "${2:-}" = "N" ]; then
prompt="y/N"
default=N
else
prompt="y/n"
default=
fi

# Ask the question
printf "${light_cyan}$1"
read -p " [$prompt] " REPLY

# Default?
if [ -z "$REPLY" ]; then
REPLY=$default
fi

printf "${reset}"

# Check if the reply is valid
case "$REPLY" in
Y*|y*) return 0 ;;
N*|n*) return 1 ;;
esac
done
}

function is_root() {
if [ -z $USR ]; then
USR=$(whoami)
fi
if [ "${USR}" == "root" ]; then
# 0 = true
return 0
else
# 1 = false
return 1
fi
}

function sudo_active() {
if sudo -nv 2> /dev/null; then
# 0 = true
return 0
else
# 1 = false
return 1
fi
}

function is_wslg_socket() {
if [ -L /tmp/.X11-unix ]; then
# 0 = true
return 0
else
# 1 = false
return 1
fi
}

function user_exists() {
if id "$1" &>/dev/null; then
# 0 = true
return 0
else
# 1 = false
return 1
fi
}

function remove_wslg_socket(){
printf "\n\t${red}A WSLg socket exists that prevent KeX from starting.${reset}"
printf "\n\t${red}Moving the socket now. This will not adversely affect WSL or KeX.\n${reset}"
sudo ${WSLGSOCK} remove
return $?
}

function restore_wslg_socket(){
sudo ${WSLGSOCK} restore
return $?
}

function status_wslg_socket(){
status=$(${WSLGSOCK} status)
result=$?
if [ "$result" -ne 0 ]; then
printf "\t${green}${status}${reset}\n"
else
printf "\t${red}${status}${reset}\n"
fi
return $result
}

function create_user(){
if ! user_exists $1; then
printf "Creating user $1\n"
useradd -m $1
return $?
fi
}

function start-kex() {
if is_wslg_socket; then
remove_wslg_socket
fi
if [ ! -f ~/.vnc/passwd ]; then
passwd-kex
fi
if is_root; then
SCREEN=":2"
else
SCREEN=":1"
fi
if [ -z $SOUND ]; then
unset PULSE_SERVER
else
export PULSE_SERVER=tcp:${HOSTIP}
fi
${VNCSRV} -useold -xstartup ${XSTARTUP} -SecurityTypes=VeNCrypt,TLSVnc $SCREEN >/dev/null 2>&1 </dev/null
starting_kex=1
return 0
}

function stop-kex() {
taskkill.exe /IM win-kex /T /F >/dev/null 2>&1
local output_1=$(${VNCSRV} -kill :1 2>&1)
local output_2=$(${VNCSRV} -kill :2 2>&1)
if [[ "${output_1}" == *"success!"* || "${output_2}" == *"success!"* ]]; then
printf "\t${light_cyan}Win-KeX Win stopped\n${reset}"
return 0
fi
return 1
}

function start-esmkex() {
export DESKTOP="XFCE"
sudo ${XRDPSERVICE} start
return $?
}

function stop-esmkex() {
sudo ${XRDPSERVICE} stop
if [ "$?" -eq 0 ]; then
printf "\t${light_cyan}Win-KeX ESM stopped\n${reset}"
return 0
fi
return 1
}

function status-esmkex(){
if $(${XRDPSERVICE} status); then
printf "\t${green}Win-KeX ESM is running.${restore}\n"
else
printf "\tWin-KeX ESM is stopped.\n"
fi
return $result
}

function start-xkex() {
if is_wslg_socket; then
remove_wslg_socket
fi
log="/tmp/win-kexsl_$(whoami).log"
if [ "$NOWGL" == "1" ]; then
$XSERV :3 -ac -terminate ${XMULTIMONITORS} -logfile $log -multiwindow -lesspointer -clipboard >/dev/null 2>&1 &
else
$XSERV :3 -ac -terminate ${XMULTIMONITORS} -logfile $log -multiwindow -lesspointer -clipboard -wgl >/dev/null 2>&1 &
fi
return 0
}

function stop-xkex() {
taskkill.exe /IM vcxsrv.exe /T /F >/dev/null 2>&1
if [ "$?" -eq 0 ]; then
printf "\t${light_cyan}Win-KeX SL stopped\n${reset}"
return 0
fi
return 1
}

function status-xkex(){
##status=$(powershell.exe get-process vcxsrv 2>&1)
status=$(tasklist.exe | grep vcxsrv)
if [ $? -eq 0 ]; then
printf "\t${green}Win-KeX SL is running.${restore}\n"
else
printf "\tWin-KeX SL is stopped.\n"
fi
return $result
}

function passwd-kex() {
vncpasswd
return $?
}

function read_passwd() {
local passwd
stty_orig=$(stty -g) # save original terminal setting
stty -echo # turn-off echoing
IFS= read -r passwd # read the password
stty "$stty_orig" # restore terminal setting
echo "$passwd"
}

function exist_esm_passwd() {
USR=$(whoami)
cmdkey.exe /list:LegacyGeneric:target=TERMSRV/${HOST} | grep -q $USR
return $?
}

function set_esm_passwd() {
USR=$(whoami)
printf "Please enter ESM password for user ${USR}:"
passwd=$(read_passwd)
printf "\n"
cmdkey.exe /generic:TERMSRV/${HOST} /user:${USR} /pass:${passwd} >/dev/null 2>&1 &
}

function status-all() {
printf "\n"
if status-kex >/dev/null 2>&1; then
printf "\t${green}KeX Server is running.${reset}\n"
else
printf "\tKex Server is stopped.\n"
fi
status-xkex
status-esmkex
status_wslg_socket
}

function status-kex() {
local result
sessions=$(vncserver -list | sed s/"TigerVNC"/"Win-KeX"/)
if [[ $sessions == *"590"* ]]; then
printf "\n${sessions}\n"
printf "\nYou can use the Win-KeX client to connect to any of these displays.\n\n"
result=0
else
if [ ! -z \$starting_kex ]; then
printf '\nError connecting to the KeX server.\n'
printf 'Please try "kex start" to start the service.\n'
printf 'If the server fails to start, please try "kex kill" or restart your WSL2 session and try again.\n\n'
result=1
fi
fi
return $result
}

function start-client() {
if is_root; then
SCREEN=":2"
unset PASSWD
else
SCREEN=":1"
local PASSWD="-passwd ${HOME}/.vnc/passwd"
fi
if [ -z $MULTISCREEN ]; then
local FULLSCREEN="FullScreen=1"
else
local FULLSCREEN="FullScreen=0 FullScreenAllMonitors=0"
fi
# If KeX is started from the Windows home directory, it fails to open the passwd file
# Let's work around it by starting kex from the rootfs
cd ~
${PRE} ${WINKEX} -SecurityTypes VeNCrypt,TLSVnc -ReconnectOnError $RECONN_ON_ERR $PASSWD $FULLSCREEN 127.0.0.1$SCREEN >/dev/null 2>&1 &
cd - >/dev/null 2>&1
}

function start-esmclient() {
if [ ! -f ~/.win-kex.rdp ]; then
cp $WINKEXDIR/xrdp/win-kex.rdp ~/.win-kex.rdp
fi
if ! exist_esm_passwd; then
set_esm_passwd
fi
if [ -z $SOUND ]; then
if [ -f ~/.config/autostart/pulseaudio.desktop ]; then
rm -f ~/.config/autostart/pulseaudio.desktop
fi
else
if [ ! -d ~/.config/autostart ]; then
mkdir -p ~/.config/autostart
fi
cp $WINKEXDIR/xrdp/pulseaudio.desktop ~/.config/autostart/
fi
cd ~
mstsc.exe .win-kex.rdp /v:${HOST}:3390 &
cd - >/dev/null 2>&1
return $?
}

function start-wtclient() {
while true
do
clear
printf "\n\t${blue}Win-KeX session is active\n\tClose this window to terminate Win-Kex\n${reset}"
# If KeX is started from the Windows home directory, it fails to open the passwd file
# Let's work around it by starting kex from the rootfs
cd ~
if [ "$mode" == "sl" ]; then
start-xclient
while true; do
read -n 1
done
elif [ "$mode" == "esm" ]; then
start-esmclient
local pid=$!
while kill -0 $pid 2> /dev/null; do
sleep 1
done
else
if [ -z $MULTISCREEN ]; then
local FULLSCREEN="FullScreen=1"
else
local FULLSCREEN="FullScreen=0 FullScreenAllMonitors=0"
fi
${WINKEX} -SecurityTypes VeNCrypt,TLSVnc -passwd $HOME/.vnc/passwd $FULLSCREEN 127.0.0.1:1
fi
cd - >/dev/null 2>&1
if ask "\n\tWin-Kex session disconnected.\n\tWould you like to reconnect?" "Y"; then
printf "\n\tReconnecting Win-Kex session\n"
else
stop-kex
exit 0
fi
done
}

function start-xclient() {
XFCE_DESKTOP_DISABLED="0"
SESSION=${HOSTIP}:3
export DISPLAY=$SESSION.0
export GDK_BACKEND=x11
if [ ! "$NOWGL" == "1" ]; then
export LIBGL_ALWAYS_INDIRECT=1
fi
if [ -z $SOUND ]; then
unset PULSE_SERVER
else
export PULSE_SERVER=tcp:${HOSTIP}
fi
## Clean up stale sessions first
pkill -ef "dbus-launch --exit-with-session xfce4-session" > /dev/null 2>&1

## Launch new xfce session
dbus-launch --exit-with-session xfce4-session > /dev/null 2>&1 &
if [ ! -z ${XDG_CACHE_HOME} ]; then
SESSION_CACHE="${XDG_CACHE_HOME}/sessions/xfce4-session-"
fi
SESSION_FILE="${SESSION_CACHE}${SESSION}"
printf "\n\t${light_cyan}Checking ${SESSION_FILE}${reset}\n"
if [ -f ${SESSION_FILE} ]; then
if ! grep "xfdesktop" ${SESSION_FILE} >/dev/null 2>&1; then
XFCE_DESKTOP_DISABLED="1"
printf "\t${light_cyan}SL mode already enabled${reset}\n"
fi
fi
if [ ! ${XFCE_DESKTOP_DISABLED} == "1" ]; then
printf "\t${light_cyan}Enabling SL mode${reset}\n"
i=1
nopid=0
until pids=$(pidof xfdesktop)
do
i=$((i + 1))
sleep 1
if [ $i -ge $SLTIMEOUT ]; then
nopid=1
break
fi
done
##printf "nopid = $nopid\n"
if [ $nopid == "0" ]; then
printf "\t${light_cyan}Desktop started after $i seconds, enabling transparency now${reset}\n"
while pids=$(pidof xfdesktop)
do
xfdesktop -Q >/dev/null 2>&1
done
else
printf "\t${light_cyan}Waited $i seconds for desktop, giving up${reset}\n"
fi
## Repeat that, just in case
if [ $nopid == "0" ]; then
while pids=$(pidof xfdesktop)
do
xfdesktop -Q >/dev/null 2>&1
done
fi
## Save the session
printf "\t${light_cyan}Saving Win-KeX SL session${reset}\n"
dbus-send --session --dest=org.xfce.SessionManager --print-reply /org/xfce/SessionManager org.xfce.Session.Manager.Checkpoint string:"" >/dev/null 2>&1
fi
printf "\t${light_cyan}Started Win-KeX SL${reset}\n"
return 0
}

function kill-kex() {
printf "\n\n"
stop-kex
stop-xkex
stop-esmkex
stop-sound
pkill ssh-agent
pkill Xtigervnc
pkill xiccd
pkill pulseaudio
pkill -9 -f pulseaudio.exe
pkill xcape
pkill Xorg
pkill xrdp-chansrv
return $?
}

function start-sound() {
cd /usr/lib/win-kex/pulse
./pulseaudio.exe -F config.pa > /dev/null 2>&1 &
cd - > /dev/null 2>&1 &
}

function stop-sound() {
pkill -9 -f pulseaudio.exe
}

unset mode
unset cmd
while [[ $# -gt 0 ]]; do
case $1 in
# PARAMETERS:
-i|--ip)
# Use IP address instead of localhost
# Fixes latency issues on Arm (as with version 19041.423)
IP=1
shift
;;
-s|--sound)
SOUND=1
shift
;;
-m|--multiscreen)
MULTISCREEN=1
XMULTIMONITORS="-nomultimonitors"
shift
;;
-n|--nowgl)
NOWGL=1
shift
;;
-r|--norc)
RECONN_ON_ERR=0
shift
;;
-w|--wait)
# Wait longer for desktop to start in SL mode when launched for first time
# Can be used on slower machines where the desktop takes longer than
# 100 seconds to start. Only required on first start to enable transparency
SLTIMEOUT=300
shift
;;
# MODES:
esm|--esm)
mode=esm
shift
;;
sl|--sl)
mode=sl
shift
;;
win|--win)
mode=win
shift
;;
# COMMANDS:
wslg-remove|--wslg-remove)
cmd=remove_wslg
shift
;;
wslg-restore|--wslg-restore)
cmd=restore_wslg
shift
;;
wslg-status|--wslg-status)
cmd=status_wslg
shift
;;
kill|--kill)
cmd=kill
shift
;;
passwd|--passwd)
cmd=passwd
shift
;;
start|--start)
cmd=start
shift
;;
start-client|start-c|--start-client|--start-c)
cmd=start-client
shift
;;
start-sound|--start-sound)
cmd=start-sound
shift
;;
status|--status)
cmd=status
shift
;;
stop|--stop)
cmd=stop
shift
;;
stop-sound|--stop-sound)
cmd=stop-sound
shift
;;
wtstart|--wtstart)
cmd=wtstart
shift
;;
help|-h|--help)
cmd=help
shift
;;
--version)
cmd=version
shift
;;
*)
if [ -z $cmd ]; then
cmd=default
fi
shift
;;
esac
done

if [ "$SOUND" == "1" ] && [ ! "$mode" == "esm" ] && [ ! "$ARCH" == "aarch64" ]; then
stop-sound
start-sound
fi

if [ "$IP" == "1" ]; then
HOST=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
fi

case $cmd in
remove_wslg)
if is_wslg_socket; then
remove_wslg_socket
fi
exit
;;
restore_wslg)
if ! is_wslg_socket; then
restore_wslg_socket
fi
exit
;;
status_wslg)
printf "\n"
status_wslg_socket
exit
;;
esac

if [ "$ARCH" == "aarch64" ]; then
case $cmd in
start)
if [ "$mode" == "sl" ]; then
print_wrong_arch
elif [ "$mode" == "esm" ]; then
start-esmkex
else
start-esmkex
fi
;;
stop)
printf "\n"
if [ "$mode" == "sl" ]; then
print_wrong_arch
elif [ "$mode" == "esm" ]; then
stop-esmkex
else
stop-esmkex
fi
;;
start-client)
if [ "$mode" == "sl" ]; then
print_wrong_arch
elif [ "$mode" == "esm" ]; then
start-esmclient
else
start-esmclient
fi
;;
status)
if [ "$mode" == "sl" ]; then
printf "\n"
status-xkex
elif [ "$mode" == "esm" ]; then
printf "\n"
status-esmkex
elif [ "$mode" == "win" ]; then
status-kex
else
status-all
fi
;;
passwd)
if [ "$mode" == "esm" ]; then
set_esm_passwd
elif [ ! "$mode" == "sl" ]; then
set_esm_passwd
else
printf "\n\t${red}This command is not supported in \"$mode\" mode ${reset}\n"
fi
;;
kill)
kill-kex
;;
start-sound)
print_wrong_arch
;;
stop-sound)
print_wrong_arch
;;
wtstart)
if [ "$mode" == "sl" ]; then
print_wrong_arch
elif [ "$mode" == "esm" ]; then
stop-esmkex
start-esmkex
start-wtclient
else
mode=esm
stop-esmkex
start-esmkex
start-wtclient
fi
;;
help)
print_help
;;
version)
print_version
;;
*)
if [ "$mode" == "sl" ]; then
print_wrong_arch
elif [ "$mode" == "win" ]; then
print_wrong_arch
else
start-esmkex
start-esmclient
fi
;;
esac
else
case $cmd in
start)
if [ "$mode" == "sl" ]; then
printf "\n"
stop-xkex
start-xkex
elif [ "$mode" == "esm" ]; then
start-esmkex
else
start-kex
fi
;;
stop)
printf "\n"
if [ "$mode" == "sl" ]; then
stop-xkex
elif [ "$mode" == "esm" ]; then
stop-esmkex
else
stop-kex
fi
;;
start-client)
if [ "$mode" == "sl" ]; then
start-xclient
elif [ "$mode" == "esm" ]; then
start-esmclient
else
start-client
fi
;;
status)
if [ "$mode" == "sl" ]; then
printf "\n"
status-xkex
elif [ "$mode" == "esm" ]; then
printf "\n"
status-esmkex
elif [ "$mode" == "win" ]; then
status-kex
else
status-all
fi
;;
passwd)
if [ "$mode" == "esm" ]; then
set_esm_passwd
elif [ ! "$mode" == "sl" ]; then
passwd-kex
else
printf "\n\t${red}This command is not supported in \"$mode\" mode ${reset}\n"
fi
;;
kill)
stop-kex
kill-kex
;;
start-sound)
stop-sound
start-sound
;;
stop-sound)
stop-sound
;;
wtstart)
if [ "$mode" == "sl" ]; then
printf "\n"
stop-xkex
start-xkex
start-wtclient
elif [ "$mode" == "esm" ]; then
stop-esmkex
start-esmkex
start-wtclient
else
start-kex
start-wtclient
fi
;;
help)
print_help
;;
version)
print_version
;;
*)
if [ "$mode" == "sl" ]; then
printf "\n"
stop-xkex
start-xkex
start-xclient
elif [ "$mode" == "esm" ]; then
start-esmkex
start-esmclient
else
start-kex
status-kex
start-client
fi
;;
esac
fi