Compare commits

..

No commits in common. "main" and "1.0.10" have entirely different histories.
main ... 1.0.10

6 changed files with 95 additions and 33 deletions

84
app.py
View file

@ -7,9 +7,11 @@ import random
import sqlite3
import time
import html
import zipfile
from argparse import ArgumentParser
from flask import Flask, request, render_template, send_file
from datetime import datetime
from io import BytesIO
# stuff
with open(f"{os.getcwd()}/config.json", "r") as f:
@ -17,6 +19,7 @@ with open(f"{os.getcwd()}/config.json", "r") as f:
parser = ArgumentParser(prog="syscheck_receiver", description="Server that saves SysCheck report uploads.")
parser.add_argument("-d", "--debug", dest="debug", action='store_true', help="Runs with Flask debug server instead of Waitress. DO NOT USE IN PRODUCTION!!!!")
parser.add_argument("-r", "--replace-url", dest="replace_url", help="Allows to replace the default sysCheck url with your own (mostly meant for the pre-provided docker images).")
args = parser.parse_args()
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
@ -36,11 +39,6 @@ def return_error(message: string, code: int):
resp.headers["Content-Type"] = "application/json"
return resp
def no_cf_chunking(txt):
resp = flask.Response(txt)
resp.headers["X-Content-Length"] = len(txt.encode("utf-8")) # Cloudflares Proxy strips "Content-Length" when chunking, so we just re-add it manually.
return resp
# docker
if config["docker"]:
report_dir = "/data/reports"
@ -49,6 +47,11 @@ else:
report_dir = f"{os.getcwd()}/reports"
db_dir = f"{os.getcwd()}/reports.db"
if args.replace_url is None:
replace_url = config["replace_str"]
else:
replace_url = args.replace_url
# sever code
app = Flask('syscheck_receiver')
@ -69,27 +72,30 @@ def index():
return render_template("index.html", uploadIndex=uploadIndex, report_count=report_count[0][0], svr_ver=config["version"]), 200
@app.route("/syscheck_receiver.php", methods=["POST"])
@app.route("/syscheck_up.php", methods=["POST"]) # SysCheckME-dev
@app.route("/syscheck_receiver.php", methods=["POST"]) # literally anything else (DNS?)
def syscheck_report():
form_data = request.form.to_dict(flat=False)
report_txt = form_data["syscheck"][0]
console_id = get_console_id(report_txt)[:-4]
# check if console id: is present
console_id = get_console_id(report_txt)
if console_id == "0":
return no_cf_chunking("ERROR: Not a valid sysCheck!"), 200
# check if syscheck isn't too small or too large
if len(report_txt.encode("utf-8")) > 6144:
return no_cf_chunking("ERROR: Report is too large! Max is 6KB."), 200
elif len(report_txt.encode("utf-8")) < 1330:
return no_cf_chunking("ERROR: Report is too small! Min is 1.3KB."), 200
return "ERROR: Not a valid sysCheck!", 200
# figure difference between syscheck2 and syscheckhde and newer
if report_txt.split("\n")[0].startswith("sysCheck v2.1.0b19"):
console_id_censor = console_id[:-4]+"****"
old_syscheck = True
else:
old_syscheck = False
console_id = console_id[:-4]
timestamp = int(time.time())
report_id = id_generator(6, 'AaBbCcDdFfeEgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWXxYyZz1234567890')
if form_data["password"][0] == config["upload_password"]:
if form_data["password"][0] in config["upload_passwords"]:
try:
with open(f"{report_dir}/{report_id}.csv", "a+") as report:
if old_syscheck:
report.write(report_txt.replace(console_id, console_id_censor))
else:
report.write(report_txt)
db = sqlite3.connect(db_dir)
@ -98,26 +104,50 @@ def syscheck_report():
db.commit()
db.close()
return no_cf_chunking(f"Success! Report ID: {report_id}"), 200
return f"Success! Report ID: {report_id}", 200
except Exception as ex:
print(ex)
return no_cf_chunking("ERROR: Failed to save SysCheck report!"), 200
else:
return no_cf_chunking("ERROR: Unauthorized"), 200
return "ERROR: Failed to save SysCheck report!", 200
@app.route("/download_csv", methods=["GET"], defaults={'_route': 'direct'})
@app.route("/view_report", methods=["GET"], defaults={'_route': 'template'})
def view_report(_route):
else:
return "ERROR: Unauthorized", 200
@app.route("/view_report", methods=["GET"])
def view_report():
report_id = request.args.get("id")
if os.path.isfile(f"{report_dir}/{report_id}.csv"):
if _route == "template":
with open(f"{report_dir}/{report_id}.csv", "r") as report:
return render_template("view_report.html", report_id=report_id, report_content=html.escape(report.read()), svr_ver=config["version"]), 200
else:
return send_file(f"{report_dir}/{report_id}.csv", as_attachment=True, download_name="report.csv")
else:
return "Report does not exist.", 404
@app.route("/syscheck_dl", methods=["GET"])
def syscheck():
if len("http://syscheck.rc24.xyz/syscheck_receiver.php") < len(replace_url):
return "Replacement host has to be exactly 46 characters; Specified URL is too long!", 400
elif len("http://syscheck.rc24.xyz/syscheck_receiver.php") > len(replace_url):
return "Replacement host has to be exactly 46 characters; Specified URL is too short!", 400
dol = BytesIO()
zip = BytesIO()
# hex edit boot.dol
dol2 = open(f"{os.getcwd()}/static/syscheck/boot.dol", "rb")
dol.write(dol2.read().replace("http://syscheck.rc24.xyz/syscheck_receiver.php".encode("utf-8"), replace_url.encode("utf-8")))
dol.seek(0)
dol2.close()
zf = zipfile.ZipFile(zip, "w", zipfile.ZIP_DEFLATED, False)
zf.writestr("apps/SysCheckME/boot.dol", dol.read())
dol.close()
zf.write(f"{os.getcwd()}/static/syscheck/icon.png", "apps/SysCheckME/icon.png")
zf.write(f"{os.getcwd()}/static/syscheck/meta.xml", "apps/SysCheckME/meta.xml")
zf.close()
zip.seek(0)
# send zipfile
return send_file(zip, mimetype="application/zip", as_attachment=True, download_name="SysCheckME.zip"), 200
# handle errors
@app.errorhandler(400)
@app.errorhandler(404)

