Created
December 9, 2017 19:43
-
-
Save mjonasz/48ae3fd6c4fbb8a853b91bbfa16b9a7f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# dostajemy kostke rubika z qrcodem, trzeba ją ułożyć i przeczytać qr cody, w którymś jest link do następnego levelu | |
# tutaj zamiast ją układać robię permutacje krawędzi * permutacje rogów (z odpowiednim obrotem), | |
# to daje 4!*4! per ściane, czyli jeszcze *6 per kostke - to je spoko, najwolniejsze tu jest ściąganie obrazków z japonii | |
from PIL import Image | |
import zbarlight | |
import itertools | |
import requests | |
from io import BytesIO | |
from enum import Enum | |
CORNER = "CORNER" | |
EDGE = "EDGE" | |
CENTER = "CENTER" | |
def find_color(im): | |
for x in range(0, im.width): | |
for y in range(0, im.height): | |
pixel = im.getpixel((x, y)) | |
if pixel != (0, 0, 0): | |
return pixel | |
def preview(im): | |
prev = im.resize((41 * 6, 41 * 6)) | |
prev.show() | |
def combine_blocks(corners, edges, center): | |
im = Image.new('RGB', (41, 41)) | |
im.paste(corners[0], (0, 0, 14, 14)) | |
im.paste(corners[1], (41 - 14, 0, 41, 14)) | |
im.paste(corners[2], (41 - 14, 41 - 14, 41, 41)) | |
im.paste(corners[3], (0, 41 - 14, 14, 41)) | |
im.paste(edges[0], (14, 0, 14 + 13, 14)) | |
im.paste(edges[1], (41 - 14, 14, 41, 14 + 13)) | |
im.paste(edges[2], (14, 41 - 14, 14 + 13, 41)) | |
im.paste(edges[3], (0, 14, 14, 14 + 13)) | |
im.paste(center, (14, 14, 41 - 14, 41 - 14)) | |
return im | |
def parse_wall(im): | |
corners = [] | |
edges = [] | |
center = [] | |
im = im.resize((41, 41)) | |
corners.append(im.crop((0, 0, 14, 14))) | |
corners.append(im.crop((41 - 14, 0, 41, 14))) | |
corners.append(im.crop((41 - 14, 41 - 14, 41, 41))) | |
corners.append(im.crop((0, 41 - 14, 14, 41))) | |
edges.append(im.crop((14, 0, 14 + 13, 14))) | |
edges.append(im.crop((41 - 14, 14, 41, 14 + 13))) | |
edges.append(im.crop((14, 41 - 14, 14 + 13, 41))) | |
edges.append(im.crop((0, 14, 14, 14 + 13))) | |
center.append(im.crop((14, 14, 41 - 14, 41 - 14))) | |
# preview(combine_blocks(corners, edges, center[0])) | |
all_blocks = [] | |
for i in range(0, 4): | |
all_blocks.append({"im": corners[i], "pos": i, "color": find_color(corners[i]), "type": CORNER}) | |
all_blocks.append({"im": edges[i], "pos": i, "color": find_color(edges[i]), "type": EDGE}) | |
all_blocks.append({"im": center[0], "pos": 0, "color": find_color(center[0]), "type": CENTER}) | |
return all_blocks | |
def download_image(name): | |
url = f"http://qubicrube.pwn.seccon.jp:33654/images/{name}" | |
print(url) | |
response = requests.get(url) | |
return Image.open(BytesIO(response.content)) | |
def read_images(base): | |
names = "UDFBLR" | |
load_image = lambda name: download_image(f"{base}_{name}.png") | |
return list(map(load_image, names)) | |
def read_qr(im): | |
code = zbarlight.scan_codes('qrcode', im.resize((41 * 5, 41 * 2))) | |
if code is not None: | |
return code[0].strip() | |
def extract_all_colors(blocks): | |
colors = set() | |
for block in blocks: | |
colors.add(block["color"]) | |
return colors | |
def rotate(block, desired_pos): | |
pos = block["pos"] | |
im = block["im"] | |
num_of_rotations = (desired_pos - pos + 4) % 4 | |
# print(f"{desired_pos} - {pos} = {num_of_rotations}") | |
return im.rotate(-90 * num_of_rotations, expand=True) | |
def rotate_group(blocks): | |
rotated = [] | |
for i in range(0, 4): | |
# print("START") | |
# print(blocks[i]) | |
# print("--------") | |
# print(rotate(blocks[i], i)) | |
rotated.append(rotate(blocks[i], i)) | |
# print("END") | |
return rotated | |
def solve_wall(blocks): | |
corners = list(filter(lambda b: b["type"] == CORNER, blocks)) | |
edges = list(filter(lambda b: b["type"] == EDGE, blocks)) | |
center = list(filter(lambda b: b["type"] == CENTER, blocks)) | |
corners_perms = itertools.permutations(corners) | |
edges_perms = itertools.permutations(edges) | |
center = center[0]["im"] | |
x = 0 | |
for corners_perm, edges_perm in itertools.product(corners_perms, edges_perms): | |
# print(rotate_group(edges_perm)) | |
new_im = combine_blocks(rotate_group(corners_perm), rotate_group(edges_perm), center) | |
# preview(new_im) | |
# input("click") | |
# new_im.save(f"test/{x}.png", "png") | |
x = x + 1 | |
qr = read_qr(new_im) | |
if qr is not None: | |
return qr | |
# images = read_images("02c286df1bbd7923d1f7") | |
def solve(code): | |
images = read_images(code) | |
all_blocks = [] | |
for im in images: | |
all_blocks = all_blocks + parse_wall(im) | |
colors = extract_all_colors(all_blocks) | |
for color in colors: | |
singe_color_blocks = list(filter(lambda b: b["color"] == color, all_blocks)) | |
solved = solve_wall(singe_color_blocks).decode() | |
if solved.endswith("/ 50"): | |
print(solved) | |
if solved.startswith("SECCON{"): | |
print(solved) | |
if solved.startswith("http"): | |
return solved | |
code = "01000000000000000000" | |
while code is not None: | |
code = solve(code) | |
code = code.split("/")[-1] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment