Wednesday 21 November 2012

Owning the flag: PoliCTF

We like to imagine the good ol' days of princesses and dragons, where the heroes sat around a smoky tavern waiting for quests from frail old wizards. These days, the heroes of our time sit around computers getting their quests from a server on the Internet. That was how our weekend went...

An eager group of us met up Saturday at 1 pm — Alex, Colin, Jay, Jeremy, Mak, Richard, and I (Ron). Armed with junk food and piles of computer gear, we set out on our quest: to capture all the flags!

The clock ticked. It hit 1:00. Nothing yet. 1:01, 1:02, and finally at 1:03 the first challenges were up! Mak started decrypting them while the rest of us waited. Slowly, we started getting the puzzles. A PCAP of a SSH session for Forensics, a C program that said "U MAD?" for Bin-Pwn, a bunch of encrypted data for Crypto, and an obscure Hackers reference for Grab-Bag.

An hour of derping later, and all we could wonder is what we had gotten ourselves into. As we were working, other teams were completing challenges, and we were falling behind. What's going on? Are we that derpy!? New challenges were unlocking — a bitmap with faded text for Forensics, a network service for Bin-Pwn that was a calculator, and a photo of a crazy breadboard for Grab-Bag. And there we sat, still derping.

Grab-Bag 100: Hackers

Eventually, Richard realized that the obscure Hackers reference meant we had to watch the movie and find the scene where they showed the Garbage File. So he and Mak fired up Netflix, and spent a half-hour jumping around looking for the two frames in which the hex dump of the file showed the address we needed. First flag: DEFEATED! 100 points! w00t! High fives all around!

Things were looking good! Let's get our hopes up so we can really feel it good when we fail!

Forensics 100: Beep beeeeeep beep

Next up, the SSH session. After a bunch of screwing around looking for any kind of data leakage, we started looking at the SSH traffic. Nothing jumped out, and we didn't even have the handshake so we didn't know how it was encrypted. WAT DO?

Eventually, the challenge coordinators released a hint: "This challenge could just as easily be RSH". Wait, what? SSH is encrypted, RSH is not. Hmm! That led me to start thinking of covert channels. We started looking at the packets' metadata, but didn't see anything interesting. Alex points out that there are large and odd gaps in the ssh traffic, like eight second gaps once in awhile. We opened a timing graph, and I said, "This is modulated.", and we were right. A horrified look crossed Mak's face as we all came to the realization: it's Morse code. With SSH packets. Wow.

So, we decoded it, and sure enough, it was a flag. FLAG 2! There was much rejoicing, and the best high five I've ever had with Mak. I swear we were breaking atomic bonds between our hands... [Editor's Note: I still have flashbacks and phantom pains as a result.]

By that time, it was 8 or 9 pm. We were in the middle of the pack and going strong. But I'm not gonna lie, the rest of the night/morning is a bit of a blur, fuelled by junk food and sugar, so I'm just going to hit on the high points, to the best of my recollection, in vaguely chronological order.

Bin-Pwn 300: Please don't ask me about Bin-Pwn 300

Bin-Pwn 300. Oh God, Bin-Pwn 300. It was a Linux binary that was running on their server. It became quickly obvious that you had to exploit it, but despite reversing the whole damn thing, I couldn't find the issue. I'm supposed to be good at that stuff! Sadly, I'm not so good at Linux debugging/hacking, so it slipped through the cracks despite spending all night on it. Sadfaec. :(

Luckily, I'm not the only one with a nemesis! Forensics 200. You can see the look of horror on Mak's face just by mentioning it. When I brought it up in the SkullSpace meeting, he publicly threatened to stab me in the face. It's just that good!

Forensics 200: Please ask Mak about Forensics 200

Forensics 200 was a BMP image.

The hint noted "This file is big 54 + PixelArraySize." That's it. We already knew from the previous level, the Morse code, that there would be something hidden in some insane manner. Looking closely, we could see that there was some text somewhat superimposed on the image. Mak wrote a Ruby script that would take the original BMP as input and output a directory full of mangled BMPs with the same pixel data, but with a different height and width declared. Alex ran the script and eventually identified the text as "BITCHES BITCHES EVERYWHERE". Surprisingly quickly, Mak, in the supercomputer he calls a brain, realized that the bytes were encoded funny, and that there was likely some stenography on the pixel data in there, causing the strange colouring. He threw together another Ruby script, and before long had pulled out the least-significant nibble (4-bit value) from each byte of pixel data to form a new file. And guess what? IT WAS ANOTHER IMAGE!