View file

@ -1,7 +1,11 @@
{
"ip": "0.0.0.0",
"port": "6969",
"version": "1.1.2",
"upload_password": "B277eNGp789a",
"version": "1.0.10",
"upload_passwords": [
"d2wRuTEObSAN",
"B277eNGp789a"
],
"replace_str": "http://syscheck.crafterpika.cc/syscheck_up.php",
"docker": false
}

BIN
static/syscheck/boot.dol Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
static/syscheck/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

29
static/syscheck/meta.xml Normal file
View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1">
<name>SysCheck ModMii Edition</name>
<coder>blackb0x, JoostinOnline, Double_A, R2-D2199, Nano</coder>
<version>2.5.0</version>
<release_date>20230309000000</release_date>
<short_description>System Checker ModMii Edition</short_description>
<long_description>Homebrew application which does several checks on installed IOS and custom IOS:
- Base IOS Detection
- vIOS Detection
- Beer Ticket
- IOS Stub
- Fake Signature (aka Trucha Bug)
- ES_DiVerify (aka ES_Identify)
- Flash Access
- NAND Access
- Boot2 Access
- USB 2.0
SysCheck generates a report on the root of your storage device (e.g. usb:/SysCheck.csv).
The author can not be held responsible for any damage SysCheck might cause!</long_description>
<arguments>
<arg>--debug=false</arg>
<arg>--forceNoAHBPROT=false</arg>
<arg>--skipIOS=0</arg>
</arguments>
<no_ios_reload/>
</app>

View file

@ -9,8 +9,7 @@
</head>
<body>
<div class="topnav">
<a href="https://github.com/modmii/SysCheck-ModMii-Edition/releases/latest" target="_blank">Download SysCheckME</a>
<a href="https://wii.hacks.guide/syscheck" target="_blank">How to use</a>
<a href="/syscheck_dl">Download SysCheckME</a>
</div>
<center>
<h1>Latest Uploads:</h1>