Tags: python dora pil 

Rating:

Original writeup (https://youtu.be/o0uSt88KG9k).
hardcoreitFeb. 9, 2020, 9:21 a.m.

The nice solution would have been to use openCV as the non dora images are always the same.
I am not really familiar with OpenCV, so created a fast and dirty heuristics based solution: Asks only i case if the heuristics do not give a definitive answer:

from pwn import *
import base64
from PIL import Image

conn = remote('misc.ctf.nullcon.net',8000)
print(conn.recvline())

counter = 0

forbidden_list = [120, 140, 197, 188, 126, 24, 72, 207, 99, 207, 71, 236, 205, 233, 250, 211, 183, 239, 73, 42, 18]
good_list = [43, 133, 166, 184]

auto = "_"
def dovote():
file = open(str(counter) +auto +".png", "wb")
file.write(base64.b64decode(conn.recvline()))
file.close()

img = Image.open(str(counter) + auto+".png")

width, height = img.size

ignored = img.getpixel((0,0))

pixels = img.load()

votes = []
votecount = [0,0,0,0]
#Where's Dora? 1 for upper right, 2 for upper left, 3 for lower left, 4 for lower right\n

for x in range(width):
for y in range(height):
pixel = img.getpixel((x,y))
if x< 10 and y< 10:
pixels[x,y] = (255,0,0,255) #and (pixel[0] + pixel[1] + pixel[2]) < (220*3)
if pixel != ignored and abs(pixel[0]-ignored[0]) > 40 and ((pixel[0]!=pixel[1] and abs(pixel[0]-pixel[1]) > 5) or (pixel[0] in good_list)) and pixel[3]==255: # and ((pixel[0] < 250 and pixel[0] not in forbidden_list) or (abs(pixel[0]-pixel[1])>15)) :
weight = 1
if pixel[0] in good_list:
weight = 10
if abs(pixel[0]-pixel[1]) > 20:
weight = 100

if x > width/2 and y < height/2:
votes.append(1)
votecount[0] = votecount[0]+weight
if x < width/2 and y < height/2:
votes.append(2)
votecount[1] = votecount[1]+weight
if x < width/2 and y > height/2:
votes.append(3)
votecount[2] = votecount[2]+weight
if x > width/2 and y > height/2:
votes.append(4)
votecount[3] = votecount[3]+weight
else:
pixels[x,y]=(255,255,255,255)
print(votecount)

# img.show()

maximu = max(votecount)
vote = str(votecount.index(maximu) +1)
treshold = 1000
if (maximu != votecount[0] and abs(votecount[0]-maximu) < treshold) or (maximu != votecount[1] and abs(votecount[1]-maximu) < treshold) or (maximu != votecount[2] and abs(votecount[2]-maximu) < treshold) or (maximu != votecount[3] and abs(votecount[3]-maximu) < treshold):
img2 = Image.open(str(counter) + auto+".png")
img2.show()
print("which number to send?")
vote = int(raw_input())

print("vote" + str(vote))

conn.sendline(str(vote))

for i in range(1000):
dovote()
print(conn.recvline())
counter = counter + 1

print(conn.recvline())
print(conn.recvline())

conn.close()