accountserver: port for exclusive use inside a docker container

master
EmaMaker 2021-12-05 21:42:46 +01:00
parent ecf5be5515
commit 36c8424b34
10 changed files with 426 additions and 0 deletions

View File

@ -0,0 +1,7 @@
# syntax=docker/dockerfile:1
FROM python:3.10-bullseye
WORKDIR /code
EXPOSE 12345
COPY ./code/account_server.py ./account_server.py
CMD [ "python3", "-u", "/code/account_server.py"]

View File

@ -0,0 +1,14 @@
06prgzamm96@esiix.com
jhv8mtemi@esiix.com
6bgfngq6@yoggm.com
fohxil@xojxe.com
b4d0o0y5pg@esiix.com
i3z8qtab@xojxe.com
l5wbup@1secmail.com
ryysw0@1secmail.net
m5l7868ar@wwjmp.com
ue8oqa0lf0j@1secmail.net
17k2l9@1secmail.com
c5xm6j@1secmail.net
mud0ud@esiix.com
t788egrvdp@wwjmp.com

View File

@ -0,0 +1,112 @@
''' This file needs to be run outside of the GShellAutomator script
Starts a TCP server on localhost, to which GSA asks for accounts and reports problems
Command list:
givacc: Client is requesting a qwiklabs account to use. Take one from the available list and return it, then put it in the suspended list
remacc: Client reported the account is not working anymore, and it needs to be delete (TODO: make this script test is the account is really unusable)
'''
import time
import json
import socket
import random
import threading
from multiprocessing import Process, Manager
def qwprint(*s):
msg = ''.join(a + " " for a in s)
print("[QWAccountServer]", msg)
def handle_clients(available_list, suspended_dict, todelete_list):
while True:
(clientsocket, address) = socket.accept()
command = clientsocket.recv(1024).decode("utf-8").split("|")
if command[0] != "":
if command[0] == "givacc":
account_valid = False
while not account_valid:
account = available_list[random.randint(0, len(available_list)-1)]
if (not account in suspended_dict.keys() ) and (not account in todelete_list):
account_valid = True
suspended_dict[account] = time.time()
clientsocket.send(account.encode("utf-8"))
qwprint("Received a request for a new account, choose", account)
elif command[0] == "remacc":
if command[1]in suspended_dict:
del suspended_dict[command[1]]
todelete_list.append(command[1])
clientsocket.close()
qwprint("Received a request to delete", command[1], "adding to list!")
def openfiles():
available = open('/account_data/qwiklabs_available_accounts.txt', 'r+')
suspended = open('/account_data/qwiklabs_suspended.txt', 'r+')
todelete = open('/account_data/qwiklabs_todelete.txt', 'r+')
return available, suspended, todelete
if __name__ == "__main__":
qwprint("Starting QWAccountServer")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket:
socket.bind(("0.0.0.0", 12345))
socket.listen(5)
with Manager() as manager:
available, suspended, todelete = openfiles()
# create the list from the files
available_list = manager.list([line.strip() for line in available.readlines()])
try:
suspended_dict = manager.dict(json.loads(suspended.read()))
except:
suspended_dict = manager.dict({})
todelete_list = manager.list([line.strip() for line in todelete.readlines()])
p = Process(target=handle_clients, args=(available_list, suspended_dict, todelete_list))
p.start()
last_update_time = time.time()
while True:
try:
tounsuspend = []
for account in suspended_dict:
if time.time()-suspended_dict[account] > 3600: #time is stored in seconds, so this is 3600 after an hour os first being suspened
tounsuspend.append(account)
qwprint("Unsuspend " + account+ " as enough time as passed")
for account in tounsuspend:
del suspended_dict[account]
except:
pass
#update list
if time.time() - last_update_time > 5:
qwprint("Cyclic update of files")
last_update_time = time.time()
available, suspended, todelete = openfiles()
#clear files, update with data loaded from the program
available.truncate(0)
suspended.truncate(0)
todelete.truncate(0)
#put data in there
available.writelines([(l + "\n") for l in available_list])
suspended.write(json.dumps(dict(suspended_dict)))
todelete.writelines([(l + "\n") for l in todelete_list])
#close files for it to take effect
available.close()
suspended.close()
todelete.close()
# else:
# print("no time to update", str(time.time() - last_update_time))

View File

@ -0,0 +1,16 @@
import socket
acc = ""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("0.0.0.0", 12345))
s.send(b"givacc")
acc = s.recv(1024)
print(acc)
s.close()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("0.0.0.0", 12345))
s.send(b"remacc|t788egrvdp@wwjmp.com")
print(s.recv(1024))
s.close()

View File

@ -0,0 +1,193 @@
from utils import browser_manager
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.alert import Alert, Command
from selenium.webdriver.common.keys import Keys
import requests
import os
import urllib
# recaptcha libraries
import pydub
import speech_recognition as sr
from bs4 import BeautifulSoup
from utils.global_vars import PROXY
class QL_CreateAccount:
def create_account(self):
self.info = RandomNameGenerator(self.proxy).get_person_info()
self.driver = browser_manager.start_browser()
self.temp_mail = TempMail()
self.temp_mail_address = self.temp_mail.get_new_temp_mail()
self.sign_up()
self.accept_eula()
print("Account created!".format(self.info, self.temp_mail_address))
def sign_up(self):
print("[+] Creating a new account for with mail [{}:{}]".format(self.info, self.temp_mail_address))
self.driver.get("https://www.qwiklabs.com/users/sign_up")
time.sleep(1.5)
#accept goddamn cookies
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
time.sleep(2)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_first_name", self.info[0], after_delay=1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_last_name", self.info[1], after_delay=1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_email", self.temp_mail_address, after_delay=1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_company_name", self.info[2], after_delay=1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye", after_delay=1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password_confirmation", "hellogoodbye", after_delay=1.5)
time.sleep(10)
self.resolve_captcha('/html/body/div[1]/div[1]/div[2]/form[2]/div[8]/div/div/iframe', "recaptcha-checkbox", "/html/body/div[4]/div[4]", "recaptcha-audio-button")
time.sleep(5)
self.driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/form[2]/div[9]/button').click()
def resolve_captcha(self, frame1_xpath, checkbox_classname, frame2_container_xpath, audio_id):
# switch to recaptcha frame
# frames = self.driver.find_elements_by_tag_name("iframe")
# self.driver.switch_to.frame(frames[0])
self.driver.switch_to.frame(self.driver.find_element_by_xpath(frame1_xpath))
browser_manager.delay(self.driver)
# click on checkbox to activate recaptcha
self.driver.find_element_by_class_name(checkbox_classname).click()
# switch to recaptcha audio control frame
self.driver.switch_to.default_content()
frame2_container = browser_manager.waitForElement(self.driver, By.XPATH, frame2_container_xpath)
# Sometimes the captcha gets accepted right away
if frame2_container is False:
return
frames = frame2_container.find_elements_by_tag_name("iframe")
self.driver.switch_to.frame(frames[0])
browser_manager.delay(self.driver)
# click on audio challenge
self.driver.find_element_by_id(audio_id).click()
# switch to recaptcha audio challenge frame
self.driver.switch_to.default_content()
frames = self.driver.find_elements_by_tag_name("iframe")
self.driver.switch_to.frame(frames[-1])
browser_manager.delay(self.driver)
# get the mp3 audio file
src = self.driver.find_element_by_id("audio-source").get_attribute("src")
print("[INFO] Audio src: %s" % src)
# download the mp3 audio file from the source
urllib.request.urlretrieve(src, os.path.normpath(os.getcwd() + "\\sample.mp3"))
browser_manager.delay(self.driver)
# load downloaded mp3 audio file as .wav
try:
sound = pydub.AudioSegment.from_mp3(os.path.normpath(os.getcwd() + "\\sample.mp3"))
sound.export(os.path.normpath(os.getcwd() + "\\sample.wav"), format="wav")
sample_audio = sr.AudioFile(os.path.normpath(os.getcwd() + "\\sample.wav"))
except Exception:
print("[ERR] Please run program as administrator or download ffmpeg manually, "
"http://blog.gregzaal.com/how-to-install-ffmpeg-on-windows/")
# translate audio to text with google voice recognition
r = sr.Recognizer()
with sample_audio as source:
audio = r.record(source)
key = r.recognize_google(audio)
print("[INFO] Recaptcha Passcode: %s" % key)
# key in results and submit
self.driver.find_element_by_id("audio-response").send_keys(key.lower())
self.driver.find_element_by_id("audio-response").send_keys(Keys.ENTER)
self.driver.switch_to.default_content()
browser_manager.delay(self.driver)
# self.driver.find_element_by_id("recaptcha-verify-button").click()
# browser_manager.delay(self.driver)
def accept_eula(self):
self.driver.get(self.temp_mail.get_confirmation_link())
time.sleep(5)
#insert password
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", "hellogoodbye", after_delay=1.5)
browser_manager.clickButton(self.driver, By.XPATH, "/html/body/div[2]/div[1]/div[2]/form/div[4]/button")
time.sleep(10)
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
time.sleep(2)
self.resolve_captcha('/html/body/div[1]/form/div/div/div/div/div/iframe', "recaptcha-checkbox", "/html/body/div[4]/div[4]", "recaptcha-audio-button")
time.sleep(5)
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[1]/form/input[5]')
time.sleep(1000)
class RandomNameGenerator():
def __init__(self):
self.proxyDict = {
"socks" : PROXY,
"socksVersion" : 5
}
def get_person_info(self):
if PROXY:
r = requests.get('https://randomuser.me/api', proxies=self.proxyDict)
else:
r = requests.get('https://randomuser.me/api')
firstname = r.json()['results'][0]['name']['first']
lastname = r.json()['results'][0]['name']['last']
#use city as company
company = r.json()['results'][0]['location']['city']
return (firstname, lastname, company)
# get a temp mail from https://www.1secmail.com/api/ and handle it using requests
class TempMail:
def __init__(self):
self.proxyDict = {
"socks" : PROXY,
"socksVersion" : 5
}
# Open a new tab, head over to temp-mail.org, click the delete button and get a new temp mail
def get_new_temp_mail(self):
self.email = requests.get('https://www.1secmail.com/api/v1/?action=genRandomMailbox', proxies=self.proxyDict).json()[0]
return self.email
# Wait for qwiklabs confirmation email to arrive, click it
def get_confirmation_link(self):
arrived = False
while arrived == False:
print('Waiting for confirmation email')
fetched_msg = requests.get('https://www.1secmail.com/api/v1/?action=getMessages&login=' + self.email.split('@')[0] + '&domain='+self.email.split('@')[1], proxies=self.proxyDict)
arrived = fetched_msg.text != '[]'
time.sleep(2)
print('Email arrived')
msg_id = fetched_msg.json()[0]['id']
email = requests.get('https://www.1secmail.com/api/v1/?action=readMessage&login=' + self.email.split('@')[0] + '&domain='+self.email.split('@')[1] + '&id=' + str(msg_id))
body = email.json()['body']
soup = BeautifulSoup(body, 'html.parser')
a = ""
for link in soup.find_all('a'):
if 'confirmation' in link.get('href'):
a = link.get('href')
print("Here's the confirmation link " + a)
return a

