I decided to learn Ruby, so I present my first experiment in a new language: Termbrot!

Termbrot iterates over points in the complex plane, animating the image as it discards points from the Mandelbrot set. Get it on GitHub.


Dear Google, Please Stop This

I hate it when Google auto-corrects my searches without telling me.

I didn’t search for Magic or hotkeys. It’s okay to auto-correct, but give me an undo link.


Bypassing Little Snitch

“Little Snitch informs you whenever a program attempts to establish an outgoing Internet connection. You can then choose to allow or deny this connection, or define a rule how to handle similar, future connection attempts. This reliably prevents private data from being sent out without your knowledge. Little Snitch runs inconspicuously in the background and it can also detect network related activity of viruses, trojans and other malware.” — Little Snitch website


Programs like Little Snitch instill users with a false sense of security. Mac owners often use Little Snitch to prevent pirated applications from dialing home and to ensure that cracked versions of software don’t contain spyware. Nothing could be more naive: If an attacker can run code in the right context, it’s game over. Apps like Little Snitch can’t possibly prevent that.

Keep in mind that this specific attack could have been prevented, but there are more insidious ways to bypass Little Snitch. The security model is broken by design.

How to bypass Little Snitch

Once a binary is allowed access to the internet, Little Snitch will continue to allow access even if the binary changes. On OS X, applications are usually installed by dragging them to the Applications folder. This means they are owned by the user who installed them. Firefox and Chrome take advantage of this to auto-update without the root password. We can use this to overwrite binaries.

We bypass Little Snitch by replacing a trusted binary with our own executable; it will execute with the network-permissions of the original app.


We need a binary that connects to the internet and we can’t use an interpreted language. For your convenience, here is one such program.

Download it. Then compile as follows:

brew install curl && brew link curl

You can ensure that Little Snitch is working by running ./payload.

Lets backup Firefox and replace it.

mv /Applications/Firefox.app/Contents/MacOS/firefox{,.orig}
mv payload /Applications/Firefox.app/Contents/MacOS/firefox

That’s it. If you were writing a program that needed network access without permission,  you would do this programatically and execute Firefox. That’s not the case here, so launch Firefox manually and examine /little_snitch_example.txt

Lastly, you probably want to use Firefox again:

mv /Applications/Firefox.app/Contents/MacOS/firefox{.orig,}

Closing Notes

In real usage, you should examine ~/Library/Application Support/Little Snitch/rules.usr.xpl to pick the right binary.

Lastly, all testing was done on Snow Leopard. You may need to tweak this for Lion or the App Store.


Use of void in C prototypes

A giant died this morning. My condolences go to Dennis Ritchie’s family and friends.

In memory of Dennis, here is a short history lesson about C prototypes. Have you ever wondered why the following is legal?

#include <stdio.h>;

void foo () {
    printf("Goodbye, World!\n");

int main (int argc, char **argv) {
    foo(1); /* Call foo with a non-existent parameter */
    return 0;

$ gcc test.c -Wall -Werror
$ ./a.out
Goodbye, World!

This is legal for historical reasons. In pre-ANSI C function prototypes didn’t include parameters. C89 introduced parameters in prototypes, but it continued to recognize the old syntax for backwards compatibility.

If you want to declare a function foo that really takes no parameters, use void:

void foo (void);

Installing lxml on Leopard

I’m surely the last developer using Leopard, but Snow Leopard couldn’t compete with Ubuntu and Lion has more warts than the Wicked Witch of the West.

Anyway, you can’t just install lxml with pip (the preferred way of installing Python libraries) because lxml depends on a recent version of libxml2. If you try, gcc will stop when it encounters missing headers added in later versions of libxml2:

libxml/schematron.h: No such file or directory blah blah blah

Instead, use the fabulous Homebrew to install a newer version of libxml2 and then run pip with that version.

brew install libxml2
pip install lxml --install-option="--with-xml2-config=/usr/local/Cellar/libxml2/2.7.8/bin/xml2-config"
Pages ... 1 2 3 4 5 6 7 8