Skip to content

Commit

Permalink
security checks bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
dyang886 committed Mar 28, 2024
1 parent e4af7d0 commit 2705a0c
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 40 deletions.
105 changes: 88 additions & 17 deletions helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
from bs4 import BeautifulSoup
from fuzzywuzzy import fuzz
import polib
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtCore import Qt, QEventLoop, QThread, QTimer, pyqtSignal, QUrl
from PyQt6.QtGui import QIcon, QPixmap
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import QDialog, QCheckBox, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, QLabel, QLineEdit, QMessageBox, QFileDialog
import requests

Expand Down Expand Up @@ -286,14 +287,86 @@ def run(self):
self.error.emit(str(e))


class BrowserDialog(QDialog):
content_ready = pyqtSignal(str)

def __init__(self, parent=None):
super().__init__(parent)
self.browser = QWebEngineView(self)
layout = QVBoxLayout(self)
layout.addWidget(self.browser)
self.setLayout(layout)
self.resize(800, 600)
self.setWindowTitle(tr("Please complete any security checks..."))
self.setWindowIcon(QIcon(resource_path("assets/logo.ico")))

self.check_timer = QTimer(self)
self.found_content = False
self.check_count = 0

def load_url(self, url, target_text):
self.url = url
self.target_text = target_text
self.found_content = False
self.check_count = 0
self.browser.loadFinished.connect(self.on_load_finished)
self.browser.load(QUrl(self.url))
self.hide()

def on_load_finished(self, success):
self.check_timer.timeout.connect(self.check_content)
self.check_timer.start(1000)

def check_content(self):
if self.check_count >= 3:
self.show()
self.check_count += 1
self.browser.page().toHtml(self.handle_html)

def handle_html(self, html):
if self.target_text in html:
self.found_content = True
self.check_timer.stop()
self.content_ready.emit(html)
self.close()

def closeEvent(self, event):
if not self.found_content:
self.check_timer.stop()
self.browser.loadFinished.disconnect(self.on_load_finished)
self.content_ready.emit("")
event.accept()


class DownloadBaseThread(QThread):
message = pyqtSignal(str, str)
messageBox = pyqtSignal(str, str, str)
finished = pyqtSignal(int)
loadUrl = pyqtSignal(str, str)

trainer_urls = {} # Store search results: {trainer name: download link}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
}

def __init__(self, parent=None):
super().__init__(parent)
self.html_content = ""
self.browser_dialog = BrowserDialog()
self.loadUrl.connect(self.browser_dialog.load_url)
self.browser_dialog.content_ready.connect(self.handle_content_ready)

def get_webpage_content(self, url, target_text):
self.loop = QEventLoop()
self.loadUrl.emit(url, target_text)
self.loop.exec()

return BeautifulSoup(self.html_content, 'html.parser')

def handle_content_ready(self, html_content):
self.html_content = html_content
if self.loop.isRunning():
self.loop.quit()

def is_internet_connected(self, urls=None, timeout=5):
if urls is None:
Expand Down Expand Up @@ -446,7 +519,6 @@ def run(self):
self.finished.emit(1)
return

# ts initialization will pop up a cmd window
try:
global ts
if "translators" not in sys.modules:
Expand Down Expand Up @@ -510,7 +582,7 @@ def run(self):

if len(DownloadBaseThread.trainer_urls) == 0:
self.message.emit(tr("No results found."), "failure")
self.finished(1)
self.finished.emit(1)
return

self.finished.emit(0)
Expand Down Expand Up @@ -574,14 +646,13 @@ def translate_keyword(self, keyword):
def search_from_archive(self, keywordList):
# Search for results from fling archive
url = "https://archive.flingtrainer.com/"
reqs = requests.get(url, headers=self.headers)
archiveHTML = BeautifulSoup(reqs.text, 'html.parser')
archiveHTML = self.get_webpage_content(url, "FLiNG Trainers Archive")

# Check if the request was successful
if reqs.status_code == 200:
self.message.emit(tr("Request success!") + " 1/2", "success")
if archiveHTML.find():
self.message.emit(tr("Connection success!") + " 1/2", "success")
else:
self.message.emit(tr("Request failed with status code: ") + str(reqs.status_code), "failure")
self.message.emit(tr("Connection failed.") + " 1/2", "failure")

for link in archiveHTML.find_all(target="_self"):
# parse trainer name
Expand All @@ -598,13 +669,13 @@ def search_from_archive(self, keywordList):
def search_from_main_site(self, keywordList):
# Search for results from fling main site, prioritized, will replace same trainer from archive
url = "https://flingtrainer.com/all-trainers-a-z/"
reqs = requests.get(url, headers=self.headers)
mainSiteHTML = BeautifulSoup(reqs.text, 'html.parser')
mainSiteHTML = self.get_webpage_content(url, "All Trainers (A-Z)")

