Added Hex QR
This commit is contained in:
parent
d8b5b66298
commit
3eaefc7d26
8 changed files with 371 additions and 1 deletions
3
count.py
3
count.py
|
@ -20,6 +20,7 @@ for problem_name in problem_names:
|
||||||
pass
|
pass
|
||||||
# print traceback.format_exc()
|
# print traceback.format_exc()
|
||||||
|
|
||||||
|
problems.sort(key=lambda p: p.get("value"), reverse=True)
|
||||||
print "Grand Total: %d" % len(problems)
|
print "Grand Total: %d" % len(problems)
|
||||||
print "Category Breakdown:"
|
print "Category Breakdown:"
|
||||||
|
|
||||||
|
@ -29,4 +30,4 @@ for category, count in categories:
|
||||||
print " %s: %s" % (category, count)
|
print " %s: %s" % (category, count)
|
||||||
for problem in problems:
|
for problem in problems:
|
||||||
if problem.get("category") != category: continue
|
if problem.get("category") != category: continue
|
||||||
print " %s" % problem.get("title")
|
print " %s [%s]" % (problem.get("title"), problem.get("value"))
|
||||||
|
|
1
qrt/description.md
Normal file
1
qrt/description.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I've stumbled upon a very strange [QR code](${flag_png})... seems like it was generated with [this generator](http://hexqr.web.easyctf.com). What could it mean?
|
BIN
qrt/flag.png
Normal file
BIN
qrt/flag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
22
qrt/grader.py
Normal file
22
qrt/grader.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
from cStringIO import StringIO
|
||||||
|
from qrt import generate
|
||||||
|
|
||||||
|
FLAG = "are_triangles_more_secure_than_squares?_%s}"
|
||||||
|
|
||||||
|
def get_salt(random):
|
||||||
|
return "".join([random.choice("0123456789abcdef") for i in range(8)])
|
||||||
|
|
||||||
|
def generate(random):
|
||||||
|
salt = get_salt(random)
|
||||||
|
im = generate("easyctf{%s}" % (FLAG % salt))
|
||||||
|
flag = StringIO()
|
||||||
|
im.save(buf, format="PNG")
|
||||||
|
return dict(files={
|
||||||
|
"flag.png": flag
|
||||||
|
})
|
||||||
|
|
||||||
|
def grade(random, key):
|
||||||
|
salt = get_salt(random)
|
||||||
|
if key.find(FLAG % salt) >= 0:
|
||||||
|
return True, "Correct!"
|
||||||
|
return False, "Nope."
|
5
qrt/problem.yml
Normal file
5
qrt/problem.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
title: Hex QR
|
||||||
|
category: Programming
|
||||||
|
value: 200
|
||||||
|
author: mzhang
|
||||||
|
autogen: true
|
311
qrt/qrt.py
Normal file
311
qrt/qrt.py
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from math import ceil, sqrt
|
||||||
|
|
||||||
|
ALTCONST = sqrt(3) / 2.0
|
||||||
|
ISIZE = 784.0
|
||||||
|
IMARGIN = 22.0
|
||||||
|
|
||||||
|
def empty_hex(size):
|
||||||
|
c = 0
|
||||||
|
points = []
|
||||||
|
for i in range(2, size * 2 + 2, 2):
|
||||||
|
points.append([0] * i)
|
||||||
|
middle = []
|
||||||
|
for i in range(size * 2 - 1):
|
||||||
|
row = [0] * (size * 2)
|
||||||
|
middle.append(row)
|
||||||
|
epoints = list(row[:] for row in points[::-1])
|
||||||
|
return points + middle + epoints
|
||||||
|
|
||||||
|
def intify(points):
|
||||||
|
return map(lambda c: (int(c[0]), int(c[1])), points)
|
||||||
|
|
||||||
|
def draw_triangle(im, points, cell, size):
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
# draw.polygon(points, outline=(0, 0, 0))
|
||||||
|
if cell:
|
||||||
|
draw.polygon(intify(points), fill=(0, 0, 0))
|
||||||
|
return im
|
||||||
|
|
||||||
|
def getsection(i, size):
|
||||||
|
return 0 if i <= size - 1 else (1 if i < 3 * size - 1 else 2)
|
||||||
|
|
||||||
|
def getspace(size):
|
||||||
|
return max(0, sum(len(filter(lambda a: a == 0, b)) for b in empty_hex(size)) - 2)
|
||||||
|
|
||||||
|
def generate(string, debug=False):
|
||||||
|
size = 0
|
||||||
|
binstring = bin(int(string.encode("hex"), 16)).strip("0b")
|
||||||
|
while size < 2 or getspace(size + 1) < len(binstring):
|
||||||
|
size += 1
|
||||||
|
n = getspace(size)
|
||||||
|
# print size, len(binstring)
|
||||||
|
if debug: print "SIZE", size, " n =", n
|
||||||
|
im = Image.new("RGB", (int(ISIZE), int(ISIZE)), "white")
|
||||||
|
pattern = empty_hex(size)
|
||||||
|
# print len(binstring)
|
||||||
|
# print sum(len(i) for i in pattern)
|
||||||
|
pattern[0][len(string) % 2] = 1
|
||||||
|
curr = (1, 1 + len(string) % 2, 3 - len(string) % 2)
|
||||||
|
# 0 1
|
||||||
|
# 3 2
|
||||||
|
for c in range(n): # range(len(binstring)):
|
||||||
|
i, j, d = curr
|
||||||
|
row = pattern[i]
|
||||||
|
if c < len(binstring):
|
||||||
|
b = int(binstring[c])
|
||||||
|
pattern[i][j] = b
|
||||||
|
if c % 2 == 0:
|
||||||
|
pattern[i][j] ^= 1
|
||||||
|
|
||||||
|
section = getsection(i, size)
|
||||||
|
leftfacing = [j % 2 == 0, j % 2 != (i - size) % 2, j % 2 == 0][section]
|
||||||
|
if debug: print "c =", c, ", i =", i, ", j =", j, ", d =", d, ", s =", section, ", l =", leftfacing
|
||||||
|
if section == 0:
|
||||||
|
if getsection(i + 1, size) == 0:
|
||||||
|
if leftfacing:
|
||||||
|
if d == 0:
|
||||||
|
if j == 0:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i - 1, j - 1, d
|
||||||
|
elif d == 1 or d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j + 1, d
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
curr = i + 1, j + 2, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i - 1, j - 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif getsection(i + 1, size) == 1:
|
||||||
|
if leftfacing:
|
||||||
|
if d == 0:
|
||||||
|
if j == 0:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i - 1, j - 1, d
|
||||||
|
elif d == 1 or d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i - 1, j - 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif section == 1:
|
||||||
|
if getsection(i - 1, size) == 0:
|
||||||
|
if leftfacing:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
if d == 1:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 1 or d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if j == 0:
|
||||||
|
if d == 0:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
if d == 0 or d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif getsection(i - 1, size) == 1:
|
||||||
|
if getsection(i + 1, size) == 1:
|
||||||
|
if leftfacing:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 1 or d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if j == 0:
|
||||||
|
if d == 0:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 2, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
if d == 0 or d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif getsection(i + 1, size) == 2:
|
||||||
|
if leftfacing:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
else:
|
||||||
|
if d == 0:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j, d
|
||||||
|
elif d == 3:
|
||||||
|
if j == 0:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif section == 2:
|
||||||
|
if getsection(i - 1, size) == 1:
|
||||||
|
if leftfacing:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
if j == 0:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i + 1, j - 1, d
|
||||||
|
else:
|
||||||
|
if d == 0 or d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j, d
|
||||||
|
elif d == 2:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
curr = i + 1, j - 2, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i + 1, j - 1, d
|
||||||
|
elif getsection(i - 1, size) == 2:
|
||||||
|
if leftfacing:
|
||||||
|
if d == 0:
|
||||||
|
curr = i - 1, j + 1, d
|
||||||
|
elif d == 1 or d == 2:
|
||||||
|
curr = i, j + 1, d
|
||||||
|
elif d == 3:
|
||||||
|
if j == 0:
|
||||||
|
curr = i + 1, j, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
curr = i + 1, j - 1, d
|
||||||
|
else:
|
||||||
|
if j == len(row) - 1:
|
||||||
|
if d == 0:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j + 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j - 2, (d + 2) % 4
|
||||||
|
else:
|
||||||
|
if d == 0 or d == 3:
|
||||||
|
curr = i, j - 1, d
|
||||||
|
elif d == 1:
|
||||||
|
curr = i - 1, j + 1, d
|
||||||
|
elif d == 2:
|
||||||
|
curr = i + 1, j - 1, d
|
||||||
|
# for i in range(len(pattern)):
|
||||||
|
# for j in range(len(pattern[i])):
|
||||||
|
# section = 0 if i <= size - 1 else (1 if i < 3 * size - 1 else 2)
|
||||||
|
# leftfacing = [j % 2 == 0, j % 2 != (i - size) % 2, j % 2 == 0][section]
|
||||||
|
# if not leftfacing:
|
||||||
|
# print j,
|
||||||
|
# print
|
||||||
|
sidelen = (ISIZE - IMARGIN * 2) / (2.0 * size)
|
||||||
|
altitude = sidelen * ALTCONST
|
||||||
|
# print sidelen, altitude
|
||||||
|
for i in range(len(pattern)):
|
||||||
|
section = getsection(i, size)
|
||||||
|
row = pattern[i]
|
||||||
|
rowleft = (ISIZE / 2) - (altitude * len(row) / 2)
|
||||||
|
if section % 2 == 0:
|
||||||
|
evenrow = i % 2 == 0
|
||||||
|
for j in range(len(row)):
|
||||||
|
cell = row[j]
|
||||||
|
top = ceil(i / 2.0) * sidelen - (0.5 * sidelen if not evenrow else 0) + IMARGIN
|
||||||
|
bottom = top + sidelen
|
||||||
|
if j % 2 == 0:
|
||||||
|
points = [
|
||||||
|
(rowleft + altitude * j, top + sidelen / 2),
|
||||||
|
(rowleft + altitude * (j + 1), top), (rowleft + altitude * (j + 1), bottom)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
points = [
|
||||||
|
(rowleft + altitude * (j + 1), top + sidelen / 2),
|
||||||
|
(rowleft + altitude * j, top), (rowleft + altitude * j, bottom)
|
||||||
|
]
|
||||||
|
draw_triangle(im, points, cell, size)
|
||||||
|
else:
|
||||||
|
evenrow = (i - size) % 2 == 1
|
||||||
|
for j in range(len(row)):
|
||||||
|
cell = row[j]
|
||||||
|
top = ceil(i / 2.0) * sidelen - (0.5 * sidelen if i % 2 == 1 else 0) + IMARGIN
|
||||||
|
bottom = top + sidelen
|
||||||
|
if j % 2 == (i - size) % 2:
|
||||||
|
points = [
|
||||||
|
(rowleft + altitude * (j + 1), top + sidelen / 2),
|
||||||
|
(rowleft + altitude * j, top), (rowleft + altitude * j, bottom)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
points = [
|
||||||
|
(rowleft + altitude * j, top + sidelen / 2),
|
||||||
|
(rowleft + altitude * (j + 1), top), (rowleft + altitude * (j + 1), bottom)
|
||||||
|
]
|
||||||
|
draw_triangle(im, points, cell, size)
|
||||||
|
return im
|
||||||
|
|
||||||
|
# im = generate("easyctf{are_triangles_more_secure_than_squares?}")
|
||||||
|
# im.save("flag.png")
|
||||||
|
|
||||||
|
# for i in range(40, 60):
|
||||||
|
# generate("A" * i, "/tmp/%d.png" % i)
|
BIN
qrt/qrt.pyc
Normal file
BIN
qrt/qrt.pyc
Normal file
Binary file not shown.
30
qrt/server.py
Normal file
30
qrt/server.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from flask import Flask, request
|
||||||
|
from qrt import generate
|
||||||
|
from base64 import b64encode
|
||||||
|
from binascii import b2a_base64
|
||||||
|
from cStringIO import StringIO
|
||||||
|
from traceback import format_exc
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/", methods=["GET", "POST"])
|
||||||
|
def index():
|
||||||
|
try:
|
||||||
|
html = "<title>hex qr</title><form method=post>enter a string: <input type=text name=text value='%s' autocomplete=off autofocus /></form>"
|
||||||
|
if request.method == "POST":
|
||||||
|
if not request.form.get("text"):
|
||||||
|
html %= ""
|
||||||
|
html += "<p>empty</p>"
|
||||||
|
else:
|
||||||
|
html %= request.form["text"]
|
||||||
|
im = generate(request.form["text"])
|
||||||
|
buf = StringIO()
|
||||||
|
im.save(buf, format="JPEG")
|
||||||
|
html += "<img src='data:image/jpeg;base64,%s'>" % b2a_base64(buf.getvalue())
|
||||||
|
else:
|
||||||
|
html %= ""
|
||||||
|
return html
|
||||||
|
except:
|
||||||
|
return "<!--\nthere's a problem, here's the details:\n%s\n-->" % format_exc()
|
||||||
|
|
||||||
|
app.run(host="0.0.0.0", port=5000)
|
Loading…
Reference in a new issue