View File

@ -0,0 +1,72 @@
from utils import browser_manager
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.common.alert import Command
class QL_DeleteAccount:
def __init__(self, account):
self.account = account
def delete_account(self):
self.driver = browser_manager.start_browser()
self.sign_in()
self.delete()
def sign_in(self):
print("[+] Signing in using account [{}:{}]".format(self.account[0], self.account[1]))
self.driver.get("https://www.qwiklabs.com/users/sign_in")
time.sleep(1.5)
#accept goddamn cookies
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
time.sleep(2)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_email", self.account[0])
time.sleep(1.5)
browser_manager.inputText(self.driver, By.CSS_SELECTOR, "#user_password", self.account[1])
time.sleep(1.5)
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, "#new_user > div.form-actions > button")
time.sleep(5)
def delete(self):
# Click on profile icon, it's under a shadow-dom element
root1 = self.driver.find_element_by_css_selector("#my_account")
shadow = browser_manager.expand_shadow_element(self.driver, root1)
profile = shadow.find_element_by_css_selector('.ql-icon-button')
profile.click()
time.sleep(2)
# head over to settings
settings = self.driver.find_element_by_css_selector('#settings')
settings.click()
time.sleep(2)
#accept goddamn cookies
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/div[2]/div/button')
time.sleep(2)
# select 'security' tab
root1 = browser_manager.waitForElement(self.driver, By.XPATH, '/html/body/ql-drawer-container/ql-drawer/ql-sidenav/ql-sidenav-item[4]')
shadow = browser_manager.expand_shadow_element(self.driver, root1)
root1.click()
time.sleep(2)
# button = shadow.find_element_by_css_selector('.sidenav-item')
# button.click()
browser_manager.clickButton(self.driver, By.XPATH, '/html/body/ql-drawer-container/ql-drawer-content/main/div[3]/div[2]/div/a')
time.sleep(5)
#delete history
browser_manager.clickButton(self.driver, By.CSS_SELECTOR, '#delete_account_history_are_you_sure > div > div > div > a:nth-child(2)')
time.sleep(8)
# finally accept the deletition of the account
al = self.driver.switch_to.alert
al.accept()
print("Account {} deleted!".format(self.account))

View File

@ -0,0 +1,8 @@
services:
accountserver:
build: .
ports:
- "12345:12345"
volumes:
- ./code:/code
- ./account_data:/account_data

4
QWAccountServer/start.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
#sudo docker compose up
sudo docker compose up --build