if reqs.status_code == 200:
self.message.emit(tr("Request success!") + " 2/2", "success")
if mainSiteHTML.find():
self.message.emit(tr("Connection success!") + " 2/2", "success")
else:
self.message.emit(tr("Request failed with status code: ") + str(reqs.status_code), "failure")
self.message.emit(tr("Connection failed.") + " 2/2", "failure")
time.sleep(0.5)

for ul in mainSiteHTML.find_all('ul'):
for li in ul.find_all('li'):
Expand Down Expand Up @@ -715,7 +786,7 @@ def run(self):
cnt += 1
# Warn user if extra files found
if cnt > 0:
QMessageBox.information(self, tr("Attention"), tr("Additional actions required\nPlease check folder for details!"))
self.messageBox.emit("info", tr("Attention"), tr("Additional actions required\nPlease check folder for details!"))
os.startfile(self.tempDir)

os.makedirs(self.trainerPath, exist_ok=True)
Expand All @@ -737,7 +808,7 @@ def run(self):
os.remove(rhLog)

except Exception as e:
QMessageBox.critical(self, tr("Error"), tr("Could not find the downloaded trainer file, please try turning your antivirus software off."))
self.messageBox.emit("error", tr("Error"), tr("Could not find the downloaded trainer file, please try turning your antivirus software off."))
self.finished.emit(1)
return

Expand Down Expand Up @@ -805,4 +876,4 @@ def remove_bgMusic(self, source_exe, resource_type_list):
subprocess.run(command, creationflags=subprocess.CREATE_NO_WINDOW)
else:
# Try the next resource type if any remain
self.remove_bgMusic(source_exe, resource_type_list)
self.remove_bgMusic(source_exe, resource_type_list)
Binary file modified locale/en_US/LC_MESSAGES/Game Cheats Manager.mo
Binary file not shown.
11 changes: 7 additions & 4 deletions locale/en_US/LC_MESSAGES/Game Cheats Manager.po
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ msgstr "About"
msgid "Version:"
msgstr "Version:"

msgid "Please complete any security checks..."
msgstr "Please complete any security checks..."

msgid "Translation request failed with status code:"
msgstr "Translation request failed with status code:"

Expand Down Expand Up @@ -85,11 +88,11 @@ msgstr "Translating keywords..."
msgid "No translations found."
msgstr "No translations found."

msgid "Request success!"
msgstr "Request success!"
msgid "Connection success!"
msgstr "Connection success!"

msgid "Request failed with status code:"
msgstr "Request failed with status code:"
msgid "Connection failed."
msgstr "Connection failed."

msgid "Translating trainer name..."
msgstr "Translating trainer name..."
Expand Down
Binary file modified locale/zh_CN/LC_MESSAGES/Game Cheats Manager.mo
Binary file not shown.
11 changes: 7 additions & 4 deletions locale/zh_CN/LC_MESSAGES/Game Cheats Manager.po
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ msgstr "关于"
msgid "Version:"
msgstr "版本:"

msgid "Please complete any security checks..."
msgstr "请完成所有安全检查..."

msgid "Translation request failed with status code:"
msgstr "翻译请求失败,状态代码为:"

Expand Down Expand Up @@ -85,11 +88,11 @@ msgstr "翻译关键词中..."
msgid "No translations found."
msgstr "未找到翻译。"

msgid "Request success!"
msgstr "请求成功!"
msgid "Connection success!"
msgstr "连接成功!"

msgid "Request failed with status code:"
msgstr "请求失败,状态代码为:"
msgid "Connection failed."
msgstr "连接失败。"

msgid "Translating trainer name..."
msgstr "翻译修改器中..."
Expand Down
Binary file modified locale/zh_TW/LC_MESSAGES/Game Cheats Manager.mo
Binary file not shown.
11 changes: 7 additions & 4 deletions locale/zh_TW/LC_MESSAGES/Game Cheats Manager.po
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ msgstr "關於"
msgid "Version:"
msgstr "版本:"

msgid "Please complete any security checks..."
msgstr "請完成所有安全檢查..."

msgid "Translation request failed with status code:"
msgstr "翻譯請求失敗,狀態碼為:"

Expand Down Expand Up @@ -85,11 +88,11 @@ msgstr "翻譯關鍵字..."
msgid "No translations found."
msgstr "未找到翻譯。"

