Add app
This commit is contained in:
174
.gitignore
vendored
Normal file
174
.gitignore
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
73
app.py
Normal file
73
app.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from __future__ import annotations
|
||||
from flask import Flask, render_template
|
||||
import subprocess
|
||||
from time import sleep
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
def extractAsciiFromDump(dump: [str]) -> [str]:
|
||||
res = ""
|
||||
for line in dump:
|
||||
res += line.split("|")[-1].strip()
|
||||
return res
|
||||
|
||||
usingPm3 = False
|
||||
|
||||
@app.route('/api/uid')
|
||||
def uid():
|
||||
'''
|
||||
Read the UID of a visible ISO-14443A card.
|
||||
'''
|
||||
uid = None
|
||||
global usingPm3
|
||||
while usingPm3:
|
||||
sleep(0.1)
|
||||
usingPm3 = True
|
||||
try:
|
||||
output = subprocess.check_output(["proxmark3", "/dev/ttyACM0", "-c", "hf 14a read"], text=True, stderr=subprocess.DEVNULL).split("\n")
|
||||
for line in output:
|
||||
if "UID: " in line:
|
||||
uid = line[line.index("UID: ")+4:].strip()
|
||||
break
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
finally:
|
||||
print(uid)
|
||||
usingPm3 = False
|
||||
return {
|
||||
"uid": uid
|
||||
}
|
||||
|
||||
@app.route('/api/sector/<sector>')
|
||||
def sector(sector):
|
||||
'''
|
||||
Read a sector from a visible Mifare Classic card.
|
||||
'''
|
||||
dump = None
|
||||
global usingPm3
|
||||
while usingPm3:
|
||||
sleep(0.1)
|
||||
usingPm3 = True
|
||||
try:
|
||||
output = subprocess.check_output(["proxmark3", "/dev/ttyACM0", "-c", f"hf mf cgetsc -s {sector}"], text=True, stderr=subprocess.DEVNULL).split("\n")
|
||||
for i, line in enumerate(output):
|
||||
if "--> hf mf cgetsc -s " in line:
|
||||
dump = extractAsciiFromDump(output[i+4:])
|
||||
break
|
||||
finally:
|
||||
usingPm3 = False
|
||||
return {
|
||||
"dump": dump
|
||||
}
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template("door.html",
|
||||
allowed_ids={
|
||||
# "44 61 76 65": ["Welcome CEO", [(3, "I am a very important CEO so open this door now!.........i......")]],
|
||||
"44 61 76 65": ["Welcome CEO<br/></br>flag{yep_big_boss}", []], # CEO
|
||||
"3C 36 6A 22": ["The site manager would like to see you in their office. Please speak to APO Grove, and tell him the cleaner sent you.<br/></br>flag{ooh_a_manager}", []], # Developer
|
||||
"2F 92 5D B2": ["Thanks for doing our cleaning! I found a card on a desk earlier. It has a label saying \"UID: 3C 36 6A 22\". Not sure what to do with it.<br/></br>flag{another_lost_card}", []], # Cleaner
|
||||
})
|
||||
|
||||
app.run(host='127.0.0.1', port=8080)
|
||||
70
app_2.py
Normal file
70
app_2.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from __future__ import annotations
|
||||
from flask import Flask, render_template
|
||||
import subprocess
|
||||
from time import sleep
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
def extractAsciiFromDump(dump: [str]) -> [str]:
|
||||
res = ""
|
||||
for line in dump:
|
||||
res += line.split("|")[-1].strip()
|
||||
return res
|
||||
|
||||
usingPm3 = False
|
||||
|
||||
@app.route('/api/uid')
|
||||
def uid():
|
||||
'''
|
||||
Read the UID of a visible ISO-14443A card.
|
||||
'''
|
||||
uid = None
|
||||
global usingPm3
|
||||
while usingPm3:
|
||||
sleep(0.1)
|
||||
usingPm3 = True
|
||||
try:
|
||||
output = subprocess.check_output(["proxmark3", "/dev/ttyACM1", "-c", "hf 14a read"], text=True, stderr=subprocess.DEVNULL).split("\n")
|
||||
for line in output:
|
||||
if "UID: " in line:
|
||||
uid = line[line.index("UID: ")+4:].strip()
|
||||
break
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
finally:
|
||||
print(uid)
|
||||
usingPm3 = False
|
||||
return {
|
||||
"uid": uid
|
||||
}
|
||||
|
||||
@app.route('/api/sector/<sector>')
|
||||
def sector(sector):
|
||||
'''
|
||||
Read a sector from a visible Mifare Classic card.
|
||||
'''
|
||||
dump = None
|
||||
global usingPm3
|
||||
while usingPm3:
|
||||
sleep(0.1)
|
||||
usingPm3 = True
|
||||
try:
|
||||
output = subprocess.check_output(["proxmark3", "/dev/ttyACM1", "-c", f"hf mf cgetsc -s {sector}"], text=True, stderr=subprocess.DEVNULL).split("\n")
|
||||
for i, line in enumerate(output):
|
||||
if "--> hf mf cgetsc -s " in line:
|
||||
dump = extractAsciiFromDump(output[i+4:])
|
||||
break
|
||||
finally:
|
||||
usingPm3 = False
|
||||
return {
|
||||
"dump": dump
|
||||
}
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template("door.html",
|
||||
allowed_ids={
|
||||
"44 61 76 65": ["Welcome CEO<br/></br>flag{open_them_all}", [(3, "I am a very important CEO so open this door now!.........i......")]], # CEO
|
||||
})
|
||||
|
||||
app.run(host='127.0.0.1', port=8081)
|
||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
Flask==3.1.0
|
||||
125
templates/door.html
Normal file
125
templates/door.html
Normal file
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Smart Door Lock</title>
|
||||
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#lockContainer {
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#lockIcon {
|
||||
font-size: 60px;
|
||||
color: #3498db; /* Default color for locked icon */
|
||||
}
|
||||
|
||||
#idCardStatus {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
p.accessGranted {
|
||||
color: #2ecc71;
|
||||
}
|
||||
|
||||
p.accessDenied {
|
||||
color: #e74c3c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="lockContainer">
|
||||
<div id="lockIcon">🔒</div>
|
||||
<div id="idCardStatus">
|
||||
<p>Waiting for card...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var requestInProgress = false;
|
||||
var currentUid = null;
|
||||
|
||||
const checkIdCardContents = async (sector, requiredContents) => {
|
||||
const data = await fetch("/api/sector/" + sector);
|
||||
const dump = (await data.json()).dump;
|
||||
console.log(dump === requiredContents);
|
||||
return dump === requiredContents;
|
||||
};
|
||||
|
||||
const checkIdCardStatus = () => {
|
||||
fetch("/api/uid").then(async (data) => {
|
||||
const uid = (await data.json()).uid;
|
||||
if (uid === currentUid) {
|
||||
setTimeout(checkIdCardStatus, 0);
|
||||
return;
|
||||
}
|
||||
currentUid = uid;
|
||||
if (uid) {
|
||||
const item = {{allowed_ids|tojson}}[uid];
|
||||
if (item === undefined) updateStatus("Access Denied - ID: " + uid, "accessDenied", "🔒"); // Change to locked icon
|
||||
else if (item[1].length > 0) {
|
||||
updateStatus("ID: " + uid, "", "🔒", "<b>Reading card, please wait...</b>");
|
||||
let contentsCorrect = true;
|
||||
for (let sectorInfo of item[1]) {
|
||||
if (!(await checkIdCardContents(...sectorInfo))) {
|
||||
contentsCorrect = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (contentsCorrect) {
|
||||
updateStatus("Unlocked - ID: " + uid, "accessGranted", "🔓", item[0] + "<br/></br><b>Card contents correct</b>");
|
||||
} else {
|
||||
updateStatus("Access Denied - ID: " + uid, "accessDenied", "🔒", "<b>Card contents incorrect</b>");
|
||||
}
|
||||
} else {
|
||||
updateStatus("Unlocked - ID: " + uid, "accessGranted", "🔓", item[0]);
|
||||
}
|
||||
} else {
|
||||
updateStatus("Waiting for card...", "", "🔒"); // No loading icon
|
||||
}
|
||||
|
||||
setTimeout(checkIdCardStatus, 0);
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
updateStatus("Error occurred while checking ID card status.", "", "🔒"); // No loading icon
|
||||
setTimeout(checkIdCardStatus, 0);
|
||||
});
|
||||
}
|
||||
|
||||
const updateStatus = (status, className, icon, message = '') => {
|
||||
$("#idCardStatus").html("<p class='" + className + "'>" + status + "</p>");
|
||||
if (message != '') {
|
||||
$("#idCardStatus").append("<br/><p class='" + className + "'>" + message + "</p>");}
|
||||
$("#lockIcon").html(icon);
|
||||
};
|
||||
|
||||
// Initial check when the page loads
|
||||
checkIdCardStatus();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user