Thursday, November 20, 2014

Quantum Mechanics: Weird Light

Have you ever shopped for sunglasses before?  They're ridiculously expensive, especially if you get the special polarized ones.  Ever wonder what that means?

If you've ever looked at a lake before when the sun is somewhat low, you'll notice that there's glare, and it's hard to see below the surface.  Light from the sun bounces off the water, and the ones that create the glare are "propagating" in the horizontal direction (in incoherent light, which comes from the sun, they're propagating in every direction).

By "propagating," I mean you can imagine it as a sine wave that's moving along some axis.  So horizontally-polarized light is moving left-right-left-right-left-right really really fast.  (That's not what's actually happening but go with it! It works for our analogy).

Suppose you're wearing shutter shades, like the ones Obama is wearing:

(Not my art! Please don't sue me.)
You can imagine that light propagating in the vertical direction (up-down-up-down) get blocked by the shutters, so only horizontally-polarized light goes through.  This is what a polarized filter does, and this is essentially what those overpriced sunglasses do, with microscopic shutters.

What if you take a pair of sunglasses, and turn it 90 degrees?  Now you have a vertically-polarized filter, that only lets in vertical light, and blocks out horizontal light.  If you take both of these sunglasses and put them one in front of the other, what happens?

Light hits the horizontally-polarized filter, horizontal light goes through.  Horizontal light hits the vertically-polarized filter, nothing gets through.

(This is an experiment that you can and should do, by the way.  Find a Walgreens somewhere and try this).

Now, what if you put another filter, but rotated it 45 degrees?  So you have a horizontal filter, a 45 degree filter, and a vertical filter, in front of each other.  What happens?

The sensible thing to say is, well!  Filters only block light!  So if you take the configuration with the horizontal filter + the vertical filter, and you get no light, then doing the horizontal + 45 + vertical should also get no light!

But that's not what actually happens.  You actually get 12.5% of the light you put in.


Somehow, putting an extra filter in the apparatus managed to create light, even though filters only block.  More accurately, the 45-degree filter actually destroyed some information about the horizontal filter.

I'm going to allude to the punch line early, this is the same sort of mechanism at play behind Heisenberg's uncertainty principle.  Some properties can't be successfully measured at the same time.  With Heisenberg, it's position and momentum.  With sunglasses, it's propagation direction between two axes.

What if you had five sunglasses instead?  One horizontal, one at 22.5 degrees, one at 45 degrees, one at 67.5 degrees, then one vertical?  You get more light.  The more filters you put in in this manner, the less light that is actually filtered out.

If you have an infinite number of filters, all a tiny angle away from each other, such that you start from the horizontal and end up at the vertical, you actually end up getting 100% of the light going through, as if you had no filters at all.

Clearly this is some demented stuff, and as far as I know, no one fully understands it.  We're good at modeling it, but not explaining it in any satisfactory, classical way.

Some extra thoughts:
Let's go back to two filters: one at horizontal and one at 45 degrees.  If you send in 100 photons of light, and all 100 get through the horizontal filter, 50 of those get through the 45 degree filter.  But which 50?

Let's send in one photon.  It gets through half of the time, and half of the time not.  Same experiment, different results.  There must be some variable we aren't taking into account; the photons that we are preparing, which we think are identical, must not be in some way.  No one has found such a variable.

So as far as we know, setting up the same experiment does not always yield the same result.

This is the Copenhagen interpretation: science is not perfectly deterministic, as we thought it'd be.

Einstein hated this.  He famously stated that "God does not play dice," and that quantum mechanics must be incomplete.  But almost every experiment we've run seems to reinforce the Copenhagen interpretation.

Contrary to what some philosophers thought, this hasn't destroyed science.  We're perfectly capable of designing things such that the probability of crazy things happening is very, very, very small.  So it's not a big deal, yo.

Been a while!

Some updates:

Currently in my second year at University of California, Berkeley, studying electrical engineering and computer science.  Excellent school, people are generally friendly and knowledgeable, and very eager to learn.

Been getting a lot more interested in the hardware side of things.  Started doing some amateur radio.  Taking a quantum mechanics class.  Designed and fabricated a PCB, used it to set up a light strip that syncs to my computer screen.  And teaching a class!  About 20 students, teaching how to design a car that drives around a maze.  Workload is fairly intensive which means I don't have much time for casual blogging, hence the 2-year hiatus.

And I kind of miss game development.

I've had a few ideas that I want to make at some point, not while in college but maybe a few years after graduation.  Definitely a cool hobby and a bit sad I haven't maintained contact with much of anyone who still makes games.

But anyways!

I've been itching to do some quantum mechanics stuff recently.  Mostly to solidify what I'm learning about it in class.  If I start a new blog, I know what's going to happen: I'm going to have yet another blog with a single post, and then nothing.  So I'm just going to continue off of this one, and maybe transfer in the future, despite this one having a lot of posts I'm really not proud of.

(For the record, I'm really not proud of about 80% of anything I ever said in high school.  That hasn't changed -- I'm still saying dumb shit!)

To anyone who still reads this (?!): Hello! I have not been stabbed, if you have also not been stabbed, let us communicate again.

That is all.  Next posts will probably be some quantum mechanics stuff.  That's all I really feel like writing about right now.

Monday, July 29, 2013

MITRE 2013 Writeup : Network 200

Wireshark .pcap file shows a bunch of TCP and HTTP requests, most notably to  Saving the TCP stream into a file...

HTTP/1.1 200 OK
Server: Apache
X-Powered-By: PHP/5.4.14
Expires: Sun, 14 Jul 2013 21:17:37 GMT
Vary: User-Agent,Accept-Encoding
X-Frame-Options: SAMEORIGIN
X-DNS-Prefetch-Control: on
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 14 Jul 2013 20:17:37 GMT
X-Varnish: 155913018
Age: 0
Via: 1.1 varnish
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Varnish-Cache: 0
Connection: close

...and loading it up onto localhost via ncat...

elliptic@elliptic:~/solved/network200$ sudo ncat -l 80 < stream

...yields the vimeo video.

01010100 01101000 01100101 00100000 01101011 01100101 01111001 
T        h        e                 k        e        y
00100000 01101001 01110011 00100000 01001101 01000011 01000001 
         i        s                 M        C        A
00101101 00110101 00111000 01000010 01000101 00110001 00110100 
-        5        8        B        E        1        4
00110111 01000001 00100000 00111010 00101001
7        A                 :        )


MITRE 2013 Writeup : Binary 200 #2

ELF Linux executable file named Game.bin.  Running it shows usage instructions that show that it takes one parameter:

elliptic@elliptic:~/solved/bin2002$ ./Game.bin
Usage: ./Game.bin

keyFile - The file containing your CD Key

Strings table and cat were both uninteresting.  Disassembling the main function in GDB yielded some nice things.

. Stack initialization
   0x0804896c <+0>:    push   ebp
   0x0804896d <+1>:    mov    ebp,esp
   0x0804896f <+3>:    push   ebx
   0x08048970 <+4>:    and    esp,0xfffffff0
   0x08048973 <+7>:    sub    esp,0x170
. If fewer than 1 parameter, jump to 0x80489AC
   0x08048979 <+13>:    cmp    DWORD PTR [ebp+0x8],0x1
   0x0804897d <+17>:    jg     0x80489ac

. Usage
   0x0804897f <+19>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048982 <+22>:    mov    eax,DWORD PTR [eax]
   0x08048984 <+24>:    mov    DWORD PTR [esp+0x4],eax
   0x08048988 <+28>:    mov    DWORD PTR [esp],0x8049d90 ; 0x8049d90 = "Usage: %s \n"
   0x0804898f <+35>:    call   0x80487e0
   0x08048994 <+40>:    mov    DWORD PTR [esp],0x8049da8 ; 0x8049da8 = "\nkeyFile - The file containing your CD Key"
   0x0804899b <+47>:    call   0x8048840
   0x080489a0 <+52>:    mov    DWORD PTR [esp],0x0
   0x080489a7 <+59>:    call   0x8048870 ; end
. Body
   0x080489ac <+64>:    mov    eax,DWORD PTR [ebp+0xc]
   0x080489af <+67>:    add    eax,0x4
   0x080489b2 <+70>:    mov    eax,DWORD PTR [eax]
   0x080489b4 <+72>:    mov    DWORD PTR [esp+0x4],0x8049dd3 ; 0x8049dd3 = "rb"
   0x080489bc <+80>:    mov    DWORD PTR [esp],eax
   0x080489bf <+83>:    call   0x80487d0 ; Opens some file with read ("rb") permissions; probably keyFile?
   0x080489c4 <+88>:    mov    DWORD PTR [esp+0x160],eax
   0x080489cb <+95>:    cmp    DWORD PTR [esp+0x160],0x0 ; Check if we can open the file
   0x080489d3 <+103>:    jne    0x80489ed

   0x080489d5 <+105>:    mov    DWORD PTR [esp],0x8049dd8 ; 0x8049dd8 = "Error - couldn't open key file"
   0x080489dc <+112>:    call   0x8048790
   0x080489e1 <+117>:    mov    DWORD PTR [esp],0x1
   0x080489e8 <+124>:    call   0x8048870 ; end

   0x080489ed <+129>:    mov    eax,DWORD PTR [esp+0x160]
   0x080489f4 <+136>:    mov    DWORD PTR [esp+0xc],eax ; file pointer
   0x080489f8 <+140>:    mov    DWORD PTR [esp+0x8],0x1 ; number of elements in buffer (1)
   0x08048a00 <+148>:    mov    DWORD PTR [esp+0x4],0x80 ; size of elements in buffer (0x80 = 128 bytes)
   0x08048a08 <+156>:    lea    eax,[esp+0xb8]
   0x08048a0f <+163>:    mov    DWORD PTR [esp],eax ; buffer
   0x08048a12 <+166>:    call   0x8048850 ; read elements into buffer
   0x08048a17 <+171>:    mov    DWORD PTR [esp+0x15c],eax
   0x08048a1e <+178>:    cmp    DWORD PTR [esp+0x15c],0x1 ; if successful (fread returns the number of elements successfully read)
   0x08048a26 <+186>:    je     0x8048a59

   0x08048a28 <+188>:    mov    eax,ds:0x804a16c
   0x08048a2d <+193>:    mov    DWORD PTR [esp+0xc],eax
   0x08048a31 <+197>:    mov    DWORD PTR [esp+0x8],0x1f
   0x08048a39 <+205>:    mov    DWORD PTR [esp+0x4],0x1
   0x08048a41 <+213>:    mov    DWORD PTR [esp],0x8049df8 ; 0x8049df8 = "Error: couldn't read whole key\n"
   0x08048a48 <+220>:    call   0x80487f0
   0x08048a4d <+225>:    mov    DWORD PTR [esp],0x2
   0x08048a54 <+232>:    call   0x8048870 ; end

Here, the program calls a bunch of really scary things like time and random, probably to compare against the key you enter.  The correct key is 128 bytes of randomness?  Probably not the key you're looking for.

   0x08048a59 <+237>:    mov    DWORD PTR [esp],0x0
   0x08048a60 <+244>:    call   0x8048810

The more interesting part; why is it calling SDL functions?  SDL is used for drawing.

   0x08048b67 <+507>:    mov    DWORD PTR [esp],0x0
   0x08048b6e <+514>:    call   0x80487c0
   0x08048b73 <+519>:    test   eax,eax
   0x08048b75 <+521>:    je     0x8048ba2

   0x08048b77 <+523>:    call   0x8048860
   0x08048b7c <+528>:    mov    edx,DWORD PTR ds:0x804a16c
   0x08048b82 <+534>:    mov    DWORD PTR [esp+0x8],eax
   0x08048b86 <+538>:    mov    DWORD PTR [esp+0x4],0x8049e30
   0x08048b8e <+546>:    mov    DWORD PTR [esp],edx
   0x08048b91 <+549>:    call   0x8048800
   0x08048b96 <+554>:    mov    DWORD PTR [esp],0x4
   0x08048b9d <+561>:    call   0x8048870
   0x08048ba2 <+566>:    mov    DWORD PTR [esp+0xc],0x0
   0x08048baa <+574>:    mov    DWORD PTR [esp+0x8],0x10
   0x08048bb2 <+582>:    mov    DWORD PTR [esp+0x4],0x12c
   0x08048bba <+590>:    mov    DWORD PTR [esp],0x140
   0x08048bc1 <+597>:    call   0x8048780
   0x08049ce0 <+4980>:    cmp    ax,0x13f
   0x08049ce4 <+4984>:    jle    0x8049c85

   0x08049ce6 <+4986>:    mov    DWORD PTR [esp],0x3
   0x08049ced <+4993>:    call   0x8048830
   0x08049cf2 <+4998>:    mov    eax,0x0
   0x08049cf7 <+5003>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x08049cfa <+5006>:    leave 
   0x08049cfb <+5007>:    ret

We don't actually need the key to get here.  Jumping to 0x08048b67 runs the SDL code:

(gdb) break main
Breakpoint 1 at 0x8048970
(gdb) run
Starting program: /home/elliptic/solved/bin2002/Game.bin
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/".

Breakpoint 1, 0x08048970 in main ()
(gdb) jump *0x08048b67
Continuing at 0x8048b67.

..spawning the window:


MITRE 2013 Writeup : Binary 200 #1

This one wasn't even a binary.  It was a JAR file that you disassembled to yield the following:

// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page:
// Decompiler options: packimports(3)
// Source File Name:

import java.util.Scanner;

public class Overrated

    public Overrated()

    public static void main(String args[])
        String s = new String();
        String s1 = "3d38629f056c942d561b63dbe8e94653";
        Scanner scanner = new Scanner(;
        for(; !encrypt(s).equals(s1); s = scanner.nextLine())
            System.out.print("Please enter the correct flag to continue: ");

        System.out.println("Good job!");

    public static String encrypt(String s)
        String s1 = "";
            MessageDigest messagedigest = MessageDigest.getInstance("MD5");
            byte abyte0[] = messagedigest.digest();
            String s2 = "";
            for(int i = 0; i < abyte0.length; i++)
                String s3 = Integer.toHexString(0xff & abyte0[i]);
                if(s3.length() == 1)
                    s1 = (new StringBuilder()).append(s1).append("0").append(s3).toString();
                    s1 = (new StringBuilder()).append(s1).append(s3).toString();

        catch(NoSuchAlgorithmException nosuchalgorithmexception) { }
        return s1;

32-byte MD5.  Pull up your favorite hash cracker and set it up for an 8-byte bruteforce salted with MCA- and with the character set 0123456789ABCDEF:

elliptic@elliptic:~/hashcat-0.46$ ./hashcat-cli32.bin -m20 -a3 --custom-charset1=?dABCDEF --pw-min=8 --pw-max=8 hash.txt ?1?1?1?1?1?1?1?1
Initializing hashcat v0.46 by atom with 8 threads and 32mb segment-size...

Added hashes from file hash.txt: 1 (1 salts)
Activating quick-digest mode for single-hash with salt

NOTE: press enter for status-screen


All hashes have been recovered

Input.Mode: Mask (?1?1?1?1?1?1?1?1)
Index.....: 0/1 (segment), 4294967296 (words), 0 (bytes)
Recovered.: 1/1 hashes, 1/1 salts
Speed/sec.: - plains, 10.39M words
Progress..: 254333816/4294967296 (5.92%)
Running...: 00:00:00:24
Estimated.: 00:00:06:28

Started: Mon Jul 29 21:41:45 2013
Stopped: Mon Jul 29 21:42:09 2013


MITRE 2013 Writeup : Binary 100

This one was actually broken and unsolvable for some time.  It was a Linux executable that displayed the following:

elliptic@elliptic:~/solved/bin100$ ./hello
Hello, World!
Don't forget the dash

Wow.  Uninformative.  Let's open it in GDB:

elliptic@elliptic:~/solved/bin100$ gdb --quiet hello
Reading symbols from /home/elliptic/solved/bin100/hello...(no debugging symbols found)...done.
(gdb) info fun
All defined functions:

Non-debugging symbols:
0x080482b8  _init
0x080482f0  puts
0x080482f0  puts@plt
0x08048300  __gmon_start__
0x08048300  __gmon_start__@plt
0x08048310  __libc_start_main
0x08048310  __libc_start_main@plt
0x08048320  _start
0x08048350  deregister_tm_clones
0x08048380  register_tm_clones
0x080483c0  __do_global_dtors_aux
0x080483e0  frame_dummy
0x0804840c  main
0x08048428  MCA02076b3d
0x08048450  __libc_csu_fini
0x08048460  __libc_csu_init
0x080484ba  __i686.get_pc_thunk.bx
0x080484c0  _fini

A basic look at the function list gives the key outright.  MCA-02076B3D