WPICTF 2019 S3L3CT Writeup
Apr 15, 2019 14:29 · 491 words · 3 minute read
Problem
Points: 400
Solves: 3
Are you smarter than an AI?
https://drive.google.com/open?id=1Inoxm1Wyiq6keSVwBt9zU5aRbRaScuTq
made by calper-pq
Solution
Getting started
For this challenge, you are given three npy files: X.npy
, Y.npy
, and key.npy
.
With some googling, I found that npy files can be loaded with numpy:
import numpy as np
data_x = np.load('./X.npy')
data_y = np.load('./Y.npy')
data_key = np.load('./key.npy')
print data_x.shape
print data_y.shape
print data_key.shape
❯ python main.py
(10000, 50, 50, 3)
(10000,)
(296, 50, 50, 3)
Judging from the shape of the data, I made an educated guess that X.npy
and Y.npy
are the training inputs and training outputs, and our goal is to make a machine learning algorithm that can predict the outputs for the data stored in the key.npy
file.
Since the outputs in Y.npy
are either 0 or 1, we can expect to get a binary string with the length of 296 that would likely be the flag.
Making a convolutional neural network
Now our task becomes making a neural network that can classify the data for us.
The shape of the data helped again as (50, 50, 3) hinted at the fact that the input could be seen as a 50x50 pixel RGB image, and we can use a neural network that is best optimized for image recognition - a convolutional neural network.
I won’t go into the details about how a convolutional neural network works because there are already quite a lot of good resources out there. Here are just a few that I used:
- Machine Learning is Fun! Part 3: Deep Learning and Convolutional Neural Networks
- A Beginner’s Guide To Understanding Convolutional Neural Networks
I picked Keras as my library of choice simply because I have used it before for a few other CTF challenges (this and this).
Now I have a scope that is narrow enough: I need to build a convolutional neural network using Keras to do binary image classification. Let the google rampage begin.
Striking gold
After reading around 20 articles online and experimenting with a few different models, I finally found one that works.
Using the model described in this great article, here’s my final code:
import keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, Activation, MaxPooling2D, BatchNormalization, Dropout
from keras.utils import to_categorical
import numpy as np
model = Sequential()
data_x = np.load('./X.npy')
data_y = np.load('./Y.npy')
data_key = np.load('./key.npy')
data_y = to_categorical(data_y)
x_train = data_x[:len(data_x)//2]
x_test = data_x[len(data_x)//2:]
y_train = data_y[:len(data_x)//2]
y_test = data_y[len(data_x)//2:]
model = Sequential()
model.add(Conv2D(32, kernel_size = (3, 3), activation='relu', input_shape=(50, 50, 3),data_format="channels_last",))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Conv2D(96, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
# model.add(Conv2D(32, kernel_size=(3,3), activation='relu'))
# model.add(MaxPooling2D(pool_size=(2,2)))
# model.add(BatchNormalization())
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
#model.add(Dropout(0.3))
model.add(Dense(2, activation = 'softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.SGD(lr=0.01),
metrics=['accuracy'])
print model.summary()
model.fit(x_train, y_train, epochs=20, batch_size=50, verbose=1, validation_data=(x_test, y_test),)
model.save('my_model.h5')
v = model.predict(data_key)
print v
flag = ''
for i in range(len(v)):
k = v[i]
if k[0] > k[1]:
flag+='0'
else:
flag+='1'
print flag
flag: WPI{+++#(((--ELON_IS_SKYNET--)))#+++}