Month: October 2017

Pwn2Win CTF 2017 – Differential Privacy – Crypto

Is it possible to have privacy on these days? The Rebelious Fingers do not think so. Get the flag.

nc 200.136.213.143 9999

Right off the bat we know this has something to do with differential privacy (Such a surprise!) and we have a server so lets connect to it.

Hello, chose an option:
[1] Info
[2] Query the flag (in ASCII)
[3] Quit

Basic menu, lets see the options.

1
You can query the flag, but the characters are private (indistinguishable).
Differential privacy mechanism: Laplace
Sensitivity: ||125 – 45|| = 80
Epsilon: 6.5

2
[85, 89, 108, -16, 78, 67, 123, 61, 110, 96, 103, 85, 107, 116, 122, 130, 96, 83, 108, 136, 100, 94, 103, 90, 117, 102, 73, 118, 118, 112, 112, 105, 101, 110, 143, 103, 75]

Mhm, well not sure what to do with this yet. I don’t really know much about differential privacy, so let’s research. Differential privacy is used to encode data in such a way that you can’t discern any single persons input while keeping the actual statistical findings of the data intact. It does this by adding a Laplace random number set by some parameters to the value. Because the average of the Laplace function is 0, the average of the data set stays about the same.

At this point, I was at a loss. I would work on some other problems and come back to this one now and then. Then I noticed that the query values change on successive connections. Because the center of the Laplace function is 0, if you take the average of a lot of different encodings, it should be the original value! Python time!

from pwn import *
import ast

host = "200.136.213.143"
port = 9999

#This is the ammount of values to keep after throwing out the largest and smallest values.
#[100,50,10,7,6,5,4,3,2,1,-10,-50,-100] will keep [7,6,5,4,3,2,1]
sample = 7


def get_list():
  #get a new data set from the server
  #turn it into a list
  conn = remote(host,port)
  conn.recvuntil("t\n")
  conn.send(b"2\n")
  data = ast.literal_eval(conn.recvline().decode().strip())
  conn.close()
  #print(data)
  return data

gotten = None

while True:
  d = get_list()

  if not gotten:
    #initialize the gotten array if it hasn't been
    gotten = [[] for j in d]

  for j,v in enumerate(d):
    #add each new value to the corresponding sub-array
    gotten[j].append(v)

  if len(gotten[0]) > sample + 1:
    #After we've gotten enough data
    r = max([1,int((len(gotten[0])-sample)/2)])
    for vals in gotten:
      #For each character, sort it's values and average the sample
      work = vals[:]
      work = sorted(work)[r:-r]
      print(chr(int(round(sum(work)/len(work)))), end="")
    print(" ", len(gotten[0]))

Running this code will print out an estimate of the correct string after each ‘download.’ After 20 updates, the output is something like this

FTK*>VzHY_m`qxqu\lpmtbqmpd]xdf\nqesd|

This makes almost no sense, so lets make a bigger data set.

After 400 updates, it’s looking a bit better

CSF-BR{H`am_jtut_filserjng`uie^npird}

General flag structure is there, and maybe the beginnings of some words.
Let’s keep going. 1622 updates later we get

CTF-BR{I_am_jtst_filtering_the_noise}

Only one incomplete word! Looks like it’s probably “just” let’s try that! It worked!

CTF-BR{I_am_just_filtering_the_noise}

~T

Posted by Tanner in CTF, Posts

Pwn2Win CTF 2017 – Top Secret – Electronics

Molly was able to take pictures of a strange digital circuit sketch, along with an also strange message. All of these things were inside an envelope in a safe, which was labeled “Top Secret”.

We believe it might contain Butcher Corp’s plans for the future, can you help us read the message?

Strange Circuit.jpg
Message.txt

To start off we are given a circuit diagram and an input file. Taking a look at the circuit, I recognized the JK Flip-Flop zero to seven counter in the upper right, with the current value being fed into a MUX. Following this, we see that the MUX is sending a positive value to one of eight transistors which in turn provide a ground to one row of diodes. Looking over the circuit, we can note that there are 9 (0-8) inputs, this matches the Message.txt file we got. Input 0 is used to clock the JK Flip-Flop circuit, while inputs 1-8 are fed to the grid of diodes.

At this point, I was a little stuck. I didn’t understand how to get anything useful from this. So I showed the diagram to an Electrical Engineering friend of mine. He suggested that the diode grid was actually a Light Emitting Diode grid. Immediately I realized that had to be it, it’s an LED matrix! So some quick python code to read in the file and…

Well that doesn’t look right… I think I see “CTF” in there, but… Well no, something went wrong. Back to the circuit! Then I realized, inputs 2,3,7, and 8 are inverted! They go through two transistors! Let’s invert those inputs in the code!

There it is! We got a flag!

Here’s the code I used to generate the correct flag.

from PIL import Image

#Black and white pixels
OFF = (0,0,0)
ON = (255,255,255)

#Read in the file and split it into "letters"
with open("Message.txt", 'r') as f:
    blocks = f.read().split("\n\n")

#Create an empty image with the right dimensions
img = Image.new("RGB", (len(blocks)*8,8))

for n,block in enumerate(blocks):
    #Set the x offset depending on the character
    dx = n*8
    
    #Split the block into lines only using positive clocked lines
    #We don't care about the zero lines
    chunked = []
    for line in block.split("\n"):
        if line[0] == "1":
            chunked.append(line.split(" ")[1:])

    print(chunked)
    
    #Draw the pixels
    for y,chunk in enumerate(chunked):
        for x,val in enumerate(chunk):
            #Should this one be inverted?
            if x in [1,2,6,7]:
                if val == "0":
                    pix = OFF
                else:
                    pix = ON
            else:
                if val == "1":
                    pix = OFF
                else:
                    pix = ON

            img.putpixel((x+dx,y), pix)

img.save("solved.png")

~T

Posted by Tanner in CTF, Posts