That image, Mak eventually realized after some nudging from Mark, had extra data after the pixel data. It was a 7zip archive! By midnight, we had the 7zip archive. By 1pm the next day, we still had the 7zip archive. It turns out, the password was stego-encoded in the second BMP in a way that we never did figure out. We still don't understand it now that another team has explained it to us. It was a sad time...

At some point pizza showed up. I don't eat pizza, but I also had a box of oranges, triscuits, bunny-shaped graham crackers, chips, dip, guacamole, bagels, ... well, let's just say I had a lot of food. Also a couple bottles of Kambucha. I love that stuff!

Anyway, on to other flags. Did I mention I worked on Bin-Pwn 300 all night? I'm still upset with that.

Bin-Pwn 100: U MAD?

Other flags... oh yeah, Bin-Pwn 100. Jay, poor Jay, spent far too much time chasing a white rabbit on that one. See, they had a weird combination of whitespace in each line: tabs and spaces. We tried all sorts of stego techniques, but no luck.

Let me back up. The level was a simple .c file that used a copy of libjpeg.a to generate an image saying "U MAD?" — the answer was, of course, "Yes, fuck off." At least, it was by the end of the night.

So anyway, Jay was playing with the whitespace in various ways and getting nowhere. He also tried to compile it against a system version of libjpeg.a and hash the output images... they were identical. So no hidden features in libjpeg.a. WAT DO?

That's when Alex took a look. Or maybe it was later, things are kinda hazy. Alex opened up libjpeg.a as an archive (and that night, I learned that .a files are just collections of .o files  — who knew?) and discovered a .jpeg file embedded. That's not right! The jpeg file, however, had a corrupted header. But, once he took the header from the original "U MAD?" .jpeg file and stuck it on the new one, it displayed a key above the text. We no longer mad, bro!

At some point that night, Ian and Marcella showed up and took some pictures. They are here. It was cool to see some friendly faces in the middle of the night. Actually, a lot of people stopped by here and there to help and cheer us on.

Bin-Pwn 200: 1 + 1 = 2

Bin-Pwn 200 was, basically, a calculator. You netcat to their server on a given port and it lets you enter two numbers and an operator. Those values are combined and the result is printed. That's it. What the fuzzle!?

This is where Jay saved us. He discovered that whitespace was handled wrong. If you added spaces, multiple numbers were used. For example, "1 1 1", "+", "2 2" would wind up as "7". How do? He quickly realized that he was looking at a Lisp-based evaluator. At that point, he had to leave.

Mak and Nick, a remote teammate, took over and started looking at this puzzle. They eventually figured out which Lisp dialect it is, and used these things they called "lambdas" to do all the magic: listing files, reading them, etc. With that, they managed to read "flag.txt" in the calculator's working directory and get the flag. BOOM!

I remember the sun coming up. Sunday was a beautiful day, I think. I pulled my car around without putting on a jacket. The sun felt nice after 24 hours in a chair...

Bin-Pwn 400: Hutlh ghItlh pIqaD

If we couldn't get Bin-Pwn 300, how the heck were we supposed to get Bin-Pwn 400!? Who knows, but we tried anyway!

Once again, we were given a server and a port. But this time, we also had a username. The server was called "alien-server" or something. It was a SSH server, and we didn't have a password. Okay... so we need to break SSH? LAME!

After poking around a bit, Alex remembered that he had to send a SSH public key to the organizers to register our team for the contest. Aha! Sure enough, we logged in, expecting a shell. As the famous Chuck Testa would say, nope!

We logged in, and the server starts saying weird things. It starts by saying "loS", then waiting ten seconds, followed by other gibberish. I love me some ciphers, so I thought this might be fun! For fun, Alex Googled one of the phrases. We found an English-Klingon dictionary. Yup, it's Klingon. We bashed our heads trying to figure out what to type, but all it would respond with is "bad message" or something.

Nick discovered that the Klingon letter 'ch' could be used to read a file. But only a couple files were available, specifically, the files that were the source of the shell itself.

Once we had access to the files, Nick and I started working on how to exploit the system. Eventually we realized that we could get the system to interpret (or JIT compile, more likely) arbitrary C++ code by using a bunch of weird Klingon commands. I managed to write a file-reader to read flag.txt, and boom! We had another flag! I woke up Mak to high five him. It was a good time.

Shortly after that, I realized I couldn't stay vertical anymore so I laid down. I remember the voices fading out, the coldness, and then waking up with an arm covered in drool. An hour or two of sleep will do that. I woke up to cheering and high fives...

Grab-Bag 300: Duckrolled

I, probably fortunately, slept through this level. It was JavaScript code that, through a combination of nested packing, syntax errors, obfuscation, and duckrolling — was very annoying to decode.

Here's how I understand it happening: I went to sleep, Mark and Mak starting typing and pointing excitedly at the screen, then I was being woken up for high fives. It was a great level, at least for me. I wish they'd solve more like that. [Editor's Note: I wish you'd snore less. (-:|3]

By the time I woke up, I realized I was mostly useless and instead of continuing to bash my head, I started cleaning up and taking out the garbage. That way, when the clock ran out, I could go straight home and get some more, much needed, sleep...

Grab-Bag 200: Blinkenlights

Now, if there's one thing I don't know — and believe me, there are a ton of one things I don't know — it's circuit diagrams. And, worse yet, pictures of breadboards with unknown ICs.

Once this level unlocked, we had a bunch of people looking at it. Andrew, Ben, Justin, Richard, and more. There were LEDs and wires and chips and resisters and stuff, and they had to figure out which LEDs would go on, I assume. What else do LEDs do, really?

After a couple hints from the organizers, including an extra image of the contraption from a new angle so that the wiring was actually visible, and working on it for the entire night, Richard figured it out, and we captured our sixth flag. This put us into tenth place overall, but unfortunately we lost a position in the last forty-five minutes of the contest.

And that's a wrap!

And that was the end. Six flags, eleventh place, and maybe six hours of sleep between the four of us who stayed the night (Alex, Mak, Richard, and I). It was intense!

Personally, I had a great time, and based on feedback from the others, so did they. As I said, we derped the hell outta the contest, but considering we got eleventh place with only four consistently present members on our team, that's darn good.

If I did it again, what would I do differently?
  • I'd get more sleep. I realize I burnt myself out. I bet I could have done better with a proper sleep.
  • Next, I'd try to get together a bigger group, and sleep/work in shifts.
  • I'd also like more space to work, and scratch paper.
  • I'd also like to suck less at debugging Linux applications.
All in all, though, I'm really happy with how it went. I approve!

If you're interested in helping out with other CTF challenges, email me, ron at, and let me know! I'll add you to our mailing list and we'll let you know when we plan to do our next time.

Monday 5 November 2012

SkullSpace 2.0: The new frontier

Hey everybody,

This is the story of SkullSpace's landlord troubles, the mistakes we made, and how we resolved them to create SkullSpace 2.0. Spoiler: it isn't created yet, but you can help by donating! Now, on with the story...

Operation: SkullSpace 1.0

So, let's start with the backstory. We signed a one-year lease a long time ago - June of 2011, give or take. SkullSpace alone signed the lease, and AssentWorks came along as a sublease. They were (and still are!) close friends, and had very similar goals, so we were happy to share space with them.

At the time, we didn't really know what we were getting into, but we knew we were going to make it work. Why? Because SkullSpace was already full of awesome people and only getting better. It was a one-year lease, which was comfortable for us - if the worst happened, we could cut our losses and run.

I realize I'm almost two years late, but I uploaded some pictures from way back then to show you what the space looked like when we moved in, as well as some pictures of our very first renovations. Quite a change from how it looked at our Grand Opening, eh?

Lease status: renewed

A year later, it came time to sign a new lease. This time, the lease had both SkullSpace and AssentWorks on it. Both of us had grown as organizations, and the new lease reflected that. The rent was a little more, but we could afford it. It was still dirt cheap, and utilities were included! The only downside was that the building was poorly maintained. Getting things fixed - like windows that like to fall out and smash on the ground three stories below - took months, when they actually fixed stuff. There were also constant issues with the elevator, plumbing, lights, and everything else. But it was cheap!

In the year-and-a-half since we moved in, I learned everything from building walls to fixing toilets to making a hackerspace into a home. Mike Loney took the reigns and made the renovations happen. I learned so much, and it was fantastic; I wouldn't trade that experience for anything!

"You guys cost us how much!?"

Now, fast forward to last month: October 2012. The landlord - that is, the people who own the building - saw the electrical bill. Apparently they'd been paying it without looking, and they freaked out. It turns out, maintaining an old leaky building with no insulation and largely electrical heat (and cooling) isn't cheap! And despite our lease explicitly saying that electrical was included, they wanted us to pay it. In our opinion, no dice.

This is where it gets interesting. Our lease had a stipulation in it saying that, with six-months of warning, they could terminate the agreement and leave us on the street. We knew that risk and were prepared to move if it was ever invoked. As a hackerspace, we're agile. We can survive! Heck, our friends at Protospace were homeless for awhile, and I'm sure they aren't the first!

That being said, we share the space with our friends at AssentWorks, and they had a big grant coming down the pipe. For them, the choice was obvious: make the landlords happy to avoid being kicked out. For them, losing space unannounced would cost a whole lot more than the electrical bill they were being asked to pay!

Divide and conquer

Now, the landlords - in a smart but also asshole move - used this dissonance to their advantage: they talked to AssentWorks directly, basically leaving their own property management firm and SkullSpace out of the negotiations, and AssentWorks chose to pay the bill and sign a new lease as the sole entity inhabiting the floor, but with the option to sublet to us. A reasonable choice, of course - I would have done the same if I was in their shoes.

That left SkullSpace and AssentWorks in an interesting predicament. If SkullSpace stayed, we'd be expected to pay half of a bill that we can't afford. If we left, we left AssentWorks holding the hot potato, which isn't fair. So, we talked to AssentWorks about options - can we pay you back over time? Can we pay part of the bill? etc.

In the end, AssentWorks gave us three options: one, we stay, pay half the bill, pay rent and utilities three months in advance. Impossible. Two, we leave in 2 months (end of December), and pay the rent in advance, and pay our half of the electrical bill. Three, we leave in a month - end of November - and pay nothing, not even our November rent. That last deal was extremely fair - it was AssentWorks recognizing that they expected more of us than we could afford, and giving out the option to cut and run. I can't thank them enough for that one!

Just to re-iterate: our position was always that we don't pay any of the electrical bill, and that AssentWorks shouldn't have either. Our lease explicitly stated that it was paid for, and if the landlords screwed up then that's their problem. Of course, that's not how business really works.

We (the SkullSpace Board of Directors) sat down at the table with AssentWorks a few times to hammer out these options, and later to discuss them. After bringing the amazing Ian Trump on board (that's his company site, since I don't have a better link), we managed to hammer out a deal that was mutually satisfactory: We stay for three months - until the end of January - paying a portion of our half of the electrical bill, and pay our utilities for those three months. At the end of January, we'd cut and run. The SkullSpace Board and AssentWorks both supported this plan.

"Your plan's bad and you should feel bad"

Last Tuesday (October 30, 2012), we brought that plan to the membership. And, the membership said no. They want to leave at the end of November. Ooookay!

This is the magic of a hackerspace: the Board can propose one thing, and be totally shot down. It was awesome! Justin - our former Operations Manager - had done a bunch of groundwork on finding a new space. Although it wasn't financially feasible yet - and as of now it still may not be - he sold it really well. His plan was that we give AssentWorks our notice that we're leaving at the end of November and sign this new lease. RIGHT NOW, basically. It was scary, to me, that there was so much support for a plan that I had just heard. But, it is what it is.

It wasn't until Mak - our former Vice President - pointed out that leaving the space in a month and getting the expensive space that Justin was looking for aren't both required. We can give our notice and move to either the space Justin proposed or another space, just as easily. Or even spend time homeless and saving money if we need to. Smart!

So, the membership overwhelmingly supported terminating our lease at the end of November, and finding a new space. The Justin Plan is still a viable option, and is becoming more viable every day. We started an Indiegogo campaign to help fund the move and to make our new space - wherever it happens to be - into a home.

Whatever we get and wherever we end up, it will be awesome, because we have awesome people. And that's what a hackerspace is about: the people. SkullSpace 2.0: Coming soon, to Winnipeg.

And, that's where we are now. Still exploring options, looking around, and figuring out WTF we can do to make this work.

Lessons learned

This is the most important part, in my opinion. Particularly for others who are reading this. How did we get into this tight spot, and why.

We, in my opinion, made at least two fundamental mistakes. And they're mistakes that I see other hackerspaces making all the time, and that I call them for.

First, we depended on an unsustainable rent. We had a massive amount of space - 4000 sq.ft. - for peanuts - $750/month all-in. The problem is, we depended on that. We had an emergency fund saved up, but in the end we couldn't afford the proper rent for the space, so we lost it. A lot of hackerspaces depend on having cheap rents - below market price - to sustain themselves. Not smart!

And second, we were tied too closely to AssentWorks. Getting into a position where another entity can cause you hardship - either on purpose or by accident - is dangerous. Especially as a hackerspace, since I believe strongly in openness, and I let everybody see my cards. When it comes to a situation where we have to do a business negotiation, I feel like they know everything about me and I know nothing about them, which isn't fair.

As I said before - and it's important - AssentWorks was actually really good to us. They made a business decision - and I believe it was a wrong one, although I would have done the same - to pay the landlord money that they didn't owe him. But they gave us an out, and let us cut and run, without owing them anything. I'm extremely grateful for that! A more cruel organization could have made this very difficult for us.

So, lessons learned: don't rely on others to make an unsustainable model work. Make sure you can afford market rates for real estate. BAM! Done. :)

And, one last time, please donate! Help make SkullSpace 2.0 happen!