Skip to content

Latest commit

 

History

History
 
 

seccon_wars_100

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Seccon Wars (Stegano, 100p)

https://youtu.be/8SFsln4VyEk

###PL ENG

Na filmie wideo zalinkowanym w zadaniu wyraźnie widać zarysy QR CODE, ale jest on zbyt rozmazany by odczytać go bezpośrednio.

Po chwili zastanowienia (jednym z pomysłów było ręczne naprawianie QR kodu "w paincie") wpadliśmy na pomysł uśrednienia wartości piksela dla wielu screenów i odczytania qr codu z takiego uśrednionego obrazu (powinien być czytelniejszy wtedy)

Najpierw napisaliśmy program w C# robiący screeny przeglądarki, żeby mieć co uśredniać:

private class User32 {
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}

public void CaptureApplication(string procName, int i) {
    var proc = Process.GetProcessesByName(procName)[0];
    var rect = new User32.Rect();
    User32.GetWindowRect(proc.MainWindowHandle, ref rect);

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    Graphics graphics = Graphics.FromImage(bmp);
    graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);

    bmp.Save("frame" + i + ".png", ImageFormat.Png);
}

protected override void OnLoad(EventArgs e) {
    int i = 0;
    while (true) {
        i++;
        CaptureApplication("firefox", i);
        Thread.Sleep(100);
    }
    base.OnLoad(e);
}

A następnie niewielki skrypt uśredniający obrazy z folderu (szczerze mówiąc, to tak naprawdę to skopiowaliśmy go z SO):

import os, numpy, PIL
from PIL import Image

# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=[filename for filename in allfiles if  filename[-4:] in [".png",".PNG"]]

# Assuming all images are the same size, get dimensions of first image
w,h=Image.open(imlist[0]).size
N=len(imlist)

# Create a numpy array of floats to store the average (assume RGB images)
arr=numpy.zeros((h,w,3),numpy.float)

# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
    imarr=numpy.array(Image.open(im).convert("RGB"),dtype=numpy.float)
    arr=arr+imarr/N

# Round values in array and cast as 8-bit integer
arr=numpy.array(numpy.round(arr),dtype=numpy.uint8)

# Generate, save and preview final image
out=Image.fromarray(arr,mode="RGB")
out.save("Average.png")
out.show()

Wynik działania:

Po poprawieniu kontrastu, odczytujemy wynik:

SECCON{TH3F0RC3AVVAK3N53P7}

ENG version

In video linked in the description we can clearly see outline of QR CODE, but it's too dark to be read directly

After a while (one of our first ideas was to draw qr code by hand in mspaint), we decided to capture a lot of video frames and average all pixels.

First, we have written C# script to take browser screenshot every 0.1s:

private class User32 {
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}

public void CaptureApplication(string procName, int i) {
    var proc = Process.GetProcessesByName(procName)[0];
    var rect = new User32.Rect();
    User32.GetWindowRect(proc.MainWindowHandle, ref rect);

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    Graphics graphics = Graphics.FromImage(bmp);
    graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);

    bmp.Save("frame" + i + ".png", ImageFormat.Png);
}

protected override void OnLoad(EventArgs e) {
    int i = 0;
    while (true) {
        i++;
        CaptureApplication("firefox", i);
        Thread.Sleep(100);
    }
    base.OnLoad(e);
}

And then tiny script to average every pixel and save result (to be honest, we just stole it from SO):

import os, numpy, PIL
from PIL import Image

# Access all PNG files in directory
allfiles=os.listdir(os.getcwd())
imlist=[filename for filename in allfiles if  filename[-4:] in [".png",".PNG"]]

# Assuming all images are the same size, get dimensions of first image
w,h=Image.open(imlist[0]).size
N=len(imlist)

# Create a numpy array of floats to store the average (assume RGB images)
arr=numpy.zeros((h,w,3),numpy.float)

# Build up average pixel intensities, casting each image as an array of floats
for im in imlist:
    imarr=numpy.array(Image.open(im).convert("RGB"),dtype=numpy.float)
    arr=arr+imarr/N

# Round values in array and cast as 8-bit integer
arr=numpy.array(numpy.round(arr),dtype=numpy.uint8)

# Generate, save and preview final image
out=Image.fromarray(arr,mode="RGB")
out.save("Average.png")
out.show()

And the result is:

After improving contrast and decoding QR CODE:

SECCON{TH3F0RC3AVVAK3N53P7}