msgid "Request success!"
msgstr "請求成功!"
msgid "Connection success!"
msgstr "連接成功!"

msgid "Request failed with status code:"
msgstr "請求失敗,狀態碼為:"
msgid "Connection failed."
msgstr "連結失敗。"

msgid "Translating trainer name..."
msgstr "翻譯修改器名稱..."
Expand Down
65 changes: 55 additions & 10 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import shutil
import sys

from PyQt6.QtCore import Qt
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QAction, QColor, QFont, QFontDatabase, QIcon, QPixmap
from PyQt6.QtWidgets import QApplication, QFileDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidgetItem, QMainWindow, QMessageBox, QPushButton, QVBoxLayout, QWidget, QListWidget
from tendo import singleton
Expand All @@ -27,7 +27,7 @@ def __init__(self):
self.setFixedSize(self.size())

# Version, user prompts, and links
self.appVersion = "2.0.0"
self.appVersion = "2.0.0-beta"
self.githubLink = "https://github.com/dyang886/Game-Cheats-Manager"
self.updateLink = "https://api.github.com/repos/dyang886/Game-Cheats-Manager/releases/latest"
self.trainerSearchEntryPrompt = tr("Search for installed")
Expand Down Expand Up @@ -169,6 +169,12 @@ def __init__(self):

self.show_cheats()

# Check for trainer update timer
self.timer = QTimer(self)
self.timer.timeout.connect(self.on_check_update)
self.on_check_update()
self.timer.start(300000)

# ===========================================================================
# Core functions
# ===========================================================================
Expand Down Expand Up @@ -277,6 +283,38 @@ def change_path(self):
self.downloadListBox.addItem(tr("No path selected."))
self.enable_all_widgets()
return

def on_check_update(self):
# The binary pattern representing "FLiNGTrainerNamedPipe_" followed by some null bytes and the date
pattern_hex = '46 00 4c 00 69 00 4E 00 47 00 54 00 72 00 61 00 69 00 6E 00 65 00 72 00 4E 00 61 00 6D 00 65 00 64 00 50 00 69 00 70 00 65 00 5F'
# Convert the hex pattern to binary
pattern = bytes.fromhex(''.join(pattern_hex.split()))

for index, trainerPath in enumerate(self.trainers.values()):
trainerBuildDate = ""
checkUpdateUrl = "https://flingtrainer.com/tag/"

with open(trainerPath, 'rb') as file:
content = file.read()
pattern_index = content.find(pattern)

if pattern_index == -1:
continue

# Find the start of the date string after the pattern and skip null bytes (00)
start_index = pattern_index + len(pattern)
while content[start_index] == 0:
start_index += 1

# The date could be "Mar 8 2024" or "Dec 10 2022"
date_match = re.search(rb'\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{1,2}\s+\d{4}\b', content[start_index:])

if date_match:
trainerBuildDate = date_match.group().decode('utf-8')
# print(trainerBuildDate)

# extract trainer name


def on_migration_finished(self, new_path):
self.trainerPath = new_path
Expand All @@ -297,10 +335,10 @@ def download_display(self, keyword):
self.downloadable = False
self.searchable = False

self.download_thread = DownloadDisplayThread(keyword, self)
self.download_thread.message.connect(self.on_message)
self.download_thread.finished.connect(self.on_display_finished)
self.download_thread.start()
display_thread = DownloadDisplayThread(keyword, self)
display_thread.message.connect(self.on_message)
display_thread.finished.connect(self.on_display_finished)
display_thread.start()

def on_message(self, message, type=None):
item = QListWidgetItem(message)
Expand Down Expand Up @@ -332,10 +370,17 @@ def download_trainers(self, index):
self.downloadable = False
self.searchable = False

self.download_thread = DownloadTrainersThread(index, self.trainerPath, self.trainers, self)
self.download_thread.message.connect(self.on_message)
self.download_thread.finished.connect(self.on_download_finished)
self.download_thread.start()
download_thread = DownloadTrainersThread(index, self.trainerPath, self.trainers, self)
download_thread.message.connect(self.on_message)
download_thread.messageBox.connect(self.on_message_box)
download_thread.finished.connect(self.on_download_finished)
download_thread.start()

def on_message_box(self, type, title, text):
if type == "info":
QMessageBox.information(self, title, text)
elif type == "error":
QMessageBox.critical(self, title, text)

def on_download_finished(self, status):
self.downloadable = False
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ beautifulsoup4
fuzzywuzzy
polib
PyQt6
PyQt6-WebEngine
python-Levenshtein
requests
tendo
tendo

0 comments on commit 2705a0c

Please sign in to comment.