Get credentials from qwiklabs
after too many consequent attempts the account gets kinda blocked and the course is unable to start. No captcha gets asked - probably the usage patterns look legit enough Future improvements: multiple accounts, using a random one each time. Probably google colab can still be used with selenium, now that the big problem of reliably getting credentials has been overcomemaster
commit
c9e053306d
|
@ -0,0 +1,22 @@
|
|||
# <b> Google Colab Automator, without Selenium! </b>
|
||||
|
||||
## <b> What is this </b>
|
||||
Google Colab is a Google service which gives free, temporary, use of virtual machines with powerful NVIDIA Tesla GPUs. Normally this is used to train ML and other AI models, but nothing impedes the use of the service for other purposes, such has password cracking with hashcat or crypto mining.
|
||||
The downside is that the account gets temporary blocked when a too long intense use is detected.
|
||||
Qwiklabs (qwiklabs.com) is a third-party service which gives temporary Google Accounts for training in Google Cloud Shell use. Their first course (https://www.qwiklabs.com/focuses/2794?parent=catalog) is completely free, others require some in-site credits to be purchased.
|
||||
Combining the two services, infinite temporary and disposable Google Accounts can be obtained from qwiklabs and used for mining on colab, until the qwiklabs session expires or the miner gets blocked by Colab. At such point, a new session can be started. That's basically free money. Obviously this can also be used for non-malicious tasks, as long as the Colab notebook is publicly available (e.g. as a github gist). After a certain time number of times repeating the course, the qwiklabs account might reach it's <i>quota</i> for that course and a new one needs to be created. I'll will look into a way of automating account creation in the future. For now, use temp mails from temp-mail.org when creating accounts
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## <b> Why no selenium </b>
|
||||
Selenium carries some javascript and other stuff which can easily be detected by most websites - GColab and Qwiklabs included - and get the session blocked, especially if captchas are involved (There are workarounds to captchas for selenium - https://github.com/ohyicong/recaptcha_v2_solver - but often the captcha doesn't even get presented to the user if an automated browser session is detected)
|
||||
<br>
|
||||
<br>
|
||||
## <b> The workaround </b>
|
||||
Use a plain chrome/firefox session, and automate by programmatically controlling mouse and keyboard. Basic anonimizing of the web session is still needed (spoof ip/mac, change useragent/geolocation/timezone). Actions need to be done at a human speed, or the bot could be recognized as an actual one
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## <b> Mouse and Keyboard automation </b>
|
||||
Mouse and keyboard are automated using https://pyautogui.readthedocs.io/en/latest/<br>
|
||||
For simpicity, and to avoid messing up the OS by clicking on the wrong stuff, both chrome and pyautogui can be started in a separate Xephyr (https://wiki.archlinux.org/title/Xephyr) window, where they can harm no one.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
#change mac
|
||||
sudo ip link set wlp3s0 down
|
||||
sudo macchanger -r wlp3s0
|
||||
sudo ip link set wlp3s0 up
|
||||
|
||||
#Start xephyr window
|
||||
Xephyr -br -ac -noreset -screen 800x600 :1 &
|
||||
# Start a copyq server, that will be used to copy the email and password of the obtained account from the clipboard of Xephyr
|
||||
DISPLAY=:1 copyq &
|
||||
# sleep 5
|
||||
|
||||
#Start chrome
|
||||
#--proxy-server=socks5://127.0.0.1:9050
|
||||
DISPLAY=:1 /usr/bin/google-chrome-stable --user-data-dir='./chrome-profile' --no-first-run &
|
||||
|
||||
#Wait enough to let chrome start up
|
||||
sleep 5
|
||||
|
||||
#Now start the actual bot, we're in a safe environment
|
||||
source venv/bin/activate #switch to virtual env
|
||||
DISPLAY=:1 python main.py
|
||||
|
||||
# Clear chrome profile
|
||||
rm -rf ./chrome-profile
|
|
@ -0,0 +1,35 @@
|
|||
'''
|
||||
This classes holds the coordinates for all the elements that need to be clicked on the screen.
|
||||
All the coordinates are kept as percentages of the screen resolution and are recalculated at runtime
|
||||
'''
|
||||
|
||||
class Gui:
|
||||
def __init__(self, width, height):
|
||||
Gui.chrome_gui = Chrome(width, height)
|
||||
Gui.qwiklabs_gui = Qwiklabs(width, height)
|
||||
|
||||
class Chrome(Gui):
|
||||
SEARCH_BAR_PERCENTAGE = (0.5, 0.1)
|
||||
|
||||
def __init__(self, width, height):
|
||||
Chrome.SEARCH_BAR=width*Chrome.SEARCH_BAR_PERCENTAGE[0], height*Chrome.SEARCH_BAR_PERCENTAGE[1]
|
||||
|
||||
class Qwiklabs(Gui):
|
||||
JOIN_BTN_PERCENTAGE = (0.775, 0.183)
|
||||
SIGN_IN_BTN_PERCENTAGE = (0.2125, 0.73)
|
||||
EMAIL_TEXTBOX_PERCENTAGE = (0.5, 0.73)
|
||||
COURSE_BTN_PERCENTAGE = (0.29, 0.45)
|
||||
STARTLAB_BTN_PERCENTAGE = (0.125, 0.31)
|
||||
CAPTCHA_BTN_PERCENTAGE = (0.075, 0.425)
|
||||
EMAIL_COPY_BTN_PERCENTAGE = (0.3125, 0.7)
|
||||
PASSWORD_COPY_BTN_PERCENTAGE = (0.3125, 0.82)
|
||||
|
||||
def __init__(self, width, height):
|
||||
Qwiklabs.JOIN_BTN=width*Qwiklabs.JOIN_BTN_PERCENTAGE[0], height*Qwiklabs.JOIN_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.SIGN_IN_BTN=width*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[0], height*Qwiklabs.SIGN_IN_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.EMAIL_TEXTBOX=width*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[0], height*Qwiklabs.EMAIL_TEXTBOX_PERCENTAGE[1]
|
||||
Qwiklabs.COURSE_BTN=width*Qwiklabs.COURSE_BTN_PERCENTAGE[0], height*Qwiklabs.COURSE_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.STARTLAB_BTN=width*Qwiklabs.STARTLAB_BTN_PERCENTAGE[0], height*Qwiklabs.STARTLAB_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.CAPTCHA_BTN=width*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[0], height*Qwiklabs.CAPTCHA_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.EMAIL_COPY_BTN=width*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.EMAIL_COPY_BTN_PERCENTAGE[1]
|
||||
Qwiklabs.PASSWORD_COPY_BTN=width*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[0], height*Qwiklabs.PASSWORD_COPY_BTN_PERCENTAGE[1]
|
|
@ -0,0 +1,109 @@
|
|||
import gui
|
||||
import pyautogui
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
def main():
|
||||
pyautogui.FAILSAFE = False
|
||||
|
||||
screenWidth, screenHeight = pyautogui.size()
|
||||
ui = gui.Gui(screenWidth, screenHeight)
|
||||
|
||||
print("Screen is {} {}".format(screenWidth, screenHeight))
|
||||
|
||||
print("Accessing course on qwiklabs")
|
||||
# Head over to the course on qwiklabs.com
|
||||
pyautogui.press('f6')
|
||||
pyautogui.write("qwiklabs.com")
|
||||
pyautogui.press('/')
|
||||
pyautogui.write("focuses")
|
||||
pyautogui.press('/')
|
||||
pyautogui.write("2794")
|
||||
pyautogui.press('?')
|
||||
pyautogui.write("parent")
|
||||
pyautogui.press('=')
|
||||
pyautogui.write("catalog")
|
||||
pyautogui.press('enter')
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
print("Signing in")
|
||||
pyautogui.moveTo(0,0)
|
||||
|
||||
# Click join button
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.JOIN_BTN[0], ui.qwiklabs_gui.JOIN_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click(button='left')
|
||||
time.sleep(5)
|
||||
|
||||
# Move to the end of the page
|
||||
pyautogui.press('pgdn')
|
||||
|
||||
print("Moving from sign up to sign in")
|
||||
# switch to sign in button
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.SIGN_IN_BTN[0], ui.qwiklabs_gui.SIGN_IN_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click(button='left')
|
||||
time.sleep(5)
|
||||
|
||||
# switch to email textbox, the rest is done via kbd
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.EMAIL_TEXTBOX[0], ui.qwiklabs_gui.EMAIL_TEXTBOX[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click(button='left')
|
||||
time.sleep(2)
|
||||
|
||||
print("Inserting credentials")
|
||||
# account; "mopopa1077@5sword.com", "hellogoodbye"
|
||||
account = ("mopopa1077@5sword.com", "hellogoodbye")
|
||||
username = account[0]
|
||||
password = account[1]
|
||||
first_part = username.split('@')[0]
|
||||
second_part = username.split('@')[1]
|
||||
|
||||
pyautogui.press('@')
|
||||
pyautogui.press('left')
|
||||
pyautogui.write(first_part, interval=0.2)
|
||||
pyautogui.press('right')
|
||||
pyautogui.write(second_part, interval=0.2)
|
||||
pyautogui.press('\t')
|
||||
pyautogui.write(password, interval=0.2)
|
||||
pyautogui.press('enter')
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
# Start course
|
||||
time.sleep(5)
|
||||
print("Starting the course")
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.STARTLAB_BTN[0], ui.qwiklabs_gui.STARTLAB_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click()
|
||||
|
||||
# Accept captcha - sometimes they don't even ask for actual verification
|
||||
# time.sleep(5)
|
||||
# print("Accepting captcha (not needed really)")
|
||||
# pyautogui.moveTo(ui.qwiklabs_gui.CAPTCHA_BTN[0], ui.qwiklabs_gui.CAPTCHA_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
# pyautogui.click()
|
||||
|
||||
|
||||
bashCommand = "copyq clipboard"
|
||||
# Copy username to clipboard
|
||||
time.sleep(20)
|
||||
print("Copying email")
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.EMAIL_COPY_BTN[0], ui.qwiklabs_gui.EMAIL_COPY_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click()
|
||||
g_email = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8')
|
||||
|
||||
# Copy password to clipboard
|
||||
time.sleep(5)
|
||||
print("Copying password")
|
||||
pyautogui.moveTo(ui.qwiklabs_gui.PASSWORD_COPY_BTN[0], ui.qwiklabs_gui.PASSWORD_COPY_BTN[1], 3, pyautogui.easeOutQuad)
|
||||
pyautogui.click()
|
||||
g_password = subprocess.check_output(['bash','-c', bashCommand]).decode('utf-8')
|
||||
|
||||
print(g_email, g_password)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# while True:
|
||||
# print(pyautogui.position())
|
||||
|
||||
main()
|
|
@ -0,0 +1,2 @@
|
|||
pyautogui
|
||||
pyperclip
|
Loading…
Reference in New Issue